aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2009-03-30 22:30:33 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-04-22 16:54:38 -0400
commit203c4805e91786f9a010bc7945a0fde70c9da28e (patch)
tree00415276b2fe65713f066ffe07b11ad2d8b6bea8 /drivers/net/wireless/ath
parent1878f77e13b9d720b78c4f818b94bfd4a7f596e5 (diff)
atheros: put atheros wireless drivers into ath/
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/Kconfig6
-rw-r--r--drivers/net/wireless/ath/Makefile4
-rw-r--r--drivers/net/wireless/ath/ar9170/Kconfig18
-rw-r--r--drivers/net/wireless/ath/ar9170/Makefile3
-rw-r--r--drivers/net/wireless/ath/ar9170/ar9170.h212
-rw-r--r--drivers/net/wireless/ath/ar9170/cmd.c129
-rw-r--r--drivers/net/wireless/ath/ar9170/cmd.h91
-rw-r--r--drivers/net/wireless/ath/ar9170/eeprom.h179
-rw-r--r--drivers/net/wireless/ath/ar9170/hw.h417
-rw-r--r--drivers/net/wireless/ath/ar9170/led.c171
-rw-r--r--drivers/net/wireless/ath/ar9170/mac.c452
-rw-r--r--drivers/net/wireless/ath/ar9170/main.c1690
-rw-r--r--drivers/net/wireless/ath/ar9170/phy.c1240
-rw-r--r--drivers/net/wireless/ath/ar9170/usb.c822
-rw-r--r--drivers/net/wireless/ath/ar9170/usb.h74
-rw-r--r--drivers/net/wireless/ath/ath5k/Kconfig41
-rw-r--r--drivers/net/wireless/ath/ath5k/Makefile15
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h1354
-rw-r--r--drivers/net/wireless/ath/ath5k/attach.c348
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c3110
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h190
-rw-r--r--drivers/net/wireless/ath/ath5k/caps.c195
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.c538
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.h203
-rw-r--r--drivers/net/wireless/ath/ath5k/desc.c696
-rw-r--r--drivers/net/wireless/ath/ath5k/desc.h332
-rw-r--r--drivers/net/wireless/ath/ath5k/dma.c705
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.c1769
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.h441
-rw-r--r--drivers/net/wireless/ath/ath5k/gpio.c176
-rw-r--r--drivers/net/wireless/ath/ath5k/initvals.c1557
-rw-r--r--drivers/net/wireless/ath/ath5k/led.c176
-rw-r--r--drivers/net/wireless/ath/ath5k/pcu.c1174
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c2599
-rw-r--r--drivers/net/wireless/ath/ath5k/qcu.c546
-rw-r--r--drivers/net/wireless/ath/ath5k/reg.h2589
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c1346
-rw-r--r--drivers/net/wireless/ath/ath5k/rfbuffer.h1181
-rw-r--r--drivers/net/wireless/ath/ath5k/rfgain.h516
-rw-r--r--drivers/net/wireless/ath/ath9k/Kconfig24
-rw-r--r--drivers/net/wireless/ath/ath9k/Makefile18
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c192
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c822
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.h138
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h730
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c743
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c1060
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.h124
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c562
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h161
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.c2813
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h509
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c3861
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h631
-rw-r--r--drivers/net/wireless/ath/ath9k/initvals.h4848
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c976
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h680
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c2890
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c295
-rw-r--r--drivers/net/wireless/ath/ath9k/phy.c424
-rw-r--r--drivers/net/wireless/ath/ath9k/phy.h576
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c1752
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.h216
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c704
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h1511
-rw-r--r--drivers/net/wireless/ath/ath9k/virtual.c662
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c2171
67 files changed, 57397 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index 76517a45a212..d26e7b485315 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -1,4 +1,8 @@
1config ATH_COMMON 1config ATH_COMMON
2 tristate "Atheros Wireless Cards Shared Support" 2 tristate "Atheros Wireless Cards"
3 depends on ATH5K || ATH9K || AR9170_USB 3 depends on ATH5K || ATH9K || AR9170_USB
4 4
5source "drivers/net/wireless/ath/ath5k/Kconfig"
6source "drivers/net/wireless/ath/ath9k/Kconfig"
7source "drivers/net/wireless/ath/ar9170/Kconfig"
8
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile
index bc77646f90ad..a005b919233f 100644
--- a/drivers/net/wireless/ath/Makefile
+++ b/drivers/net/wireless/ath/Makefile
@@ -1,3 +1,7 @@
1obj-$(CONFIG_ATH5K) += ath5k/
2obj-$(CONFIG_ATH9K) += ath9k/
3obj-$(CONFIG_AR9170_USB) += ar9170/
4
1obj-$(CONFIG_ATH_COMMON) += ath.o 5obj-$(CONFIG_ATH_COMMON) += ath.o
2ath-objs := regd.o 6ath-objs := regd.o
3 7
diff --git a/drivers/net/wireless/ath/ar9170/Kconfig b/drivers/net/wireless/ath/ar9170/Kconfig
new file mode 100644
index 000000000000..b99e3263ee6d
--- /dev/null
+++ b/drivers/net/wireless/ath/ar9170/Kconfig
@@ -0,0 +1,18 @@
1config AR9170_USB
2 tristate "Atheros AR9170 802.11n USB support"
3 depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL
4 select FW_LOADER
5 select ATH_COMMON
6 help
7 This is a driver for the Atheros "otus" 802.11n USB devices.
8
9 These devices require additional firmware (2 files).
10 For now, these files can be downloaded from here:
11 http://wireless.kernel.org/en/users/Drivers/ar9170
12
13 If you choose to build a module, it'll be called ar9170usb.
14
15config AR9170_LEDS
16 bool
17 depends on AR9170_USB && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = AR9170_USB)
18 default y
diff --git a/drivers/net/wireless/ath/ar9170/Makefile b/drivers/net/wireless/ath/ar9170/Makefile
new file mode 100644
index 000000000000..8d91c7ee3215
--- /dev/null
+++ b/drivers/net/wireless/ath/ar9170/Makefile
@@ -0,0 +1,3 @@
1ar9170usb-objs := usb.o main.o cmd.o mac.o phy.o led.o
2
3obj-$(CONFIG_AR9170_USB) += ar9170usb.o
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h
new file mode 100644
index 000000000000..f797495faa56
--- /dev/null
+++ b/drivers/net/wireless/ath/ar9170/ar9170.h
@@ -0,0 +1,212 @@
1/*
2 * Atheros AR9170 driver
3 *
4 * Driver specific definitions
5 *
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, see
20 * http://www.gnu.org/licenses/.
21 *
22 * This file incorporates work covered by the following copyright and
23 * permission notice:
24 * Copyright (c) 2007-2008 Atheros Communications, Inc.
25 *
26 * Permission to use, copy, modify, and/or distribute this software for any
27 * purpose with or without fee is hereby granted, provided that the above
28 * copyright notice and this permission notice appear in all copies.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
31 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
32 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
33 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
34 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
35 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
36 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37 */
38#ifndef __AR9170_H
39#define __AR9170_H
40
41#include <linux/completion.h>
42#include <linux/spinlock.h>
43#include <net/wireless.h>
44#include <net/mac80211.h>
45#ifdef CONFIG_AR9170_LEDS
46#include <linux/leds.h>
47#endif /* CONFIG_AR9170_LEDS */
48#include "eeprom.h"
49#include "hw.h"
50
51#include "../regd.h"
52
53#define PAYLOAD_MAX (AR9170_MAX_CMD_LEN/4 - 1)
54
55enum ar9170_bw {
56 AR9170_BW_20,
57 AR9170_BW_40_BELOW,
58 AR9170_BW_40_ABOVE,
59
60 __AR9170_NUM_BW,
61};
62
63enum ar9170_rf_init_mode {
64 AR9170_RFI_NONE,
65 AR9170_RFI_WARM,
66 AR9170_RFI_COLD,
67};
68
69#define AR9170_MAX_RX_BUFFER_SIZE 8192
70
71#ifdef CONFIG_AR9170_LEDS
72struct ar9170;
73
74struct ar9170_led {
75 struct ar9170 *ar;
76 struct led_classdev l;
77 char name[32];
78 unsigned int toggled;
79 bool registered;
80};
81
82#endif /* CONFIG_AR9170_LEDS */
83
84enum ar9170_device_state {
85 AR9170_UNKNOWN_STATE,
86 AR9170_STOPPED,
87 AR9170_IDLE,
88 AR9170_STARTED,
89 AR9170_ASSOCIATED,
90};
91
92struct ar9170 {
93 struct ieee80211_hw *hw;
94 struct mutex mutex;
95 enum ar9170_device_state state;
96
97 int (*open)(struct ar9170 *);
98 void (*stop)(struct ar9170 *);
99 int (*tx)(struct ar9170 *, struct sk_buff *, bool, unsigned int);
100 int (*exec_cmd)(struct ar9170 *, enum ar9170_cmd, u32 ,
101 void *, u32 , void *);
102 void (*callback_cmd)(struct ar9170 *, u32 , void *);
103
104 /* interface mode settings */
105 struct ieee80211_vif *vif;
106 u8 mac_addr[ETH_ALEN];
107 u8 bssid[ETH_ALEN];
108
109 /* beaconing */
110 struct sk_buff *beacon;
111 struct work_struct beacon_work;
112
113 /* cryptographic engine */
114 u64 usedkeys;
115 bool rx_software_decryption;
116 bool disable_offload;
117
118 /* filter settings */
119 struct work_struct filter_config_work;
120 u64 cur_mc_hash, want_mc_hash;
121 u32 cur_filter, want_filter;
122 unsigned int filter_changed;
123 bool sniffer_enabled;
124
125 /* PHY */
126 struct ieee80211_channel *channel;
127 int noise[4];
128
129 /* power calibration data */
130 u8 power_5G_leg[4];
131 u8 power_2G_cck[4];
132 u8 power_2G_ofdm[4];
133 u8 power_5G_ht20[8];
134 u8 power_5G_ht40[8];
135 u8 power_2G_ht20[8];
136 u8 power_2G_ht40[8];
137
138#ifdef CONFIG_AR9170_LEDS
139 struct delayed_work led_work;
140 struct ar9170_led leds[AR9170_NUM_LEDS];
141#endif /* CONFIG_AR9170_LEDS */
142
143 /* qos queue settings */
144 spinlock_t tx_stats_lock;
145 struct ieee80211_tx_queue_stats tx_stats[5];
146 struct ieee80211_tx_queue_params edcf[5];
147
148 spinlock_t cmdlock;
149 __le32 cmdbuf[PAYLOAD_MAX + 1];
150
151 /* MAC statistics */
152 struct ieee80211_low_level_stats stats;
153
154 /* EEPROM */
155 struct ar9170_eeprom eeprom;
156 struct ath_regulatory regulatory;
157
158 /* global tx status for unregistered Stations. */
159 struct sk_buff_head global_tx_status;
160 struct sk_buff_head global_tx_status_waste;
161 struct delayed_work tx_status_janitor;
162};
163
164struct ar9170_sta_info {
165 struct sk_buff_head tx_status[__AR9170_NUM_TXQ];
166};
167
168#define IS_STARTED(a) (a->state >= AR9170_STARTED)
169#define IS_ACCEPTING_CMD(a) (a->state >= AR9170_IDLE)
170
171#define AR9170_FILTER_CHANGED_PROMISC BIT(0)
172#define AR9170_FILTER_CHANGED_MULTICAST BIT(1)
173#define AR9170_FILTER_CHANGED_FRAMEFILTER BIT(2)
174
175/* exported interface */
176void *ar9170_alloc(size_t priv_size);
177int ar9170_register(struct ar9170 *ar, struct device *pdev);
178void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb);
179void ar9170_unregister(struct ar9170 *ar);
180void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb,
181 bool update_statistics, u16 tx_status);
182
183/* MAC */
184int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
185int ar9170_init_mac(struct ar9170 *ar);
186int ar9170_set_qos(struct ar9170 *ar);
187int ar9170_update_multicast(struct ar9170 *ar);
188int ar9170_update_frame_filter(struct ar9170 *ar);
189int ar9170_set_operating_mode(struct ar9170 *ar);
190int ar9170_set_beacon_timers(struct ar9170 *ar);
191int ar9170_set_hwretry_limit(struct ar9170 *ar, u32 max_retry);
192int ar9170_update_beacon(struct ar9170 *ar);
193void ar9170_new_beacon(struct work_struct *work);
194int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype,
195 u8 keyidx, u8 *keydata, int keylen);
196int ar9170_disable_key(struct ar9170 *ar, u8 id);
197
198/* LEDs */
199#ifdef CONFIG_AR9170_LEDS
200int ar9170_register_leds(struct ar9170 *ar);
201void ar9170_unregister_leds(struct ar9170 *ar);
202#endif /* CONFIG_AR9170_LEDS */
203int ar9170_init_leds(struct ar9170 *ar);
204int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state);
205
206/* PHY / RF */
207int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band);
208int ar9170_init_rf(struct ar9170 *ar);
209int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
210 enum ar9170_rf_init_mode rfi, enum ar9170_bw bw);
211
212#endif /* __AR9170_H */
diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c
new file mode 100644
index 000000000000..f57a6200167b
--- /dev/null
+++ b/drivers/net/wireless/ath/ar9170/cmd.c
@@ -0,0 +1,129 @@
1/*
2 * Atheros AR9170 driver
3 *
4 * Basic HW register/memory/command access functions
5 *
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, see
20 * http://www.gnu.org/licenses/.
21 *
22 * This file incorporates work covered by the following copyright and
23 * permission notice:
24 * Copyright (c) 2007-2008 Atheros Communications, Inc.
25 *
26 * Permission to use, copy, modify, and/or distribute this software for any
27 * purpose with or without fee is hereby granted, provided that the above
28 * copyright notice and this permission notice appear in all copies.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
31 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
32 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
33 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
34 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
35 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
36 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37 */
38
39#include "ar9170.h"
40#include "cmd.h"
41
42int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len)
43{
44 int err;
45
46 if (unlikely(!IS_ACCEPTING_CMD(ar)))
47 return 0;
48
49 err = ar->exec_cmd(ar, AR9170_CMD_WMEM, len, (u8 *) data, 0, NULL);
50 if (err)
51 printk(KERN_DEBUG "%s: writing memory failed\n",
52 wiphy_name(ar->hw->wiphy));
53 return err;
54}
55
56int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)
57{
58 __le32 buf[2] = {
59 cpu_to_le32(reg),
60 cpu_to_le32(val),
61 };
62 int err;
63
64 if (unlikely(!IS_ACCEPTING_CMD(ar)))
65 return 0;
66
67 err = ar->exec_cmd(ar, AR9170_CMD_WREG, sizeof(buf),
68 (u8 *) buf, 0, NULL);
69 if (err)
70 printk(KERN_DEBUG "%s: writing reg %#x (val %#x) failed\n",
71 wiphy_name(ar->hw->wiphy), reg, val);
72 return err;
73}
74
75static int ar9170_read_mreg(struct ar9170 *ar, int nregs,
76 const u32 *regs, u32 *out)
77{
78 int i, err;
79 __le32 *offs, *res;
80
81 if (unlikely(!IS_ACCEPTING_CMD(ar)))
82 return 0;
83
84 /* abuse "out" for the register offsets, must be same length */
85 offs = (__le32 *)out;
86 for (i = 0; i < nregs; i++)
87 offs[i] = cpu_to_le32(regs[i]);
88
89 /* also use the same buffer for the input */
90 res = (__le32 *)out;
91
92 err = ar->exec_cmd(ar, AR9170_CMD_RREG,
93 4 * nregs, (u8 *)offs,
94 4 * nregs, (u8 *)res);
95 if (err)
96 return err;
97
98 /* convert result to cpu endian */
99 for (i = 0; i < nregs; i++)
100 out[i] = le32_to_cpu(res[i]);
101
102 return 0;
103}
104
105int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val)
106{
107 return ar9170_read_mreg(ar, 1, &reg, val);
108}
109
110int ar9170_echo_test(struct ar9170 *ar, u32 v)
111{
112 __le32 echobuf = cpu_to_le32(v);
113 __le32 echores;
114 int err;
115
116 if (unlikely(!IS_ACCEPTING_CMD(ar)))
117 return -ENODEV;
118
119 err = ar->exec_cmd(ar, AR9170_CMD_ECHO,
120 4, (u8 *)&echobuf,
121 4, (u8 *)&echores);
122 if (err)
123 return err;
124
125 if (echobuf != echores)
126 return -EINVAL;
127
128 return 0;
129}
diff --git a/drivers/net/wireless/ath/ar9170/cmd.h b/drivers/net/wireless/ath/ar9170/cmd.h
new file mode 100644
index 000000000000..a4f0e50e52b4
--- /dev/null
+++ b/drivers/net/wireless/ath/ar9170/cmd.h
@@ -0,0 +1,91 @@
1/*
2 * Atheros AR9170 driver
3 *
4 * Basic HW register/memory/command access functions
5 *
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, see
20 * http://www.gnu.org/licenses/.
21 *
22 * This file incorporates work covered by the following copyright and
23 * permission notice:
24 * Copyright (c) 2007-2008 Atheros Communications, Inc.
25 *
26 * Permission to use, copy, modify, and/or distribute this software for any
27 * purpose with or without fee is hereby granted, provided that the above
28 * copyright notice and this permission notice appear in all copies.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
31 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
32 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
33 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
34 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
35 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
36 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37 */
38#ifndef __CMD_H
39#define __CMD_H
40
41#include "ar9170.h"
42
43/* basic HW access */
44int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len);
45int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val);
46int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val);
47int ar9170_echo_test(struct ar9170 *ar, u32 v);
48
49/*
50 * Macros to facilitate writing multiple registers in a single
51 * write-combining USB command. Note that when the first group
52 * fails the whole thing will fail without any others attempted,
53 * but you won't know which write in the group failed.
54 */
55#define ar9170_regwrite_begin(ar) \
56do { \
57 int __nreg = 0, __err = 0; \
58 struct ar9170 *__ar = ar;
59
60#define ar9170_regwrite(r, v) do { \
61 __ar->cmdbuf[2 * __nreg + 1] = cpu_to_le32(r); \
62 __ar->cmdbuf[2 * __nreg + 2] = cpu_to_le32(v); \
63 __nreg++; \
64 if ((__nreg >= PAYLOAD_MAX/2)) { \
65 if (IS_ACCEPTING_CMD(__ar)) \
66 __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \
67 8 * __nreg, \
68 (u8 *) &__ar->cmdbuf[1], \
69 0, NULL); \
70 __nreg = 0; \
71 if (__err) \
72 goto __regwrite_out; \
73 } \
74} while (0)
75
76#define ar9170_regwrite_finish() \
77__regwrite_out : \
78 if (__nreg) { \
79 if (IS_ACCEPTING_CMD(__ar)) \
80 __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \
81 8 * __nreg, \
82 (u8 *) &__ar->cmdbuf[1], \
83 0, NULL); \
84 __nreg = 0; \
85 }
86
87#define ar9170_regwrite_result() \
88 __err; \
89} while (0);
90
91#endif /* __CMD_H */
diff --git a/drivers/net/wireless/ath/ar9170/eeprom.h b/drivers/net/wireless/ath/ar9170/eeprom.h
new file mode 100644
index 000000000000..d2c8cc83f1dd
--- /dev/null
+++ b/drivers/net/wireless/ath/ar9170/eeprom.h
@@ -0,0 +1,179 @@
1/*
2 * Atheros AR9170 driver
3 *
4 * EEPROM layout
5 *
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, see
20 * http://www.gnu.org/licenses/.
21 *
22 * This file incorporates work covered by the following copyright and
23 * permission notice:
24 * Copyright (c) 2007-2008 Atheros Communications, Inc.
25 *
26 * Permission to use, copy, modify, and/or distribute this software for any
27 * purpose with or without fee is hereby granted, provided that the above
28 * copyright notice and this permission notice appear in all copies.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
31 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
32 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
33 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
34 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
35 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
36 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37 */
38#ifndef __AR9170_EEPROM_H
39#define __AR9170_EEPROM_H
40
41#define AR5416_MAX_CHAINS 2
42#define AR5416_MODAL_SPURS 5
43
44struct ar9170_eeprom_modal {
45 __le32 antCtrlChain[AR5416_MAX_CHAINS];
46 __le32 antCtrlCommon;
47 s8 antennaGainCh[AR5416_MAX_CHAINS];
48 u8 switchSettling;
49 u8 txRxAttenCh[AR5416_MAX_CHAINS];
50 u8 rxTxMarginCh[AR5416_MAX_CHAINS];
51 s8 adcDesiredSize;
52 s8 pgaDesiredSize;
53 u8 xlnaGainCh[AR5416_MAX_CHAINS];
54 u8 txEndToXpaOff;
55 u8 txEndToRxOn;
56 u8 txFrameToXpaOn;
57 u8 thresh62;
58 s8 noiseFloorThreshCh[AR5416_MAX_CHAINS];
59 u8 xpdGain;
60 u8 xpd;
61 s8 iqCalICh[AR5416_MAX_CHAINS];
62 s8 iqCalQCh[AR5416_MAX_CHAINS];
63 u8 pdGainOverlap;
64 u8 ob;
65 u8 db;
66 u8 xpaBiasLvl;
67 u8 pwrDecreaseFor2Chain;
68 u8 pwrDecreaseFor3Chain;
69 u8 txFrameToDataStart;
70 u8 txFrameToPaOn;
71 u8 ht40PowerIncForPdadc;
72 u8 bswAtten[AR5416_MAX_CHAINS];
73 u8 bswMargin[AR5416_MAX_CHAINS];
74 u8 swSettleHt40;
75 u8 reserved[22];
76 struct spur_channel {
77 __le16 spurChan;
78 u8 spurRangeLow;
79 u8 spurRangeHigh;
80 } __packed spur_channels[AR5416_MODAL_SPURS];
81} __packed;
82
83#define AR5416_NUM_PD_GAINS 4
84#define AR5416_PD_GAIN_ICEPTS 5
85
86struct ar9170_calibration_data_per_freq {
87 u8 pwr_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
88 u8 vpd_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
89} __packed;
90
91#define AR5416_NUM_5G_CAL_PIERS 8
92#define AR5416_NUM_2G_CAL_PIERS 4
93
94#define AR5416_NUM_5G_TARGET_PWRS 8
95#define AR5416_NUM_2G_CCK_TARGET_PWRS 3
96#define AR5416_NUM_2G_OFDM_TARGET_PWRS 4
97#define AR5416_MAX_NUM_TGT_PWRS 8
98
99struct ar9170_calibration_target_power_legacy {
100 u8 freq;
101 u8 power[4];
102} __packed;
103
104struct ar9170_calibration_target_power_ht {
105 u8 freq;
106 u8 power[8];
107} __packed;
108
109#define AR5416_NUM_CTLS 24
110
111struct ar9170_calctl_edges {
112 u8 channel;
113#define AR9170_CALCTL_EDGE_FLAGS 0xC0
114 u8 power_flags;
115} __packed;
116
117#define AR5416_NUM_BAND_EDGES 8
118
119struct ar9170_calctl_data {
120 struct ar9170_calctl_edges
121 control_edges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
122} __packed;
123
124
125struct ar9170_eeprom {
126 __le16 length;
127 __le16 checksum;
128 __le16 version;
129 u8 operating_flags;
130#define AR9170_OPFLAG_5GHZ 1
131#define AR9170_OPFLAG_2GHZ 2
132 u8 misc;
133 __le16 reg_domain[2];
134 u8 mac_address[6];
135 u8 rx_mask;
136 u8 tx_mask;
137 __le16 rf_silent;
138 __le16 bluetooth_options;
139 __le16 device_capabilities;
140 __le32 build_number;
141 u8 deviceType;
142 u8 reserved[33];
143
144 u8 customer_data[64];
145
146 struct ar9170_eeprom_modal
147 modal_header[2];
148
149 u8 cal_freq_pier_5G[AR5416_NUM_5G_CAL_PIERS];
150 u8 cal_freq_pier_2G[AR5416_NUM_2G_CAL_PIERS];
151
152 struct ar9170_calibration_data_per_freq
153 cal_pier_data_5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS],
154 cal_pier_data_2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
155
156 /* power calibration data */
157 struct ar9170_calibration_target_power_legacy
158 cal_tgt_pwr_5G[AR5416_NUM_5G_TARGET_PWRS];
159 struct ar9170_calibration_target_power_ht
160 cal_tgt_pwr_5G_ht20[AR5416_NUM_5G_TARGET_PWRS],
161 cal_tgt_pwr_5G_ht40[AR5416_NUM_5G_TARGET_PWRS];
162
163 struct ar9170_calibration_target_power_legacy
164 cal_tgt_pwr_2G_cck[AR5416_NUM_2G_CCK_TARGET_PWRS],
165 cal_tgt_pwr_2G_ofdm[AR5416_NUM_2G_OFDM_TARGET_PWRS];
166 struct ar9170_calibration_target_power_ht
167 cal_tgt_pwr_2G_ht20[AR5416_NUM_2G_OFDM_TARGET_PWRS],
168 cal_tgt_pwr_2G_ht40[AR5416_NUM_2G_OFDM_TARGET_PWRS];
169
170 /* conformance testing limits */
171 u8 ctl_index[AR5416_NUM_CTLS];
172 struct ar9170_calctl_data
173 ctl_data[AR5416_NUM_CTLS];
174
175 u8 pad;
176 __le16 subsystem_id;
177} __packed;
178
179#endif /* __AR9170_EEPROM_H */
diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h
new file mode 100644
index 000000000000..53e250a4278f
--- /dev/null
+++ b/drivers/net/wireless/ath/ar9170/hw.h
@@ -0,0 +1,417 @@
1/*
2 * Atheros AR9170 driver
3 *
4 * Hardware-specific definitions
5 *
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, see
20 * http://www.gnu.org/licenses/.
21 *
22 * This file incorporates work covered by the following copyright and
23 * permission notice:
24 * Copyright (c) 2007-2008 Atheros Communications, Inc.
25 *
26 * Permission to use, copy, modify, and/or distribute this software for any
27 * purpose with or without fee is hereby granted, provided that the above
28 * copyright notice and this permission notice appear in all copies.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
31 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
32 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
33 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
34 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
35 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
36 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37 */
38#ifndef __AR9170_HW_H
39#define __AR9170_HW_H
40
41#define AR9170_MAX_CMD_LEN 64
42
43enum ar9170_cmd {
44 AR9170_CMD_RREG = 0x00,
45 AR9170_CMD_WREG = 0x01,
46 AR9170_CMD_RMEM = 0x02,
47 AR9170_CMD_WMEM = 0x03,
48 AR9170_CMD_BITAND = 0x04,
49 AR9170_CMD_BITOR = 0x05,
50 AR9170_CMD_EKEY = 0x28,
51 AR9170_CMD_DKEY = 0x29,
52 AR9170_CMD_FREQUENCY = 0x30,
53 AR9170_CMD_RF_INIT = 0x31,
54 AR9170_CMD_SYNTH = 0x32,
55 AR9170_CMD_FREQ_START = 0x33,
56 AR9170_CMD_ECHO = 0x80,
57 AR9170_CMD_TALLY = 0x81,
58 AR9170_CMD_TALLY_APD = 0x82,
59 AR9170_CMD_CONFIG = 0x83,
60 AR9170_CMD_RESET = 0x90,
61 AR9170_CMD_DKRESET = 0x91,
62 AR9170_CMD_DKTX_STATUS = 0x92,
63 AR9170_CMD_FDC = 0xA0,
64 AR9170_CMD_WREEPROM = 0xB0,
65 AR9170_CMD_WFLASH = 0xB0,
66 AR9170_CMD_FLASH_ERASE = 0xB1,
67 AR9170_CMD_FLASH_PROG = 0xB2,
68 AR9170_CMD_FLASH_CHKSUM = 0xB3,
69 AR9170_CMD_FLASH_READ = 0xB4,
70 AR9170_CMD_FW_DL_INIT = 0xB5,
71 AR9170_CMD_MEM_WREEPROM = 0xBB,
72};
73
74/* endpoints */
75#define AR9170_EP_TX 1
76#define AR9170_EP_RX 2
77#define AR9170_EP_IRQ 3
78#define AR9170_EP_CMD 4
79
80#define AR9170_EEPROM_START 0x1600
81
82#define AR9170_GPIO_REG_BASE 0x1d0100
83#define AR9170_GPIO_REG_PORT_TYPE AR9170_GPIO_REG_BASE
84#define AR9170_GPIO_REG_DATA (AR9170_GPIO_REG_BASE + 4)
85#define AR9170_NUM_LEDS 2
86
87
88#define AR9170_USB_REG_BASE 0x1e1000
89#define AR9170_USB_REG_DMA_CTL (AR9170_USB_REG_BASE + 0x108)
90#define AR9170_DMA_CTL_ENABLE_TO_DEVICE 0x1
91#define AR9170_DMA_CTL_ENABLE_FROM_DEVICE 0x2
92#define AR9170_DMA_CTL_HIGH_SPEED 0x4
93#define AR9170_DMA_CTL_PACKET_MODE 0x8
94
95#define AR9170_USB_REG_MAX_AGG_UPLOAD (AR9170_USB_REG_BASE + 0x110)
96#define AR9170_USB_REG_UPLOAD_TIME_CTL (AR9170_USB_REG_BASE + 0x114)
97
98
99
100#define AR9170_MAC_REG_BASE 0x1c3000
101
102#define AR9170_MAC_REG_TSF_L (AR9170_MAC_REG_BASE + 0x514)
103#define AR9170_MAC_REG_TSF_H (AR9170_MAC_REG_BASE + 0x518)
104
105#define AR9170_MAC_REG_ATIM_WINDOW (AR9170_MAC_REG_BASE + 0x51C)
106#define AR9170_MAC_REG_BCN_PERIOD (AR9170_MAC_REG_BASE + 0x520)
107#define AR9170_MAC_REG_PRETBTT (AR9170_MAC_REG_BASE + 0x524)
108
109#define AR9170_MAC_REG_MAC_ADDR_L (AR9170_MAC_REG_BASE + 0x610)
110#define AR9170_MAC_REG_MAC_ADDR_H (AR9170_MAC_REG_BASE + 0x614)
111#define AR9170_MAC_REG_BSSID_L (AR9170_MAC_REG_BASE + 0x618)
112#define AR9170_MAC_REG_BSSID_H (AR9170_MAC_REG_BASE + 0x61c)
113
114#define AR9170_MAC_REG_GROUP_HASH_TBL_L (AR9170_MAC_REG_BASE + 0x624)
115#define AR9170_MAC_REG_GROUP_HASH_TBL_H (AR9170_MAC_REG_BASE + 0x628)
116
117#define AR9170_MAC_REG_RX_TIMEOUT (AR9170_MAC_REG_BASE + 0x62C)
118
119#define AR9170_MAC_REG_BASIC_RATE (AR9170_MAC_REG_BASE + 0x630)
120#define AR9170_MAC_REG_MANDATORY_RATE (AR9170_MAC_REG_BASE + 0x634)
121#define AR9170_MAC_REG_RTS_CTS_RATE (AR9170_MAC_REG_BASE + 0x638)
122#define AR9170_MAC_REG_BACKOFF_PROTECT (AR9170_MAC_REG_BASE + 0x63c)
123#define AR9170_MAC_REG_RX_THRESHOLD (AR9170_MAC_REG_BASE + 0x640)
124#define AR9170_MAC_REG_RX_PE_DELAY (AR9170_MAC_REG_BASE + 0x64C)
125
126#define AR9170_MAC_REG_DYNAMIC_SIFS_ACK (AR9170_MAC_REG_BASE + 0x658)
127#define AR9170_MAC_REG_SNIFFER (AR9170_MAC_REG_BASE + 0x674)
128#define AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC BIT(0)
129#define AR9170_MAC_REG_SNIFFER_DEFAULTS 0x02000000
130#define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678)
131#define AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE BIT(3)
132#define AR9170_MAC_REG_ENCRYPTION_DEFAULTS 0x70
133
134#define AR9170_MAC_REG_MISC_680 (AR9170_MAC_REG_BASE + 0x680)
135#define AR9170_MAC_REG_TX_UNDERRUN (AR9170_MAC_REG_BASE + 0x688)
136
137#define AR9170_MAC_REG_FRAMETYPE_FILTER (AR9170_MAC_REG_BASE + 0x68c)
138#define AR9170_MAC_REG_FTF_ASSOC_REQ BIT(0)
139#define AR9170_MAC_REG_FTF_ASSOC_RESP BIT(1)
140#define AR9170_MAC_REG_FTF_REASSOC_REQ BIT(2)
141#define AR9170_MAC_REG_FTF_REASSOC_RESP BIT(3)
142#define AR9170_MAC_REG_FTF_PRB_REQ BIT(4)
143#define AR9170_MAC_REG_FTF_PRB_RESP BIT(5)
144#define AR9170_MAC_REG_FTF_BIT6 BIT(6)
145#define AR9170_MAC_REG_FTF_BIT7 BIT(7)
146#define AR9170_MAC_REG_FTF_BEACON BIT(8)
147#define AR9170_MAC_REG_FTF_ATIM BIT(9)
148#define AR9170_MAC_REG_FTF_DEASSOC BIT(10)
149#define AR9170_MAC_REG_FTF_AUTH BIT(11)
150#define AR9170_MAC_REG_FTF_DEAUTH BIT(12)
151#define AR9170_MAC_REG_FTF_BIT13 BIT(13)
152#define AR9170_MAC_REG_FTF_BIT14 BIT(14)
153#define AR9170_MAC_REG_FTF_BIT15 BIT(15)
154#define AR9170_MAC_REG_FTF_BAR BIT(24)
155#define AR9170_MAC_REG_FTF_BIT25 BIT(25)
156#define AR9170_MAC_REG_FTF_PSPOLL BIT(26)
157#define AR9170_MAC_REG_FTF_RTS BIT(27)
158#define AR9170_MAC_REG_FTF_CTS BIT(28)
159#define AR9170_MAC_REG_FTF_ACK BIT(29)
160#define AR9170_MAC_REG_FTF_CFE BIT(30)
161#define AR9170_MAC_REG_FTF_CFE_ACK BIT(31)
162#define AR9170_MAC_REG_FTF_DEFAULTS 0x0500ffff
163#define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff
164
165#define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6A0)
166#define AR9170_MAC_REG_RX_CRC32 (AR9170_MAC_REG_BASE + 0x6A4)
167#define AR9170_MAC_REG_RX_CRC16 (AR9170_MAC_REG_BASE + 0x6A8)
168#define AR9170_MAC_REG_RX_ERR_DECRYPTION_UNI (AR9170_MAC_REG_BASE + 0x6AC)
169#define AR9170_MAC_REG_RX_OVERRUN (AR9170_MAC_REG_BASE + 0x6B0)
170#define AR9170_MAC_REG_RX_ERR_DECRYPTION_MUL (AR9170_MAC_REG_BASE + 0x6BC)
171#define AR9170_MAC_REG_TX_RETRY (AR9170_MAC_REG_BASE + 0x6CC)
172#define AR9170_MAC_REG_TX_TOTAL (AR9170_MAC_REG_BASE + 0x6F4)
173
174
175#define AR9170_MAC_REG_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0x690)
176#define AR9170_MAC_REG_EIFS_AND_SIFS (AR9170_MAC_REG_BASE + 0x698)
177
178#define AR9170_MAC_REG_SLOT_TIME (AR9170_MAC_REG_BASE + 0x6F0)
179
180#define AR9170_MAC_REG_POWERMANAGEMENT (AR9170_MAC_REG_BASE + 0x700)
181#define AR9170_MAC_REG_POWERMGT_IBSS 0xe0
182#define AR9170_MAC_REG_POWERMGT_AP 0xa1
183#define AR9170_MAC_REG_POWERMGT_STA 0x2
184#define AR9170_MAC_REG_POWERMGT_AP_WDS 0x3
185#define AR9170_MAC_REG_POWERMGT_DEFAULTS (0xf << 24)
186
187#define AR9170_MAC_REG_ROLL_CALL_TBL_L (AR9170_MAC_REG_BASE + 0x704)
188#define AR9170_MAC_REG_ROLL_CALL_TBL_H (AR9170_MAC_REG_BASE + 0x708)
189
190#define AR9170_MAC_REG_AC0_CW (AR9170_MAC_REG_BASE + 0xB00)
191#define AR9170_MAC_REG_AC1_CW (AR9170_MAC_REG_BASE + 0xB04)
192#define AR9170_MAC_REG_AC2_CW (AR9170_MAC_REG_BASE + 0xB08)
193#define AR9170_MAC_REG_AC3_CW (AR9170_MAC_REG_BASE + 0xB0C)
194#define AR9170_MAC_REG_AC4_CW (AR9170_MAC_REG_BASE + 0xB10)
195#define AR9170_MAC_REG_AC1_AC0_AIFS (AR9170_MAC_REG_BASE + 0xB14)
196#define AR9170_MAC_REG_AC3_AC2_AIFS (AR9170_MAC_REG_BASE + 0xB18)
197
198#define AR9170_MAC_REG_RETRY_MAX (AR9170_MAC_REG_BASE + 0xB28)
199
200#define AR9170_MAC_REG_FCS_SELECT (AR9170_MAC_REG_BASE + 0xBB0)
201#define AR9170_MAC_FCS_SWFCS 0x1
202#define AR9170_MAC_FCS_FIFO_PROT 0x4
203
204
205#define AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND (AR9170_MAC_REG_BASE + 0xB30)
206
207#define AR9170_MAC_REG_AC1_AC0_TXOP (AR9170_MAC_REG_BASE + 0xB44)
208#define AR9170_MAC_REG_AC3_AC2_TXOP (AR9170_MAC_REG_BASE + 0xB48)
209
210#define AR9170_MAC_REG_ACK_TABLE (AR9170_MAC_REG_BASE + 0xC00)
211#define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xC50)
212
213#define AR9170_MAC_REG_TXRX_MPI (AR9170_MAC_REG_BASE + 0xD7C)
214#define AR9170_MAC_TXRX_MPI_TX_MPI_MASK 0x0000000f
215#define AR9170_MAC_TXRX_MPI_TX_TO_MASK 0x0000fff0
216#define AR9170_MAC_TXRX_MPI_RX_MPI_MASK 0x000f0000
217#define AR9170_MAC_TXRX_MPI_RX_TO_MASK 0xfff00000
218
219#define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xD84)
220#define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xD88)
221#define AR9170_MAC_REG_BCN_PLCP (AR9170_MAC_REG_BASE + 0xD90)
222#define AR9170_MAC_REG_BCN_CTRL (AR9170_MAC_REG_BASE + 0xD94)
223#define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xDA0)
224#define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xDA4)
225
226
227#define AR9170_PWR_REG_BASE 0x1D4000
228
229#define AR9170_PWR_REG_CLOCK_SEL (AR9170_PWR_REG_BASE + 0x008)
230#define AR9170_PWR_CLK_AHB_40MHZ 0
231#define AR9170_PWR_CLK_AHB_20_22MHZ 1
232#define AR9170_PWR_CLK_AHB_40_44MHZ 2
233#define AR9170_PWR_CLK_AHB_80_88MHZ 3
234#define AR9170_PWR_CLK_DAC_160_INV_DLY 0x70
235
236
237/* put beacon here in memory */
238#define AR9170_BEACON_BUFFER_ADDRESS 0x117900
239
240
241struct ar9170_tx_control {
242 __le16 length;
243 __le16 mac_control;
244 __le32 phy_control;
245 u8 frame_data[0];
246} __packed;
247
248/* these are either-or */
249#define AR9170_TX_MAC_PROT_RTS 0x0001
250#define AR9170_TX_MAC_PROT_CTS 0x0002
251
252#define AR9170_TX_MAC_NO_ACK 0x0004
253/* if unset, MAC will only do SIFS space before frame */
254#define AR9170_TX_MAC_BACKOFF 0x0008
255#define AR9170_TX_MAC_BURST 0x0010
256#define AR9170_TX_MAC_AGGR 0x0020
257
258/* encryption is a two-bit field */
259#define AR9170_TX_MAC_ENCR_NONE 0x0000
260#define AR9170_TX_MAC_ENCR_RC4 0x0040
261#define AR9170_TX_MAC_ENCR_CENC 0x0080
262#define AR9170_TX_MAC_ENCR_AES 0x00c0
263
264#define AR9170_TX_MAC_MMIC 0x0100
265#define AR9170_TX_MAC_HW_DURATION 0x0200
266#define AR9170_TX_MAC_QOS_SHIFT 10
267#define AR9170_TX_MAC_QOS_MASK (3 << AR9170_TX_MAC_QOS_SHIFT)
268#define AR9170_TX_MAC_AGGR_QOS_BIT1 0x0400
269#define AR9170_TX_MAC_AGGR_QOS_BIT2 0x0800
270#define AR9170_TX_MAC_DISABLE_TXOP 0x1000
271#define AR9170_TX_MAC_TXOP_RIFS 0x2000
272#define AR9170_TX_MAC_IMM_AMPDU 0x4000
273#define AR9170_TX_MAC_RATE_PROBE 0x8000
274
275/* either-or */
276#define AR9170_TX_PHY_MOD_CCK 0x00000000
277#define AR9170_TX_PHY_MOD_OFDM 0x00000001
278#define AR9170_TX_PHY_MOD_HT 0x00000002
279
280/* depends on modulation */
281#define AR9170_TX_PHY_SHORT_PREAMBLE 0x00000004
282#define AR9170_TX_PHY_GREENFIELD 0x00000004
283
284#define AR9170_TX_PHY_BW_SHIFT 3
285#define AR9170_TX_PHY_BW_MASK (3 << AR9170_TX_PHY_BW_SHIFT)
286#define AR9170_TX_PHY_BW_20MHZ 0
287#define AR9170_TX_PHY_BW_40MHZ 2
288#define AR9170_TX_PHY_BW_40MHZ_DUP 3
289
290#define AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT 6
291#define AR9170_TX_PHY_TX_HEAVY_CLIP_MASK (7 << AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT)
292
293#define AR9170_TX_PHY_TX_PWR_SHIFT 9
294#define AR9170_TX_PHY_TX_PWR_MASK (0x3f << AR9170_TX_PHY_TX_PWR_SHIFT)
295
296/* not part of the hw-spec */
297#define AR9170_TX_PHY_QOS_SHIFT 25
298#define AR9170_TX_PHY_QOS_MASK (3 << AR9170_TX_PHY_QOS_SHIFT)
299
300#define AR9170_TX_PHY_TXCHAIN_SHIFT 15
301#define AR9170_TX_PHY_TXCHAIN_MASK (7 << AR9170_TX_PHY_TXCHAIN_SHIFT)
302#define AR9170_TX_PHY_TXCHAIN_1 1
303/* use for cck, ofdm 6/9/12/18/24 and HT if capable */
304#define AR9170_TX_PHY_TXCHAIN_2 5
305
306#define AR9170_TX_PHY_MCS_SHIFT 18
307#define AR9170_TX_PHY_MCS_MASK (0x7f << AR9170_TX_PHY_MCS_SHIFT)
308
309#define AR9170_TX_PHY_SHORT_GI 0x80000000
310
311struct ar9170_rx_head {
312 u8 plcp[12];
313} __packed;
314
315struct ar9170_rx_tail {
316 union {
317 struct {
318 u8 rssi_ant0, rssi_ant1, rssi_ant2,
319 rssi_ant0x, rssi_ant1x, rssi_ant2x,
320 rssi_combined;
321 } __packed;
322 u8 rssi[7];
323 } __packed;
324
325 u8 evm_stream0[6], evm_stream1[6];
326 u8 phy_err;
327 u8 SAidx, DAidx;
328 u8 error;
329 u8 status;
330} __packed;
331
332#define AR9170_ENC_ALG_NONE 0x0
333#define AR9170_ENC_ALG_WEP64 0x1
334#define AR9170_ENC_ALG_TKIP 0x2
335#define AR9170_ENC_ALG_AESCCMP 0x4
336#define AR9170_ENC_ALG_WEP128 0x5
337#define AR9170_ENC_ALG_WEP256 0x6
338#define AR9170_ENC_ALG_CENC 0x7
339
340#define AR9170_RX_ENC_SOFTWARE 0x8
341
342static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t)
343{
344 return (t->SAidx & 0xc0) >> 4 |
345 (t->DAidx & 0xc0) >> 6;
346}
347
348#define AR9170_RX_STATUS_MODULATION_MASK 0x03
349#define AR9170_RX_STATUS_MODULATION_CCK 0x00
350#define AR9170_RX_STATUS_MODULATION_OFDM 0x01
351#define AR9170_RX_STATUS_MODULATION_HT 0x02
352#define AR9170_RX_STATUS_MODULATION_DUPOFDM 0x03
353
354/* depends on modulation */
355#define AR9170_RX_STATUS_SHORT_PREAMBLE 0x08
356#define AR9170_RX_STATUS_GREENFIELD 0x08
357
358#define AR9170_RX_STATUS_MPDU_MASK 0x30
359#define AR9170_RX_STATUS_MPDU_SINGLE 0x00
360#define AR9170_RX_STATUS_MPDU_FIRST 0x10
361#define AR9170_RX_STATUS_MPDU_MIDDLE 0x20
362#define AR9170_RX_STATUS_MPDU_LAST 0x30
363
364
365#define AR9170_RX_ERROR_RXTO 0x01
366#define AR9170_RX_ERROR_OVERRUN 0x02
367#define AR9170_RX_ERROR_DECRYPT 0x04
368#define AR9170_RX_ERROR_FCS 0x08
369#define AR9170_RX_ERROR_WRONG_RA 0x10
370#define AR9170_RX_ERROR_PLCP 0x20
371#define AR9170_RX_ERROR_MMIC 0x40
372
373struct ar9170_cmd_tx_status {
374 __le16 unkn;
375 u8 dst[ETH_ALEN];
376 __le32 rate;
377 __le16 status;
378} __packed;
379
380#define AR9170_TX_STATUS_COMPLETE 0x00
381#define AR9170_TX_STATUS_RETRY 0x01
382#define AR9170_TX_STATUS_FAILED 0x02
383
384struct ar9170_cmd_ba_failed_count {
385 __le16 failed;
386 __le16 rate;
387} __packed;
388
389struct ar9170_cmd_response {
390 u8 flag;
391 u8 type;
392
393 union {
394 struct ar9170_cmd_tx_status tx_status;
395 struct ar9170_cmd_ba_failed_count ba_fail_cnt;
396 u8 data[0];
397 };
398} __packed;
399
400/* QoS */
401
402/* mac80211 queue to HW/FW map */
403static const u8 ar9170_qos_hwmap[4] = { 3, 2, 0, 1 };
404
405/* HW/FW queue to mac80211 map */
406static const u8 ar9170_qos_mac80211map[4] = { 2, 3, 1, 0 };
407
408enum ar9170_txq {
409 AR9170_TXQ_BE,
410 AR9170_TXQ_BK,
411 AR9170_TXQ_VI,
412 AR9170_TXQ_VO,
413
414 __AR9170_NUM_TXQ,
415};
416
417#endif /* __AR9170_HW_H */
diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c
new file mode 100644
index 000000000000..341cead7f606
--- /dev/null
+++ b/drivers/net/wireless/ath/ar9170/led.c
@@ -0,0 +1,171 @@
1/*
2 * Atheros AR9170 driver
3 *
4 * LED handling
5 *
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, see
20 * http://www.gnu.org/licenses/.
21 *
22 * This file incorporates work covered by the following copyright and
23 * permission notice:
24 * Copyright (c) 2007-2008 Atheros Communications, Inc.
25 *
26 * Permission to use, copy, modify, and/or distribute this software for any
27 * purpose with or without fee is hereby granted, provided that the above
28 * copyright notice and this permission notice appear in all copies.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
31 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
32 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
33 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
34 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
35 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
36 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37 */
38
39#include "ar9170.h"
40#include "cmd.h"
41
42int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state)
43{
44 return ar9170_write_reg(ar, AR9170_GPIO_REG_DATA, led_state);
45}
46
47int ar9170_init_leds(struct ar9170 *ar)
48{
49 int err;
50
51 /* disable LEDs */
52 /* GPIO [0/1 mode: output, 2/3: input] */
53 err = ar9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3);
54 if (err)
55 goto out;
56
57 /* GPIO 0/1 value: off */
58 err = ar9170_set_leds_state(ar, 0);
59
60out:
61 return err;
62}
63
64#ifdef CONFIG_AR9170_LEDS
65static void ar9170_update_leds(struct work_struct *work)
66{
67 struct ar9170 *ar = container_of(work, struct ar9170, led_work.work);
68 int i, tmp, blink_delay = 1000;
69 u32 led_val = 0;
70 bool rerun = false;
71
72 if (unlikely(!IS_ACCEPTING_CMD(ar)))
73 return ;
74
75 mutex_lock(&ar->mutex);
76 for (i = 0; i < AR9170_NUM_LEDS; i++)
77 if (ar->leds[i].toggled) {
78 led_val |= 1 << i;
79
80 tmp = 70 + 200 / (ar->leds[i].toggled);
81 if (tmp < blink_delay)
82 blink_delay = tmp;
83
84 if (ar->leds[i].toggled > 1)
85 ar->leds[i].toggled = 0;
86
87 rerun = true;
88 }
89
90 ar9170_set_leds_state(ar, led_val);
91 mutex_unlock(&ar->mutex);
92
93 if (rerun)
94 queue_delayed_work(ar->hw->workqueue, &ar->led_work,
95 msecs_to_jiffies(blink_delay));
96}
97
98static void ar9170_led_brightness_set(struct led_classdev *led,
99 enum led_brightness brightness)
100{
101 struct ar9170_led *arl = container_of(led, struct ar9170_led, l);
102 struct ar9170 *ar = arl->ar;
103
104 arl->toggled++;
105
106 if (likely(IS_ACCEPTING_CMD(ar) && brightness))
107 queue_delayed_work(ar->hw->workqueue, &ar->led_work, HZ/10);
108}
109
110static int ar9170_register_led(struct ar9170 *ar, int i, char *name,
111 char *trigger)
112{
113 int err;
114
115 snprintf(ar->leds[i].name, sizeof(ar->leds[i].name),
116 "ar9170-%s::%s", wiphy_name(ar->hw->wiphy), name);
117
118 ar->leds[i].ar = ar;
119 ar->leds[i].l.name = ar->leds[i].name;
120 ar->leds[i].l.brightness_set = ar9170_led_brightness_set;
121 ar->leds[i].l.brightness = 0;
122 ar->leds[i].l.default_trigger = trigger;
123
124 err = led_classdev_register(wiphy_dev(ar->hw->wiphy),
125 &ar->leds[i].l);
126 if (err)
127 printk(KERN_ERR "%s: failed to register %s LED (%d).\n",
128 wiphy_name(ar->hw->wiphy), ar->leds[i].name, err);
129 else
130 ar->leds[i].registered = true;
131
132 return err;
133}
134
135void ar9170_unregister_leds(struct ar9170 *ar)
136{
137 int i;
138
139 cancel_delayed_work_sync(&ar->led_work);
140
141 for (i = 0; i < AR9170_NUM_LEDS; i++)
142 if (ar->leds[i].registered) {
143 led_classdev_unregister(&ar->leds[i].l);
144 ar->leds[i].registered = false;
145 }
146}
147
148int ar9170_register_leds(struct ar9170 *ar)
149{
150 int err;
151
152 INIT_DELAYED_WORK(&ar->led_work, ar9170_update_leds);
153
154 err = ar9170_register_led(ar, 0, "tx",
155 ieee80211_get_tx_led_name(ar->hw));
156 if (err)
157 goto fail;
158
159 err = ar9170_register_led(ar, 1, "assoc",
160 ieee80211_get_assoc_led_name(ar->hw));
161 if (err)
162 goto fail;
163
164 return 0;
165
166fail:
167 ar9170_unregister_leds(ar);
168 return err;
169}
170
171#endif /* CONFIG_AR9170_LEDS */
diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c
new file mode 100644
index 000000000000..c8fa3073169f
--- /dev/null
+++ b/drivers/net/wireless/ath/ar9170/mac.c
@@ -0,0 +1,452 @@
1/*
2 * Atheros AR9170 driver
3 *
4 * MAC programming
5 *
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, see
20 * http://www.gnu.org/licenses/.
21 *
22 * This file incorporates work covered by the following copyright and
23 * permission notice:
24 * Copyright (c) 2007-2008 Atheros Communications, Inc.
25 *
26 * Permission to use, copy, modify, and/or distribute this software for any
27 * purpose with or without fee is hereby granted, provided that the above
28 * copyright notice and this permission notice appear in all copies.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
31 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
32 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
33 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
34 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
35 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
36 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37 */
38#include "ar9170.h"
39#include "cmd.h"
40
41int ar9170_set_qos(struct ar9170 *ar)
42{
43 ar9170_regwrite_begin(ar);
44
45 ar9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min |
46 (ar->edcf[0].cw_max << 16));
47 ar9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min |
48 (ar->edcf[1].cw_max << 16));
49 ar9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min |
50 (ar->edcf[2].cw_max << 16));
51 ar9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min |
52 (ar->edcf[3].cw_max << 16));
53 ar9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min |
54 (ar->edcf[4].cw_max << 16));
55
56 ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_AIFS,
57 ((ar->edcf[0].aifs * 9 + 10)) |
58 ((ar->edcf[1].aifs * 9 + 10) << 12) |
59 ((ar->edcf[2].aifs * 9 + 10) << 24));
60 ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_AIFS,
61 ((ar->edcf[2].aifs * 9 + 10) >> 8) |
62 ((ar->edcf[3].aifs * 9 + 10) << 4) |
63 ((ar->edcf[4].aifs * 9 + 10) << 16));
64
65 ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP,
66 ar->edcf[0].txop | ar->edcf[1].txop << 16);
67 ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP,
68 ar->edcf[1].txop | ar->edcf[3].txop << 16);
69
70 ar9170_regwrite_finish();
71
72 return ar9170_regwrite_result();
73}
74
75int ar9170_init_mac(struct ar9170 *ar)
76{
77 ar9170_regwrite_begin(ar);
78
79 ar9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40);
80
81 ar9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0);
82
83 /* enable MMIC */
84 ar9170_regwrite(AR9170_MAC_REG_SNIFFER,
85 AR9170_MAC_REG_SNIFFER_DEFAULTS);
86
87 ar9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80);
88
89 ar9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70);
90 ar9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000);
91 ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10);
92
93 /* CF-END mode */
94 ar9170_regwrite(0x1c3b2c, 0x19000000);
95
96 /* NAV protects ACK only (in TXOP) */
97 ar9170_regwrite(0x1c3b38, 0x201);
98
99 /* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */
100 /* OTUS set AM to 0x1 */
101 ar9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170);
102
103 ar9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105);
104
105 /* AGG test code*/
106 /* Aggregation MAX number and timeout */
107 ar9170_regwrite(0x1c3b9c, 0x10000a);
108
109 ar9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
110 AR9170_MAC_REG_FTF_DEFAULTS);
111
112 /* Enable deaggregator, response in sniffer mode */
113 ar9170_regwrite(0x1c3c40, 0x1 | 1<<30);
114
115 /* rate sets */
116 ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f);
117 ar9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f);
118 ar9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x10b01bb);
119
120 /* MIMO response control */
121 ar9170_regwrite(0x1c3694, 0x4003C1E);/* bit 26~28 otus-AM */
122
123 /* switch MAC to OTUS interface */
124 ar9170_regwrite(0x1c3600, 0x3);
125
126 ar9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff);
127
128 /* set PHY register read timeout (??) */
129 ar9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008);
130
131 /* Disable Rx TimeOut, workaround for BB. */
132 ar9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0);
133
134 /* Set CPU clock frequency to 88/80MHz */
135 ar9170_regwrite(AR9170_PWR_REG_CLOCK_SEL,
136 AR9170_PWR_CLK_AHB_80_88MHZ |
137 AR9170_PWR_CLK_DAC_160_INV_DLY);
138
139 /* Set WLAN DMA interrupt mode: generate int per packet */
140 ar9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011);
141
142 ar9170_regwrite(AR9170_MAC_REG_FCS_SELECT,
143 AR9170_MAC_FCS_FIFO_PROT);
144
145 /* Disables the CF_END frame, undocumented register */
146 ar9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND,
147 0x141E0F48);
148
149 ar9170_regwrite_finish();
150
151 return ar9170_regwrite_result();
152}
153
154static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac)
155{
156 static const u8 zero[ETH_ALEN] = { 0 };
157
158 if (!mac)
159 mac = zero;
160
161 ar9170_regwrite_begin(ar);
162
163 ar9170_regwrite(reg,
164 (mac[3] << 24) | (mac[2] << 16) |
165 (mac[1] << 8) | mac[0]);
166
167 ar9170_regwrite(reg + 4, (mac[5] << 8) | mac[4]);
168
169 ar9170_regwrite_finish();
170
171 return ar9170_regwrite_result();
172}
173
174int ar9170_update_multicast(struct ar9170 *ar)
175{
176 int err;
177
178 ar9170_regwrite_begin(ar);
179 ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H,
180 ar->want_mc_hash >> 32);
181 ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L,
182 ar->want_mc_hash);
183
184 ar9170_regwrite_finish();
185 err = ar9170_regwrite_result();
186
187 if (err)
188 return err;
189
190 ar->cur_mc_hash = ar->want_mc_hash;
191
192 return 0;
193}
194
195int ar9170_update_frame_filter(struct ar9170 *ar)
196{
197 int err;
198
199 err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER,
200 ar->want_filter);
201
202 if (err)
203 return err;
204
205 ar->cur_filter = ar->want_filter;
206
207 return 0;
208}
209
210static int ar9170_set_promiscouous(struct ar9170 *ar)
211{
212 u32 encr_mode, sniffer;
213 int err;
214
215 err = ar9170_read_reg(ar, AR9170_MAC_REG_SNIFFER, &sniffer);
216 if (err)
217 return err;
218
219 err = ar9170_read_reg(ar, AR9170_MAC_REG_ENCRYPTION, &encr_mode);
220 if (err)
221 return err;
222
223 if (ar->sniffer_enabled) {
224 sniffer |= AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC;
225
226 /*
227 * Rx decryption works in place.
228 *
229 * If we don't disable it, the hardware will render all
230 * encrypted frames which are encrypted with an unknown
231 * key useless.
232 */
233
234 encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE;
235 ar->sniffer_enabled = true;
236 } else {
237 sniffer &= ~AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC;
238
239 if (ar->rx_software_decryption)
240 encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE;
241 else
242 encr_mode &= ~AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE;
243 }
244
245 ar9170_regwrite_begin(ar);
246 ar9170_regwrite(AR9170_MAC_REG_ENCRYPTION, encr_mode);
247 ar9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer);
248 ar9170_regwrite_finish();
249
250 return ar9170_regwrite_result();
251}
252
253int ar9170_set_operating_mode(struct ar9170 *ar)
254{
255 u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS;
256 u8 *mac_addr, *bssid;
257 int err;
258
259 if (ar->vif) {
260 mac_addr = ar->mac_addr;
261 bssid = ar->bssid;
262
263 switch (ar->vif->type) {
264 case NL80211_IFTYPE_MESH_POINT:
265 case NL80211_IFTYPE_ADHOC:
266 pm_mode |= AR9170_MAC_REG_POWERMGT_IBSS;
267 break;
268/* case NL80211_IFTYPE_AP:
269 pm_mode |= AR9170_MAC_REG_POWERMGT_AP;
270 break;*/
271 case NL80211_IFTYPE_WDS:
272 pm_mode |= AR9170_MAC_REG_POWERMGT_AP_WDS;
273 break;
274 case NL80211_IFTYPE_MONITOR:
275 ar->sniffer_enabled = true;
276 ar->rx_software_decryption = true;
277 break;
278 default:
279 pm_mode |= AR9170_MAC_REG_POWERMGT_STA;
280 break;
281 }
282 } else {
283 mac_addr = NULL;
284 bssid = NULL;
285 }
286
287 err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr);
288 if (err)
289 return err;
290
291 err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid);
292 if (err)
293 return err;
294
295 err = ar9170_set_promiscouous(ar);
296 if (err)
297 return err;
298
299 ar9170_regwrite_begin(ar);
300
301 ar9170_regwrite(AR9170_MAC_REG_POWERMANAGEMENT, pm_mode);
302 ar9170_regwrite_finish();
303
304 return ar9170_regwrite_result();
305}
306
307int ar9170_set_hwretry_limit(struct ar9170 *ar, unsigned int max_retry)
308{
309 u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111);
310
311 return ar9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp);
312}
313
314int ar9170_set_beacon_timers(struct ar9170 *ar)
315{
316 u32 v = 0;
317 u32 pretbtt = 0;
318
319 v |= ar->hw->conf.beacon_int;
320
321 if (ar->vif) {
322 switch (ar->vif->type) {
323 case NL80211_IFTYPE_MESH_POINT:
324 case NL80211_IFTYPE_ADHOC:
325 v |= BIT(25);
326 break;
327 case NL80211_IFTYPE_AP:
328 v |= BIT(24);
329 pretbtt = (ar->hw->conf.beacon_int - 6) << 16;
330 break;
331 default:
332 break;
333 }
334
335 v |= ar->vif->bss_conf.dtim_period << 16;
336 }
337
338 ar9170_regwrite_begin(ar);
339
340 ar9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt);
341 ar9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v);
342 ar9170_regwrite_finish();
343 return ar9170_regwrite_result();
344}
345
346int ar9170_update_beacon(struct ar9170 *ar)
347{
348 struct sk_buff *skb;
349 __le32 *data, *old = NULL;
350 u32 word;
351 int i;
352
353 skb = ieee80211_beacon_get(ar->hw, ar->vif);
354 if (!skb)
355 return -ENOMEM;
356
357 data = (__le32 *)skb->data;
358 if (ar->beacon)
359 old = (__le32 *)ar->beacon->data;
360
361 ar9170_regwrite_begin(ar);
362 for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
363 /*
364 * XXX: This accesses beyond skb data for up
365 * to the last 3 bytes!!
366 */
367
368 if (old && (data[i] == old[i]))
369 continue;
370
371 word = le32_to_cpu(data[i]);
372 ar9170_regwrite(AR9170_BEACON_BUFFER_ADDRESS + 4 * i, word);
373 }
374
375 /* XXX: use skb->cb info */
376 if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ)
377 ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP,
378 ((skb->len + 4) << (3+16)) + 0x0400);
379 else
380 ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP,
381 ((skb->len + 4) << (3+16)) + 0x0400);
382
383 ar9170_regwrite(AR9170_MAC_REG_BCN_LENGTH, skb->len + 4);
384 ar9170_regwrite(AR9170_MAC_REG_BCN_ADDR, AR9170_BEACON_BUFFER_ADDRESS);
385 ar9170_regwrite(AR9170_MAC_REG_BCN_CTRL, 1);
386
387 ar9170_regwrite_finish();
388
389 dev_kfree_skb(ar->beacon);
390 ar->beacon = skb;
391
392 return ar9170_regwrite_result();
393}
394
395void ar9170_new_beacon(struct work_struct *work)
396{
397 struct ar9170 *ar = container_of(work, struct ar9170,
398 beacon_work);
399 struct sk_buff *skb;
400
401 if (unlikely(!IS_STARTED(ar)))
402 return ;
403
404 mutex_lock(&ar->mutex);
405
406 if (!ar->vif)
407 goto out;
408
409 ar9170_update_beacon(ar);
410
411 rcu_read_lock();
412 while ((skb = ieee80211_get_buffered_bc(ar->hw, ar->vif)))
413 ar9170_op_tx(ar->hw, skb);
414
415 rcu_read_unlock();
416
417 out:
418 mutex_unlock(&ar->mutex);
419}
420
421int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype,
422 u8 keyidx, u8 *keydata, int keylen)
423{
424 __le32 vals[7];
425 static const u8 bcast[ETH_ALEN] =
426 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
427 u8 dummy;
428
429 mac = mac ? : bcast;
430
431 vals[0] = cpu_to_le32((keyidx << 16) + id);
432 vals[1] = cpu_to_le32(mac[1] << 24 | mac[0] << 16 | ktype);
433 vals[2] = cpu_to_le32(mac[5] << 24 | mac[4] << 16 |
434 mac[3] << 8 | mac[2]);
435 memset(&vals[3], 0, 16);
436 if (keydata)
437 memcpy(&vals[3], keydata, keylen);
438
439 return ar->exec_cmd(ar, AR9170_CMD_EKEY,
440 sizeof(vals), (u8 *)vals,
441 1, &dummy);
442}
443
444int ar9170_disable_key(struct ar9170 *ar, u8 id)
445{
446 __le32 val = cpu_to_le32(id);
447 u8 dummy;
448
449 return ar->exec_cmd(ar, AR9170_CMD_EKEY,
450 sizeof(val), (u8 *)&val,
451 1, &dummy);
452}
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
new file mode 100644
index 000000000000..8de0ff9f580b
--- /dev/null
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -0,0 +1,1690 @@
1/*
2 * Atheros AR9170 driver
3 *
4 * mac80211 interaction code
5 *
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7 * Copyright 2009, Christian Lamparter <chunkeey@web.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; see the file COPYING. If not, see
21 * http://www.gnu.org/licenses/.
22 *
23 * This file incorporates work covered by the following copyright and
24 * permission notice:
25 * Copyright (c) 2007-2008 Atheros Communications, Inc.
26 *
27 * Permission to use, copy, modify, and/or distribute this software for any
28 * purpose with or without fee is hereby granted, provided that the above
29 * copyright notice and this permission notice appear in all copies.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
32 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
33 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
34 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
35 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
36 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
37 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
38 */
39
40#include <linux/init.h>
41#include <linux/module.h>
42#include <linux/etherdevice.h>
43#include <net/mac80211.h>
44#include "ar9170.h"
45#include "hw.h"
46#include "cmd.h"
47
48static int modparam_nohwcrypt;
49module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
50MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
51
52#define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \
53 .bitrate = (_bitrate), \
54 .flags = (_flags), \
55 .hw_value = (_hw_rate) | (_txpidx) << 4, \
56}
57
58static struct ieee80211_rate __ar9170_ratetable[] = {
59 RATE(10, 0, 0, 0),
60 RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE),
61 RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE),
62 RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE),
63 RATE(60, 0xb, 0, 0),
64 RATE(90, 0xf, 0, 0),
65 RATE(120, 0xa, 0, 0),
66 RATE(180, 0xe, 0, 0),
67 RATE(240, 0x9, 0, 0),
68 RATE(360, 0xd, 1, 0),
69 RATE(480, 0x8, 2, 0),
70 RATE(540, 0xc, 3, 0),
71};
72#undef RATE
73
74#define ar9170_g_ratetable (__ar9170_ratetable + 0)
75#define ar9170_g_ratetable_size 12
76#define ar9170_a_ratetable (__ar9170_ratetable + 4)
77#define ar9170_a_ratetable_size 8
78
79/*
80 * NB: The hw_value is used as an index into the ar9170_phy_freq_params
81 * array in phy.c so that we don't have to do frequency lookups!
82 */
83#define CHAN(_freq, _idx) { \
84 .center_freq = (_freq), \
85 .hw_value = (_idx), \
86 .max_power = 18, /* XXX */ \
87}
88
89static struct ieee80211_channel ar9170_2ghz_chantable[] = {
90 CHAN(2412, 0),
91 CHAN(2417, 1),
92 CHAN(2422, 2),
93 CHAN(2427, 3),
94 CHAN(2432, 4),
95 CHAN(2437, 5),
96 CHAN(2442, 6),
97 CHAN(2447, 7),
98 CHAN(2452, 8),
99 CHAN(2457, 9),
100 CHAN(2462, 10),
101 CHAN(2467, 11),
102 CHAN(2472, 12),
103 CHAN(2484, 13),
104};
105
106static struct ieee80211_channel ar9170_5ghz_chantable[] = {
107 CHAN(4920, 14),
108 CHAN(4940, 15),
109 CHAN(4960, 16),
110 CHAN(4980, 17),
111 CHAN(5040, 18),
112 CHAN(5060, 19),
113 CHAN(5080, 20),
114 CHAN(5180, 21),
115 CHAN(5200, 22),
116 CHAN(5220, 23),
117 CHAN(5240, 24),
118 CHAN(5260, 25),
119 CHAN(5280, 26),
120 CHAN(5300, 27),
121 CHAN(5320, 28),
122 CHAN(5500, 29),
123 CHAN(5520, 30),
124 CHAN(5540, 31),
125 CHAN(5560, 32),
126 CHAN(5580, 33),
127 CHAN(5600, 34),
128 CHAN(5620, 35),
129 CHAN(5640, 36),
130 CHAN(5660, 37),
131 CHAN(5680, 38),
132 CHAN(5700, 39),
133 CHAN(5745, 40),
134 CHAN(5765, 41),
135 CHAN(5785, 42),
136 CHAN(5805, 43),
137 CHAN(5825, 44),
138 CHAN(5170, 45),
139 CHAN(5190, 46),
140 CHAN(5210, 47),
141 CHAN(5230, 48),
142};
143#undef CHAN
144
145static struct ieee80211_supported_band ar9170_band_2GHz = {
146 .channels = ar9170_2ghz_chantable,
147 .n_channels = ARRAY_SIZE(ar9170_2ghz_chantable),
148 .bitrates = ar9170_g_ratetable,
149 .n_bitrates = ar9170_g_ratetable_size,
150};
151
152#ifdef AR9170_QUEUE_DEBUG
153/*
154 * In case some wants works with AR9170's crazy tx_status queueing techniques.
155 * He might need this rather useful probing function.
156 *
157 * NOTE: caller must hold the queue's spinlock!
158 */
159
160static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb)
161{
162 struct ar9170_tx_control *txc = (void *) skb->data;
163 struct ieee80211_hdr *hdr = (void *)txc->frame_data;
164
165 printk(KERN_DEBUG "%s: => FRAME [skb:%p, queue:%d, DA:[%pM] "
166 "mac_control:%04x, phy_control:%08x]\n",
167 wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb),
168 ieee80211_get_DA(hdr), le16_to_cpu(txc->mac_control),
169 le32_to_cpu(txc->phy_control));
170}
171
172static void ar9170_dump_station_tx_status_queue(struct ar9170 *ar,
173 struct sk_buff_head *queue)
174{
175 struct sk_buff *skb;
176 int i = 0;
177
178 printk(KERN_DEBUG "---[ cut here ]---\n");
179 printk(KERN_DEBUG "%s: %d entries in tx_status queue.\n",
180 wiphy_name(ar->hw->wiphy), skb_queue_len(queue));
181
182 skb_queue_walk(queue, skb) {
183 struct ar9170_tx_control *txc = (void *) skb->data;
184 struct ieee80211_hdr *hdr = (void *)txc->frame_data;
185
186 printk(KERN_DEBUG "index:%d => \n", i);
187 ar9170_print_txheader(ar, skb);
188 }
189 printk(KERN_DEBUG "---[ end ]---\n");
190}
191#endif /* AR9170_QUEUE_DEBUG */
192
193static struct ieee80211_supported_band ar9170_band_5GHz = {
194 .channels = ar9170_5ghz_chantable,
195 .n_channels = ARRAY_SIZE(ar9170_5ghz_chantable),
196 .bitrates = ar9170_a_ratetable,
197 .n_bitrates = ar9170_a_ratetable_size,
198};
199
200void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb,
201 bool valid_status, u16 tx_status)
202{
203 struct ieee80211_tx_info *txinfo;
204 unsigned int retries = 0, queue = skb_get_queue_mapping(skb);
205 unsigned long flags;
206
207 spin_lock_irqsave(&ar->tx_stats_lock, flags);
208 ar->tx_stats[queue].len--;
209 if (ieee80211_queue_stopped(ar->hw, queue))
210 ieee80211_wake_queue(ar->hw, queue);
211 spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
212
213 txinfo = IEEE80211_SKB_CB(skb);
214 ieee80211_tx_info_clear_status(txinfo);
215
216 switch (tx_status) {
217 case AR9170_TX_STATUS_RETRY:
218 retries = 2;
219 case AR9170_TX_STATUS_COMPLETE:
220 txinfo->flags |= IEEE80211_TX_STAT_ACK;
221 break;
222
223 case AR9170_TX_STATUS_FAILED:
224 retries = ar->hw->conf.long_frame_max_tx_count;
225 break;
226
227 default:
228 printk(KERN_ERR "%s: invalid tx_status response (%x).\n",
229 wiphy_name(ar->hw->wiphy), tx_status);
230 break;
231 }
232
233 if (valid_status)
234 txinfo->status.rates[0].count = retries + 1;
235
236 skb_pull(skb, sizeof(struct ar9170_tx_control));
237 ieee80211_tx_status_irqsafe(ar->hw, skb);
238}
239
240static struct sk_buff *ar9170_find_skb_in_queue(struct ar9170 *ar,
241 const u8 *mac,
242 const u32 queue,
243 struct sk_buff_head *q)
244{
245 unsigned long flags;
246 struct sk_buff *skb;
247
248 spin_lock_irqsave(&q->lock, flags);
249 skb_queue_walk(q, skb) {
250 struct ar9170_tx_control *txc = (void *) skb->data;
251 struct ieee80211_hdr *hdr = (void *) txc->frame_data;
252 u32 txc_queue = (le32_to_cpu(txc->phy_control) &
253 AR9170_TX_PHY_QOS_MASK) >>
254 AR9170_TX_PHY_QOS_SHIFT;
255
256 if ((queue != txc_queue) ||
257 (compare_ether_addr(ieee80211_get_DA(hdr), mac)))
258 continue;
259
260 __skb_unlink(skb, q);
261 spin_unlock_irqrestore(&q->lock, flags);
262 return skb;
263 }
264 spin_unlock_irqrestore(&q->lock, flags);
265 return NULL;
266}
267
268static struct sk_buff *ar9170_find_queued_skb(struct ar9170 *ar, const u8 *mac,
269 const u32 queue)
270{
271 struct ieee80211_sta *sta;
272 struct sk_buff *skb;
273
274 /*
275 * Unfortunately, the firmware does not tell to which (queued) frame
276 * this transmission status report belongs to.
277 *
278 * So we have to make risky guesses - with the scarce information
279 * the firmware provided (-> destination MAC, and phy_control) -
280 * and hope that we picked the right one...
281 */
282 rcu_read_lock();
283 sta = ieee80211_find_sta(ar->hw, mac);
284
285 if (likely(sta)) {
286 struct ar9170_sta_info *sta_priv = (void *) sta->drv_priv;
287 skb = skb_dequeue(&sta_priv->tx_status[queue]);
288 rcu_read_unlock();
289 if (likely(skb))
290 return skb;
291 } else
292 rcu_read_unlock();
293
294 /* scan the waste queue for candidates */
295 skb = ar9170_find_skb_in_queue(ar, mac, queue,
296 &ar->global_tx_status_waste);
297 if (!skb) {
298 /* so it still _must_ be in the global list. */
299 skb = ar9170_find_skb_in_queue(ar, mac, queue,
300 &ar->global_tx_status);
301 }
302
303#ifdef AR9170_QUEUE_DEBUG
304 if (unlikely((!skb) && net_ratelimit())) {
305 printk(KERN_ERR "%s: ESS:[%pM] does not have any "
306 "outstanding frames in this queue (%d).\n",
307 wiphy_name(ar->hw->wiphy), mac, queue);
308 }
309#endif /* AR9170_QUEUE_DEBUG */
310 return skb;
311}
312
313/*
314 * This worker tries to keep the global tx_status queue empty.
315 * So we can guarantee that incoming tx_status reports for
316 * unregistered stations are always synced with the actual
317 * frame - which we think - belongs to.
318 */
319
320static void ar9170_tx_status_janitor(struct work_struct *work)
321{
322 struct ar9170 *ar = container_of(work, struct ar9170,
323 tx_status_janitor.work);
324 struct sk_buff *skb;
325
326 if (unlikely(!IS_STARTED(ar)))
327 return ;
328
329 mutex_lock(&ar->mutex);
330 /* recycle the garbage back to mac80211... one by one. */
331 while ((skb = skb_dequeue(&ar->global_tx_status_waste))) {
332#ifdef AR9170_QUEUE_DEBUG
333 printk(KERN_DEBUG "%s: dispose queued frame =>\n",
334 wiphy_name(ar->hw->wiphy));
335 ar9170_print_txheader(ar, skb);
336#endif /* AR9170_QUEUE_DEBUG */
337 ar9170_handle_tx_status(ar, skb, false,
338 AR9170_TX_STATUS_FAILED);
339 }
340
341 while ((skb = skb_dequeue(&ar->global_tx_status))) {
342#ifdef AR9170_QUEUE_DEBUG
343 printk(KERN_DEBUG "%s: moving frame into waste queue =>\n",
344 wiphy_name(ar->hw->wiphy));
345
346 ar9170_print_txheader(ar, skb);
347#endif /* AR9170_QUEUE_DEBUG */
348 skb_queue_tail(&ar->global_tx_status_waste, skb);
349 }
350
351 /* recall the janitor in 100ms - if there's garbage in the can. */
352 if (skb_queue_len(&ar->global_tx_status_waste) > 0)
353 queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor,
354 msecs_to_jiffies(100));
355
356 mutex_unlock(&ar->mutex);
357}
358
359static void ar9170_handle_command_response(struct ar9170 *ar,
360 void *buf, u32 len)
361{
362 struct ar9170_cmd_response *cmd = (void *) buf;
363
364 if ((cmd->type & 0xc0) != 0xc0) {
365 ar->callback_cmd(ar, len, buf);
366 return;
367 }
368
369 /* hardware event handlers */
370 switch (cmd->type) {
371 case 0xc1: {
372 /*
373 * TX status notification:
374 * bytes: 0c c1 XX YY M1 M2 M3 M4 M5 M6 R4 R3 R2 R1 S2 S1
375 *
376 * XX always 81
377 * YY always 00
378 * M1-M6 is the MAC address
379 * R1-R4 is the transmit rate
380 * S1-S2 is the transmit status
381 */
382
383 struct sk_buff *skb;
384 u32 queue = (le32_to_cpu(cmd->tx_status.rate) &
385 AR9170_TX_PHY_QOS_MASK) >> AR9170_TX_PHY_QOS_SHIFT;
386
387 skb = ar9170_find_queued_skb(ar, cmd->tx_status.dst, queue);
388 if (unlikely(!skb))
389 return ;
390
391 ar9170_handle_tx_status(ar, skb, true,
392 le16_to_cpu(cmd->tx_status.status));
393 break;
394 }
395
396 case 0xc0:
397 /*
398 * pre-TBTT event
399 */
400 if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP)
401 queue_work(ar->hw->workqueue, &ar->beacon_work);
402 break;
403
404 case 0xc2:
405 /*
406 * (IBSS) beacon send notification
407 * bytes: 04 c2 XX YY B4 B3 B2 B1
408 *
409 * XX always 80
410 * YY always 00
411 * B1-B4 "should" be the number of send out beacons.
412 */
413 break;
414
415 case 0xc3:
416 /* End of Atim Window */
417 break;
418
419 case 0xc4:
420 case 0xc5:
421 /* BlockACK events */
422 break;
423
424 case 0xc6:
425 /* Watchdog Interrupt */
426 break;
427
428 case 0xc9:
429 /* retransmission issue / SIFS/EIFS collision ?! */
430 break;
431
432 default:
433 printk(KERN_INFO "received unhandled event %x\n", cmd->type);
434 print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len);
435 break;
436 }
437}
438
439/*
440 * If the frame alignment is right (or the kernel has
441 * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
442 * is only a single MPDU in the USB frame, then we can
443 * submit to mac80211 the SKB directly. However, since
444 * there may be multiple packets in one SKB in stream
445 * mode, and we need to observe the proper ordering,
446 * this is non-trivial.
447 */
448static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
449{
450 struct sk_buff *skb;
451 struct ar9170_rx_head *head = (void *)buf;
452 struct ar9170_rx_tail *tail;
453 struct ieee80211_rx_status status;
454 int mpdu_len, i;
455 u8 error, antennas = 0, decrypt;
456 __le16 fc;
457 int reserved;
458
459 if (unlikely(!IS_STARTED(ar)))
460 return ;
461
462 /* Received MPDU */
463 mpdu_len = len;
464 mpdu_len -= sizeof(struct ar9170_rx_head);
465 mpdu_len -= sizeof(struct ar9170_rx_tail);
466 BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12);
467 BUILD_BUG_ON(sizeof(struct ar9170_rx_tail) != 24);
468
469 if (mpdu_len <= FCS_LEN)
470 return;
471
472 tail = (void *)(buf + sizeof(struct ar9170_rx_head) + mpdu_len);
473
474 for (i = 0; i < 3; i++)
475 if (tail->rssi[i] != 0x80)
476 antennas |= BIT(i);
477
478 /* post-process RSSI */
479 for (i = 0; i < 7; i++)
480 if (tail->rssi[i] & 0x80)
481 tail->rssi[i] = ((tail->rssi[i] & 0x7f) + 1) & 0x7f;
482
483 memset(&status, 0, sizeof(status));
484
485 status.band = ar->channel->band;
486 status.freq = ar->channel->center_freq;
487 status.signal = ar->noise[0] + tail->rssi_combined;
488 status.noise = ar->noise[0];
489 status.antenna = antennas;
490
491 switch (tail->status & AR9170_RX_STATUS_MODULATION_MASK) {
492 case AR9170_RX_STATUS_MODULATION_CCK:
493 if (tail->status & AR9170_RX_STATUS_SHORT_PREAMBLE)
494 status.flag |= RX_FLAG_SHORTPRE;
495 switch (head->plcp[0]) {
496 case 0x0a:
497 status.rate_idx = 0;
498 break;
499 case 0x14:
500 status.rate_idx = 1;
501 break;
502 case 0x37:
503 status.rate_idx = 2;
504 break;
505 case 0x6e:
506 status.rate_idx = 3;
507 break;
508 default:
509 if ((!ar->sniffer_enabled) && (net_ratelimit()))
510 printk(KERN_ERR "%s: invalid plcp cck rate "
511 "(%x).\n", wiphy_name(ar->hw->wiphy),
512 head->plcp[0]);
513 return;
514 }
515 break;
516 case AR9170_RX_STATUS_MODULATION_OFDM:
517 switch (head->plcp[0] & 0xF) {
518 case 0xB:
519 status.rate_idx = 0;
520 break;
521 case 0xF:
522 status.rate_idx = 1;
523 break;
524 case 0xA:
525 status.rate_idx = 2;
526 break;
527 case 0xE:
528 status.rate_idx = 3;
529 break;
530 case 0x9:
531 status.rate_idx = 4;
532 break;
533 case 0xD:
534 status.rate_idx = 5;
535 break;
536 case 0x8:
537 status.rate_idx = 6;
538 break;
539 case 0xC:
540 status.rate_idx = 7;
541 break;
542 default:
543 if ((!ar->sniffer_enabled) && (net_ratelimit()))
544 printk(KERN_ERR "%s: invalid plcp ofdm rate "
545 "(%x).\n", wiphy_name(ar->hw->wiphy),
546 head->plcp[0]);
547 return;
548 }
549 if (status.band == IEEE80211_BAND_2GHZ)
550 status.rate_idx += 4;
551 break;
552 case AR9170_RX_STATUS_MODULATION_HT:
553 case AR9170_RX_STATUS_MODULATION_DUPOFDM:
554 /* XXX */
555
556 if (net_ratelimit())
557 printk(KERN_ERR "%s: invalid modulation\n",
558 wiphy_name(ar->hw->wiphy));
559 return;
560 }
561
562 error = tail->error;
563
564 if (error & AR9170_RX_ERROR_MMIC) {
565 status.flag |= RX_FLAG_MMIC_ERROR;
566 error &= ~AR9170_RX_ERROR_MMIC;
567 }
568
569 if (error & AR9170_RX_ERROR_PLCP) {
570 status.flag |= RX_FLAG_FAILED_PLCP_CRC;
571 error &= ~AR9170_RX_ERROR_PLCP;
572 }
573
574 if (error & AR9170_RX_ERROR_FCS) {
575 status.flag |= RX_FLAG_FAILED_FCS_CRC;
576 error &= ~AR9170_RX_ERROR_FCS;
577 }
578
579 decrypt = ar9170_get_decrypt_type(tail);
580 if (!(decrypt & AR9170_RX_ENC_SOFTWARE) &&
581 decrypt != AR9170_ENC_ALG_NONE)
582 status.flag |= RX_FLAG_DECRYPTED;
583
584 /* ignore wrong RA errors */
585 error &= ~AR9170_RX_ERROR_WRONG_RA;
586
587 if (error & AR9170_RX_ERROR_DECRYPT) {
588 error &= ~AR9170_RX_ERROR_DECRYPT;
589
590 /*
591 * Rx decryption is done in place,
592 * the original data is lost anyway.
593 */
594 return ;
595 }
596
597 /* drop any other error frames */
598 if ((error) && (net_ratelimit())) {
599 printk(KERN_DEBUG "%s: errors: %#x\n",
600 wiphy_name(ar->hw->wiphy), error);
601 return;
602 }
603
604 buf += sizeof(struct ar9170_rx_head);
605 fc = *(__le16 *)buf;
606
607 if (ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc))
608 reserved = 32 + 2;
609 else
610 reserved = 32;
611
612 skb = dev_alloc_skb(mpdu_len + reserved);
613 if (!skb)
614 return;
615
616 skb_reserve(skb, reserved);
617 memcpy(skb_put(skb, mpdu_len), buf, mpdu_len);
618 ieee80211_rx_irqsafe(ar->hw, skb, &status);
619}
620
621void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb)
622{
623 unsigned int i, tlen, resplen;
624 u8 *tbuf, *respbuf;
625
626 tbuf = skb->data;
627 tlen = skb->len;
628
629 while (tlen >= 4) {
630 int clen = tbuf[1] << 8 | tbuf[0];
631 int wlen = (clen + 3) & ~3;
632
633 /*
634 * parse stream (if any)
635 */
636 if (tbuf[2] != 0 || tbuf[3] != 0x4e) {
637 printk(KERN_ERR "%s: missing tag!\n",
638 wiphy_name(ar->hw->wiphy));
639 return ;
640 }
641 if (wlen > tlen - 4) {
642 printk(KERN_ERR "%s: invalid RX (%d, %d, %d)\n",
643 wiphy_name(ar->hw->wiphy), clen, wlen, tlen);
644 print_hex_dump(KERN_DEBUG, "data: ",
645 DUMP_PREFIX_OFFSET,
646 16, 1, tbuf, tlen, true);
647 return ;
648 }
649 resplen = clen;
650 respbuf = tbuf + 4;
651 tbuf += wlen + 4;
652 tlen -= wlen + 4;
653
654 i = 0;
655
656 /* weird thing, but this is the same in the original driver */
657 while (resplen > 2 && i < 12 &&
658 respbuf[0] == 0xff && respbuf[1] == 0xff) {
659 i += 2;
660 resplen -= 2;
661 respbuf += 2;
662 }
663
664 if (resplen < 4)
665 continue;
666
667 /* found the 6 * 0xffff marker? */
668 if (i == 12)
669 ar9170_handle_command_response(ar, respbuf, resplen);
670 else
671 ar9170_handle_mpdu(ar, respbuf, resplen);
672 }
673
674 if (tlen)
675 printk(KERN_ERR "%s: buffer remains!\n",
676 wiphy_name(ar->hw->wiphy));
677}
678
679#define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \
680do { \
681 queue.aifs = ai_fs; \
682 queue.cw_min = cwmin; \
683 queue.cw_max = cwmax; \
684 queue.txop = _txop; \
685} while (0)
686
687static int ar9170_op_start(struct ieee80211_hw *hw)
688{
689 struct ar9170 *ar = hw->priv;
690 int err, i;
691
692 mutex_lock(&ar->mutex);
693
694 /* reinitialize queues statistics */
695 memset(&ar->tx_stats, 0, sizeof(ar->tx_stats));
696 for (i = 0; i < ARRAY_SIZE(ar->tx_stats); i++)
697 ar->tx_stats[i].limit = 8;
698
699 /* reset QoS defaults */
700 AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT*/
701 AR9170_FILL_QUEUE(ar->edcf[1], 7, 15, 1023, 0); /* BACKGROUND */
702 AR9170_FILL_QUEUE(ar->edcf[2], 2, 7, 15, 94); /* VIDEO */
703 AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */
704 AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */
705
706 err = ar->open(ar);
707 if (err)
708 goto out;
709
710 err = ar9170_init_mac(ar);
711 if (err)
712 goto out;
713
714 err = ar9170_set_qos(ar);
715 if (err)
716 goto out;
717
718 err = ar9170_init_phy(ar, IEEE80211_BAND_2GHZ);
719 if (err)
720 goto out;
721
722 err = ar9170_init_rf(ar);
723 if (err)
724 goto out;
725
726 /* start DMA */
727 err = ar9170_write_reg(ar, 0x1c3d30, 0x100);
728 if (err)
729 goto out;
730
731 ar->state = AR9170_STARTED;
732
733out:
734 mutex_unlock(&ar->mutex);
735 return err;
736}
737
738static void ar9170_op_stop(struct ieee80211_hw *hw)
739{
740 struct ar9170 *ar = hw->priv;
741
742 if (IS_STARTED(ar))
743 ar->state = AR9170_IDLE;
744
745 flush_workqueue(ar->hw->workqueue);
746
747 mutex_lock(&ar->mutex);
748 cancel_delayed_work_sync(&ar->tx_status_janitor);
749 cancel_work_sync(&ar->filter_config_work);
750 cancel_work_sync(&ar->beacon_work);
751 skb_queue_purge(&ar->global_tx_status_waste);
752 skb_queue_purge(&ar->global_tx_status);
753
754 if (IS_ACCEPTING_CMD(ar)) {
755 ar9170_set_leds_state(ar, 0);
756
757 /* stop DMA */
758 ar9170_write_reg(ar, 0x1c3d30, 0);
759 ar->stop(ar);
760 }
761
762 mutex_unlock(&ar->mutex);
763}
764
765int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
766{
767 struct ar9170 *ar = hw->priv;
768 struct ieee80211_hdr *hdr;
769 struct ar9170_tx_control *txc;
770 struct ieee80211_tx_info *info;
771 struct ieee80211_rate *rate = NULL;
772 struct ieee80211_tx_rate *txrate;
773 unsigned int queue = skb_get_queue_mapping(skb);
774 unsigned long flags = 0;
775 struct ar9170_sta_info *sta_info = NULL;
776 u32 power, chains;
777 u16 keytype = 0;
778 u16 len, icv = 0;
779 int err;
780 bool tx_status;
781
782 if (unlikely(!IS_STARTED(ar)))
783 goto err_free;
784
785 hdr = (void *)skb->data;
786 info = IEEE80211_SKB_CB(skb);
787 len = skb->len;
788
789 spin_lock_irqsave(&ar->tx_stats_lock, flags);
790 if (ar->tx_stats[queue].limit < ar->tx_stats[queue].len) {
791 spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
792 return NETDEV_TX_OK;
793 }
794
795 ar->tx_stats[queue].len++;
796 ar->tx_stats[queue].count++;
797 if (ar->tx_stats[queue].limit == ar->tx_stats[queue].len)
798 ieee80211_stop_queue(hw, queue);
799
800 spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
801
802 txc = (void *)skb_push(skb, sizeof(*txc));
803
804 tx_status = (((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) != 0) ||
805 ((info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) != 0));
806
807 if (info->control.hw_key) {
808 icv = info->control.hw_key->icv_len;
809
810 switch (info->control.hw_key->alg) {
811 case ALG_WEP:
812 keytype = AR9170_TX_MAC_ENCR_RC4;
813 break;
814 case ALG_TKIP:
815 keytype = AR9170_TX_MAC_ENCR_RC4;
816 break;
817 case ALG_CCMP:
818 keytype = AR9170_TX_MAC_ENCR_AES;
819 break;
820 default:
821 WARN_ON(1);
822 goto err_dequeue;
823 }
824 }
825
826 /* Length */
827 txc->length = cpu_to_le16(len + icv + 4);
828
829 txc->mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION |
830 AR9170_TX_MAC_BACKOFF);
831 txc->mac_control |= cpu_to_le16(ar9170_qos_hwmap[queue] <<
832 AR9170_TX_MAC_QOS_SHIFT);
833 txc->mac_control |= cpu_to_le16(keytype);
834 txc->phy_control = cpu_to_le32(0);
835
836 if (info->flags & IEEE80211_TX_CTL_NO_ACK)
837 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK);
838
839 if (info->flags & IEEE80211_TX_CTL_AMPDU)
840 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR);
841
842 txrate = &info->control.rates[0];
843
844 if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
845 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
846 else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS)
847 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
848
849 if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
850 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD);
851
852 if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
853 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE);
854
855 if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
856 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ);
857 /* this works because 40 MHz is 2 and dup is 3 */
858 if (txrate->flags & IEEE80211_TX_RC_DUP_DATA)
859 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP);
860
861 if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
862 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI);
863
864 if (txrate->flags & IEEE80211_TX_RC_MCS) {
865 u32 r = txrate->idx;
866 u8 *txpower;
867
868 r <<= AR9170_TX_PHY_MCS_SHIFT;
869 if (WARN_ON(r & ~AR9170_TX_PHY_MCS_MASK))
870 goto err_dequeue;
871 txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK);
872 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT);
873
874 if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
875 if (info->band == IEEE80211_BAND_5GHZ)
876 txpower = ar->power_5G_ht40;
877 else
878 txpower = ar->power_2G_ht40;
879 } else {
880 if (info->band == IEEE80211_BAND_5GHZ)
881 txpower = ar->power_5G_ht20;
882 else
883 txpower = ar->power_2G_ht20;
884 }
885
886 power = txpower[(txrate->idx) & 7];
887 } else {
888 u8 *txpower;
889 u32 mod;
890 u32 phyrate;
891 u8 idx = txrate->idx;
892
893 if (info->band != IEEE80211_BAND_2GHZ) {
894 idx += 4;
895 txpower = ar->power_5G_leg;
896 mod = AR9170_TX_PHY_MOD_OFDM;
897 } else {
898 if (idx < 4) {
899 txpower = ar->power_2G_cck;
900 mod = AR9170_TX_PHY_MOD_CCK;
901 } else {
902 mod = AR9170_TX_PHY_MOD_OFDM;
903 txpower = ar->power_2G_ofdm;
904 }
905 }
906
907 rate = &__ar9170_ratetable[idx];
908
909 phyrate = rate->hw_value & 0xF;
910 power = txpower[(rate->hw_value & 0x30) >> 4];
911 phyrate <<= AR9170_TX_PHY_MCS_SHIFT;
912
913 txc->phy_control |= cpu_to_le32(mod);
914 txc->phy_control |= cpu_to_le32(phyrate);
915 }
916
917 power <<= AR9170_TX_PHY_TX_PWR_SHIFT;
918 power &= AR9170_TX_PHY_TX_PWR_MASK;
919 txc->phy_control |= cpu_to_le32(power);
920
921 /* set TX chains */
922 if (ar->eeprom.tx_mask == 1) {
923 chains = AR9170_TX_PHY_TXCHAIN_1;
924 } else {
925 chains = AR9170_TX_PHY_TXCHAIN_2;
926
927 /* >= 36M legacy OFDM - use only one chain */
928 if (rate && rate->bitrate >= 360)
929 chains = AR9170_TX_PHY_TXCHAIN_1;
930 }
931 txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT);
932
933 if (tx_status) {
934 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE);
935 /*
936 * WARNING:
937 * Putting the QoS queue bits into an unexplored territory is
938 * certainly not elegant.
939 *
940 * In my defense: This idea provides a reasonable way to
941 * smuggle valuable information to the tx_status callback.
942 * Also, the idea behind this bit-abuse came straight from
943 * the original driver code.
944 */
945
946 txc->phy_control |=
947 cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT);
948
949 if (info->control.sta) {
950 sta_info = (void *) info->control.sta->drv_priv;
951 skb_queue_tail(&sta_info->tx_status[queue], skb);
952 } else {
953 skb_queue_tail(&ar->global_tx_status, skb);
954
955 queue_delayed_work(ar->hw->workqueue,
956 &ar->tx_status_janitor,
957 msecs_to_jiffies(100));
958 }
959 }
960
961 err = ar->tx(ar, skb, tx_status, 0);
962 if (unlikely(tx_status && err)) {
963 if (info->control.sta)
964 skb_unlink(skb, &sta_info->tx_status[queue]);
965 else
966 skb_unlink(skb, &ar->global_tx_status);
967 }
968
969 return NETDEV_TX_OK;
970
971err_dequeue:
972 spin_lock_irqsave(&ar->tx_stats_lock, flags);
973 ar->tx_stats[queue].len--;
974 ar->tx_stats[queue].count--;
975 spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
976
977err_free:
978 dev_kfree_skb(skb);
979 return NETDEV_TX_OK;
980}
981
982static int ar9170_op_add_interface(struct ieee80211_hw *hw,
983 struct ieee80211_if_init_conf *conf)
984{
985 struct ar9170 *ar = hw->priv;
986 int err = 0;
987
988 mutex_lock(&ar->mutex);
989
990 if (ar->vif) {
991 err = -EBUSY;
992 goto unlock;
993 }
994
995 ar->vif = conf->vif;
996 memcpy(ar->mac_addr, conf->mac_addr, ETH_ALEN);
997
998 if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) {
999 ar->rx_software_decryption = true;
1000 ar->disable_offload = true;
1001 }
1002
1003 ar->cur_filter = 0;
1004 ar->want_filter = AR9170_MAC_REG_FTF_DEFAULTS;
1005 err = ar9170_update_frame_filter(ar);
1006 if (err)
1007 goto unlock;
1008
1009 err = ar9170_set_operating_mode(ar);
1010
1011unlock:
1012 mutex_unlock(&ar->mutex);
1013 return err;
1014}
1015
1016static void ar9170_op_remove_interface(struct ieee80211_hw *hw,
1017 struct ieee80211_if_init_conf *conf)
1018{
1019 struct ar9170 *ar = hw->priv;
1020
1021 mutex_lock(&ar->mutex);
1022 ar->vif = NULL;
1023 ar->want_filter = 0;
1024 ar9170_update_frame_filter(ar);
1025 ar9170_set_beacon_timers(ar);
1026 dev_kfree_skb(ar->beacon);
1027 ar->beacon = NULL;
1028 ar->sniffer_enabled = false;
1029 ar->rx_software_decryption = false;
1030 ar9170_set_operating_mode(ar);
1031 mutex_unlock(&ar->mutex);
1032}
1033
1034static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed)
1035{
1036 struct ar9170 *ar = hw->priv;
1037 int err = 0;
1038
1039 mutex_lock(&ar->mutex);
1040
1041 if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) {
1042 /* TODO */
1043 err = 0;
1044 }
1045
1046 if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
1047 /* TODO */
1048 err = 0;
1049 }
1050
1051 if (changed & IEEE80211_CONF_CHANGE_PS) {
1052 /* TODO */
1053 err = 0;
1054 }
1055
1056 if (changed & IEEE80211_CONF_CHANGE_POWER) {
1057 /* TODO */
1058 err = 0;
1059 }
1060
1061 if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
1062 /*
1063 * is it long_frame_max_tx_count or short_frame_max_tx_count?
1064 */
1065
1066 err = ar9170_set_hwretry_limit(ar,
1067 ar->hw->conf.long_frame_max_tx_count);
1068 if (err)
1069 goto out;
1070 }
1071
1072 if (changed & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) {
1073 err = ar9170_set_beacon_timers(ar);
1074 if (err)
1075 goto out;
1076 }
1077
1078 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
1079 err = ar9170_set_channel(ar, hw->conf.channel,
1080 AR9170_RFI_NONE, AR9170_BW_20);
1081 if (err)
1082 goto out;
1083 /* adjust slot time for 5 GHz */
1084 if (hw->conf.channel->band == IEEE80211_BAND_5GHZ)
1085 err = ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME,
1086 9 << 10);
1087 }
1088
1089out:
1090 mutex_unlock(&ar->mutex);
1091 return err;
1092}
1093
1094static int ar9170_op_config_interface(struct ieee80211_hw *hw,
1095 struct ieee80211_vif *vif,
1096 struct ieee80211_if_conf *conf)
1097{
1098 struct ar9170 *ar = hw->priv;
1099 int err = 0;
1100
1101 mutex_lock(&ar->mutex);
1102
1103 if (conf->changed & IEEE80211_IFCC_BSSID) {
1104 memcpy(ar->bssid, conf->bssid, ETH_ALEN);
1105 err = ar9170_set_operating_mode(ar);
1106 }
1107
1108 if (conf->changed & IEEE80211_IFCC_BEACON) {
1109 err = ar9170_update_beacon(ar);
1110
1111 if (err)
1112 goto out;
1113 err = ar9170_set_beacon_timers(ar);
1114 }
1115
1116out:
1117 mutex_unlock(&ar->mutex);
1118 return err;
1119}
1120
1121static void ar9170_set_filters(struct work_struct *work)
1122{
1123 struct ar9170 *ar = container_of(work, struct ar9170,
1124 filter_config_work);
1125 int err;
1126
1127 if (unlikely(!IS_STARTED(ar)))
1128 return ;
1129
1130 mutex_lock(&ar->mutex);
1131 if (ar->filter_changed & AR9170_FILTER_CHANGED_PROMISC) {
1132 err = ar9170_set_operating_mode(ar);
1133 if (err)
1134 goto unlock;
1135 }
1136
1137 if (ar->filter_changed & AR9170_FILTER_CHANGED_MULTICAST) {
1138 err = ar9170_update_multicast(ar);
1139 if (err)
1140 goto unlock;
1141 }
1142
1143 if (ar->filter_changed & AR9170_FILTER_CHANGED_FRAMEFILTER)
1144 err = ar9170_update_frame_filter(ar);
1145
1146unlock:
1147 mutex_unlock(&ar->mutex);
1148}
1149
1150static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
1151 unsigned int changed_flags,
1152 unsigned int *new_flags,
1153 int mc_count, struct dev_mc_list *mclist)
1154{
1155 struct ar9170 *ar = hw->priv;
1156
1157 /* mask supported flags */
1158 *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC |
1159 FIF_PROMISC_IN_BSS;
1160
1161 /*
1162 * We can support more by setting the sniffer bit and
1163 * then checking the error flags, later.
1164 */
1165
1166 if (changed_flags & FIF_ALLMULTI) {
1167 if (*new_flags & FIF_ALLMULTI) {
1168 ar->want_mc_hash = ~0ULL;
1169 } else {
1170 u64 mchash;
1171 int i;
1172
1173 /* always get broadcast frames */
1174 mchash = 1ULL << (0xff>>2);
1175
1176 for (i = 0; i < mc_count; i++) {
1177 if (WARN_ON(!mclist))
1178 break;
1179 mchash |= 1ULL << (mclist->dmi_addr[5] >> 2);
1180 mclist = mclist->next;
1181 }
1182 ar->want_mc_hash = mchash;
1183 }
1184 ar->filter_changed |= AR9170_FILTER_CHANGED_MULTICAST;
1185 }
1186
1187 if (changed_flags & FIF_CONTROL) {
1188 u32 filter = AR9170_MAC_REG_FTF_PSPOLL |
1189 AR9170_MAC_REG_FTF_RTS |
1190 AR9170_MAC_REG_FTF_CTS |
1191 AR9170_MAC_REG_FTF_ACK |
1192 AR9170_MAC_REG_FTF_CFE |
1193 AR9170_MAC_REG_FTF_CFE_ACK;
1194
1195 if (*new_flags & FIF_CONTROL)
1196 ar->want_filter = ar->cur_filter | filter;
1197 else
1198 ar->want_filter = ar->cur_filter & ~filter;
1199
1200 ar->filter_changed |= AR9170_FILTER_CHANGED_FRAMEFILTER;
1201 }
1202
1203 if (changed_flags & FIF_PROMISC_IN_BSS) {
1204 ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0;
1205 ar->filter_changed |= AR9170_FILTER_CHANGED_PROMISC;
1206 }
1207
1208 if (likely(IS_STARTED(ar)))
1209 queue_work(ar->hw->workqueue, &ar->filter_config_work);
1210}
1211
1212static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
1213 struct ieee80211_vif *vif,
1214 struct ieee80211_bss_conf *bss_conf,
1215 u32 changed)
1216{
1217 struct ar9170 *ar = hw->priv;
1218 int err = 0;
1219
1220 mutex_lock(&ar->mutex);
1221
1222 ar9170_regwrite_begin(ar);
1223
1224 if (changed & BSS_CHANGED_ASSOC) {
1225 ar->state = bss_conf->assoc ? AR9170_ASSOCIATED : ar->state;
1226
1227#ifndef CONFIG_AR9170_LEDS
1228 /* enable assoc LED. */
1229 err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0);
1230#endif /* CONFIG_AR9170_LEDS */
1231 }
1232
1233 if (changed & BSS_CHANGED_HT) {
1234 /* TODO */
1235 err = 0;
1236 }
1237
1238 if (changed & BSS_CHANGED_ERP_SLOT) {
1239 u32 slottime = 20;
1240
1241 if (bss_conf->use_short_slot)
1242 slottime = 9;
1243
1244 ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, slottime << 10);
1245 }
1246
1247 if (changed & BSS_CHANGED_BASIC_RATES) {
1248 u32 cck, ofdm;
1249
1250 if (hw->conf.channel->band == IEEE80211_BAND_5GHZ) {
1251 ofdm = bss_conf->basic_rates;
1252 cck = 0;
1253 } else {
1254 /* four cck rates */
1255 cck = bss_conf->basic_rates & 0xf;
1256 ofdm = bss_conf->basic_rates >> 4;
1257 }
1258 ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE,
1259 ofdm << 8 | cck);
1260 }
1261
1262 ar9170_regwrite_finish();
1263 err = ar9170_regwrite_result();
1264 mutex_unlock(&ar->mutex);
1265}
1266
1267static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw)
1268{
1269 struct ar9170 *ar = hw->priv;
1270 int err;
1271 u32 tsf_low;
1272 u32 tsf_high;
1273 u64 tsf;
1274
1275 mutex_lock(&ar->mutex);
1276 err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_L, &tsf_low);
1277 if (!err)
1278 err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_H, &tsf_high);
1279 mutex_unlock(&ar->mutex);
1280
1281 if (WARN_ON(err))
1282 return 0;
1283
1284 tsf = tsf_high;
1285 tsf = (tsf << 32) | tsf_low;
1286 return tsf;
1287}
1288
1289static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
1290 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
1291 struct ieee80211_key_conf *key)
1292{
1293 struct ar9170 *ar = hw->priv;
1294 int err = 0, i;
1295 u8 ktype;
1296
1297 if ((!ar->vif) || (ar->disable_offload))
1298 return -EOPNOTSUPP;
1299
1300 switch (key->alg) {
1301 case ALG_WEP:
1302 if (key->keylen == LEN_WEP40)
1303 ktype = AR9170_ENC_ALG_WEP64;
1304 else
1305 ktype = AR9170_ENC_ALG_WEP128;
1306 break;
1307 case ALG_TKIP:
1308 ktype = AR9170_ENC_ALG_TKIP;
1309 break;
1310 case ALG_CCMP:
1311 ktype = AR9170_ENC_ALG_AESCCMP;
1312 break;
1313 default:
1314 return -EOPNOTSUPP;
1315 }
1316
1317 mutex_lock(&ar->mutex);
1318 if (cmd == SET_KEY) {
1319 if (unlikely(!IS_STARTED(ar))) {
1320 err = -EOPNOTSUPP;
1321 goto out;
1322 }
1323
1324 /* group keys need all-zeroes address */
1325 if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
1326 sta = NULL;
1327
1328 if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
1329 for (i = 0; i < 64; i++)
1330 if (!(ar->usedkeys & BIT(i)))
1331 break;
1332 if (i == 64) {
1333 ar->rx_software_decryption = true;
1334 ar9170_set_operating_mode(ar);
1335 err = -ENOSPC;
1336 goto out;
1337 }
1338 } else {
1339 i = 64 + key->keyidx;
1340 }
1341
1342 key->hw_key_idx = i;
1343
1344 err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, ktype, 0,
1345 key->key, min_t(u8, 16, key->keylen));
1346 if (err)
1347 goto out;
1348
1349 if (key->alg == ALG_TKIP) {
1350 err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL,
1351 ktype, 1, key->key + 16, 16);
1352 if (err)
1353 goto out;
1354
1355 /*
1356 * hardware is not capable generating the MMIC
1357 * for fragmented frames!
1358 */
1359 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
1360 }
1361
1362 if (i < 64)
1363 ar->usedkeys |= BIT(i);
1364
1365 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
1366 } else {
1367 if (unlikely(!IS_STARTED(ar))) {
1368 /* The device is gone... together with the key ;-) */
1369 err = 0;
1370 goto out;
1371 }
1372
1373 err = ar9170_disable_key(ar, key->hw_key_idx);
1374 if (err)
1375 goto out;
1376
1377 if (key->hw_key_idx < 64) {
1378 ar->usedkeys &= ~BIT(key->hw_key_idx);
1379 } else {
1380 err = ar9170_upload_key(ar, key->hw_key_idx, NULL,
1381 AR9170_ENC_ALG_NONE, 0,
1382 NULL, 0);
1383 if (err)
1384 goto out;
1385
1386 if (key->alg == ALG_TKIP) {
1387 err = ar9170_upload_key(ar, key->hw_key_idx,
1388 NULL,
1389 AR9170_ENC_ALG_NONE, 1,
1390 NULL, 0);
1391 if (err)
1392 goto out;
1393 }
1394
1395 }
1396 }
1397
1398 ar9170_regwrite_begin(ar);
1399 ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_L, ar->usedkeys);
1400 ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_H, ar->usedkeys >> 32);
1401 ar9170_regwrite_finish();
1402 err = ar9170_regwrite_result();
1403
1404out:
1405 mutex_unlock(&ar->mutex);
1406
1407 return err;
1408}
1409
1410static void ar9170_sta_notify(struct ieee80211_hw *hw,
1411 struct ieee80211_vif *vif,
1412 enum sta_notify_cmd cmd,
1413 struct ieee80211_sta *sta)
1414{
1415 struct ar9170 *ar = hw->priv;
1416 struct ar9170_sta_info *info = (void *) sta->drv_priv;
1417 struct sk_buff *skb;
1418 unsigned int i;
1419
1420 switch (cmd) {
1421 case STA_NOTIFY_ADD:
1422 for (i = 0; i < ar->hw->queues; i++)
1423 skb_queue_head_init(&info->tx_status[i]);
1424 break;
1425
1426 case STA_NOTIFY_REMOVE:
1427
1428 /*
1429 * transfer all outstanding frames that need a tx_status
1430 * reports to the global tx_status queue
1431 */
1432
1433 for (i = 0; i < ar->hw->queues; i++) {
1434 while ((skb = skb_dequeue(&info->tx_status[i]))) {
1435#ifdef AR9170_QUEUE_DEBUG
1436 printk(KERN_DEBUG "%s: queueing frame in "
1437 "global tx_status queue =>\n",
1438 wiphy_name(ar->hw->wiphy));
1439
1440 ar9170_print_txheader(ar, skb);
1441#endif /* AR9170_QUEUE_DEBUG */
1442 skb_queue_tail(&ar->global_tx_status, skb);
1443 }
1444 }
1445 queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor,
1446 msecs_to_jiffies(100));
1447 break;
1448
1449 default:
1450 break;
1451 }
1452}
1453
1454static int ar9170_get_stats(struct ieee80211_hw *hw,
1455 struct ieee80211_low_level_stats *stats)
1456{
1457 struct ar9170 *ar = hw->priv;
1458 u32 val;
1459 int err;
1460
1461 mutex_lock(&ar->mutex);
1462 err = ar9170_read_reg(ar, AR9170_MAC_REG_TX_RETRY, &val);
1463 ar->stats.dot11ACKFailureCount += val;
1464
1465 memcpy(stats, &ar->stats, sizeof(*stats));
1466 mutex_unlock(&ar->mutex);
1467
1468 return 0;
1469}
1470
1471static int ar9170_get_tx_stats(struct ieee80211_hw *hw,
1472 struct ieee80211_tx_queue_stats *tx_stats)
1473{
1474 struct ar9170 *ar = hw->priv;
1475
1476 spin_lock_bh(&ar->tx_stats_lock);
1477 memcpy(tx_stats, ar->tx_stats, sizeof(tx_stats[0]) * hw->queues);
1478 spin_unlock_bh(&ar->tx_stats_lock);
1479
1480 return 0;
1481}
1482
1483static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue,
1484 const struct ieee80211_tx_queue_params *param)
1485{
1486 struct ar9170 *ar = hw->priv;
1487 int ret;
1488
1489 mutex_lock(&ar->mutex);
1490 if ((param) && !(queue > ar->hw->queues)) {
1491 memcpy(&ar->edcf[ar9170_qos_hwmap[queue]],
1492 param, sizeof(*param));
1493
1494 ret = ar9170_set_qos(ar);
1495 } else
1496 ret = -EINVAL;
1497
1498 mutex_unlock(&ar->mutex);
1499 return ret;
1500}
1501
1502static const struct ieee80211_ops ar9170_ops = {
1503 .start = ar9170_op_start,
1504 .stop = ar9170_op_stop,
1505 .tx = ar9170_op_tx,
1506 .add_interface = ar9170_op_add_interface,
1507 .remove_interface = ar9170_op_remove_interface,
1508 .config = ar9170_op_config,
1509 .config_interface = ar9170_op_config_interface,
1510 .configure_filter = ar9170_op_configure_filter,
1511 .conf_tx = ar9170_conf_tx,
1512 .bss_info_changed = ar9170_op_bss_info_changed,
1513 .get_tsf = ar9170_op_get_tsf,
1514 .set_key = ar9170_set_key,
1515 .sta_notify = ar9170_sta_notify,
1516 .get_stats = ar9170_get_stats,
1517 .get_tx_stats = ar9170_get_tx_stats,
1518};
1519
1520void *ar9170_alloc(size_t priv_size)
1521{
1522 struct ieee80211_hw *hw;
1523 struct ar9170 *ar;
1524 int i;
1525
1526 hw = ieee80211_alloc_hw(priv_size, &ar9170_ops);
1527 if (!hw)
1528 return ERR_PTR(-ENOMEM);
1529
1530 ar = hw->priv;
1531 ar->hw = hw;
1532
1533 mutex_init(&ar->mutex);
1534 spin_lock_init(&ar->cmdlock);
1535 spin_lock_init(&ar->tx_stats_lock);
1536 skb_queue_head_init(&ar->global_tx_status);
1537 skb_queue_head_init(&ar->global_tx_status_waste);
1538 INIT_WORK(&ar->filter_config_work, ar9170_set_filters);
1539 INIT_WORK(&ar->beacon_work, ar9170_new_beacon);
1540 INIT_DELAYED_WORK(&ar->tx_status_janitor, ar9170_tx_status_janitor);
1541
1542 /* all hw supports 2.4 GHz, so set channel to 1 by default */
1543 ar->channel = &ar9170_2ghz_chantable[0];
1544
1545 /* first part of wiphy init */
1546 ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
1547 BIT(NL80211_IFTYPE_WDS) |
1548 BIT(NL80211_IFTYPE_ADHOC);
1549 ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
1550 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
1551 IEEE80211_HW_SIGNAL_DBM |
1552 IEEE80211_HW_NOISE_DBM;
1553
1554 ar->hw->queues = __AR9170_NUM_TXQ;
1555 ar->hw->extra_tx_headroom = 8;
1556 ar->hw->sta_data_size = sizeof(struct ar9170_sta_info);
1557
1558 ar->hw->max_rates = 1;
1559 ar->hw->max_rate_tries = 3;
1560
1561 for (i = 0; i < ARRAY_SIZE(ar->noise); i++)
1562 ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */
1563
1564 return ar;
1565}
1566
1567static int ar9170_read_eeprom(struct ar9170 *ar)
1568{
1569#define RW 8 /* number of words to read at once */
1570#define RB (sizeof(u32) * RW)
1571 DECLARE_MAC_BUF(mbuf);
1572 u8 *eeprom = (void *)&ar->eeprom;
1573 u8 *addr = ar->eeprom.mac_address;
1574 __le32 offsets[RW];
1575 int i, j, err, bands = 0;
1576
1577 BUILD_BUG_ON(sizeof(ar->eeprom) & 3);
1578
1579 BUILD_BUG_ON(RB > AR9170_MAX_CMD_LEN - 4);
1580#ifndef __CHECKER__
1581 /* don't want to handle trailing remains */
1582 BUILD_BUG_ON(sizeof(ar->eeprom) % RB);
1583#endif
1584
1585 for (i = 0; i < sizeof(ar->eeprom)/RB; i++) {
1586 for (j = 0; j < RW; j++)
1587 offsets[j] = cpu_to_le32(AR9170_EEPROM_START +
1588 RB * i + 4 * j);
1589
1590 err = ar->exec_cmd(ar, AR9170_CMD_RREG,
1591 RB, (u8 *) &offsets,
1592 RB, eeprom + RB * i);
1593 if (err)
1594 return err;
1595 }
1596
1597#undef RW
1598#undef RB
1599
1600 if (ar->eeprom.length == cpu_to_le16(0xFFFF))
1601 return -ENODATA;
1602
1603 if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) {
1604 ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar9170_band_2GHz;
1605 bands++;
1606 }
1607 if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) {
1608 ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz;
1609 bands++;
1610 }
1611 /*
1612 * I measured this, a bandswitch takes roughly
1613 * 135 ms and a frequency switch about 80.
1614 *
1615 * FIXME: measure these values again once EEPROM settings
1616 * are used, that will influence them!
1617 */
1618 if (bands == 2)
1619 ar->hw->channel_change_time = 135 * 1000;
1620 else
1621 ar->hw->channel_change_time = 80 * 1000;
1622
1623 ar->regulatory.current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
1624 ar->regulatory.current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
1625
1626 /* second part of wiphy init */
1627 SET_IEEE80211_PERM_ADDR(ar->hw, addr);
1628
1629 return bands ? 0 : -EINVAL;
1630}
1631
1632static int ar9170_reg_notifier(struct wiphy *wiphy,
1633 struct regulatory_request *request)
1634{
1635 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
1636 struct ar9170 *ar = hw->priv;
1637
1638 return ath_reg_notifier_apply(wiphy, request, &ar->regulatory);
1639}
1640
1641int ar9170_register(struct ar9170 *ar, struct device *pdev)
1642{
1643 int err;
1644
1645 /* try to read EEPROM, init MAC addr */
1646 err = ar9170_read_eeprom(ar);
1647 if (err)
1648 goto err_out;
1649
1650 err = ath_regd_init(&ar->regulatory, ar->hw->wiphy,
1651 ar9170_reg_notifier);
1652
1653 err = ieee80211_register_hw(ar->hw);
1654 if (err)
1655 goto err_out;
1656
1657 if (!ath_is_world_regd(&ar->regulatory))
1658 regulatory_hint(ar->hw->wiphy, ar->regulatory.alpha2);
1659
1660 err = ar9170_init_leds(ar);
1661 if (err)
1662 goto err_unreg;
1663
1664#ifdef CONFIG_AR9170_LEDS
1665 err = ar9170_register_leds(ar);
1666 if (err)
1667 goto err_unreg;
1668#endif /* CONFIG_AR9170_LEDS */
1669
1670 dev_info(pdev, "Atheros AR9170 is registered as '%s'\n",
1671 wiphy_name(ar->hw->wiphy));
1672
1673 return err;
1674
1675err_unreg:
1676 ieee80211_unregister_hw(ar->hw);
1677
1678err_out:
1679 return err;
1680}
1681
1682void ar9170_unregister(struct ar9170 *ar)
1683{
1684#ifdef CONFIG_AR9170_LEDS
1685 ar9170_unregister_leds(ar);
1686#endif /* CONFIG_AR9170_LEDS */
1687
1688 ieee80211_unregister_hw(ar->hw);
1689 mutex_destroy(&ar->mutex);
1690}
diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c
new file mode 100644
index 000000000000..6ce20754b8e7
--- /dev/null
+++ b/drivers/net/wireless/ath/ar9170/phy.c
@@ -0,0 +1,1240 @@
1/*
2 * Atheros AR9170 driver
3 *
4 * PHY and RF code
5 *
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, see
20 * http://www.gnu.org/licenses/.
21 *
22 * This file incorporates work covered by the following copyright and
23 * permission notice:
24 * Copyright (c) 2007-2008 Atheros Communications, Inc.
25 *
26 * Permission to use, copy, modify, and/or distribute this software for any
27 * purpose with or without fee is hereby granted, provided that the above
28 * copyright notice and this permission notice appear in all copies.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
31 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
32 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
33 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
34 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
35 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
36 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37 */
38
39#include <linux/bitrev.h>
40#include "ar9170.h"
41#include "cmd.h"
42
43static int ar9170_init_power_cal(struct ar9170 *ar)
44{
45 ar9170_regwrite_begin(ar);
46
47 ar9170_regwrite(0x1bc000 + 0x993c, 0x7f);
48 ar9170_regwrite(0x1bc000 + 0x9934, 0x3f3f3f3f);
49 ar9170_regwrite(0x1bc000 + 0x9938, 0x3f3f3f3f);
50 ar9170_regwrite(0x1bc000 + 0xa234, 0x3f3f3f3f);
51 ar9170_regwrite(0x1bc000 + 0xa238, 0x3f3f3f3f);
52 ar9170_regwrite(0x1bc000 + 0xa38c, 0x3f3f3f3f);
53 ar9170_regwrite(0x1bc000 + 0xa390, 0x3f3f3f3f);
54 ar9170_regwrite(0x1bc000 + 0xa3cc, 0x3f3f3f3f);
55 ar9170_regwrite(0x1bc000 + 0xa3d0, 0x3f3f3f3f);
56 ar9170_regwrite(0x1bc000 + 0xa3d4, 0x3f3f3f3f);
57
58 ar9170_regwrite_finish();
59 return ar9170_regwrite_result();
60}
61
62struct ar9170_phy_init {
63 u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20;
64};
65
66static struct ar9170_phy_init ar5416_phy_init[] = {
67 { 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
68 { 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, },
69 { 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
70 { 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, },
71 { 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, },
72 { 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, },
73 { 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, },
74 { 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
75 { 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, },
76 { 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, },
77 { 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, },
78 { 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, },
79 { 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
80 { 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, },
81 { 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
82 { 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, },
83 { 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, },
84 { 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, },
85 { 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, },
86 { 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, },
87 { 0x1c5850, 0x6c48b4e4, 0x6c48b4e4, 0x6c48b0e4, 0x6c48b0e4, },
88 { 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, },
89 { 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, },
90 { 0x1c585c, 0x31395c5e, 0x31395c5e, 0x31395c5e, 0x31395c5e, },
91 { 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, },
92 { 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, },
93 { 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, },
94 { 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
95 { 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
96 { 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
97 { 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
98 { 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, },
99 { 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, },
100 { 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, },
101 { 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, },
102 { 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, },
103 { 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
104 { 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, },
105 { 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
106 { 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
107 { 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, },
108 { 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, },
109 { 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, },
110 { 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, },
111 { 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, },
112 { 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, },
113 { 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
114 { 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, },
115 { 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, },
116 { 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
117 { 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
118 { 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
119 { 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
120 { 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
121 { 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
122 { 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
123 { 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
124 { 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
125 { 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
126 { 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
127 { 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
128 { 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
129 { 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, },
130 { 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, },
131 { 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, },
132 { 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, },
133 { 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, },
134 { 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, },
135 { 0x1c59c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, },
136 { 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, },
137 { 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, },
138 { 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
139 { 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
140 { 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
141 { 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, },
142 { 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, },
143 { 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, },
144 { 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, },
145 { 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
146 { 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, },
147 { 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
148 { 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, },
149 { 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, },
150 { 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, },
151 { 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, },
152 { 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, },
153 { 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, },
154 { 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, },
155 { 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, },
156 { 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, },
157 { 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, },
158 { 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, },
159 { 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, },
160 { 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, },
161 { 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, },
162 { 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, },
163 { 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, },
164 { 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, },
165 { 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, },
166 { 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, },
167 { 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, },
168 { 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, },
169 { 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, },
170 { 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, },
171 { 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, },
172 { 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, },
173 { 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, },
174 { 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, },
175 { 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, },
176 { 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, },
177 { 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, },
178 { 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, },
179 { 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, },
180 { 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, },
181 { 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, },
182 { 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, },
183 { 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, },
184 { 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, },
185 { 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, },
186 { 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, },
187 { 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
188 { 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
189 { 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
190 { 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
191 { 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
192 { 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
193 { 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
194 { 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
195 { 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
196 { 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
197 { 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
198 { 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
199 { 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
200 { 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
201 { 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
202 { 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
203 { 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
204 { 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
205 { 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
206 { 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
207 { 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
208 { 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
209 { 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
210 { 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
211 { 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
212 { 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
213 { 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, },
214 { 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, },
215 { 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, },
216 { 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, },
217 { 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, },
218 { 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, },
219 { 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, },
220 { 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, },
221 { 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, },
222 { 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, },
223 { 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, },
224 { 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, },
225 { 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, },
226 { 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, },
227 { 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, },
228 { 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, },
229 { 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, },
230 { 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, },
231 { 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, },
232 { 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, },
233 { 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, },
234 { 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, },
235 { 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, },
236 { 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, },
237 { 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, },
238 { 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, },
239 { 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, },
240 { 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, },
241 { 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, },
242 { 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, },
243 { 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, },
244 { 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, },
245 { 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, },
246 { 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, },
247 { 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, },
248 { 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, },
249 { 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, },
250 { 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, },
251 { 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, },
252 { 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
253 { 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
254 { 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
255 { 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
256 { 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
257 { 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
258 { 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
259 { 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
260 { 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
261 { 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
262 { 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
263 { 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
264 { 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
265 { 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
266 { 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
267 { 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
268 { 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
269 { 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
270 { 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
271 { 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
272 { 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
273 { 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, },
274 { 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, },
275 { 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
276 { 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
277 { 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
278 { 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
279 { 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
280 { 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
281 { 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
282 { 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
283 { 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
284 { 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
285 { 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
286 { 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
287 { 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
288 { 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
289 { 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
290 { 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
291 { 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
292 { 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
293 { 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, },
294 { 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, },
295 { 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, },
296 { 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
297 { 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, },
298 { 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, },
299 { 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, },
300 { 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, },
301 { 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, },
302 { 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, },
303 { 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, },
304 { 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
305 { 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, },
306 { 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
307 { 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
308 { 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, },
309 { 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, },
310 { 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, },
311 { 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, },
312 { 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
313 { 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, },
314 { 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
315 { 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, },
316 { 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, },
317 { 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, },
318 { 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, },
319 { 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
320 { 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
321 { 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, },
322 { 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
323 { 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, },
324 { 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, },
325 { 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, },
326 { 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, },
327 { 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, },
328 { 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, },
329 { 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, },
330 { 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, },
331 { 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, },
332 { 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, },
333 { 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, },
334 { 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, },
335 { 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
336 { 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
337 { 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
338 { 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
339 { 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
340 { 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
341 { 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
342 { 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
343 { 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
344 { 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
345 { 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, },
346 { 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, },
347 { 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, },
348 { 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
349 { 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
350 { 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
351 { 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, },
352 { 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
353 { 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
354 { 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
355 { 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
356 { 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
357 { 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
358 { 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
359 { 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
360 { 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
361 { 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
362 { 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
363 { 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
364 { 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
365 { 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
366 { 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
367 { 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
368 { 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
369 { 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, },
370 { 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, },
371 { 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, },
372 { 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
373 { 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
374 { 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
375 { 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, },
376 { 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, },
377 { 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
378 { 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
379 { 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
380/* { 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */
381 { 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, },
382 { 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, },
383 { 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, },
384 { 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, },
385 { 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, },
386 { 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, },
387 { 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, },
388 { 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, },
389 { 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, },
390 { 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, },
391 { 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, },
392 { 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, },
393 { 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, },
394 { 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, },
395 { 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, },
396 { 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, }
397};
398
399int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
400{
401 int i, err;
402 u32 val;
403 bool is_2ghz = band == IEEE80211_BAND_2GHZ;
404 bool is_40mhz = false; /* XXX: for now */
405
406 ar9170_regwrite_begin(ar);
407
408 for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) {
409 if (is_40mhz) {
410 if (is_2ghz)
411 val = ar5416_phy_init[i]._2ghz_40;
412 else
413 val = ar5416_phy_init[i]._5ghz_40;
414 } else {
415 if (is_2ghz)
416 val = ar5416_phy_init[i]._2ghz_20;
417 else
418 val = ar5416_phy_init[i]._5ghz_20;
419 }
420
421 ar9170_regwrite(ar5416_phy_init[i].reg, val);
422 }
423
424 ar9170_regwrite_finish();
425 err = ar9170_regwrite_result();
426 if (err)
427 return err;
428
429 /* XXX: use EEPROM data here! */
430
431 err = ar9170_init_power_cal(ar);
432 if (err)
433 return err;
434
435 /* XXX: remove magic! */
436 if (is_2ghz)
437 err = ar9170_write_reg(ar, 0x1d4014, 0x5163);
438 else
439 err = ar9170_write_reg(ar, 0x1d4014, 0x5143);
440
441 return err;
442}
443
444struct ar9170_rf_init {
445 u32 reg, _5ghz, _2ghz;
446};
447
448static struct ar9170_rf_init ar9170_rf_init[] = {
449 /* bank 0 */
450 { 0x1c58b0, 0x1e5795e5, 0x1e5795e5},
451 { 0x1c58e0, 0x02008020, 0x02008020},
452 /* bank 1 */
453 { 0x1c58b0, 0x02108421, 0x02108421},
454 { 0x1c58ec, 0x00000008, 0x00000008},
455 /* bank 2 */
456 { 0x1c58b0, 0x0e73ff17, 0x0e73ff17},
457 { 0x1c58e0, 0x00000420, 0x00000420},
458 /* bank 3 */
459 { 0x1c58f0, 0x01400018, 0x01c00018},
460 /* bank 4 */
461 { 0x1c58b0, 0x000001a1, 0x000001a1},
462 { 0x1c58e8, 0x00000001, 0x00000001},
463 /* bank 5 */
464 { 0x1c58b0, 0x00000013, 0x00000013},
465 { 0x1c58e4, 0x00000002, 0x00000002},
466 /* bank 6 */
467 { 0x1c58b0, 0x00000000, 0x00000000},
468 { 0x1c58b0, 0x00000000, 0x00000000},
469 { 0x1c58b0, 0x00000000, 0x00000000},
470 { 0x1c58b0, 0x00000000, 0x00000000},
471 { 0x1c58b0, 0x00000000, 0x00000000},
472 { 0x1c58b0, 0x00004000, 0x00004000},
473 { 0x1c58b0, 0x00006c00, 0x00006c00},
474 { 0x1c58b0, 0x00002c00, 0x00002c00},
475 { 0x1c58b0, 0x00004800, 0x00004800},
476 { 0x1c58b0, 0x00004000, 0x00004000},
477 { 0x1c58b0, 0x00006000, 0x00006000},
478 { 0x1c58b0, 0x00001000, 0x00001000},
479 { 0x1c58b0, 0x00004000, 0x00004000},
480 { 0x1c58b0, 0x00007c00, 0x00007c00},
481 { 0x1c58b0, 0x00007c00, 0x00007c00},
482 { 0x1c58b0, 0x00007c00, 0x00007c00},
483 { 0x1c58b0, 0x00007c00, 0x00007c00},
484 { 0x1c58b0, 0x00007c00, 0x00007c00},
485 { 0x1c58b0, 0x00087c00, 0x00087c00},
486 { 0x1c58b0, 0x00007c00, 0x00007c00},
487 { 0x1c58b0, 0x00005400, 0x00005400},
488 { 0x1c58b0, 0x00000c00, 0x00000c00},
489 { 0x1c58b0, 0x00001800, 0x00001800},
490 { 0x1c58b0, 0x00007c00, 0x00007c00},
491 { 0x1c58b0, 0x00006c00, 0x00006c00},
492 { 0x1c58b0, 0x00006c00, 0x00006c00},
493 { 0x1c58b0, 0x00007c00, 0x00007c00},
494 { 0x1c58b0, 0x00002c00, 0x00002c00},
495 { 0x1c58b0, 0x00003c00, 0x00003c00},
496 { 0x1c58b0, 0x00003800, 0x00003800},
497 { 0x1c58b0, 0x00001c00, 0x00001c00},
498 { 0x1c58b0, 0x00000800, 0x00000800},
499 { 0x1c58b0, 0x00000408, 0x00000408},
500 { 0x1c58b0, 0x00004c15, 0x00004c15},
501 { 0x1c58b0, 0x00004188, 0x00004188},
502 { 0x1c58b0, 0x0000201e, 0x0000201e},
503 { 0x1c58b0, 0x00010408, 0x00010408},
504 { 0x1c58b0, 0x00000801, 0x00000801},
505 { 0x1c58b0, 0x00000c08, 0x00000c08},
506 { 0x1c58b0, 0x0000181e, 0x0000181e},
507 { 0x1c58b0, 0x00001016, 0x00001016},
508 { 0x1c58b0, 0x00002800, 0x00002800},
509 { 0x1c58b0, 0x00004010, 0x00004010},
510 { 0x1c58b0, 0x0000081c, 0x0000081c},
511 { 0x1c58b0, 0x00000115, 0x00000115},
512 { 0x1c58b0, 0x00000015, 0x00000015},
513 { 0x1c58b0, 0x00000066, 0x00000066},
514 { 0x1c58b0, 0x0000001c, 0x0000001c},
515 { 0x1c58b0, 0x00000000, 0x00000000},
516 { 0x1c58b0, 0x00000004, 0x00000004},
517 { 0x1c58b0, 0x00000015, 0x00000015},
518 { 0x1c58b0, 0x0000001f, 0x0000001f},
519 { 0x1c58e0, 0x00000000, 0x00000400},
520 /* bank 7 */
521 { 0x1c58b0, 0x000000a0, 0x000000a0},
522 { 0x1c58b0, 0x00000000, 0x00000000},
523 { 0x1c58b0, 0x00000040, 0x00000040},
524 { 0x1c58f0, 0x0000001c, 0x0000001c},
525};
526
527static int ar9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz)
528{
529 int err, i;
530
531 ar9170_regwrite_begin(ar);
532
533 for (i = 0; i < ARRAY_SIZE(ar9170_rf_init); i++)
534 ar9170_regwrite(ar9170_rf_init[i].reg,
535 band5ghz ? ar9170_rf_init[i]._5ghz
536 : ar9170_rf_init[i]._2ghz);
537
538 ar9170_regwrite_finish();
539 err = ar9170_regwrite_result();
540 if (err)
541 printk(KERN_ERR "%s: rf init failed\n",
542 wiphy_name(ar->hw->wiphy));
543 return err;
544}
545
546static int ar9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz,
547 u32 freq, enum ar9170_bw bw)
548{
549 int err;
550 u32 d0, d1, td0, td1, fd0, fd1;
551 u8 chansel;
552 u8 refsel0 = 1, refsel1 = 0;
553 u8 lf_synth = 0;
554
555 switch (bw) {
556 case AR9170_BW_40_ABOVE:
557 freq += 10;
558 break;
559 case AR9170_BW_40_BELOW:
560 freq -= 10;
561 break;
562 case AR9170_BW_20:
563 break;
564 case __AR9170_NUM_BW:
565 BUG();
566 }
567
568 if (band5ghz) {
569 if (freq % 10) {
570 chansel = (freq - 4800) / 5;
571 } else {
572 chansel = ((freq - 4800) / 10) * 2;
573 refsel0 = 0;
574 refsel1 = 1;
575 }
576 chansel = byte_rev_table[chansel];
577 } else {
578 if (freq == 2484) {
579 chansel = 10 + (freq - 2274) / 5;
580 lf_synth = 1;
581 } else
582 chansel = 16 + (freq - 2272) / 5;
583 chansel *= 4;
584 chansel = byte_rev_table[chansel];
585 }
586
587 d1 = chansel;
588 d0 = 0x21 |
589 refsel0 << 3 |
590 refsel1 << 2 |
591 lf_synth << 1;
592 td0 = d0 & 0x1f;
593 td1 = d1 & 0x1f;
594 fd0 = td1 << 5 | td0;
595
596 td0 = (d0 >> 5) & 0x7;
597 td1 = (d1 >> 5) & 0x7;
598 fd1 = td1 << 5 | td0;
599
600 ar9170_regwrite_begin(ar);
601
602 ar9170_regwrite(0x1c58b0, fd0);
603 ar9170_regwrite(0x1c58e8, fd1);
604
605 ar9170_regwrite_finish();
606 err = ar9170_regwrite_result();
607 if (err)
608 return err;
609
610 msleep(10);
611
612 return 0;
613}
614
615struct ar9170_phy_freq_params {
616 u8 coeff_exp;
617 u16 coeff_man;
618 u8 coeff_exp_shgi;
619 u16 coeff_man_shgi;
620};
621
622struct ar9170_phy_freq_entry {
623 u16 freq;
624 struct ar9170_phy_freq_params params[__AR9170_NUM_BW];
625};
626
627/* NB: must be in sync with channel tables in main! */
628static const struct ar9170_phy_freq_entry ar9170_phy_freq_params[] = {
629/*
630 * freq,
631 * 20MHz,
632 * 40MHz (below),
633 * 40Mhz (above),
634 */
635 { 2412, {
636 { 3, 21737, 3, 19563, },
637 { 3, 21827, 3, 19644, },
638 { 3, 21647, 3, 19482, },
639 } },
640 { 2417, {
641 { 3, 21692, 3, 19523, },
642 { 3, 21782, 3, 19604, },
643 { 3, 21602, 3, 19442, },
644 } },
645 { 2422, {
646 { 3, 21647, 3, 19482, },
647 { 3, 21737, 3, 19563, },
648 { 3, 21558, 3, 19402, },
649 } },
650 { 2427, {
651 { 3, 21602, 3, 19442, },
652 { 3, 21692, 3, 19523, },
653 { 3, 21514, 3, 19362, },
654 } },
655 { 2432, {
656 { 3, 21558, 3, 19402, },
657 { 3, 21647, 3, 19482, },
658 { 3, 21470, 3, 19323, },
659 } },
660 { 2437, {
661 { 3, 21514, 3, 19362, },
662 { 3, 21602, 3, 19442, },
663 { 3, 21426, 3, 19283, },
664 } },
665 { 2442, {
666 { 3, 21470, 3, 19323, },
667 { 3, 21558, 3, 19402, },
668 { 3, 21382, 3, 19244, },
669 } },
670 { 2447, {
671 { 3, 21426, 3, 19283, },
672 { 3, 21514, 3, 19362, },
673 { 3, 21339, 3, 19205, },
674 } },
675 { 2452, {
676 { 3, 21382, 3, 19244, },
677 { 3, 21470, 3, 19323, },
678 { 3, 21295, 3, 19166, },
679 } },
680 { 2457, {
681 { 3, 21339, 3, 19205, },
682 { 3, 21426, 3, 19283, },
683 { 3, 21252, 3, 19127, },
684 } },
685 { 2462, {
686 { 3, 21295, 3, 19166, },
687 { 3, 21382, 3, 19244, },
688 { 3, 21209, 3, 19088, },
689 } },
690 { 2467, {
691 { 3, 21252, 3, 19127, },
692 { 3, 21339, 3, 19205, },
693 { 3, 21166, 3, 19050, },
694 } },
695 { 2472, {
696 { 3, 21209, 3, 19088, },
697 { 3, 21295, 3, 19166, },
698 { 3, 21124, 3, 19011, },
699 } },
700 { 2484, {
701 { 3, 21107, 3, 18996, },
702 { 3, 21192, 3, 19073, },
703 { 3, 21022, 3, 18920, },
704 } },
705 { 4920, {
706 { 4, 21313, 4, 19181, },
707 { 4, 21356, 4, 19220, },
708 { 4, 21269, 4, 19142, },
709 } },
710 { 4940, {
711 { 4, 21226, 4, 19104, },
712 { 4, 21269, 4, 19142, },
713 { 4, 21183, 4, 19065, },
714 } },
715 { 4960, {
716 { 4, 21141, 4, 19027, },
717 { 4, 21183, 4, 19065, },
718 { 4, 21098, 4, 18988, },
719 } },
720 { 4980, {
721 { 4, 21056, 4, 18950, },
722 { 4, 21098, 4, 18988, },
723 { 4, 21014, 4, 18912, },
724 } },
725 { 5040, {
726 { 4, 20805, 4, 18725, },
727 { 4, 20846, 4, 18762, },
728 { 4, 20764, 4, 18687, },
729 } },
730 { 5060, {
731 { 4, 20723, 4, 18651, },
732 { 4, 20764, 4, 18687, },
733 { 4, 20682, 4, 18614, },
734 } },
735 { 5080, {
736 { 4, 20641, 4, 18577, },
737 { 4, 20682, 4, 18614, },
738 { 4, 20601, 4, 18541, },
739 } },
740 { 5180, {
741 { 4, 20243, 4, 18219, },
742 { 4, 20282, 4, 18254, },
743 { 4, 20204, 4, 18183, },
744 } },
745 { 5200, {
746 { 4, 20165, 4, 18148, },
747 { 4, 20204, 4, 18183, },
748 { 4, 20126, 4, 18114, },
749 } },
750 { 5220, {
751 { 4, 20088, 4, 18079, },
752 { 4, 20126, 4, 18114, },
753 { 4, 20049, 4, 18044, },
754 } },
755 { 5240, {
756 { 4, 20011, 4, 18010, },
757 { 4, 20049, 4, 18044, },
758 { 4, 19973, 4, 17976, },
759 } },
760 { 5260, {
761 { 4, 19935, 4, 17941, },
762 { 4, 19973, 4, 17976, },
763 { 4, 19897, 4, 17907, },
764 } },
765 { 5280, {
766 { 4, 19859, 4, 17873, },
767 { 4, 19897, 4, 17907, },
768 { 4, 19822, 4, 17840, },
769 } },
770 { 5300, {
771 { 4, 19784, 4, 17806, },
772 { 4, 19822, 4, 17840, },
773 { 4, 19747, 4, 17772, },
774 } },
775 { 5320, {
776 { 4, 19710, 4, 17739, },
777 { 4, 19747, 4, 17772, },
778 { 4, 19673, 4, 17706, },
779 } },
780 { 5500, {
781 { 4, 19065, 4, 17159, },
782 { 4, 19100, 4, 17190, },
783 { 4, 19030, 4, 17127, },
784 } },
785 { 5520, {
786 { 4, 18996, 4, 17096, },
787 { 4, 19030, 4, 17127, },
788 { 4, 18962, 4, 17065, },
789 } },
790 { 5540, {
791 { 4, 18927, 4, 17035, },
792 { 4, 18962, 4, 17065, },
793 { 4, 18893, 4, 17004, },
794 } },
795 { 5560, {
796 { 4, 18859, 4, 16973, },
797 { 4, 18893, 4, 17004, },
798 { 4, 18825, 4, 16943, },
799 } },
800 { 5580, {
801 { 4, 18792, 4, 16913, },
802 { 4, 18825, 4, 16943, },
803 { 4, 18758, 4, 16882, },
804 } },
805 { 5600, {
806 { 4, 18725, 4, 16852, },
807 { 4, 18758, 4, 16882, },
808 { 4, 18691, 4, 16822, },
809 } },
810 { 5620, {
811 { 4, 18658, 4, 16792, },
812 { 4, 18691, 4, 16822, },
813 { 4, 18625, 4, 16762, },
814 } },
815 { 5640, {
816 { 4, 18592, 4, 16733, },
817 { 4, 18625, 4, 16762, },
818 { 4, 18559, 4, 16703, },
819 } },
820 { 5660, {
821 { 4, 18526, 4, 16673, },
822 { 4, 18559, 4, 16703, },
823 { 4, 18493, 4, 16644, },
824 } },
825 { 5680, {
826 { 4, 18461, 4, 16615, },
827 { 4, 18493, 4, 16644, },
828 { 4, 18428, 4, 16586, },
829 } },
830 { 5700, {
831 { 4, 18396, 4, 16556, },
832 { 4, 18428, 4, 16586, },
833 { 4, 18364, 4, 16527, },
834 } },
835 { 5745, {
836 { 4, 18252, 4, 16427, },
837 { 4, 18284, 4, 16455, },
838 { 4, 18220, 4, 16398, },
839 } },
840 { 5765, {
841 { 4, 18189, 5, 32740, },
842 { 4, 18220, 4, 16398, },
843 { 4, 18157, 5, 32683, },
844 } },
845 { 5785, {
846 { 4, 18126, 5, 32626, },
847 { 4, 18157, 5, 32683, },
848 { 4, 18094, 5, 32570, },
849 } },
850 { 5805, {
851 { 4, 18063, 5, 32514, },
852 { 4, 18094, 5, 32570, },
853 { 4, 18032, 5, 32458, },
854 } },
855 { 5825, {
856 { 4, 18001, 5, 32402, },
857 { 4, 18032, 5, 32458, },
858 { 4, 17970, 5, 32347, },
859 } },
860 { 5170, {
861 { 4, 20282, 4, 18254, },
862 { 4, 20321, 4, 18289, },
863 { 4, 20243, 4, 18219, },
864 } },
865 { 5190, {
866 { 4, 20204, 4, 18183, },
867 { 4, 20243, 4, 18219, },
868 { 4, 20165, 4, 18148, },
869 } },
870 { 5210, {
871 { 4, 20126, 4, 18114, },
872 { 4, 20165, 4, 18148, },
873 { 4, 20088, 4, 18079, },
874 } },
875 { 5230, {
876 { 4, 20049, 4, 18044, },
877 { 4, 20088, 4, 18079, },
878 { 4, 20011, 4, 18010, },
879 } },
880};
881
882static const struct ar9170_phy_freq_params *
883ar9170_get_hw_dyn_params(struct ieee80211_channel *channel,
884 enum ar9170_bw bw)
885{
886 unsigned int chanidx = 0;
887 u16 freq = 2412;
888
889 if (channel) {
890 chanidx = channel->hw_value;
891 freq = channel->center_freq;
892 }
893
894 BUG_ON(chanidx >= ARRAY_SIZE(ar9170_phy_freq_params));
895
896 BUILD_BUG_ON(__AR9170_NUM_BW != 3);
897
898 WARN_ON(ar9170_phy_freq_params[chanidx].freq != freq);
899
900 return &ar9170_phy_freq_params[chanidx].params[bw];
901}
902
903
904int ar9170_init_rf(struct ar9170 *ar)
905{
906 const struct ar9170_phy_freq_params *freqpar;
907 __le32 cmd[7];
908 int err;
909
910 err = ar9170_init_rf_banks_0_7(ar, false);
911 if (err)
912 return err;
913
914 err = ar9170_init_rf_bank4_pwr(ar, false, 2412, AR9170_BW_20);
915 if (err)
916 return err;
917
918 freqpar = ar9170_get_hw_dyn_params(NULL, AR9170_BW_20);
919
920 cmd[0] = cpu_to_le32(2412 * 1000);
921 cmd[1] = cpu_to_le32(0);
922 cmd[2] = cpu_to_le32(1);
923 cmd[3] = cpu_to_le32(freqpar->coeff_exp);
924 cmd[4] = cpu_to_le32(freqpar->coeff_man);
925 cmd[5] = cpu_to_le32(freqpar->coeff_exp_shgi);
926 cmd[6] = cpu_to_le32(freqpar->coeff_man_shgi);
927
928 /* RF_INIT echoes the command back to us */
929 err = ar->exec_cmd(ar, AR9170_CMD_RF_INIT,
930 sizeof(cmd), (u8 *)cmd,
931 sizeof(cmd), (u8 *)cmd);
932 if (err)
933 return err;
934
935 msleep(1000);
936
937 return ar9170_echo_test(ar, 0xaabbccdd);
938}
939
940static int ar9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f)
941{
942 int idx = nfreqs - 2;
943
944 while (idx >= 0) {
945 if (f >= freqs[idx])
946 return idx;
947 idx--;
948 }
949
950 return 0;
951}
952
953static s32 ar9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
954{
955 /* nothing to interpolate, it's horizontal */
956 if (y2 == y1)
957 return y1;
958
959 /* check if we hit one of the edges */
960 if (x == x1)
961 return y1;
962 if (x == x2)
963 return y2;
964
965 /* x1 == x2 is bad, hopefully == x */
966 if (x2 == x1)
967 return y1;
968
969 return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1));
970}
971
972static u8 ar9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2)
973{
974#define SHIFT 8
975 s32 y;
976
977 y = ar9170_interpolate_s32(x << SHIFT,
978 x1 << SHIFT, y1 << SHIFT,
979 x2 << SHIFT, y2 << SHIFT);
980
981 /*
982 * XXX: unwrap this expression
983 * Isn't it just DIV_ROUND_UP(y, 1<<SHIFT)?
984 * Can we rely on the compiler to optimise away the div?
985 */
986 return (y >> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1));
987#undef SHIFT
988}
989
990static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
991{
992 struct ar9170_calibration_target_power_legacy *ctpl;
993 struct ar9170_calibration_target_power_ht *ctph;
994 u8 *ctpres;
995 int ntargets;
996 int idx, i, n;
997 u8 ackpower, ackchains, f;
998 u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS];
999
1000 if (freq < 3000)
1001 f = freq - 2300;
1002 else
1003 f = (freq - 4800)/5;
1004
1005 /*
1006 * cycle through the various modes
1007 *
1008 * legacy modes first: 5G, 2G CCK, 2G OFDM
1009 */
1010 for (i = 0; i < 3; i++) {
1011 switch (i) {
1012 case 0: /* 5 GHz legacy */
1013 ctpl = &ar->eeprom.cal_tgt_pwr_5G[0];
1014 ntargets = AR5416_NUM_5G_TARGET_PWRS;
1015 ctpres = ar->power_5G_leg;
1016 break;
1017 case 1: /* 2.4 GHz CCK */
1018 ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0];
1019 ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS;
1020 ctpres = ar->power_2G_cck;
1021 break;
1022 case 2: /* 2.4 GHz OFDM */
1023 ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0];
1024 ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
1025 ctpres = ar->power_2G_ofdm;
1026 break;
1027 default:
1028 BUG();
1029 }
1030
1031 for (n = 0; n < ntargets; n++) {
1032 if (ctpl[n].freq == 0xff)
1033 break;
1034 pwr_freqs[n] = ctpl[n].freq;
1035 }
1036 ntargets = n;
1037 idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f);
1038 for (n = 0; n < 4; n++)
1039 ctpres[n] = ar9170_interpolate_u8(
1040 f,
1041 ctpl[idx + 0].freq,
1042 ctpl[idx + 0].power[n],
1043 ctpl[idx + 1].freq,
1044 ctpl[idx + 1].power[n]);
1045 }
1046
1047 /*
1048 * HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40
1049 */
1050 for (i = 0; i < 4; i++) {
1051 switch (i) {
1052 case 0: /* 5 GHz HT 20 */
1053 ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0];
1054 ntargets = AR5416_NUM_5G_TARGET_PWRS;
1055 ctpres = ar->power_5G_ht20;
1056 break;
1057 case 1: /* 5 GHz HT 40 */
1058 ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0];
1059 ntargets = AR5416_NUM_5G_TARGET_PWRS;
1060 ctpres = ar->power_5G_ht40;
1061 break;
1062 case 2: /* 2.4 GHz HT 20 */
1063 ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0];
1064 ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
1065 ctpres = ar->power_2G_ht20;
1066 break;
1067 case 3: /* 2.4 GHz HT 40 */
1068 ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0];
1069 ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
1070 ctpres = ar->power_2G_ht40;
1071 break;
1072 default:
1073 BUG();
1074 }
1075
1076 for (n = 0; n < ntargets; n++) {
1077 if (ctph[n].freq == 0xff)
1078 break;
1079 pwr_freqs[n] = ctph[n].freq;
1080 }
1081 ntargets = n;
1082 idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f);
1083 for (n = 0; n < 8; n++)
1084 ctpres[n] = ar9170_interpolate_u8(
1085 f,
1086 ctph[idx + 0].freq,
1087 ctph[idx + 0].power[n],
1088 ctph[idx + 1].freq,
1089 ctph[idx + 1].power[n]);
1090 }
1091
1092 /* set ACK/CTS TX power */
1093 ar9170_regwrite_begin(ar);
1094
1095 if (ar->eeprom.tx_mask != 1)
1096 ackchains = AR9170_TX_PHY_TXCHAIN_2;
1097 else
1098 ackchains = AR9170_TX_PHY_TXCHAIN_1;
1099
1100 if (freq < 3000)
1101 ackpower = ar->power_2G_ofdm[0] & 0x3f;
1102 else
1103 ackpower = ar->power_5G_leg[0] & 0x3f;
1104
1105 ar9170_regwrite(0x1c3694, ackpower << 20 | ackchains << 26);
1106 ar9170_regwrite(0x1c3bb4, ackpower << 5 | ackchains << 11 |
1107 ackpower << 21 | ackchains << 27);
1108
1109 ar9170_regwrite_finish();
1110 return ar9170_regwrite_result();
1111}
1112
1113static int ar9170_calc_noise_dbm(u32 raw_noise)
1114{
1115 if (raw_noise & 0x100)
1116 return ~((raw_noise & 0x0ff) >> 1);
1117 else
1118 return (raw_noise & 0xff) >> 1;
1119}
1120
1121int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
1122 enum ar9170_rf_init_mode rfi, enum ar9170_bw bw)
1123{
1124 const struct ar9170_phy_freq_params *freqpar;
1125 u32 cmd, tmp, offs;
1126 __le32 vals[8];
1127 int i, err;
1128 bool bandswitch;
1129
1130 /* clear BB heavy clip enable */
1131 err = ar9170_write_reg(ar, 0x1c59e0, 0x200);
1132 if (err)
1133 return err;
1134
1135 /* may be NULL at first setup */
1136 if (ar->channel)
1137 bandswitch = ar->channel->band != channel->band;
1138 else
1139 bandswitch = true;
1140
1141 /* HW workaround */
1142 if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] &&
1143 channel->center_freq <= 2417)
1144 bandswitch = true;
1145
1146 err = ar->exec_cmd(ar, AR9170_CMD_FREQ_START, 0, NULL, 0, NULL);
1147 if (err)
1148 return err;
1149
1150 if (rfi != AR9170_RFI_NONE || bandswitch) {
1151 u32 val = 0x400;
1152
1153 if (rfi == AR9170_RFI_COLD)
1154 val = 0x800;
1155
1156 /* warm/cold reset BB/ADDA */
1157 err = ar9170_write_reg(ar, 0x1d4004, val);
1158 if (err)
1159 return err;
1160
1161 err = ar9170_write_reg(ar, 0x1d4004, 0x0);
1162 if (err)
1163 return err;
1164
1165 err = ar9170_init_phy(ar, channel->band);
1166 if (err)
1167 return err;
1168
1169 err = ar9170_init_rf_banks_0_7(ar,
1170 channel->band == IEEE80211_BAND_5GHZ);
1171 if (err)
1172 return err;
1173
1174 cmd = AR9170_CMD_RF_INIT;
1175 } else {
1176 cmd = AR9170_CMD_FREQUENCY;
1177 }
1178
1179 err = ar9170_init_rf_bank4_pwr(ar,
1180 channel->band == IEEE80211_BAND_5GHZ,
1181 channel->center_freq, bw);
1182 if (err)
1183 return err;
1184
1185 switch (bw) {
1186 case AR9170_BW_20:
1187 tmp = 0x240;
1188 offs = 0;
1189 break;
1190 case AR9170_BW_40_BELOW:
1191 tmp = 0x2c4;
1192 offs = 3;
1193 break;
1194 case AR9170_BW_40_ABOVE:
1195 tmp = 0x2d4;
1196 offs = 1;
1197 break;
1198 default:
1199 BUG();
1200 return -ENOSYS;
1201 }
1202
1203 if (0 /* 2 streams capable */)
1204 tmp |= 0x100;
1205
1206 err = ar9170_write_reg(ar, 0x1c5804, tmp);
1207 if (err)
1208 return err;
1209
1210 err = ar9170_set_power_cal(ar, channel->center_freq, bw);
1211 if (err)
1212 return err;
1213
1214 freqpar = ar9170_get_hw_dyn_params(channel, bw);
1215
1216 vals[0] = cpu_to_le32(channel->center_freq * 1000);
1217 vals[1] = cpu_to_le32(bw == AR9170_BW_20 ? 0 : 1);
1218 vals[2] = cpu_to_le32(offs << 2 | 1);
1219 vals[3] = cpu_to_le32(freqpar->coeff_exp);
1220 vals[4] = cpu_to_le32(freqpar->coeff_man);
1221 vals[5] = cpu_to_le32(freqpar->coeff_exp_shgi);
1222 vals[6] = cpu_to_le32(freqpar->coeff_man_shgi);
1223 vals[7] = cpu_to_le32(1000);
1224
1225 err = ar->exec_cmd(ar, cmd, sizeof(vals), (u8 *)vals,
1226 sizeof(vals), (u8 *)vals);
1227 if (err)
1228 return err;
1229
1230 for (i = 0; i < 2; i++) {
1231 ar->noise[i] = ar9170_calc_noise_dbm(
1232 (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff);
1233
1234 ar->noise[i + 2] = ar9170_calc_noise_dbm(
1235 (le32_to_cpu(vals[5 + i]) >> 23) & 0x1ff);
1236 }
1237
1238 ar->channel = channel;
1239 return 0;
1240}
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
new file mode 100644
index 000000000000..fddda477095c
--- /dev/null
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -0,0 +1,822 @@
1/*
2 * Atheros AR9170 driver
3 *
4 * USB - frontend
5 *
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7 * Copyright 2009, Christian Lamparter <chunkeey@web.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; see the file COPYING. If not, see
21 * http://www.gnu.org/licenses/.
22 *
23 * This file incorporates work covered by the following copyright and
24 * permission notice:
25 * Copyright (c) 2007-2008 Atheros Communications, Inc.
26 *
27 * Permission to use, copy, modify, and/or distribute this software for any
28 * purpose with or without fee is hereby granted, provided that the above
29 * copyright notice and this permission notice appear in all copies.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
32 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
33 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
34 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
35 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
36 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
37 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
38 */
39
40#include <linux/module.h>
41#include <linux/usb.h>
42#include <linux/firmware.h>
43#include <linux/etherdevice.h>
44#include <net/mac80211.h>
45#include "ar9170.h"
46#include "cmd.h"
47#include "hw.h"
48#include "usb.h"
49
50MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
51MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>");
52MODULE_LICENSE("GPL");
53MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless");
54MODULE_FIRMWARE("ar9170-1.fw");
55MODULE_FIRMWARE("ar9170-2.fw");
56
57static struct usb_device_id ar9170_usb_ids[] = {
58 /* Atheros 9170 */
59 { USB_DEVICE(0x0cf3, 0x9170) },
60 /* Atheros TG121N */
61 { USB_DEVICE(0x0cf3, 0x1001) },
62 /* Cace Airpcap NX */
63 { USB_DEVICE(0xcace, 0x0300) },
64 /* D-Link DWA 160A */
65 { USB_DEVICE(0x07d1, 0x3c10) },
66 /* Netgear WNDA3100 */
67 { USB_DEVICE(0x0846, 0x9010) },
68 /* Netgear WN111 v2 */
69 { USB_DEVICE(0x0846, 0x9001) },
70 /* Zydas ZD1221 */
71 { USB_DEVICE(0x0ace, 0x1221) },
72 /* ZyXEL NWD271N */
73 { USB_DEVICE(0x0586, 0x3417) },
74 /* Z-Com UB81 BG */
75 { USB_DEVICE(0x0cde, 0x0023) },
76 /* Z-Com UB82 ABG */
77 { USB_DEVICE(0x0cde, 0x0026) },
78 /* Arcadyan WN7512 */
79 { USB_DEVICE(0x083a, 0xf522) },
80 /* Planex GWUS300 */
81 { USB_DEVICE(0x2019, 0x5304) },
82 /* IO-Data WNGDNUS2 */
83 { USB_DEVICE(0x04bb, 0x093f) },
84
85 /* terminate */
86 {}
87};
88MODULE_DEVICE_TABLE(usb, ar9170_usb_ids);
89
90static void ar9170_usb_tx_urb_complete_free(struct urb *urb)
91{
92 struct sk_buff *skb = urb->context;
93 struct ar9170_usb *aru = (struct ar9170_usb *)
94 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
95
96 if (!aru) {
97 dev_kfree_skb_irq(skb);
98 return ;
99 }
100
101 ar9170_handle_tx_status(&aru->common, skb, false,
102 AR9170_TX_STATUS_COMPLETE);
103}
104
105static void ar9170_usb_tx_urb_complete(struct urb *urb)
106{
107}
108
109static void ar9170_usb_irq_completed(struct urb *urb)
110{
111 struct ar9170_usb *aru = urb->context;
112
113 switch (urb->status) {
114 /* everything is fine */
115 case 0:
116 break;
117
118 /* disconnect */
119 case -ENOENT:
120 case -ECONNRESET:
121 case -ENODEV:
122 case -ESHUTDOWN:
123 goto free;
124
125 default:
126 goto resubmit;
127 }
128
129 print_hex_dump_bytes("ar9170 irq: ", DUMP_PREFIX_OFFSET,
130 urb->transfer_buffer, urb->actual_length);
131
132resubmit:
133 usb_anchor_urb(urb, &aru->rx_submitted);
134 if (usb_submit_urb(urb, GFP_ATOMIC)) {
135 usb_unanchor_urb(urb);
136 goto free;
137 }
138
139 return;
140
141free:
142 usb_buffer_free(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma);
143}
144
145static void ar9170_usb_rx_completed(struct urb *urb)
146{
147 struct sk_buff *skb = urb->context;
148 struct ar9170_usb *aru = (struct ar9170_usb *)
149 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
150 int err;
151
152 if (!aru)
153 goto free;
154
155 switch (urb->status) {
156 /* everything is fine */
157 case 0:
158 break;
159
160 /* disconnect */
161 case -ENOENT:
162 case -ECONNRESET:
163 case -ENODEV:
164 case -ESHUTDOWN:
165 goto free;
166
167 default:
168 goto resubmit;
169 }
170
171 skb_put(skb, urb->actual_length);
172 ar9170_rx(&aru->common, skb);
173
174resubmit:
175 skb_reset_tail_pointer(skb);
176 skb_trim(skb, 0);
177
178 usb_anchor_urb(urb, &aru->rx_submitted);
179 err = usb_submit_urb(urb, GFP_ATOMIC);
180 if (err) {
181 usb_unanchor_urb(urb);
182 dev_kfree_skb_irq(skb);
183 }
184
185 return ;
186
187free:
188 dev_kfree_skb_irq(skb);
189 return;
190}
191
192static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru,
193 struct urb *urb, gfp_t gfp)
194{
195 struct sk_buff *skb;
196
197 skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE + 32, gfp);
198 if (!skb)
199 return -ENOMEM;
200
201 /* reserve some space for mac80211's radiotap */
202 skb_reserve(skb, 32);
203
204 usb_fill_bulk_urb(urb, aru->udev,
205 usb_rcvbulkpipe(aru->udev, AR9170_EP_RX),
206 skb->data, min(skb_tailroom(skb),
207 AR9170_MAX_RX_BUFFER_SIZE),
208 ar9170_usb_rx_completed, skb);
209
210 return 0;
211}
212
213static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru)
214{
215 struct urb *urb = NULL;
216 void *ibuf;
217 int err = -ENOMEM;
218
219 /* initialize interrupt endpoint */
220 urb = usb_alloc_urb(0, GFP_KERNEL);
221 if (!urb)
222 goto out;
223
224 ibuf = usb_buffer_alloc(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma);
225 if (!ibuf)
226 goto out;
227
228 usb_fill_int_urb(urb, aru->udev,
229 usb_rcvintpipe(aru->udev, AR9170_EP_IRQ), ibuf,
230 64, ar9170_usb_irq_completed, aru, 1);
231 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
232
233 usb_anchor_urb(urb, &aru->rx_submitted);
234 err = usb_submit_urb(urb, GFP_KERNEL);
235 if (err) {
236 usb_unanchor_urb(urb);
237 usb_buffer_free(aru->udev, 64, urb->transfer_buffer,
238 urb->transfer_dma);
239 }
240
241out:
242 usb_free_urb(urb);
243 return err;
244}
245
246static int ar9170_usb_alloc_rx_bulk_urbs(struct ar9170_usb *aru)
247{
248 struct urb *urb;
249 int i;
250 int err = -EINVAL;
251
252 for (i = 0; i < AR9170_NUM_RX_URBS; i++) {
253 err = -ENOMEM;
254 urb = usb_alloc_urb(0, GFP_KERNEL);
255 if (!urb)
256 goto err_out;
257
258 err = ar9170_usb_prep_rx_urb(aru, urb, GFP_KERNEL);
259 if (err) {
260 usb_free_urb(urb);
261 goto err_out;
262 }
263
264 usb_anchor_urb(urb, &aru->rx_submitted);
265 err = usb_submit_urb(urb, GFP_KERNEL);
266 if (err) {
267 usb_unanchor_urb(urb);
268 dev_kfree_skb_any((void *) urb->transfer_buffer);
269 usb_free_urb(urb);
270 goto err_out;
271 }
272 usb_free_urb(urb);
273 }
274
275 /* the device now waiting for a firmware. */
276 aru->common.state = AR9170_IDLE;
277 return 0;
278
279err_out:
280
281 usb_kill_anchored_urbs(&aru->rx_submitted);
282 return err;
283}
284
285static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru)
286{
287 int ret;
288
289 aru->common.state = AR9170_UNKNOWN_STATE;
290
291 usb_unlink_anchored_urbs(&aru->tx_submitted);
292
293 /* give the LED OFF command and the deauth frame a chance to air. */
294 ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted,
295 msecs_to_jiffies(100));
296 if (ret == 0)
297 dev_err(&aru->udev->dev, "kill pending tx urbs.\n");
298 usb_poison_anchored_urbs(&aru->tx_submitted);
299
300 usb_poison_anchored_urbs(&aru->rx_submitted);
301}
302
303static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd,
304 unsigned int plen, void *payload,
305 unsigned int outlen, void *out)
306{
307 struct ar9170_usb *aru = (void *) ar;
308 struct urb *urb = NULL;
309 unsigned long flags;
310 int err = -ENOMEM;
311
312 if (unlikely(!IS_ACCEPTING_CMD(ar)))
313 return -EPERM;
314
315 if (WARN_ON(plen > AR9170_MAX_CMD_LEN - 4))
316 return -EINVAL;
317
318 urb = usb_alloc_urb(0, GFP_ATOMIC);
319 if (unlikely(!urb))
320 goto err_free;
321
322 ar->cmdbuf[0] = cpu_to_le32(plen);
323 ar->cmdbuf[0] |= cpu_to_le32(cmd << 8);
324 /* writing multiple regs fills this buffer already */
325 if (plen && payload != (u8 *)(&ar->cmdbuf[1]))
326 memcpy(&ar->cmdbuf[1], payload, plen);
327
328 spin_lock_irqsave(&aru->common.cmdlock, flags);
329 aru->readbuf = (u8 *)out;
330 aru->readlen = outlen;
331 spin_unlock_irqrestore(&aru->common.cmdlock, flags);
332
333 usb_fill_int_urb(urb, aru->udev,
334 usb_sndbulkpipe(aru->udev, AR9170_EP_CMD),
335 aru->common.cmdbuf, plen + 4,
336 ar9170_usb_tx_urb_complete, NULL, 1);
337
338 usb_anchor_urb(urb, &aru->tx_submitted);
339 err = usb_submit_urb(urb, GFP_ATOMIC);
340 if (err) {
341 usb_unanchor_urb(urb);
342 usb_free_urb(urb);
343 goto err_unbuf;
344 }
345 usb_free_urb(urb);
346
347 err = wait_for_completion_timeout(&aru->cmd_wait, HZ);
348 if (err == 0) {
349 err = -ETIMEDOUT;
350 goto err_unbuf;
351 }
352
353 if (outlen >= 0 && aru->readlen != outlen) {
354 err = -EMSGSIZE;
355 goto err_unbuf;
356 }
357
358 return 0;
359
360err_unbuf:
361 /* Maybe the device was removed in the second we were waiting? */
362 if (IS_STARTED(ar)) {
363 dev_err(&aru->udev->dev, "no command feedback "
364 "received (%d).\n", err);
365
366 /* provide some maybe useful debug information */
367 print_hex_dump_bytes("ar9170 cmd: ", DUMP_PREFIX_NONE,
368 aru->common.cmdbuf, plen + 4);
369 dump_stack();
370 }
371
372 /* invalidate to avoid completing the next prematurely */
373 spin_lock_irqsave(&aru->common.cmdlock, flags);
374 aru->readbuf = NULL;
375 aru->readlen = 0;
376 spin_unlock_irqrestore(&aru->common.cmdlock, flags);
377
378err_free:
379
380 return err;
381}
382
383static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb,
384 bool txstatus_needed, unsigned int extra_len)
385{
386 struct ar9170_usb *aru = (struct ar9170_usb *) ar;
387 struct urb *urb;
388 int err;
389
390 if (unlikely(!IS_STARTED(ar))) {
391 /* Seriously, what were you drink... err... thinking!? */
392 return -EPERM;
393 }
394
395 urb = usb_alloc_urb(0, GFP_ATOMIC);
396 if (unlikely(!urb))
397 return -ENOMEM;
398
399 usb_fill_bulk_urb(urb, aru->udev,
400 usb_sndbulkpipe(aru->udev, AR9170_EP_TX),
401 skb->data, skb->len + extra_len, (txstatus_needed ?
402 ar9170_usb_tx_urb_complete :
403 ar9170_usb_tx_urb_complete_free), skb);
404 urb->transfer_flags |= URB_ZERO_PACKET;
405
406 usb_anchor_urb(urb, &aru->tx_submitted);
407 err = usb_submit_urb(urb, GFP_ATOMIC);
408 if (unlikely(err))
409 usb_unanchor_urb(urb);
410
411 usb_free_urb(urb);
412 return err;
413}
414
415static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer)
416{
417 struct ar9170_usb *aru = (void *) ar;
418 unsigned long flags;
419 u32 in, out;
420
421 if (!buffer)
422 return ;
423
424 in = le32_to_cpup((__le32 *)buffer);
425 out = le32_to_cpu(ar->cmdbuf[0]);
426
427 /* mask off length byte */
428 out &= ~0xFF;
429
430 if (aru->readlen >= 0) {
431 /* add expected length */
432 out |= aru->readlen;
433 } else {
434 /* add obtained length */
435 out |= in & 0xFF;
436 }
437
438 /*
439 * Some commands (e.g: AR9170_CMD_FREQUENCY) have a variable response
440 * length and we cannot predict the correct length in advance.
441 * So we only check if we provided enough space for the data.
442 */
443 if (unlikely(out < in)) {
444 dev_warn(&aru->udev->dev, "received invalid command response "
445 "got %d bytes, instead of %d bytes "
446 "and the resp length is %d bytes\n",
447 in, out, len);
448 print_hex_dump_bytes("ar9170 invalid resp: ",
449 DUMP_PREFIX_OFFSET, buffer, len);
450 /*
451 * Do not complete, then the command times out,
452 * and we get a stack trace from there.
453 */
454 return ;
455 }
456
457 spin_lock_irqsave(&aru->common.cmdlock, flags);
458 if (aru->readbuf && len > 0) {
459 memcpy(aru->readbuf, buffer + 4, len - 4);
460 aru->readbuf = NULL;
461 }
462 complete(&aru->cmd_wait);
463 spin_unlock_irqrestore(&aru->common.cmdlock, flags);
464}
465
466static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data,
467 size_t len, u32 addr, bool complete)
468{
469 int transfer, err;
470 u8 *buf = kmalloc(4096, GFP_KERNEL);
471
472 if (!buf)
473 return -ENOMEM;
474
475 while (len) {
476 transfer = min_t(int, len, 4096);
477 memcpy(buf, data, transfer);
478
479 err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0),
480 0x30 /* FW DL */, 0x40 | USB_DIR_OUT,
481 addr >> 8, 0, buf, transfer, 1000);
482
483 if (err < 0) {
484 kfree(buf);
485 return err;
486 }
487
488 len -= transfer;
489 data += transfer;
490 addr += transfer;
491 }
492 kfree(buf);
493
494 if (complete) {
495 err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0),
496 0x31 /* FW DL COMPLETE */,
497 0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 5000);
498 }
499
500 return 0;
501}
502
503static int ar9170_usb_request_firmware(struct ar9170_usb *aru)
504{
505 int err = 0;
506
507 err = request_firmware(&aru->init_values, "ar9170-1.fw",
508 &aru->udev->dev);
509 if (err) {
510 dev_err(&aru->udev->dev, "file with init values not found.\n");
511 return err;
512 }
513
514 err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev);
515 if (err) {
516 release_firmware(aru->init_values);
517 dev_err(&aru->udev->dev, "firmware file not found.\n");
518 return err;
519 }
520
521 return err;
522}
523
524static int ar9170_usb_reset(struct ar9170_usb *aru)
525{
526 int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING);
527
528 if (lock) {
529 ret = usb_lock_device_for_reset(aru->udev, aru->intf);
530 if (ret < 0) {
531 dev_err(&aru->udev->dev, "unable to lock device "
532 "for reset (%d).\n", ret);
533 return ret;
534 }
535 }
536
537 ret = usb_reset_device(aru->udev);
538 if (lock)
539 usb_unlock_device(aru->udev);
540
541 /* let it rest - for a second - */
542 msleep(1000);
543
544 return ret;
545}
546
547static int ar9170_usb_upload_firmware(struct ar9170_usb *aru)
548{
549 int err;
550
551 /* First, upload initial values to device RAM */
552 err = ar9170_usb_upload(aru, aru->init_values->data,
553 aru->init_values->size, 0x102800, false);
554 if (err) {
555 dev_err(&aru->udev->dev, "firmware part 1 "
556 "upload failed (%d).\n", err);
557 return err;
558 }
559
560 /* Then, upload the firmware itself and start it */
561 return ar9170_usb_upload(aru, aru->firmware->data, aru->firmware->size,
562 0x200000, true);
563}
564
565static int ar9170_usb_init_transport(struct ar9170_usb *aru)
566{
567 struct ar9170 *ar = (void *) &aru->common;
568 int err;
569
570 ar9170_regwrite_begin(ar);
571
572 /* Set USB Rx stream mode MAX packet number to 2 */
573 ar9170_regwrite(AR9170_USB_REG_MAX_AGG_UPLOAD, 0x4);
574
575 /* Set USB Rx stream mode timeout to 10us */
576 ar9170_regwrite(AR9170_USB_REG_UPLOAD_TIME_CTL, 0x80);
577
578 ar9170_regwrite_finish();
579
580 err = ar9170_regwrite_result();
581 if (err)
582 dev_err(&aru->udev->dev, "USB setup failed (%d).\n", err);
583
584 return err;
585}
586
587static void ar9170_usb_stop(struct ar9170 *ar)
588{
589 struct ar9170_usb *aru = (void *) ar;
590 int ret;
591
592 if (IS_ACCEPTING_CMD(ar))
593 aru->common.state = AR9170_STOPPED;
594
595 /* lets wait a while until the tx - queues are dried out */
596 ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted,
597 msecs_to_jiffies(1000));
598 if (ret == 0)
599 dev_err(&aru->udev->dev, "kill pending tx urbs.\n");
600
601 usb_poison_anchored_urbs(&aru->tx_submitted);
602
603 /*
604 * Note:
605 * So far we freed all tx urbs, but we won't dare to touch any rx urbs.
606 * Else we would end up with a unresponsive device...
607 */
608}
609
610static int ar9170_usb_open(struct ar9170 *ar)
611{
612 struct ar9170_usb *aru = (void *) ar;
613 int err;
614
615 usb_unpoison_anchored_urbs(&aru->tx_submitted);
616 err = ar9170_usb_init_transport(aru);
617 if (err) {
618 usb_poison_anchored_urbs(&aru->tx_submitted);
619 return err;
620 }
621
622 aru->common.state = AR9170_IDLE;
623 return 0;
624}
625
626static int ar9170_usb_init_device(struct ar9170_usb *aru)
627{
628 int err;
629
630 err = ar9170_usb_alloc_rx_irq_urb(aru);
631 if (err)
632 goto err_out;
633
634 err = ar9170_usb_alloc_rx_bulk_urbs(aru);
635 if (err)
636 goto err_unrx;
637
638 err = ar9170_usb_upload_firmware(aru);
639 if (err) {
640 err = ar9170_echo_test(&aru->common, 0x60d43110);
641 if (err) {
642 /* force user invention, by disabling the device */
643 err = usb_driver_set_configuration(aru->udev, -1);
644 dev_err(&aru->udev->dev, "device is in a bad state. "
645 "please reconnect it!\n");
646 goto err_unrx;
647 }
648 }
649
650 return 0;
651
652err_unrx:
653 ar9170_usb_cancel_urbs(aru);
654
655err_out:
656 return err;
657}
658
659static int ar9170_usb_probe(struct usb_interface *intf,
660 const struct usb_device_id *id)
661{
662 struct ar9170_usb *aru;
663 struct ar9170 *ar;
664 struct usb_device *udev;
665 int err;
666
667 aru = ar9170_alloc(sizeof(*aru));
668 if (IS_ERR(aru)) {
669 err = PTR_ERR(aru);
670 goto out;
671 }
672
673 udev = interface_to_usbdev(intf);
674 usb_get_dev(udev);
675 aru->udev = udev;
676 aru->intf = intf;
677 ar = &aru->common;
678
679 usb_set_intfdata(intf, aru);
680 SET_IEEE80211_DEV(ar->hw, &udev->dev);
681
682 init_usb_anchor(&aru->rx_submitted);
683 init_usb_anchor(&aru->tx_submitted);
684 init_completion(&aru->cmd_wait);
685
686 aru->common.stop = ar9170_usb_stop;
687 aru->common.open = ar9170_usb_open;
688 aru->common.tx = ar9170_usb_tx;
689 aru->common.exec_cmd = ar9170_usb_exec_cmd;
690 aru->common.callback_cmd = ar9170_usb_callback_cmd;
691
692 err = ar9170_usb_reset(aru);
693 if (err)
694 goto err_freehw;
695
696 err = ar9170_usb_request_firmware(aru);
697 if (err)
698 goto err_freehw;
699
700 err = ar9170_usb_init_device(aru);
701 if (err)
702 goto err_freefw;
703
704 err = ar9170_usb_open(ar);
705 if (err)
706 goto err_unrx;
707
708 err = ar9170_register(ar, &udev->dev);
709
710 ar9170_usb_stop(ar);
711 if (err)
712 goto err_unrx;
713
714 return 0;
715
716err_unrx:
717 ar9170_usb_cancel_urbs(aru);
718
719err_freefw:
720 release_firmware(aru->init_values);
721 release_firmware(aru->firmware);
722
723err_freehw:
724 usb_set_intfdata(intf, NULL);
725 usb_put_dev(udev);
726 ieee80211_free_hw(ar->hw);
727out:
728 return err;
729}
730
731static void ar9170_usb_disconnect(struct usb_interface *intf)
732{
733 struct ar9170_usb *aru = usb_get_intfdata(intf);
734
735 if (!aru)
736 return;
737
738 aru->common.state = AR9170_IDLE;
739 ar9170_unregister(&aru->common);
740 ar9170_usb_cancel_urbs(aru);
741
742 release_firmware(aru->init_values);
743 release_firmware(aru->firmware);
744
745 usb_put_dev(aru->udev);
746 usb_set_intfdata(intf, NULL);
747 ieee80211_free_hw(aru->common.hw);
748}
749
750#ifdef CONFIG_PM
751static int ar9170_suspend(struct usb_interface *intf,
752 pm_message_t message)
753{
754 struct ar9170_usb *aru = usb_get_intfdata(intf);
755
756 if (!aru)
757 return -ENODEV;
758
759 aru->common.state = AR9170_IDLE;
760 ar9170_usb_cancel_urbs(aru);
761
762 return 0;
763}
764
765static int ar9170_resume(struct usb_interface *intf)
766{
767 struct ar9170_usb *aru = usb_get_intfdata(intf);
768 int err;
769
770 if (!aru)
771 return -ENODEV;
772
773 usb_unpoison_anchored_urbs(&aru->rx_submitted);
774 usb_unpoison_anchored_urbs(&aru->tx_submitted);
775
776 /*
777 * FIXME: firmware upload will fail on resume.
778 * but this is better than a hang!
779 */
780
781 err = ar9170_usb_init_device(aru);
782 if (err)
783 goto err_unrx;
784
785 err = ar9170_usb_open(&aru->common);
786 if (err)
787 goto err_unrx;
788
789 return 0;
790
791err_unrx:
792 aru->common.state = AR9170_IDLE;
793 ar9170_usb_cancel_urbs(aru);
794
795 return err;
796}
797#endif /* CONFIG_PM */
798
799static struct usb_driver ar9170_driver = {
800 .name = "ar9170usb",
801 .probe = ar9170_usb_probe,
802 .disconnect = ar9170_usb_disconnect,
803 .id_table = ar9170_usb_ids,
804 .soft_unbind = 1,
805#ifdef CONFIG_PM
806 .suspend = ar9170_suspend,
807 .resume = ar9170_resume,
808#endif /* CONFIG_PM */
809};
810
811static int __init ar9170_init(void)
812{
813 return usb_register(&ar9170_driver);
814}
815
816static void __exit ar9170_exit(void)
817{
818 usb_deregister(&ar9170_driver);
819}
820
821module_init(ar9170_init);
822module_exit(ar9170_exit);
diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h
new file mode 100644
index 000000000000..f5852924cd64
--- /dev/null
+++ b/drivers/net/wireless/ath/ar9170/usb.h
@@ -0,0 +1,74 @@
1/*
2 * Atheros AR9170 USB driver
3 *
4 * Driver specific definitions
5 *
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7 * Copyright 2009, Christian Lamparter <chunkeey@web.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; see the file COPYING. If not, see
21 * http://www.gnu.org/licenses/.
22 *
23 * This file incorporates work covered by the following copyright and
24 * permission notice:
25 * Copyright (c) 2007-2008 Atheros Communications, Inc.
26 *
27 * Permission to use, copy, modify, and/or distribute this software for any
28 * purpose with or without fee is hereby granted, provided that the above
29 * copyright notice and this permission notice appear in all copies.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
32 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
33 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
34 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
35 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
36 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
37 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
38 */
39#ifndef __USB_H
40#define __USB_H
41
42#include <linux/usb.h>
43#include <linux/completion.h>
44#include <linux/spinlock.h>
45#include <linux/leds.h>
46#include <net/wireless.h>
47#include <net/mac80211.h>
48#include <linux/firmware.h>
49#include "eeprom.h"
50#include "hw.h"
51#include "ar9170.h"
52
53#define AR9170_NUM_RX_URBS 16
54
55struct firmware;
56
57struct ar9170_usb {
58 struct ar9170 common;
59 struct usb_device *udev;
60 struct usb_interface *intf;
61
62 struct usb_anchor rx_submitted;
63 struct usb_anchor tx_submitted;
64
65 spinlock_t cmdlock;
66 struct completion cmd_wait;
67 int readlen;
68 u8 *readbuf;
69
70 const struct firmware *init_values;
71 const struct firmware *firmware;
72};
73
74#endif /* __USB_H */
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig
new file mode 100644
index 000000000000..509b6f94f73b
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
@@ -0,0 +1,41 @@
1config ATH5K
2 tristate "Atheros 5xxx wireless cards support"
3 depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
4 select ATH_COMMON
5 select MAC80211_LEDS
6 select LEDS_CLASS
7 select NEW_LEDS
8 ---help---
9 This module adds support for wireless adapters based on
10 Atheros 5xxx chipset.
11
12 Currently the following chip versions are supported:
13
14 MAC: AR5211 AR5212
15 PHY: RF5111/2111 RF5112/2112 RF5413/2413
16
17 This driver uses the kernel's mac80211 subsystem.
18
19 If you choose to build a module, it'll be called ath5k. Say M if
20 unsure.
21
22config ATH5K_DEBUG
23 bool "Atheros 5xxx debugging"
24 depends on ATH5K
25 ---help---
26 Atheros 5xxx debugging messages.
27
28 Say Y, if and you will get debug options for ath5k.
29 To use this, you need to mount debugfs:
30
31 mkdir /debug/
32 mount -t debugfs debug /debug/
33
34 You will get access to files under:
35 /debug/ath5k/phy0/
36
37 To enable debug, pass the debug level to the debug module
38 parameter. For example:
39
40 modprobe ath5k debug=0x00000400
41
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile
new file mode 100644
index 000000000000..84a74c5248e5
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/Makefile
@@ -0,0 +1,15 @@
1ath5k-y += caps.o
2ath5k-y += initvals.o
3ath5k-y += eeprom.o
4ath5k-y += gpio.o
5ath5k-y += desc.o
6ath5k-y += dma.o
7ath5k-y += qcu.o
8ath5k-y += pcu.o
9ath5k-y += phy.o
10ath5k-y += reset.o
11ath5k-y += attach.o
12ath5k-y += base.o
13ath5k-y += led.o
14ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o
15obj-$(CONFIG_ATH5K) += ath5k.o
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
new file mode 100644
index 000000000000..60c6d2edc4b9
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -0,0 +1,1354 @@
1/*
2 * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#ifndef _ATH5K_H
19#define _ATH5K_H
20
21/* TODO: Clean up channel debuging -doesn't work anyway- and start
22 * working on reg. control code using all available eeprom information
23 * -rev. engineering needed- */
24#define CHAN_DEBUG 0
25
26#include <linux/io.h>
27#include <linux/types.h>
28#include <net/mac80211.h>
29
30#include "../regd.h"
31
32/* RX/TX descriptor hw structs
33 * TODO: Driver part should only see sw structs */
34#include "desc.h"
35
36/* EEPROM structs/offsets
37 * TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities)
38 * and clean up common bits, then introduce set/get functions in eeprom.c */
39#include "eeprom.h"
40
41/* PCI IDs */
42#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */
43#define PCI_DEVICE_ID_ATHEROS_AR5311 0x0011 /* AR5311 */
44#define PCI_DEVICE_ID_ATHEROS_AR5211 0x0012 /* AR5211 */
45#define PCI_DEVICE_ID_ATHEROS_AR5212 0x0013 /* AR5212 */
46#define PCI_DEVICE_ID_3COM_3CRDAG675 0x0013 /* 3CRDAG675 (Atheros AR5212) */
47#define PCI_DEVICE_ID_3COM_2_3CRPAG175 0x0013 /* 3CRPAG175 (Atheros AR5212) */
48#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 0x0207 /* AR5210 (Early) */
49#define PCI_DEVICE_ID_ATHEROS_AR5212_IBM 0x1014 /* AR5212 (IBM MiniPCI) */
50#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 0x1107 /* AR5210 (no eeprom) */
51#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 0x1113 /* AR5212 (no eeprom) */
52#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 0x1112 /* AR5211 (no eeprom) */
53#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 0xf013 /* AR5212 (emulation board) */
54#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 0xff12 /* AR5211 (emulation board) */
55#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 0xf11b /* AR5211 (emulation board) */
56#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
57#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
58#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 0x0058 /* AR5312 WMAC (AP43-030) */
59#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 0x0014 /* AR5212 compatible */
60#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 0x0015 /* AR5212 compatible */
61#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 0x0016 /* AR5212 compatible */
62#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 0x0017 /* AR5212 compatible */
63#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 0x0018 /* AR5212 compatible */
64#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 0x0019 /* AR5212 compatible */
65#define PCI_DEVICE_ID_ATHEROS_AR2413 0x001a /* AR2413 (Griffin-lite) */
66#define PCI_DEVICE_ID_ATHEROS_AR5413 0x001b /* AR5413 (Eagle) */
67#define PCI_DEVICE_ID_ATHEROS_AR5424 0x001c /* AR5424 (Condor PCI-E) */
68#define PCI_DEVICE_ID_ATHEROS_AR5416 0x0023 /* AR5416 */
69#define PCI_DEVICE_ID_ATHEROS_AR5418 0x0024 /* AR5418 */
70
71/****************************\
72 GENERIC DRIVER DEFINITIONS
73\****************************/
74
75#define ATH5K_PRINTF(fmt, ...) printk("%s: " fmt, __func__, ##__VA_ARGS__)
76
77#define ATH5K_PRINTK(_sc, _level, _fmt, ...) \
78 printk(_level "ath5k %s: " _fmt, \
79 ((_sc) && (_sc)->hw) ? wiphy_name((_sc)->hw->wiphy) : "", \
80 ##__VA_ARGS__)
81
82#define ATH5K_PRINTK_LIMIT(_sc, _level, _fmt, ...) do { \
83 if (net_ratelimit()) \
84 ATH5K_PRINTK(_sc, _level, _fmt, ##__VA_ARGS__); \
85 } while (0)
86
87#define ATH5K_INFO(_sc, _fmt, ...) \
88 ATH5K_PRINTK(_sc, KERN_INFO, _fmt, ##__VA_ARGS__)
89
90#define ATH5K_WARN(_sc, _fmt, ...) \
91 ATH5K_PRINTK_LIMIT(_sc, KERN_WARNING, _fmt, ##__VA_ARGS__)
92
93#define ATH5K_ERR(_sc, _fmt, ...) \
94 ATH5K_PRINTK_LIMIT(_sc, KERN_ERR, _fmt, ##__VA_ARGS__)
95
96/*
97 * AR5K REGISTER ACCESS
98 */
99
100/* Some macros to read/write fields */
101
102/* First shift, then mask */
103#define AR5K_REG_SM(_val, _flags) \
104 (((_val) << _flags##_S) & (_flags))
105
106/* First mask, then shift */
107#define AR5K_REG_MS(_val, _flags) \
108 (((_val) & (_flags)) >> _flags##_S)
109
110/* Some registers can hold multiple values of interest. For this
111 * reason when we want to write to these registers we must first
112 * retrieve the values which we do not want to clear (lets call this
113 * old_data) and then set the register with this and our new_value:
114 * ( old_data | new_value) */
115#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val) \
116 ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \
117 (((_val) << _flags##_S) & (_flags)), _reg)
118
119#define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask) \
120 ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & \
121 (_mask)) | (_flags), _reg)
122
123#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags) \
124 ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg)
125
126#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \
127 ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg)
128
129/* Access to PHY registers */
130#define AR5K_PHY_READ(ah, _reg) \
131 ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2))
132
133#define AR5K_PHY_WRITE(ah, _reg, _val) \
134 ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2))
135
136/* Access QCU registers per queue */
137#define AR5K_REG_READ_Q(ah, _reg, _queue) \
138 (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \
139
140#define AR5K_REG_WRITE_Q(ah, _reg, _queue) \
141 ath5k_hw_reg_write(ah, (1 << _queue), _reg)
142
143#define AR5K_Q_ENABLE_BITS(_reg, _queue) do { \
144 _reg |= 1 << _queue; \
145} while (0)
146
147#define AR5K_Q_DISABLE_BITS(_reg, _queue) do { \
148 _reg &= ~(1 << _queue); \
149} while (0)
150
151/* Used while writing initvals */
152#define AR5K_REG_WAIT(_i) do { \
153 if (_i % 64) \
154 udelay(1); \
155} while (0)
156
157/* Register dumps are done per operation mode */
158#define AR5K_INI_RFGAIN_5GHZ 0
159#define AR5K_INI_RFGAIN_2GHZ 1
160
161/* TODO: Clean this up */
162#define AR5K_INI_VAL_11A 0
163#define AR5K_INI_VAL_11A_TURBO 1
164#define AR5K_INI_VAL_11B 2
165#define AR5K_INI_VAL_11G 3
166#define AR5K_INI_VAL_11G_TURBO 4
167#define AR5K_INI_VAL_XR 0
168#define AR5K_INI_VAL_MAX 5
169
170/* Used for BSSID etc manipulation */
171#define AR5K_LOW_ID(_a)( \
172(_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \
173)
174
175#define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8)
176
177/*
178 * Some tuneable values (these should be changeable by the user)
179 * TODO: Make use of them and add more options OR use debug/configfs
180 */
181#define AR5K_TUNE_DMA_BEACON_RESP 2
182#define AR5K_TUNE_SW_BEACON_RESP 10
183#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0
184#define AR5K_TUNE_RADAR_ALERT false
185#define AR5K_TUNE_MIN_TX_FIFO_THRES 1
186#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_LEN / 64) + 1)
187#define AR5K_TUNE_REGISTER_TIMEOUT 20000
188/* Register for RSSI threshold has a mask of 0xff, so 255 seems to
189 * be the max value. */
190#define AR5K_TUNE_RSSI_THRES 129
191/* This must be set when setting the RSSI threshold otherwise it can
192 * prevent a reset. If AR5K_RSSI_THR is read after writing to it
193 * the BMISS_THRES will be seen as 0, seems harware doesn't keep
194 * track of it. Max value depends on harware. For AR5210 this is just 7.
195 * For AR5211+ this seems to be up to 255. */
196#define AR5K_TUNE_BMISS_THRES 7
197#define AR5K_TUNE_REGISTER_DWELL_TIME 20000
198#define AR5K_TUNE_BEACON_INTERVAL 100
199#define AR5K_TUNE_AIFS 2
200#define AR5K_TUNE_AIFS_11B 2
201#define AR5K_TUNE_AIFS_XR 0
202#define AR5K_TUNE_CWMIN 15
203#define AR5K_TUNE_CWMIN_11B 31
204#define AR5K_TUNE_CWMIN_XR 3
205#define AR5K_TUNE_CWMAX 1023
206#define AR5K_TUNE_CWMAX_11B 1023
207#define AR5K_TUNE_CWMAX_XR 7
208#define AR5K_TUNE_NOISE_FLOOR -72
209#define AR5K_TUNE_MAX_TXPOWER 63
210#define AR5K_TUNE_DEFAULT_TXPOWER 25
211#define AR5K_TUNE_TPC_TXPOWER false
212#define AR5K_TUNE_ANT_DIVERSITY true
213#define AR5K_TUNE_HWTXTRIES 4
214
215#define AR5K_INIT_CARR_SENSE_EN 1
216
217/*Swap RX/TX Descriptor for big endian archs*/
218#if defined(__BIG_ENDIAN)
219#define AR5K_INIT_CFG ( \
220 AR5K_CFG_SWTD | AR5K_CFG_SWRD \
221)
222#else
223#define AR5K_INIT_CFG 0x00000000
224#endif
225
226/* Initial values */
227#define AR5K_INIT_CYCRSSI_THR1 2
228#define AR5K_INIT_TX_LATENCY 502
229#define AR5K_INIT_USEC 39
230#define AR5K_INIT_USEC_TURBO 79
231#define AR5K_INIT_USEC_32 31
232#define AR5K_INIT_SLOT_TIME 396
233#define AR5K_INIT_SLOT_TIME_TURBO 480
234#define AR5K_INIT_ACK_CTS_TIMEOUT 1024
235#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800
236#define AR5K_INIT_PROG_IFS 920
237#define AR5K_INIT_PROG_IFS_TURBO 960
238#define AR5K_INIT_EIFS 3440
239#define AR5K_INIT_EIFS_TURBO 6880
240#define AR5K_INIT_SIFS 560
241#define AR5K_INIT_SIFS_TURBO 480
242#define AR5K_INIT_SH_RETRY 10
243#define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY
244#define AR5K_INIT_SSH_RETRY 32
245#define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY
246#define AR5K_INIT_TX_RETRY 10
247
248#define AR5K_INIT_TRANSMIT_LATENCY ( \
249 (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
250 (AR5K_INIT_USEC) \
251)
252#define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \
253 (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
254 (AR5K_INIT_USEC_TURBO) \
255)
256#define AR5K_INIT_PROTO_TIME_CNTRL ( \
257 (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \
258 (AR5K_INIT_PROG_IFS) \
259)
260#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \
261 (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \
262 (AR5K_INIT_PROG_IFS_TURBO) \
263)
264
265/* token to use for aifs, cwmin, cwmax in MadWiFi */
266#define AR5K_TXQ_USEDEFAULT ((u32) -1)
267
268/* GENERIC CHIPSET DEFINITIONS */
269
270/* MAC Chips */
271enum ath5k_version {
272 AR5K_AR5210 = 0,
273 AR5K_AR5211 = 1,
274 AR5K_AR5212 = 2,
275};
276
277/* PHY Chips */
278enum ath5k_radio {
279 AR5K_RF5110 = 0,
280 AR5K_RF5111 = 1,
281 AR5K_RF5112 = 2,
282 AR5K_RF2413 = 3,
283 AR5K_RF5413 = 4,
284 AR5K_RF2316 = 5,
285 AR5K_RF2317 = 6,
286 AR5K_RF2425 = 7,
287};
288
289/*
290 * Common silicon revision/version values
291 */
292
293enum ath5k_srev_type {
294 AR5K_VERSION_MAC,
295 AR5K_VERSION_RAD,
296};
297
298struct ath5k_srev_name {
299 const char *sr_name;
300 enum ath5k_srev_type sr_type;
301 u_int sr_val;
302};
303
304#define AR5K_SREV_UNKNOWN 0xffff
305
306#define AR5K_SREV_AR5210 0x00 /* Crete */
307#define AR5K_SREV_AR5311 0x10 /* Maui 1 */
308#define AR5K_SREV_AR5311A 0x20 /* Maui 2 */
309#define AR5K_SREV_AR5311B 0x30 /* Spirit */
310#define AR5K_SREV_AR5211 0x40 /* Oahu */
311#define AR5K_SREV_AR5212 0x50 /* Venice */
312#define AR5K_SREV_AR5213 0x55 /* ??? */
313#define AR5K_SREV_AR5213A 0x59 /* Hainan */
314#define AR5K_SREV_AR2413 0x78 /* Griffin lite */
315#define AR5K_SREV_AR2414 0x70 /* Griffin */
316#define AR5K_SREV_AR5424 0x90 /* Condor */
317#define AR5K_SREV_AR5413 0xa4 /* Eagle lite */
318#define AR5K_SREV_AR5414 0xa0 /* Eagle */
319#define AR5K_SREV_AR2415 0xb0 /* Talon */
320#define AR5K_SREV_AR5416 0xc0 /* PCI-E */
321#define AR5K_SREV_AR5418 0xca /* PCI-E */
322#define AR5K_SREV_AR2425 0xe0 /* Swan */
323#define AR5K_SREV_AR2417 0xf0 /* Nala */
324
325#define AR5K_SREV_RAD_5110 0x00
326#define AR5K_SREV_RAD_5111 0x10
327#define AR5K_SREV_RAD_5111A 0x15
328#define AR5K_SREV_RAD_2111 0x20
329#define AR5K_SREV_RAD_5112 0x30
330#define AR5K_SREV_RAD_5112A 0x35
331#define AR5K_SREV_RAD_5112B 0x36
332#define AR5K_SREV_RAD_2112 0x40
333#define AR5K_SREV_RAD_2112A 0x45
334#define AR5K_SREV_RAD_2112B 0x46
335#define AR5K_SREV_RAD_2413 0x50
336#define AR5K_SREV_RAD_5413 0x60
337#define AR5K_SREV_RAD_2316 0x70 /* Cobra SoC */
338#define AR5K_SREV_RAD_2317 0x80
339#define AR5K_SREV_RAD_5424 0xa0 /* Mostly same as 5413 */
340#define AR5K_SREV_RAD_2425 0xa2
341#define AR5K_SREV_RAD_5133 0xc0
342
343#define AR5K_SREV_PHY_5211 0x30
344#define AR5K_SREV_PHY_5212 0x41
345#define AR5K_SREV_PHY_5212A 0x42
346#define AR5K_SREV_PHY_5212B 0x43
347#define AR5K_SREV_PHY_2413 0x45
348#define AR5K_SREV_PHY_5413 0x61
349#define AR5K_SREV_PHY_2425 0x70
350
351/* IEEE defs */
352#define IEEE80211_MAX_LEN 2500
353
354/* TODO add support to mac80211 for vendor-specific rates and modes */
355
356/*
357 * Some of this information is based on Documentation from:
358 *
359 * http://madwifi.org/wiki/ChipsetFeatures/SuperAG
360 *
361 * Modulation for Atheros' eXtended Range - range enhancing extension that is
362 * supposed to double the distance an Atheros client device can keep a
363 * connection with an Atheros access point. This is achieved by increasing
364 * the receiver sensitivity up to, -105dBm, which is about 20dB above what
365 * the 802.11 specifications demand. In addition, new (proprietary) data rates
366 * are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s.
367 *
368 * Please note that can you either use XR or TURBO but you cannot use both,
369 * they are exclusive.
370 *
371 */
372#define MODULATION_XR 0x00000200
373/*
374 * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a
375 * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s
376 * signaling rate achieved through the bonding of two 54Mbit/s 802.11g
377 * channels. To use this feature your Access Point must also suport it.
378 * There is also a distinction between "static" and "dynamic" turbo modes:
379 *
380 * - Static: is the dumb version: devices set to this mode stick to it until
381 * the mode is turned off.
382 * - Dynamic: is the intelligent version, the network decides itself if it
383 * is ok to use turbo. As soon as traffic is detected on adjacent channels
384 * (which would get used in turbo mode), or when a non-turbo station joins
385 * the network, turbo mode won't be used until the situation changes again.
386 * Dynamic mode is achieved by Atheros' Adaptive Radio (AR) feature which
387 * monitors the used radio band in order to decide whether turbo mode may
388 * be used or not.
389 *
390 * This article claims Super G sticks to bonding of channels 5 and 6 for
391 * USA:
392 *
393 * http://www.pcworld.com/article/id,113428-page,1/article.html
394 *
395 * The channel bonding seems to be driver specific though. In addition to
396 * deciding what channels will be used, these "Turbo" modes are accomplished
397 * by also enabling the following features:
398 *
399 * - Bursting: allows multiple frames to be sent at once, rather than pausing
400 * after each frame. Bursting is a standards-compliant feature that can be
401 * used with any Access Point.
402 * - Fast frames: increases the amount of information that can be sent per
403 * frame, also resulting in a reduction of transmission overhead. It is a
404 * proprietary feature that needs to be supported by the Access Point.
405 * - Compression: data frames are compressed in real time using a Lempel Ziv
406 * algorithm. This is done transparently. Once this feature is enabled,
407 * compression and decompression takes place inside the chipset, without
408 * putting additional load on the host CPU.
409 *
410 */
411#define MODULATION_TURBO 0x00000080
412
413enum ath5k_driver_mode {
414 AR5K_MODE_11A = 0,
415 AR5K_MODE_11A_TURBO = 1,
416 AR5K_MODE_11B = 2,
417 AR5K_MODE_11G = 3,
418 AR5K_MODE_11G_TURBO = 4,
419 AR5K_MODE_XR = 0,
420 AR5K_MODE_MAX = 5
421};
422
423
424/****************\
425 TX DEFINITIONS
426\****************/
427
428/*
429 * TX Status descriptor
430 */
431struct ath5k_tx_status {
432 u16 ts_seqnum;
433 u16 ts_tstamp;
434 u8 ts_status;
435 u8 ts_rate[4];
436 u8 ts_retry[4];
437 u8 ts_final_idx;
438 s8 ts_rssi;
439 u8 ts_shortretry;
440 u8 ts_longretry;
441 u8 ts_virtcol;
442 u8 ts_antenna;
443};
444
445#define AR5K_TXSTAT_ALTRATE 0x80
446#define AR5K_TXERR_XRETRY 0x01
447#define AR5K_TXERR_FILT 0x02
448#define AR5K_TXERR_FIFO 0x04
449
450/**
451 * enum ath5k_tx_queue - Queue types used to classify tx queues.
452 * @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue
453 * @AR5K_TX_QUEUE_DATA: A normal data queue
454 * @AR5K_TX_QUEUE_XR_DATA: An XR-data queue
455 * @AR5K_TX_QUEUE_BEACON: The beacon queue
456 * @AR5K_TX_QUEUE_CAB: The after-beacon queue
457 * @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue
458 */
459enum ath5k_tx_queue {
460 AR5K_TX_QUEUE_INACTIVE = 0,
461 AR5K_TX_QUEUE_DATA,
462 AR5K_TX_QUEUE_XR_DATA,
463 AR5K_TX_QUEUE_BEACON,
464 AR5K_TX_QUEUE_CAB,
465 AR5K_TX_QUEUE_UAPSD,
466};
467
468#define AR5K_NUM_TX_QUEUES 10
469#define AR5K_NUM_TX_QUEUES_NOQCU 2
470
471/*
472 * Queue syb-types to classify normal data queues.
473 * These are the 4 Access Categories as defined in
474 * WME spec. 0 is the lowest priority and 4 is the
475 * highest. Normal data that hasn't been classified
476 * goes to the Best Effort AC.
477 */
478enum ath5k_tx_queue_subtype {
479 AR5K_WME_AC_BK = 0, /*Background traffic*/
480 AR5K_WME_AC_BE, /*Best-effort (normal) traffic)*/
481 AR5K_WME_AC_VI, /*Video traffic*/
482 AR5K_WME_AC_VO, /*Voice traffic*/
483};
484
485/*
486 * Queue ID numbers as returned by the hw functions, each number
487 * represents a hw queue. If hw does not support hw queues
488 * (eg 5210) all data goes in one queue. These match
489 * d80211 definitions (net80211/MadWiFi don't use them).
490 */
491enum ath5k_tx_queue_id {
492 AR5K_TX_QUEUE_ID_NOQCU_DATA = 0,
493 AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1,
494 AR5K_TX_QUEUE_ID_DATA_MIN = 0, /*IEEE80211_TX_QUEUE_DATA0*/
495 AR5K_TX_QUEUE_ID_DATA_MAX = 4, /*IEEE80211_TX_QUEUE_DATA4*/
496 AR5K_TX_QUEUE_ID_DATA_SVP = 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/
497 AR5K_TX_QUEUE_ID_CAB = 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/
498 AR5K_TX_QUEUE_ID_BEACON = 7, /*IEEE80211_TX_QUEUE_BEACON*/
499 AR5K_TX_QUEUE_ID_UAPSD = 8,
500 AR5K_TX_QUEUE_ID_XR_DATA = 9,
501};
502
503/*
504 * Flags to set hw queue's parameters...
505 */
506#define AR5K_TXQ_FLAG_TXOKINT_ENABLE 0x0001 /* Enable TXOK interrupt */
507#define AR5K_TXQ_FLAG_TXERRINT_ENABLE 0x0002 /* Enable TXERR interrupt */
508#define AR5K_TXQ_FLAG_TXEOLINT_ENABLE 0x0004 /* Enable TXEOL interrupt -not used- */
509#define AR5K_TXQ_FLAG_TXDESCINT_ENABLE 0x0008 /* Enable TXDESC interrupt -not used- */
510#define AR5K_TXQ_FLAG_TXURNINT_ENABLE 0x0010 /* Enable TXURN interrupt */
511#define AR5K_TXQ_FLAG_CBRORNINT_ENABLE 0x0020 /* Enable CBRORN interrupt */
512#define AR5K_TXQ_FLAG_CBRURNINT_ENABLE 0x0040 /* Enable CBRURN interrupt */
513#define AR5K_TXQ_FLAG_QTRIGINT_ENABLE 0x0080 /* Enable QTRIG interrupt */
514#define AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE 0x0100 /* Enable TXNOFRM interrupt */
515#define AR5K_TXQ_FLAG_BACKOFF_DISABLE 0x0200 /* Disable random post-backoff */
516#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE 0x0300 /* Enable ready time expiry policy (?)*/
517#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE 0x0800 /* Enable backoff while bursting */
518#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x1000 /* Disable backoff while bursting */
519#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/
520
521/*
522 * A struct to hold tx queue's parameters
523 */
524struct ath5k_txq_info {
525 enum ath5k_tx_queue tqi_type;
526 enum ath5k_tx_queue_subtype tqi_subtype;
527 u16 tqi_flags; /* Tx queue flags (see above) */
528 u32 tqi_aifs; /* Arbitrated Interframe Space */
529 s32 tqi_cw_min; /* Minimum Contention Window */
530 s32 tqi_cw_max; /* Maximum Contention Window */
531 u32 tqi_cbr_period; /* Constant bit rate period */
532 u32 tqi_cbr_overflow_limit;
533 u32 tqi_burst_time;
534 u32 tqi_ready_time; /* Not used */
535};
536
537/*
538 * Transmit packet types.
539 * used on tx control descriptor
540 * TODO: Use them inside base.c corectly
541 */
542enum ath5k_pkt_type {
543 AR5K_PKT_TYPE_NORMAL = 0,
544 AR5K_PKT_TYPE_ATIM = 1,
545 AR5K_PKT_TYPE_PSPOLL = 2,
546 AR5K_PKT_TYPE_BEACON = 3,
547 AR5K_PKT_TYPE_PROBE_RESP = 4,
548 AR5K_PKT_TYPE_PIFS = 5,
549};
550
551/*
552 * TX power and TPC settings
553 */
554#define AR5K_TXPOWER_OFDM(_r, _v) ( \
555 ((0 & 1) << ((_v) + 6)) | \
556 (((ah->ah_txpower.txp_rates_power_table[(_r)]) & 0x3f) << (_v)) \
557)
558
559#define AR5K_TXPOWER_CCK(_r, _v) ( \
560 (ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v) \
561)
562
563/*
564 * DMA size definitions (2^n+2)
565 */
566enum ath5k_dmasize {
567 AR5K_DMASIZE_4B = 0,
568 AR5K_DMASIZE_8B,
569 AR5K_DMASIZE_16B,
570 AR5K_DMASIZE_32B,
571 AR5K_DMASIZE_64B,
572 AR5K_DMASIZE_128B,
573 AR5K_DMASIZE_256B,
574 AR5K_DMASIZE_512B
575};
576
577
578/****************\
579 RX DEFINITIONS
580\****************/
581
582/*
583 * RX Status descriptor
584 */
585struct ath5k_rx_status {
586 u16 rs_datalen;
587 u16 rs_tstamp;
588 u8 rs_status;
589 u8 rs_phyerr;
590 s8 rs_rssi;
591 u8 rs_keyix;
592 u8 rs_rate;
593 u8 rs_antenna;
594 u8 rs_more;
595};
596
597#define AR5K_RXERR_CRC 0x01
598#define AR5K_RXERR_PHY 0x02
599#define AR5K_RXERR_FIFO 0x04
600#define AR5K_RXERR_DECRYPT 0x08
601#define AR5K_RXERR_MIC 0x10
602#define AR5K_RXKEYIX_INVALID ((u8) - 1)
603#define AR5K_TXKEYIX_INVALID ((u32) - 1)
604
605
606/**************************\
607 BEACON TIMERS DEFINITIONS
608\**************************/
609
610#define AR5K_BEACON_PERIOD 0x0000ffff
611#define AR5K_BEACON_ENA 0x00800000 /*enable beacon xmit*/
612#define AR5K_BEACON_RESET_TSF 0x01000000 /*force a TSF reset*/
613
614#if 0
615/**
616 * struct ath5k_beacon_state - Per-station beacon timer state.
617 * @bs_interval: in TU's, can also include the above flags
618 * @bs_cfp_max_duration: if non-zero hw is setup to coexist with a
619 * Point Coordination Function capable AP
620 */
621struct ath5k_beacon_state {
622 u32 bs_next_beacon;
623 u32 bs_next_dtim;
624 u32 bs_interval;
625 u8 bs_dtim_period;
626 u8 bs_cfp_period;
627 u16 bs_cfp_max_duration;
628 u16 bs_cfp_du_remain;
629 u16 bs_tim_offset;
630 u16 bs_sleep_duration;
631 u16 bs_bmiss_threshold;
632 u32 bs_cfp_next;
633};
634#endif
635
636
637/*
638 * TSF to TU conversion:
639 *
640 * TSF is a 64bit value in usec (microseconds).
641 * TU is a 32bit value and defined by IEEE802.11 (page 6) as "A measurement of
642 * time equal to 1024 usec", so it's roughly milliseconds (usec / 1024).
643 */
644#define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
645
646
647/*******************************\
648 GAIN OPTIMIZATION DEFINITIONS
649\*******************************/
650
651enum ath5k_rfgain {
652 AR5K_RFGAIN_INACTIVE = 0,
653 AR5K_RFGAIN_ACTIVE,
654 AR5K_RFGAIN_READ_REQUESTED,
655 AR5K_RFGAIN_NEED_CHANGE,
656};
657
658struct ath5k_gain {
659 u8 g_step_idx;
660 u8 g_current;
661 u8 g_target;
662 u8 g_low;
663 u8 g_high;
664 u8 g_f_corr;
665 u8 g_state;
666};
667
668/********************\
669 COMMON DEFINITIONS
670\********************/
671
672#define AR5K_SLOT_TIME_9 396
673#define AR5K_SLOT_TIME_20 880
674#define AR5K_SLOT_TIME_MAX 0xffff
675
676/* channel_flags */
677#define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */
678#define CHANNEL_TURBO 0x0010 /* Turbo Channel */
679#define CHANNEL_CCK 0x0020 /* CCK channel */
680#define CHANNEL_OFDM 0x0040 /* OFDM channel */
681#define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */
682#define CHANNEL_5GHZ 0x0100 /* 5GHz channel */
683#define CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed */
684#define CHANNEL_DYN 0x0400 /* Dynamic CCK-OFDM channel (for g operation) */
685#define CHANNEL_XR 0x0800 /* XR channel */
686
687#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM)
688#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK)
689#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM)
690#define CHANNEL_T (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
691#define CHANNEL_TG (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
692#define CHANNEL_108A CHANNEL_T
693#define CHANNEL_108G CHANNEL_TG
694#define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR)
695
696#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \
697 CHANNEL_TURBO)
698
699#define CHANNEL_ALL_NOTURBO (CHANNEL_ALL & ~CHANNEL_TURBO)
700#define CHANNEL_MODES CHANNEL_ALL
701
702/*
703 * Used internaly for reset_tx_queue).
704 * Also see struct struct ieee80211_channel.
705 */
706#define IS_CHAN_XR(_c) ((_c.hw_value & CHANNEL_XR) != 0)
707#define IS_CHAN_B(_c) ((_c.hw_value & CHANNEL_B) != 0)
708
709/*
710 * The following structure is used to map 2GHz channels to
711 * 5GHz Atheros channels.
712 * TODO: Clean up
713 */
714struct ath5k_athchan_2ghz {
715 u32 a2_flags;
716 u16 a2_athchan;
717};
718
719
720/******************\
721 RATE DEFINITIONS
722\******************/
723
724/**
725 * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32.
726 *
727 * The rate code is used to get the RX rate or set the TX rate on the
728 * hardware descriptors. It is also used for internal modulation control
729 * and settings.
730 *
731 * This is the hardware rate map we are aware of:
732 *
733 * rate_code 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08
734 * rate_kbps 3000 1000 ? ? ? 2000 500 48000
735 *
736 * rate_code 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10
737 * rate_kbps 24000 12000 6000 54000 36000 18000 9000 ?
738 *
739 * rate_code 17 18 19 20 21 22 23 24
740 * rate_kbps ? ? ? ? ? ? ? 11000
741 *
742 * rate_code 25 26 27 28 29 30 31 32
743 * rate_kbps 5500 2000 1000 11000S 5500S 2000S ? ?
744 *
745 * "S" indicates CCK rates with short preamble.
746 *
747 * AR5211 has different rate codes for CCK (802.11B) rates. It only uses the
748 * lowest 4 bits, so they are the same as below with a 0xF mask.
749 * (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M).
750 * We handle this in ath5k_setup_bands().
751 */
752#define AR5K_MAX_RATES 32
753
754/* B */
755#define ATH5K_RATE_CODE_1M 0x1B
756#define ATH5K_RATE_CODE_2M 0x1A
757#define ATH5K_RATE_CODE_5_5M 0x19
758#define ATH5K_RATE_CODE_11M 0x18
759/* A and G */
760#define ATH5K_RATE_CODE_6M 0x0B
761#define ATH5K_RATE_CODE_9M 0x0F
762#define ATH5K_RATE_CODE_12M 0x0A
763#define ATH5K_RATE_CODE_18M 0x0E
764#define ATH5K_RATE_CODE_24M 0x09
765#define ATH5K_RATE_CODE_36M 0x0D
766#define ATH5K_RATE_CODE_48M 0x08
767#define ATH5K_RATE_CODE_54M 0x0C
768/* XR */
769#define ATH5K_RATE_CODE_XR_500K 0x07
770#define ATH5K_RATE_CODE_XR_1M 0x02
771#define ATH5K_RATE_CODE_XR_2M 0x06
772#define ATH5K_RATE_CODE_XR_3M 0x01
773
774/* adding this flag to rate_code enables short preamble */
775#define AR5K_SET_SHORT_PREAMBLE 0x04
776
777/*
778 * Crypto definitions
779 */
780
781#define AR5K_KEYCACHE_SIZE 8
782
783/***********************\
784 HW RELATED DEFINITIONS
785\***********************/
786
787/*
788 * Misc definitions
789 */
790#define AR5K_RSSI_EP_MULTIPLIER (1<<7)
791
792#define AR5K_ASSERT_ENTRY(_e, _s) do { \
793 if (_e >= _s) \
794 return (false); \
795} while (0)
796
797/*
798 * Hardware interrupt abstraction
799 */
800
801/**
802 * enum ath5k_int - Hardware interrupt masks helpers
803 *
804 * @AR5K_INT_RX: mask to identify received frame interrupts, of type
805 * AR5K_ISR_RXOK or AR5K_ISR_RXERR
806 * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?)
807 * @AR5K_INT_RXNOFRM: No frame received (?)
808 * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The
809 * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's
810 * LinkPtr is NULL. For more details, refer to:
811 * http://www.freepatentsonline.com/20030225739.html
812 * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors).
813 * Note that Rx overrun is not always fatal, on some chips we can continue
814 * operation without reseting the card, that's why int_fatal is not
815 * common for all chips.
816 * @AR5K_INT_TX: mask to identify received frame interrupts, of type
817 * AR5K_ISR_TXOK or AR5K_ISR_TXERR
818 * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?)
819 * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold
820 * We currently do increments on interrupt by
821 * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
822 * @AR5K_INT_MIB: Indicates the Management Information Base counters should be
823 * checked. We should do this with ath5k_hw_update_mib_counters() but
824 * it seems we should also then do some noise immunity work.
825 * @AR5K_INT_RXPHY: RX PHY Error
826 * @AR5K_INT_RXKCM: RX Key cache miss
827 * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
828 * beacon that must be handled in software. The alternative is if you
829 * have VEOL support, in that case you let the hardware deal with things.
830 * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing
831 * beacons from the AP have associated with, we should probably try to
832 * reassociate. When in IBSS mode this might mean we have not received
833 * any beacons from any local stations. Note that every station in an
834 * IBSS schedules to send beacons at the Target Beacon Transmission Time
835 * (TBTT) with a random backoff.
836 * @AR5K_INT_BNR: Beacon Not Ready interrupt - ??
837 * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now
838 * until properly handled
839 * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA
840 * errors. These types of errors we can enable seem to be of type
841 * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
842 * @AR5K_INT_GLOBAL: Used to clear and set the IER
843 * @AR5K_INT_NOCARD: signals the card has been removed
844 * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same
845 * bit value
846 *
847 * These are mapped to take advantage of some common bits
848 * between the MACs, to be able to set intr properties
849 * easier. Some of them are not used yet inside hw.c. Most map
850 * to the respective hw interrupt value as they are common amogst different
851 * MACs.
852 */
853enum ath5k_int {
854 AR5K_INT_RXOK = 0x00000001,
855 AR5K_INT_RXDESC = 0x00000002,
856 AR5K_INT_RXERR = 0x00000004,
857 AR5K_INT_RXNOFRM = 0x00000008,
858 AR5K_INT_RXEOL = 0x00000010,
859 AR5K_INT_RXORN = 0x00000020,
860 AR5K_INT_TXOK = 0x00000040,
861 AR5K_INT_TXDESC = 0x00000080,
862 AR5K_INT_TXERR = 0x00000100,
863 AR5K_INT_TXNOFRM = 0x00000200,
864 AR5K_INT_TXEOL = 0x00000400,
865 AR5K_INT_TXURN = 0x00000800,
866 AR5K_INT_MIB = 0x00001000,
867 AR5K_INT_SWI = 0x00002000,
868 AR5K_INT_RXPHY = 0x00004000,
869 AR5K_INT_RXKCM = 0x00008000,
870 AR5K_INT_SWBA = 0x00010000,
871 AR5K_INT_BRSSI = 0x00020000,
872 AR5K_INT_BMISS = 0x00040000,
873 AR5K_INT_FATAL = 0x00080000, /* Non common */
874 AR5K_INT_BNR = 0x00100000, /* Non common */
875 AR5K_INT_TIM = 0x00200000, /* Non common */
876 AR5K_INT_DTIM = 0x00400000, /* Non common */
877 AR5K_INT_DTIM_SYNC = 0x00800000, /* Non common */
878 AR5K_INT_GPIO = 0x01000000,
879 AR5K_INT_BCN_TIMEOUT = 0x02000000, /* Non common */
880 AR5K_INT_CAB_TIMEOUT = 0x04000000, /* Non common */
881 AR5K_INT_RX_DOPPLER = 0x08000000, /* Non common */
882 AR5K_INT_QCBRORN = 0x10000000, /* Non common */
883 AR5K_INT_QCBRURN = 0x20000000, /* Non common */
884 AR5K_INT_QTRIG = 0x40000000, /* Non common */
885 AR5K_INT_GLOBAL = 0x80000000,
886
887 AR5K_INT_COMMON = AR5K_INT_RXOK
888 | AR5K_INT_RXDESC
889 | AR5K_INT_RXERR
890 | AR5K_INT_RXNOFRM
891 | AR5K_INT_RXEOL
892 | AR5K_INT_RXORN
893 | AR5K_INT_TXOK
894 | AR5K_INT_TXDESC
895 | AR5K_INT_TXERR
896 | AR5K_INT_TXNOFRM
897 | AR5K_INT_TXEOL
898 | AR5K_INT_TXURN
899 | AR5K_INT_MIB
900 | AR5K_INT_SWI
901 | AR5K_INT_RXPHY
902 | AR5K_INT_RXKCM
903 | AR5K_INT_SWBA
904 | AR5K_INT_BRSSI
905 | AR5K_INT_BMISS
906 | AR5K_INT_GPIO
907 | AR5K_INT_GLOBAL,
908
909 AR5K_INT_NOCARD = 0xffffffff
910};
911
912/*
913 * Power management
914 */
915enum ath5k_power_mode {
916 AR5K_PM_UNDEFINED = 0,
917 AR5K_PM_AUTO,
918 AR5K_PM_AWAKE,
919 AR5K_PM_FULL_SLEEP,
920 AR5K_PM_NETWORK_SLEEP,
921};
922
923/*
924 * These match net80211 definitions (not used in
925 * mac80211).
926 * TODO: Clean this up
927 */
928#define AR5K_LED_INIT 0 /*IEEE80211_S_INIT*/
929#define AR5K_LED_SCAN 1 /*IEEE80211_S_SCAN*/
930#define AR5K_LED_AUTH 2 /*IEEE80211_S_AUTH*/
931#define AR5K_LED_ASSOC 3 /*IEEE80211_S_ASSOC*/
932#define AR5K_LED_RUN 4 /*IEEE80211_S_RUN*/
933
934/* GPIO-controlled software LED */
935#define AR5K_SOFTLED_PIN 0
936#define AR5K_SOFTLED_ON 0
937#define AR5K_SOFTLED_OFF 1
938
939/*
940 * Chipset capabilities -see ath5k_hw_get_capability-
941 * get_capability function is not yet fully implemented
942 * in ath5k so most of these don't work yet...
943 * TODO: Implement these & merge with _TUNE_ stuff above
944 */
945enum ath5k_capability_type {
946 AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */
947 AR5K_CAP_TKIP_MIC = 2, /* Can handle TKIP MIC in hardware */
948 AR5K_CAP_TKIP_SPLIT = 3, /* TKIP uses split keys */
949 AR5K_CAP_PHYCOUNTERS = 4, /* PHY error counters */
950 AR5K_CAP_DIVERSITY = 5, /* Supports fast diversity */
951 AR5K_CAP_NUM_TXQUEUES = 6, /* Used to get max number of hw txqueues */
952 AR5K_CAP_VEOL = 7, /* Supports virtual EOL */
953 AR5K_CAP_COMPRESSION = 8, /* Supports compression */
954 AR5K_CAP_BURST = 9, /* Supports packet bursting */
955 AR5K_CAP_FASTFRAME = 10, /* Supports fast frames */
956 AR5K_CAP_TXPOW = 11, /* Used to get global tx power limit */
957 AR5K_CAP_TPC = 12, /* Can do per-packet tx power control (needed for 802.11a) */
958 AR5K_CAP_BSSIDMASK = 13, /* Supports bssid mask */
959 AR5K_CAP_MCAST_KEYSRCH = 14, /* Supports multicast key search */
960 AR5K_CAP_TSF_ADJUST = 15, /* Supports beacon tsf adjust */
961 AR5K_CAP_XR = 16, /* Supports XR mode */
962 AR5K_CAP_WME_TKIPMIC = 17, /* Supports TKIP MIC when using WMM */
963 AR5K_CAP_CHAN_HALFRATE = 18, /* Supports half rate channels */
964 AR5K_CAP_CHAN_QUARTERRATE = 19, /* Supports quarter rate channels */
965 AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */
966};
967
968
969/* XXX: we *may* move cap_range stuff to struct wiphy */
970struct ath5k_capabilities {
971 /*
972 * Supported PHY modes
973 * (ie. CHANNEL_A, CHANNEL_B, ...)
974 */
975 DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX);
976
977 /*
978 * Frequency range (without regulation restrictions)
979 */
980 struct {
981 u16 range_2ghz_min;
982 u16 range_2ghz_max;
983 u16 range_5ghz_min;
984 u16 range_5ghz_max;
985 } cap_range;
986
987 /*
988 * Values stored in the EEPROM (some of them...)
989 */
990 struct ath5k_eeprom_info cap_eeprom;
991
992 /*
993 * Queue information
994 */
995 struct {
996 u8 q_tx_num;
997 } cap_queues;
998};
999
1000
1001/***************************************\
1002 HARDWARE ABSTRACTION LAYER STRUCTURE
1003\***************************************/
1004
1005/*
1006 * Misc defines
1007 */
1008
1009#define AR5K_MAX_GPIO 10
1010#define AR5K_MAX_RF_BANKS 8
1011
1012/* TODO: Clean up and merge with ath5k_softc */
1013struct ath5k_hw {
1014 u32 ah_magic;
1015
1016 struct ath5k_softc *ah_sc;
1017 void __iomem *ah_iobase;
1018
1019 enum ath5k_int ah_imr;
1020
1021 enum nl80211_iftype ah_op_mode;
1022 enum ath5k_power_mode ah_power_mode;
1023 struct ieee80211_channel ah_current_channel;
1024 bool ah_turbo;
1025 bool ah_calibration;
1026 bool ah_running;
1027 bool ah_single_chip;
1028 bool ah_combined_mic;
1029
1030 u32 ah_mac_srev;
1031 u16 ah_mac_version;
1032 u16 ah_mac_revision;
1033 u16 ah_phy_revision;
1034 u16 ah_radio_5ghz_revision;
1035 u16 ah_radio_2ghz_revision;
1036
1037 enum ath5k_version ah_version;
1038 enum ath5k_radio ah_radio;
1039 u32 ah_phy;
1040
1041 bool ah_5ghz;
1042 bool ah_2ghz;
1043
1044#define ah_modes ah_capabilities.cap_mode
1045#define ah_ee_version ah_capabilities.cap_eeprom.ee_version
1046
1047 u32 ah_atim_window;
1048 u32 ah_aifs;
1049 u32 ah_cw_min;
1050 u32 ah_cw_max;
1051 bool ah_software_retry;
1052 u32 ah_limit_tx_retries;
1053
1054 u32 ah_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
1055 bool ah_ant_diversity;
1056
1057 u8 ah_sta_id[ETH_ALEN];
1058
1059 /* Current BSSID we are trying to assoc to / create.
1060 * This is passed by mac80211 on config_interface() and cached here for
1061 * use in resets */
1062 u8 ah_bssid[ETH_ALEN];
1063 u8 ah_bssid_mask[ETH_ALEN];
1064
1065 u32 ah_gpio[AR5K_MAX_GPIO];
1066 int ah_gpio_npins;
1067
1068 struct ath_regulatory ah_regulatory;
1069 struct ath5k_capabilities ah_capabilities;
1070
1071 struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES];
1072 u32 ah_txq_status;
1073 u32 ah_txq_imr_txok;
1074 u32 ah_txq_imr_txerr;
1075 u32 ah_txq_imr_txurn;
1076 u32 ah_txq_imr_txdesc;
1077 u32 ah_txq_imr_txeol;
1078 u32 ah_txq_imr_cbrorn;
1079 u32 ah_txq_imr_cbrurn;
1080 u32 ah_txq_imr_qtrig;
1081 u32 ah_txq_imr_nofrm;
1082 u32 ah_txq_isr;
1083 u32 *ah_rf_banks;
1084 size_t ah_rf_banks_size;
1085 size_t ah_rf_regs_count;
1086 struct ath5k_gain ah_gain;
1087 u8 ah_offset[AR5K_MAX_RF_BANKS];
1088
1089
1090 struct {
1091 /* Temporary tables used for interpolation */
1092 u8 tmpL[AR5K_EEPROM_N_PD_GAINS]
1093 [AR5K_EEPROM_POWER_TABLE_SIZE];
1094 u8 tmpR[AR5K_EEPROM_N_PD_GAINS]
1095 [AR5K_EEPROM_POWER_TABLE_SIZE];
1096 u8 txp_pd_table[AR5K_EEPROM_POWER_TABLE_SIZE * 2];
1097 u16 txp_rates_power_table[AR5K_MAX_RATES];
1098 u8 txp_min_idx;
1099 bool txp_tpc;
1100 /* Values in 0.25dB units */
1101 s16 txp_min_pwr;
1102 s16 txp_max_pwr;
1103 s16 txp_offset;
1104 s16 txp_ofdm;
1105 /* Values in dB units */
1106 s16 txp_cck_ofdm_pwr_delta;
1107 s16 txp_cck_ofdm_gainf_delta;
1108 } ah_txpower;
1109
1110 struct {
1111 bool r_enabled;
1112 int r_last_alert;
1113 struct ieee80211_channel r_last_channel;
1114 } ah_radar;
1115
1116 /* noise floor from last periodic calibration */
1117 s32 ah_noise_floor;
1118
1119 /*
1120 * Function pointers
1121 */
1122 int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc,
1123 u32 size, unsigned int flags);
1124 int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
1125 unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
1126 unsigned int, unsigned int, unsigned int, unsigned int,
1127 unsigned int, unsigned int, unsigned int);
1128 int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
1129 unsigned int, unsigned int, unsigned int, unsigned int,
1130 unsigned int, unsigned int);
1131 int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
1132 struct ath5k_tx_status *);
1133 int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *,
1134 struct ath5k_rx_status *);
1135};
1136
1137/*
1138 * Prototypes
1139 */
1140
1141/* Attach/Detach Functions */
1142extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version);
1143extern void ath5k_hw_detach(struct ath5k_hw *ah);
1144
1145/* LED functions */
1146extern int ath5k_init_leds(struct ath5k_softc *sc);
1147extern void ath5k_led_enable(struct ath5k_softc *sc);
1148extern void ath5k_led_off(struct ath5k_softc *sc);
1149extern void ath5k_unregister_leds(struct ath5k_softc *sc);
1150
1151/* Reset Functions */
1152extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
1153extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel);
1154/* Power management functions */
1155extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration);
1156
1157/* DMA Related Functions */
1158extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah);
1159extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah);
1160extern u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah);
1161extern void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr);
1162extern int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue);
1163extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue);
1164extern u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue);
1165extern int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue,
1166 u32 phys_addr);
1167extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase);
1168/* Interrupt handling */
1169extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
1170extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
1171extern enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum
1172ath5k_int new_mask);
1173extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats);
1174
1175/* EEPROM access functions */
1176extern int ath5k_eeprom_init(struct ath5k_hw *ah);
1177extern void ath5k_eeprom_detach(struct ath5k_hw *ah);
1178extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
1179extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah);
1180
1181/* Protocol Control Unit Functions */
1182extern int ath5k_hw_set_opmode(struct ath5k_hw *ah);
1183/* BSSID Functions */
1184extern void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac);
1185extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
1186extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id);
1187extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
1188/* Receive start/stop functions */
1189extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
1190extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah);
1191/* RX Filter functions */
1192extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1);
1193extern int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index);
1194extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index);
1195extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah);
1196extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter);
1197/* Beacon control functions */
1198extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah);
1199extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
1200extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
1201extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
1202extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
1203#if 0
1204extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_beacon_state *state);
1205extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah);
1206extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr);
1207#endif
1208/* ACK bit rate */
1209void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
1210/* ACK/CTS Timeouts */
1211extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout);
1212extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah);
1213extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout);
1214extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah);
1215/* Key table (WEP) functions */
1216extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
1217extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry);
1218extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac);
1219extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac);
1220
1221/* Queue Control Unit, DFS Control Unit Functions */
1222extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info);
1223extern int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
1224 const struct ath5k_txq_info *queue_info);
1225extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah,
1226 enum ath5k_tx_queue queue_type,
1227 struct ath5k_txq_info *queue_info);
1228extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
1229extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue);
1230extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue);
1231extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah);
1232extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
1233
1234/* Hardware Descriptor Functions */
1235extern int ath5k_hw_init_desc_functions(struct ath5k_hw *ah);
1236
1237/* GPIO Functions */
1238extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state);
1239extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
1240extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio);
1241extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
1242extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
1243extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
1244
1245/* Misc functions */
1246int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
1247extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
1248extern int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id);
1249extern int ath5k_hw_disable_pspoll(struct ath5k_hw *ah);
1250
1251/* Initial register settings functions */
1252extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel);
1253
1254/* Initialize RF */
1255extern int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
1256 struct ieee80211_channel *channel,
1257 unsigned int mode);
1258extern int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq);
1259extern enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah);
1260extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
1261/* PHY/RF channel functions */
1262extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
1263extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
1264/* PHY calibration */
1265extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel);
1266extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
1267/* Misc PHY functions */
1268extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
1269extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant);
1270extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah);
1271extern int ath5k_hw_phy_disable(struct ath5k_hw *ah);
1272/* TX power setup */
1273extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower);
1274extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 ee_mode, u8 txpower);
1275
1276/*
1277 * Functions used internaly
1278 */
1279
1280/*
1281 * Translate usec to hw clock units
1282 * TODO: Half/quarter rate
1283 */
1284static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
1285{
1286 return turbo ? (usec * 80) : (usec * 40);
1287}
1288
1289/*
1290 * Translate hw clock units to usec
1291 * TODO: Half/quarter rate
1292 */
1293static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
1294{
1295 return turbo ? (clock / 80) : (clock / 40);
1296}
1297
1298/*
1299 * Read from a register
1300 */
1301static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
1302{
1303 return ioread32(ah->ah_iobase + reg);
1304}
1305
1306/*
1307 * Write to a register
1308 */
1309static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
1310{
1311 iowrite32(val, ah->ah_iobase + reg);
1312}
1313
1314#if defined(_ATH5K_RESET) || defined(_ATH5K_PHY)
1315/*
1316 * Check if a register write has been completed
1317 */
1318static int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag,
1319 u32 val, bool is_set)
1320{
1321 int i;
1322 u32 data;
1323
1324 for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
1325 data = ath5k_hw_reg_read(ah, reg);
1326 if (is_set && (data & flag))
1327 break;
1328 else if ((data & flag) == val)
1329 break;
1330 udelay(15);
1331 }
1332
1333 return (i <= 0) ? -EAGAIN : 0;
1334}
1335#endif
1336
1337static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
1338{
1339 u32 retval = 0, bit, i;
1340
1341 for (i = 0; i < bits; i++) {
1342 bit = (val >> i) & 1;
1343 retval = (retval << 1) | bit;
1344 }
1345
1346 return retval;
1347}
1348
1349static inline int ath5k_pad_size(int hdrlen)
1350{
1351 return (hdrlen < 24) ? 0 : hdrlen & 3;
1352}
1353
1354#endif
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
new file mode 100644
index 000000000000..70d376c63aac
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -0,0 +1,348 @@
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 */
18
19/*************************************\
20* Attach/Detach Functions and helpers *
21\*************************************/
22
23#include <linux/pci.h>
24#include "ath5k.h"
25#include "reg.h"
26#include "debug.h"
27#include "base.h"
28
29/**
30 * ath5k_hw_post - Power On Self Test helper function
31 *
32 * @ah: The &struct ath5k_hw
33 */
34static int ath5k_hw_post(struct ath5k_hw *ah)
35{
36
37 static const u32 static_pattern[4] = {
38 0x55555555, 0xaaaaaaaa,
39 0x66666666, 0x99999999
40 };
41 static const u16 regs[2] = { AR5K_STA_ID0, AR5K_PHY(8) };
42 int i, c;
43 u16 cur_reg;
44 u32 var_pattern;
45 u32 init_val;
46 u32 cur_val;
47
48 for (c = 0; c < 2; c++) {
49
50 cur_reg = regs[c];
51
52 /* Save previous value */
53 init_val = ath5k_hw_reg_read(ah, cur_reg);
54
55 for (i = 0; i < 256; i++) {
56 var_pattern = i << 16 | i;
57 ath5k_hw_reg_write(ah, var_pattern, cur_reg);
58 cur_val = ath5k_hw_reg_read(ah, cur_reg);
59
60 if (cur_val != var_pattern) {
61 ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
62 return -EAGAIN;
63 }
64
65 /* Found on ndiswrapper dumps */
66 var_pattern = 0x0039080f;
67 ath5k_hw_reg_write(ah, var_pattern, cur_reg);
68 }
69
70 for (i = 0; i < 4; i++) {
71 var_pattern = static_pattern[i];
72 ath5k_hw_reg_write(ah, var_pattern, cur_reg);
73 cur_val = ath5k_hw_reg_read(ah, cur_reg);
74
75 if (cur_val != var_pattern) {
76 ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
77 return -EAGAIN;
78 }
79
80 /* Found on ndiswrapper dumps */
81 var_pattern = 0x003b080f;
82 ath5k_hw_reg_write(ah, var_pattern, cur_reg);
83 }
84
85 /* Restore previous value */
86 ath5k_hw_reg_write(ah, init_val, cur_reg);
87
88 }
89
90 return 0;
91
92}
93
94/**
95 * ath5k_hw_attach - Check if hw is supported and init the needed structs
96 *
97 * @sc: The &struct ath5k_softc we got from the driver's attach function
98 * @mac_version: The mac version id (check out ath5k.h) based on pci id
99 *
100 * Check if the device is supported, perform a POST and initialize the needed
101 * structs. Returns -ENOMEM if we don't have memory for the needed structs,
102 * -ENODEV if the device is not supported or prints an error msg if something
103 * else went wrong.
104 */
105struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
106{
107 struct ath5k_hw *ah;
108 struct pci_dev *pdev = sc->pdev;
109 int ret;
110 u32 srev;
111
112 /*If we passed the test malloc a ath5k_hw struct*/
113 ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
114 if (ah == NULL) {
115 ret = -ENOMEM;
116 ATH5K_ERR(sc, "out of memory\n");
117 goto err;
118 }
119
120 ah->ah_sc = sc;
121 ah->ah_iobase = sc->iobase;
122
123 /*
124 * HW information
125 */
126 ah->ah_op_mode = NL80211_IFTYPE_STATION;
127 ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
128 ah->ah_turbo = false;
129 ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
130 ah->ah_imr = 0;
131 ah->ah_atim_window = 0;
132 ah->ah_aifs = AR5K_TUNE_AIFS;
133 ah->ah_cw_min = AR5K_TUNE_CWMIN;
134 ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
135 ah->ah_software_retry = false;
136 ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
137
138 /*
139 * Set the mac version based on the pci id
140 */
141 ah->ah_version = mac_version;
142
143 /*Fill the ath5k_hw struct with the needed functions*/
144 ret = ath5k_hw_init_desc_functions(ah);
145 if (ret)
146 goto err_free;
147
148 /* Bring device out of sleep and reset it's units */
149 ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, true);
150 if (ret)
151 goto err_free;
152
153 /* Get MAC, PHY and RADIO revisions */
154 srev = ath5k_hw_reg_read(ah, AR5K_SREV);
155 ah->ah_mac_srev = srev;
156 ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
157 ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
158 ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) &
159 0xffffffff;
160 ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
161 CHANNEL_5GHZ);
162 ah->ah_phy = AR5K_PHY(0);
163
164 /* Try to identify radio chip based on it's srev */
165 switch (ah->ah_radio_5ghz_revision & 0xf0) {
166 case AR5K_SREV_RAD_5111:
167 ah->ah_radio = AR5K_RF5111;
168 ah->ah_single_chip = false;
169 ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
170 CHANNEL_2GHZ);
171 break;
172 case AR5K_SREV_RAD_5112:
173 case AR5K_SREV_RAD_2112:
174 ah->ah_radio = AR5K_RF5112;
175 ah->ah_single_chip = false;
176 ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
177 CHANNEL_2GHZ);
178 break;
179 case AR5K_SREV_RAD_2413:
180 ah->ah_radio = AR5K_RF2413;
181 ah->ah_single_chip = true;
182 break;
183 case AR5K_SREV_RAD_5413:
184 ah->ah_radio = AR5K_RF5413;
185 ah->ah_single_chip = true;
186 break;
187 case AR5K_SREV_RAD_2316:
188 ah->ah_radio = AR5K_RF2316;
189 ah->ah_single_chip = true;
190 break;
191 case AR5K_SREV_RAD_2317:
192 ah->ah_radio = AR5K_RF2317;
193 ah->ah_single_chip = true;
194 break;
195 case AR5K_SREV_RAD_5424:
196 if (ah->ah_mac_version == AR5K_SREV_AR2425 ||
197 ah->ah_mac_version == AR5K_SREV_AR2417){
198 ah->ah_radio = AR5K_RF2425;
199 ah->ah_single_chip = true;
200 } else {
201 ah->ah_radio = AR5K_RF5413;
202 ah->ah_single_chip = true;
203 }
204 break;
205 default:
206 /* Identify radio based on mac/phy srev */
207 if (ah->ah_version == AR5K_AR5210) {
208 ah->ah_radio = AR5K_RF5110;
209 ah->ah_single_chip = false;
210 } else if (ah->ah_version == AR5K_AR5211) {
211 ah->ah_radio = AR5K_RF5111;
212 ah->ah_single_chip = false;
213 ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
214 CHANNEL_2GHZ);
215 } else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) ||
216 ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) ||
217 ah->ah_phy_revision == AR5K_SREV_PHY_2425) {
218 ah->ah_radio = AR5K_RF2425;
219 ah->ah_single_chip = true;
220 ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425;
221 } else if (srev == AR5K_SREV_AR5213A &&
222 ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {
223 ah->ah_radio = AR5K_RF5112;
224 ah->ah_single_chip = false;
225 ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B;
226 } else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) {
227 ah->ah_radio = AR5K_RF2316;
228 ah->ah_single_chip = true;
229 ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;
230 } else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) ||
231 ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
232 ah->ah_radio = AR5K_RF5413;
233 ah->ah_single_chip = true;
234 ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;
235 } else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) ||
236 ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
237 ah->ah_radio = AR5K_RF2413;
238 ah->ah_single_chip = true;
239 ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413;
240 } else {
241 ATH5K_ERR(sc, "Couldn't identify radio revision.\n");
242 ret = -ENODEV;
243 goto err_free;
244 }
245 }
246
247
248 /* Return on unsuported chips (unsupported eeprom etc) */
249 if ((srev >= AR5K_SREV_AR5416) &&
250 (srev < AR5K_SREV_AR2425)) {
251 ATH5K_ERR(sc, "Device not yet supported.\n");
252 ret = -ENODEV;
253 goto err_free;
254 }
255
256 /*
257 * Write PCI-E power save settings
258 */
259 if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
260 ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES);
261 ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES);
262 /* Shut off RX when elecidle is asserted */
263 ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);
264 ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES);
265 /* TODO: EEPROM work */
266 ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES);
267 /* Shut off PLL and CLKREQ active in L1 */
268 ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES);
269 /* Preserce other settings */
270 ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES);
271 ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES);
272 ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES);
273 /* Reset SERDES to load new settings */
274 ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET);
275 mdelay(1);
276 }
277
278 /*
279 * POST
280 */
281 ret = ath5k_hw_post(ah);
282 if (ret)
283 goto err_free;
284
285 /* Enable pci core retry fix on Hainan (5213A) and later chips */
286 if (srev >= AR5K_SREV_AR5213A)
287 ath5k_hw_reg_write(ah, AR5K_PCICFG_RETRY_FIX, AR5K_PCICFG);
288
289 /*
290 * Get card capabilities, calibration values etc
291 * TODO: EEPROM work
292 */
293 ret = ath5k_eeprom_init(ah);
294 if (ret) {
295 ATH5K_ERR(sc, "unable to init EEPROM\n");
296 goto err_free;
297 }
298
299 /* Get misc capabilities */
300 ret = ath5k_hw_set_capabilities(ah);
301 if (ret) {
302 ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n",
303 sc->pdev->device);
304 goto err_free;
305 }
306
307 if (srev >= AR5K_SREV_AR2414) {
308 ah->ah_combined_mic = true;
309 AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE,
310 AR5K_MISC_MODE_COMBINED_MIC);
311 }
312
313 /* MAC address is cleared until add_interface */
314 ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){});
315
316 /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
317 memset(ah->ah_bssid, 0xff, ETH_ALEN);
318 ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
319 ath5k_hw_set_opmode(ah);
320
321 ath5k_hw_rfgain_opt_init(ah);
322
323 return ah;
324err_free:
325 kfree(ah);
326err:
327 return ERR_PTR(ret);
328}
329
330/**
331 * ath5k_hw_detach - Free the ath5k_hw struct
332 *
333 * @ah: The &struct ath5k_hw
334 */
335void ath5k_hw_detach(struct ath5k_hw *ah)
336{
337 ATH5K_TRACE(ah->ah_sc);
338
339 __set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
340
341 if (ah->ah_rf_banks != NULL)
342 kfree(ah->ah_rf_banks);
343
344 ath5k_eeprom_detach(ah);
345
346 /* assume interrupts are down */
347 kfree(ah);
348}
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
new file mode 100644
index 000000000000..ff6d4f839734
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -0,0 +1,3110 @@
1/*-
2 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
3 * Copyright (c) 2004-2005 Atheros Communications, Inc.
4 * Copyright (c) 2006 Devicescape Software, Inc.
5 * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
6 * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
7 *
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer,
15 * without modification.
16 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
17 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
18 * redistribution must be conditioned upon including a substantially
19 * similar Disclaimer requirement for further binary redistribution.
20 * 3. Neither the names of the above-listed copyright holders nor the names
21 * of any contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 *
24 * Alternatively, this software may be distributed under the terms of the
25 * GNU General Public License ("GPL") version 2 as published by the Free
26 * Software Foundation.
27 *
28 * NO WARRANTY
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
32 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
33 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
34 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
37 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
39 * THE POSSIBILITY OF SUCH DAMAGES.
40 *
41 */
42
43#include <linux/module.h>
44#include <linux/delay.h>
45#include <linux/hardirq.h>
46#include <linux/if.h>
47#include <linux/io.h>
48#include <linux/netdevice.h>
49#include <linux/cache.h>
50#include <linux/pci.h>
51#include <linux/ethtool.h>
52#include <linux/uaccess.h>
53
54#include <net/ieee80211_radiotap.h>
55
56#include <asm/unaligned.h>
57
58#include "base.h"
59#include "reg.h"
60#include "debug.h"
61
62static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
63static int modparam_nohwcrypt;
64module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
65MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
66
67static int modparam_all_channels;
68module_param_named(all_channels, modparam_all_channels, int, 0444);
69MODULE_PARM_DESC(all_channels, "Expose all channels the device can use.");
70
71
72/******************\
73* Internal defines *
74\******************/
75
76/* Module info */
77MODULE_AUTHOR("Jiri Slaby");
78MODULE_AUTHOR("Nick Kossifidis");
79MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards.");
80MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
81MODULE_LICENSE("Dual BSD/GPL");
82MODULE_VERSION("0.6.0 (EXPERIMENTAL)");
83
84
85/* Known PCI ids */
86static const struct pci_device_id ath5k_pci_id_table[] = {
87 { PCI_VDEVICE(ATHEROS, 0x0207), .driver_data = AR5K_AR5210 }, /* 5210 early */
88 { PCI_VDEVICE(ATHEROS, 0x0007), .driver_data = AR5K_AR5210 }, /* 5210 */
89 { PCI_VDEVICE(ATHEROS, 0x0011), .driver_data = AR5K_AR5211 }, /* 5311 - this is on AHB bus !*/
90 { PCI_VDEVICE(ATHEROS, 0x0012), .driver_data = AR5K_AR5211 }, /* 5211 */
91 { PCI_VDEVICE(ATHEROS, 0x0013), .driver_data = AR5K_AR5212 }, /* 5212 */
92 { PCI_VDEVICE(3COM_2, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 5212 */
93 { PCI_VDEVICE(3COM, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 3CRDAG675 5212 */
94 { PCI_VDEVICE(ATHEROS, 0x1014), .driver_data = AR5K_AR5212 }, /* IBM minipci 5212 */
95 { PCI_VDEVICE(ATHEROS, 0x0014), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
96 { PCI_VDEVICE(ATHEROS, 0x0015), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
97 { PCI_VDEVICE(ATHEROS, 0x0016), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
98 { PCI_VDEVICE(ATHEROS, 0x0017), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
99 { PCI_VDEVICE(ATHEROS, 0x0018), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
100 { PCI_VDEVICE(ATHEROS, 0x0019), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
101 { PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */
102 { PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */
103 { PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* PCI-E cards */
104 { PCI_VDEVICE(ATHEROS, 0x001d), .driver_data = AR5K_AR5212 }, /* 2417 Nala */
105 { 0 }
106};
107MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
108
109/* Known SREVs */
110static const struct ath5k_srev_name srev_names[] = {
111 { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 },
112 { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 },
113 { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A },
114 { "5311B", AR5K_VERSION_MAC, AR5K_SREV_AR5311B },
115 { "5211", AR5K_VERSION_MAC, AR5K_SREV_AR5211 },
116 { "5212", AR5K_VERSION_MAC, AR5K_SREV_AR5212 },
117 { "5213", AR5K_VERSION_MAC, AR5K_SREV_AR5213 },
118 { "5213A", AR5K_VERSION_MAC, AR5K_SREV_AR5213A },
119 { "2413", AR5K_VERSION_MAC, AR5K_SREV_AR2413 },
120 { "2414", AR5K_VERSION_MAC, AR5K_SREV_AR2414 },
121 { "5424", AR5K_VERSION_MAC, AR5K_SREV_AR5424 },
122 { "5413", AR5K_VERSION_MAC, AR5K_SREV_AR5413 },
123 { "5414", AR5K_VERSION_MAC, AR5K_SREV_AR5414 },
124 { "2415", AR5K_VERSION_MAC, AR5K_SREV_AR2415 },
125 { "5416", AR5K_VERSION_MAC, AR5K_SREV_AR5416 },
126 { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 },
127 { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 },
128 { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 },
129 { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN },
130 { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 },
131 { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 },
132 { "5111A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111A },
133 { "2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111 },
134 { "5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112 },
135 { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A },
136 { "5112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112B },
137 { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 },
138 { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A },
139 { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B },
140 { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 },
141 { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 },
142 { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 },
143 { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 },
144 { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 },
145 { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
146 { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN },
147};
148
149static const struct ieee80211_rate ath5k_rates[] = {
150 { .bitrate = 10,
151 .hw_value = ATH5K_RATE_CODE_1M, },
152 { .bitrate = 20,
153 .hw_value = ATH5K_RATE_CODE_2M,
154 .hw_value_short = ATH5K_RATE_CODE_2M | AR5K_SET_SHORT_PREAMBLE,
155 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
156 { .bitrate = 55,
157 .hw_value = ATH5K_RATE_CODE_5_5M,
158 .hw_value_short = ATH5K_RATE_CODE_5_5M | AR5K_SET_SHORT_PREAMBLE,
159 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
160 { .bitrate = 110,
161 .hw_value = ATH5K_RATE_CODE_11M,
162 .hw_value_short = ATH5K_RATE_CODE_11M | AR5K_SET_SHORT_PREAMBLE,
163 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
164 { .bitrate = 60,
165 .hw_value = ATH5K_RATE_CODE_6M,
166 .flags = 0 },
167 { .bitrate = 90,
168 .hw_value = ATH5K_RATE_CODE_9M,
169 .flags = 0 },
170 { .bitrate = 120,
171 .hw_value = ATH5K_RATE_CODE_12M,
172 .flags = 0 },
173 { .bitrate = 180,
174 .hw_value = ATH5K_RATE_CODE_18M,
175 .flags = 0 },
176 { .bitrate = 240,
177 .hw_value = ATH5K_RATE_CODE_24M,
178 .flags = 0 },
179 { .bitrate = 360,
180 .hw_value = ATH5K_RATE_CODE_36M,
181 .flags = 0 },
182 { .bitrate = 480,
183 .hw_value = ATH5K_RATE_CODE_48M,
184 .flags = 0 },
185 { .bitrate = 540,
186 .hw_value = ATH5K_RATE_CODE_54M,
187 .flags = 0 },
188 /* XR missing */
189};
190
191/*
192 * Prototypes - PCI stack related functions
193 */
194static int __devinit ath5k_pci_probe(struct pci_dev *pdev,
195 const struct pci_device_id *id);
196static void __devexit ath5k_pci_remove(struct pci_dev *pdev);
197#ifdef CONFIG_PM
198static int ath5k_pci_suspend(struct pci_dev *pdev,
199 pm_message_t state);
200static int ath5k_pci_resume(struct pci_dev *pdev);
201#else
202#define ath5k_pci_suspend NULL
203#define ath5k_pci_resume NULL
204#endif /* CONFIG_PM */
205
206static struct pci_driver ath5k_pci_driver = {
207 .name = KBUILD_MODNAME,
208 .id_table = ath5k_pci_id_table,
209 .probe = ath5k_pci_probe,
210 .remove = __devexit_p(ath5k_pci_remove),
211 .suspend = ath5k_pci_suspend,
212 .resume = ath5k_pci_resume,
213};
214
215
216
217/*
218 * Prototypes - MAC 802.11 stack related functions
219 */
220static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
221static int ath5k_reset(struct ath5k_softc *sc, bool stop, bool change_channel);
222static int ath5k_reset_wake(struct ath5k_softc *sc);
223static int ath5k_start(struct ieee80211_hw *hw);
224static void ath5k_stop(struct ieee80211_hw *hw);
225static int ath5k_add_interface(struct ieee80211_hw *hw,
226 struct ieee80211_if_init_conf *conf);
227static void ath5k_remove_interface(struct ieee80211_hw *hw,
228 struct ieee80211_if_init_conf *conf);
229static int ath5k_config(struct ieee80211_hw *hw, u32 changed);
230static int ath5k_config_interface(struct ieee80211_hw *hw,
231 struct ieee80211_vif *vif,
232 struct ieee80211_if_conf *conf);
233static void ath5k_configure_filter(struct ieee80211_hw *hw,
234 unsigned int changed_flags,
235 unsigned int *new_flags,
236 int mc_count, struct dev_mc_list *mclist);
237static int ath5k_set_key(struct ieee80211_hw *hw,
238 enum set_key_cmd cmd,
239 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
240 struct ieee80211_key_conf *key);
241static int ath5k_get_stats(struct ieee80211_hw *hw,
242 struct ieee80211_low_level_stats *stats);
243static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
244 struct ieee80211_tx_queue_stats *stats);
245static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
246static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
247static void ath5k_reset_tsf(struct ieee80211_hw *hw);
248static int ath5k_beacon_update(struct ath5k_softc *sc,
249 struct sk_buff *skb);
250static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
251 struct ieee80211_vif *vif,
252 struct ieee80211_bss_conf *bss_conf,
253 u32 changes);
254
255static const struct ieee80211_ops ath5k_hw_ops = {
256 .tx = ath5k_tx,
257 .start = ath5k_start,
258 .stop = ath5k_stop,
259 .add_interface = ath5k_add_interface,
260 .remove_interface = ath5k_remove_interface,
261 .config = ath5k_config,
262 .config_interface = ath5k_config_interface,
263 .configure_filter = ath5k_configure_filter,
264 .set_key = ath5k_set_key,
265 .get_stats = ath5k_get_stats,
266 .conf_tx = NULL,
267 .get_tx_stats = ath5k_get_tx_stats,
268 .get_tsf = ath5k_get_tsf,
269 .set_tsf = ath5k_set_tsf,
270 .reset_tsf = ath5k_reset_tsf,
271 .bss_info_changed = ath5k_bss_info_changed,
272};
273
274/*
275 * Prototypes - Internal functions
276 */
277/* Attach detach */
278static int ath5k_attach(struct pci_dev *pdev,
279 struct ieee80211_hw *hw);
280static void ath5k_detach(struct pci_dev *pdev,
281 struct ieee80211_hw *hw);
282/* Channel/mode setup */
283static inline short ath5k_ieee2mhz(short chan);
284static unsigned int ath5k_copy_channels(struct ath5k_hw *ah,
285 struct ieee80211_channel *channels,
286 unsigned int mode,
287 unsigned int max);
288static int ath5k_setup_bands(struct ieee80211_hw *hw);
289static int ath5k_chan_set(struct ath5k_softc *sc,
290 struct ieee80211_channel *chan);
291static void ath5k_setcurmode(struct ath5k_softc *sc,
292 unsigned int mode);
293static void ath5k_mode_setup(struct ath5k_softc *sc);
294
295/* Descriptor setup */
296static int ath5k_desc_alloc(struct ath5k_softc *sc,
297 struct pci_dev *pdev);
298static void ath5k_desc_free(struct ath5k_softc *sc,
299 struct pci_dev *pdev);
300/* Buffers setup */
301static int ath5k_rxbuf_setup(struct ath5k_softc *sc,
302 struct ath5k_buf *bf);
303static int ath5k_txbuf_setup(struct ath5k_softc *sc,
304 struct ath5k_buf *bf);
305static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
306 struct ath5k_buf *bf)
307{
308 BUG_ON(!bf);
309 if (!bf->skb)
310 return;
311 pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len,
312 PCI_DMA_TODEVICE);
313 dev_kfree_skb_any(bf->skb);
314 bf->skb = NULL;
315}
316
317static inline void ath5k_rxbuf_free(struct ath5k_softc *sc,
318 struct ath5k_buf *bf)
319{
320 BUG_ON(!bf);
321 if (!bf->skb)
322 return;
323 pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
324 PCI_DMA_FROMDEVICE);
325 dev_kfree_skb_any(bf->skb);
326 bf->skb = NULL;
327}
328
329
330/* Queues setup */
331static struct ath5k_txq *ath5k_txq_setup(struct ath5k_softc *sc,
332 int qtype, int subtype);
333static int ath5k_beaconq_setup(struct ath5k_hw *ah);
334static int ath5k_beaconq_config(struct ath5k_softc *sc);
335static void ath5k_txq_drainq(struct ath5k_softc *sc,
336 struct ath5k_txq *txq);
337static void ath5k_txq_cleanup(struct ath5k_softc *sc);
338static void ath5k_txq_release(struct ath5k_softc *sc);
339/* Rx handling */
340static int ath5k_rx_start(struct ath5k_softc *sc);
341static void ath5k_rx_stop(struct ath5k_softc *sc);
342static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc,
343 struct ath5k_desc *ds,
344 struct sk_buff *skb,
345 struct ath5k_rx_status *rs);
346static void ath5k_tasklet_rx(unsigned long data);
347/* Tx handling */
348static void ath5k_tx_processq(struct ath5k_softc *sc,
349 struct ath5k_txq *txq);
350static void ath5k_tasklet_tx(unsigned long data);
351/* Beacon handling */
352static int ath5k_beacon_setup(struct ath5k_softc *sc,
353 struct ath5k_buf *bf);
354static void ath5k_beacon_send(struct ath5k_softc *sc);
355static void ath5k_beacon_config(struct ath5k_softc *sc);
356static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
357static void ath5k_tasklet_beacon(unsigned long data);
358
359static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
360{
361 u64 tsf = ath5k_hw_get_tsf64(ah);
362
363 if ((tsf & 0x7fff) < rstamp)
364 tsf -= 0x8000;
365
366 return (tsf & ~0x7fff) | rstamp;
367}
368
369/* Interrupt handling */
370static int ath5k_init(struct ath5k_softc *sc);
371static int ath5k_stop_locked(struct ath5k_softc *sc);
372static int ath5k_stop_hw(struct ath5k_softc *sc);
373static irqreturn_t ath5k_intr(int irq, void *dev_id);
374static void ath5k_tasklet_reset(unsigned long data);
375
376static void ath5k_calibrate(unsigned long data);
377
378/*
379 * Module init/exit functions
380 */
381static int __init
382init_ath5k_pci(void)
383{
384 int ret;
385
386 ath5k_debug_init();
387
388 ret = pci_register_driver(&ath5k_pci_driver);
389 if (ret) {
390 printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
391 return ret;
392 }
393
394 return 0;
395}
396
397static void __exit
398exit_ath5k_pci(void)
399{
400 pci_unregister_driver(&ath5k_pci_driver);
401
402 ath5k_debug_finish();
403}
404
405module_init(init_ath5k_pci);
406module_exit(exit_ath5k_pci);
407
408
409/********************\
410* PCI Initialization *
411\********************/
412
413static const char *
414ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val)
415{
416 const char *name = "xxxxx";
417 unsigned int i;
418
419 for (i = 0; i < ARRAY_SIZE(srev_names); i++) {
420 if (srev_names[i].sr_type != type)
421 continue;
422
423 if ((val & 0xf0) == srev_names[i].sr_val)
424 name = srev_names[i].sr_name;
425
426 if ((val & 0xff) == srev_names[i].sr_val) {
427 name = srev_names[i].sr_name;
428 break;
429 }
430 }
431
432 return name;
433}
434
435static int __devinit
436ath5k_pci_probe(struct pci_dev *pdev,
437 const struct pci_device_id *id)
438{
439 void __iomem *mem;
440 struct ath5k_softc *sc;
441 struct ieee80211_hw *hw;
442 int ret;
443 u8 csz;
444
445 ret = pci_enable_device(pdev);
446 if (ret) {
447 dev_err(&pdev->dev, "can't enable device\n");
448 goto err;
449 }
450
451 /* XXX 32-bit addressing only */
452 ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
453 if (ret) {
454 dev_err(&pdev->dev, "32-bit DMA not available\n");
455 goto err_dis;
456 }
457
458 /*
459 * Cache line size is used to size and align various
460 * structures used to communicate with the hardware.
461 */
462 pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
463 if (csz == 0) {
464 /*
465 * Linux 2.4.18 (at least) writes the cache line size
466 * register as a 16-bit wide register which is wrong.
467 * We must have this setup properly for rx buffer
468 * DMA to work so force a reasonable value here if it
469 * comes up zero.
470 */
471 csz = L1_CACHE_BYTES / sizeof(u32);
472 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
473 }
474 /*
475 * The default setting of latency timer yields poor results,
476 * set it to the value used by other systems. It may be worth
477 * tweaking this setting more.
478 */
479 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
480
481 /* Enable bus mastering */
482 pci_set_master(pdev);
483
484 /*
485 * Disable the RETRY_TIMEOUT register (0x41) to keep
486 * PCI Tx retries from interfering with C3 CPU state.
487 */
488 pci_write_config_byte(pdev, 0x41, 0);
489
490 ret = pci_request_region(pdev, 0, "ath5k");
491 if (ret) {
492 dev_err(&pdev->dev, "cannot reserve PCI memory region\n");
493 goto err_dis;
494 }
495
496 mem = pci_iomap(pdev, 0, 0);
497 if (!mem) {
498 dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
499 ret = -EIO;
500 goto err_reg;
501 }
502
503 /*
504 * Allocate hw (mac80211 main struct)
505 * and hw->priv (driver private data)
506 */
507 hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
508 if (hw == NULL) {
509 dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
510 ret = -ENOMEM;
511 goto err_map;
512 }
513
514 dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
515
516 /* Initialize driver private data */
517 SET_IEEE80211_DEV(hw, &pdev->dev);
518 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
519 IEEE80211_HW_SIGNAL_DBM |
520 IEEE80211_HW_NOISE_DBM;
521
522 hw->wiphy->interface_modes =
523 BIT(NL80211_IFTYPE_STATION) |
524 BIT(NL80211_IFTYPE_ADHOC) |
525 BIT(NL80211_IFTYPE_MESH_POINT);
526
527 hw->extra_tx_headroom = 2;
528 hw->channel_change_time = 5000;
529 sc = hw->priv;
530 sc->hw = hw;
531 sc->pdev = pdev;
532
533 ath5k_debug_init_device(sc);
534
535 /*
536 * Mark the device as detached to avoid processing
537 * interrupts until setup is complete.
538 */
539 __set_bit(ATH_STAT_INVALID, sc->status);
540
541 sc->iobase = mem; /* So we can unmap it on detach */
542 sc->cachelsz = csz * sizeof(u32); /* convert to bytes */
543 sc->opmode = NL80211_IFTYPE_STATION;
544 mutex_init(&sc->lock);
545 spin_lock_init(&sc->rxbuflock);
546 spin_lock_init(&sc->txbuflock);
547 spin_lock_init(&sc->block);
548
549 /* Set private data */
550 pci_set_drvdata(pdev, hw);
551
552 /* Setup interrupt handler */
553 ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
554 if (ret) {
555 ATH5K_ERR(sc, "request_irq failed\n");
556 goto err_free;
557 }
558
559 /* Initialize device */
560 sc->ah = ath5k_hw_attach(sc, id->driver_data);
561 if (IS_ERR(sc->ah)) {
562 ret = PTR_ERR(sc->ah);
563 goto err_irq;
564 }
565
566 /* set up multi-rate retry capabilities */
567 if (sc->ah->ah_version == AR5K_AR5212) {
568 hw->max_rates = 4;
569 hw->max_rate_tries = 11;
570 }
571
572 /* Finish private driver data initialization */
573 ret = ath5k_attach(pdev, hw);
574 if (ret)
575 goto err_ah;
576
577 ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
578 ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
579 sc->ah->ah_mac_srev,
580 sc->ah->ah_phy_revision);
581
582 if (!sc->ah->ah_single_chip) {
583 /* Single chip radio (!RF5111) */
584 if (sc->ah->ah_radio_5ghz_revision &&
585 !sc->ah->ah_radio_2ghz_revision) {
586 /* No 5GHz support -> report 2GHz radio */
587 if (!test_bit(AR5K_MODE_11A,
588 sc->ah->ah_capabilities.cap_mode)) {
589 ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
590 ath5k_chip_name(AR5K_VERSION_RAD,
591 sc->ah->ah_radio_5ghz_revision),
592 sc->ah->ah_radio_5ghz_revision);
593 /* No 2GHz support (5110 and some
594 * 5Ghz only cards) -> report 5Ghz radio */
595 } else if (!test_bit(AR5K_MODE_11B,
596 sc->ah->ah_capabilities.cap_mode)) {
597 ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
598 ath5k_chip_name(AR5K_VERSION_RAD,
599 sc->ah->ah_radio_5ghz_revision),
600 sc->ah->ah_radio_5ghz_revision);
601 /* Multiband radio */
602 } else {
603 ATH5K_INFO(sc, "RF%s multiband radio found"
604 " (0x%x)\n",
605 ath5k_chip_name(AR5K_VERSION_RAD,
606 sc->ah->ah_radio_5ghz_revision),
607 sc->ah->ah_radio_5ghz_revision);
608 }
609 }
610 /* Multi chip radio (RF5111 - RF2111) ->
611 * report both 2GHz/5GHz radios */
612 else if (sc->ah->ah_radio_5ghz_revision &&
613 sc->ah->ah_radio_2ghz_revision){
614 ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
615 ath5k_chip_name(AR5K_VERSION_RAD,
616 sc->ah->ah_radio_5ghz_revision),
617 sc->ah->ah_radio_5ghz_revision);
618 ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
619 ath5k_chip_name(AR5K_VERSION_RAD,
620 sc->ah->ah_radio_2ghz_revision),
621 sc->ah->ah_radio_2ghz_revision);
622 }
623 }
624
625
626 /* ready to process interrupts */
627 __clear_bit(ATH_STAT_INVALID, sc->status);
628
629 return 0;
630err_ah:
631 ath5k_hw_detach(sc->ah);
632err_irq:
633 free_irq(pdev->irq, sc);
634err_free:
635 ieee80211_free_hw(hw);
636err_map:
637 pci_iounmap(pdev, mem);
638err_reg:
639 pci_release_region(pdev, 0);
640err_dis:
641 pci_disable_device(pdev);
642err:
643 return ret;
644}
645
646static void __devexit
647ath5k_pci_remove(struct pci_dev *pdev)
648{
649 struct ieee80211_hw *hw = pci_get_drvdata(pdev);
650 struct ath5k_softc *sc = hw->priv;
651
652 ath5k_debug_finish_device(sc);
653 ath5k_detach(pdev, hw);
654 ath5k_hw_detach(sc->ah);
655 free_irq(pdev->irq, sc);
656 pci_iounmap(pdev, sc->iobase);
657 pci_release_region(pdev, 0);
658 pci_disable_device(pdev);
659 ieee80211_free_hw(hw);
660}
661
662#ifdef CONFIG_PM
663static int
664ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
665{
666 struct ieee80211_hw *hw = pci_get_drvdata(pdev);
667 struct ath5k_softc *sc = hw->priv;
668
669 ath5k_led_off(sc);
670
671 free_irq(pdev->irq, sc);
672 pci_save_state(pdev);
673 pci_disable_device(pdev);
674 pci_set_power_state(pdev, PCI_D3hot);
675
676 return 0;
677}
678
679static int
680ath5k_pci_resume(struct pci_dev *pdev)
681{
682 struct ieee80211_hw *hw = pci_get_drvdata(pdev);
683 struct ath5k_softc *sc = hw->priv;
684 int err;
685
686 pci_restore_state(pdev);
687
688 err = pci_enable_device(pdev);
689 if (err)
690 return err;
691
692 err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
693 if (err) {
694 ATH5K_ERR(sc, "request_irq failed\n");
695 goto err_no_irq;
696 }
697
698 ath5k_led_enable(sc);
699 return 0;
700
701err_no_irq:
702 pci_disable_device(pdev);
703 return err;
704}
705#endif /* CONFIG_PM */
706
707
708/***********************\
709* Driver Initialization *
710\***********************/
711
712static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
713{
714 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
715 struct ath5k_softc *sc = hw->priv;
716 struct ath_regulatory *reg = &sc->ah->ah_regulatory;
717
718 return ath_reg_notifier_apply(wiphy, request, reg);
719}
720
721static int
722ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
723{
724 struct ath5k_softc *sc = hw->priv;
725 struct ath5k_hw *ah = sc->ah;
726 u8 mac[ETH_ALEN] = {};
727 int ret;
728
729 ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
730
731 /*
732 * Check if the MAC has multi-rate retry support.
733 * We do this by trying to setup a fake extended
734 * descriptor. MAC's that don't have support will
735 * return false w/o doing anything. MAC's that do
736 * support it will return true w/o doing anything.
737 */
738 ret = ah->ah_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0);
739 if (ret < 0)
740 goto err;
741 if (ret > 0)
742 __set_bit(ATH_STAT_MRRETRY, sc->status);
743
744 /*
745 * Collect the channel list. The 802.11 layer
746 * is resposible for filtering this list based
747 * on settings like the phy mode and regulatory
748 * domain restrictions.
749 */
750 ret = ath5k_setup_bands(hw);
751 if (ret) {
752 ATH5K_ERR(sc, "can't get channels\n");
753 goto err;
754 }
755
756 /* NB: setup here so ath5k_rate_update is happy */
757 if (test_bit(AR5K_MODE_11A, ah->ah_modes))
758 ath5k_setcurmode(sc, AR5K_MODE_11A);
759 else
760 ath5k_setcurmode(sc, AR5K_MODE_11B);
761
762 /*
763 * Allocate tx+rx descriptors and populate the lists.
764 */
765 ret = ath5k_desc_alloc(sc, pdev);
766 if (ret) {
767 ATH5K_ERR(sc, "can't allocate descriptors\n");
768 goto err;
769 }
770
771 /*
772 * Allocate hardware transmit queues: one queue for
773 * beacon frames and one data queue for each QoS
774 * priority. Note that hw functions handle reseting
775 * these queues at the needed time.
776 */
777 ret = ath5k_beaconq_setup(ah);
778 if (ret < 0) {
779 ATH5K_ERR(sc, "can't setup a beacon xmit queue\n");
780 goto err_desc;
781 }
782 sc->bhalq = ret;
783
784 sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
785 if (IS_ERR(sc->txq)) {
786 ATH5K_ERR(sc, "can't setup xmit queue\n");
787 ret = PTR_ERR(sc->txq);
788 goto err_bhal;
789 }
790
791 tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
792 tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
793 tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
794 tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
795 setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc);
796
797 ret = ath5k_eeprom_read_mac(ah, mac);
798 if (ret) {
799 ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
800 sc->pdev->device);
801 goto err_queues;
802 }
803
804 SET_IEEE80211_PERM_ADDR(hw, mac);
805 /* All MAC address bits matter for ACKs */
806 memset(sc->bssidmask, 0xff, ETH_ALEN);
807 ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
808
809 ah->ah_regulatory.current_rd =
810 ah->ah_capabilities.cap_eeprom.ee_regdomain;
811 ret = ath_regd_init(&ah->ah_regulatory, hw->wiphy, ath5k_reg_notifier);
812 if (ret) {
813 ATH5K_ERR(sc, "can't initialize regulatory system\n");
814 goto err_queues;
815 }
816
817 ret = ieee80211_register_hw(hw);
818 if (ret) {
819 ATH5K_ERR(sc, "can't register ieee80211 hw\n");
820 goto err_queues;
821 }
822
823 if (!ath_is_world_regd(&sc->ah->ah_regulatory))
824 regulatory_hint(hw->wiphy, sc->ah->ah_regulatory.alpha2);
825
826 ath5k_init_leds(sc);
827
828 return 0;
829err_queues:
830 ath5k_txq_release(sc);
831err_bhal:
832 ath5k_hw_release_tx_queue(ah, sc->bhalq);
833err_desc:
834 ath5k_desc_free(sc, pdev);
835err:
836 return ret;
837}
838
839static void
840ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
841{
842 struct ath5k_softc *sc = hw->priv;
843
844 /*
845 * NB: the order of these is important:
846 * o call the 802.11 layer before detaching ath5k_hw to
847 * insure callbacks into the driver to delete global
848 * key cache entries can be handled
849 * o reclaim the tx queue data structures after calling
850 * the 802.11 layer as we'll get called back to reclaim
851 * node state and potentially want to use them
852 * o to cleanup the tx queues the hal is called, so detach
853 * it last
854 * XXX: ??? detach ath5k_hw ???
855 * Other than that, it's straightforward...
856 */
857 ieee80211_unregister_hw(hw);
858 ath5k_desc_free(sc, pdev);
859 ath5k_txq_release(sc);
860 ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
861 ath5k_unregister_leds(sc);
862
863 /*
864 * NB: can't reclaim these until after ieee80211_ifdetach
865 * returns because we'll get called back to reclaim node
866 * state and potentially want to use them.
867 */
868}
869
870
871
872
873/********************\
874* Channel/mode setup *
875\********************/
876
877/*
878 * Convert IEEE channel number to MHz frequency.
879 */
880static inline short
881ath5k_ieee2mhz(short chan)
882{
883 if (chan <= 14 || chan >= 27)
884 return ieee80211chan2mhz(chan);
885 else
886 return 2212 + chan * 20;
887}
888
889/*
890 * Returns true for the channel numbers used without all_channels modparam.
891 */
892static bool ath5k_is_standard_channel(short chan)
893{
894 return ((chan <= 14) ||
895 /* UNII 1,2 */
896 ((chan & 3) == 0 && chan >= 36 && chan <= 64) ||
897 /* midband */
898 ((chan & 3) == 0 && chan >= 100 && chan <= 140) ||
899 /* UNII-3 */
900 ((chan & 3) == 1 && chan >= 149 && chan <= 165));
901}
902
903static unsigned int
904ath5k_copy_channels(struct ath5k_hw *ah,
905 struct ieee80211_channel *channels,
906 unsigned int mode,
907 unsigned int max)
908{
909 unsigned int i, count, size, chfreq, freq, ch;
910
911 if (!test_bit(mode, ah->ah_modes))
912 return 0;
913
914 switch (mode) {
915 case AR5K_MODE_11A:
916 case AR5K_MODE_11A_TURBO:
917 /* 1..220, but 2GHz frequencies are filtered by check_channel */
918 size = 220 ;
919 chfreq = CHANNEL_5GHZ;
920 break;
921 case AR5K_MODE_11B:
922 case AR5K_MODE_11G:
923 case AR5K_MODE_11G_TURBO:
924 size = 26;
925 chfreq = CHANNEL_2GHZ;
926 break;
927 default:
928 ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n");
929 return 0;
930 }
931
932 for (i = 0, count = 0; i < size && max > 0; i++) {
933 ch = i + 1 ;
934 freq = ath5k_ieee2mhz(ch);
935
936 /* Check if channel is supported by the chipset */
937 if (!ath5k_channel_ok(ah, freq, chfreq))
938 continue;
939
940 if (!modparam_all_channels && !ath5k_is_standard_channel(ch))
941 continue;
942
943 /* Write channel info and increment counter */
944 channels[count].center_freq = freq;
945 channels[count].band = (chfreq == CHANNEL_2GHZ) ?
946 IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
947 switch (mode) {
948 case AR5K_MODE_11A:
949 case AR5K_MODE_11G:
950 channels[count].hw_value = chfreq | CHANNEL_OFDM;
951 break;
952 case AR5K_MODE_11A_TURBO:
953 case AR5K_MODE_11G_TURBO:
954 channels[count].hw_value = chfreq |
955 CHANNEL_OFDM | CHANNEL_TURBO;
956 break;
957 case AR5K_MODE_11B:
958 channels[count].hw_value = CHANNEL_B;
959 }
960
961 count++;
962 max--;
963 }
964
965 return count;
966}
967
968static void
969ath5k_setup_rate_idx(struct ath5k_softc *sc, struct ieee80211_supported_band *b)
970{
971 u8 i;
972
973 for (i = 0; i < AR5K_MAX_RATES; i++)
974 sc->rate_idx[b->band][i] = -1;
975
976 for (i = 0; i < b->n_bitrates; i++) {
977 sc->rate_idx[b->band][b->bitrates[i].hw_value] = i;
978 if (b->bitrates[i].hw_value_short)
979 sc->rate_idx[b->band][b->bitrates[i].hw_value_short] = i;
980 }
981}
982
983static int
984ath5k_setup_bands(struct ieee80211_hw *hw)
985{
986 struct ath5k_softc *sc = hw->priv;
987 struct ath5k_hw *ah = sc->ah;
988 struct ieee80211_supported_band *sband;
989 int max_c, count_c = 0;
990 int i;
991
992 BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS);
993 max_c = ARRAY_SIZE(sc->channels);
994
995 /* 2GHz band */
996 sband = &sc->sbands[IEEE80211_BAND_2GHZ];
997 sband->band = IEEE80211_BAND_2GHZ;
998 sband->bitrates = &sc->rates[IEEE80211_BAND_2GHZ][0];
999
1000 if (test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) {
1001 /* G mode */
1002 memcpy(sband->bitrates, &ath5k_rates[0],
1003 sizeof(struct ieee80211_rate) * 12);
1004 sband->n_bitrates = 12;
1005
1006 sband->channels = sc->channels;
1007 sband->n_channels = ath5k_copy_channels(ah, sband->channels,
1008 AR5K_MODE_11G, max_c);
1009
1010 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
1011 count_c = sband->n_channels;
1012 max_c -= count_c;
1013 } else if (test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)) {
1014 /* B mode */
1015 memcpy(sband->bitrates, &ath5k_rates[0],
1016 sizeof(struct ieee80211_rate) * 4);
1017 sband->n_bitrates = 4;
1018
1019 /* 5211 only supports B rates and uses 4bit rate codes
1020 * (e.g normally we have 0x1B for 1M, but on 5211 we have 0x0B)
1021 * fix them up here:
1022 */
1023 if (ah->ah_version == AR5K_AR5211) {
1024 for (i = 0; i < 4; i++) {
1025 sband->bitrates[i].hw_value =
1026 sband->bitrates[i].hw_value & 0xF;
1027 sband->bitrates[i].hw_value_short =
1028 sband->bitrates[i].hw_value_short & 0xF;
1029 }
1030 }
1031
1032 sband->channels = sc->channels;
1033 sband->n_channels = ath5k_copy_channels(ah, sband->channels,
1034 AR5K_MODE_11B, max_c);
1035
1036 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
1037 count_c = sband->n_channels;
1038 max_c -= count_c;
1039 }
1040 ath5k_setup_rate_idx(sc, sband);
1041
1042 /* 5GHz band, A mode */
1043 if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) {
1044 sband = &sc->sbands[IEEE80211_BAND_5GHZ];
1045 sband->band = IEEE80211_BAND_5GHZ;
1046 sband->bitrates = &sc->rates[IEEE80211_BAND_5GHZ][0];
1047
1048 memcpy(sband->bitrates, &ath5k_rates[4],
1049 sizeof(struct ieee80211_rate) * 8);
1050 sband->n_bitrates = 8;
1051
1052 sband->channels = &sc->channels[count_c];
1053 sband->n_channels = ath5k_copy_channels(ah, sband->channels,
1054 AR5K_MODE_11A, max_c);
1055
1056 hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband;
1057 }
1058 ath5k_setup_rate_idx(sc, sband);
1059
1060 ath5k_debug_dump_bands(sc);
1061
1062 return 0;
1063}
1064
1065/*
1066 * Set/change channels. If the channel is really being changed,
1067 * it's done by reseting the chip. To accomplish this we must
1068 * first cleanup any pending DMA, then restart stuff after a la
1069 * ath5k_init.
1070 *
1071 * Called with sc->lock.
1072 */
1073static int
1074ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
1075{
1076 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n",
1077 sc->curchan->center_freq, chan->center_freq);
1078
1079 if (chan->center_freq != sc->curchan->center_freq ||
1080 chan->hw_value != sc->curchan->hw_value) {
1081
1082 sc->curchan = chan;
1083 sc->curband = &sc->sbands[chan->band];
1084
1085 /*
1086 * To switch channels clear any pending DMA operations;
1087 * wait long enough for the RX fifo to drain, reset the
1088 * hardware at the new frequency, and then re-enable
1089 * the relevant bits of the h/w.
1090 */
1091 return ath5k_reset(sc, true, true);
1092 }
1093
1094 return 0;
1095}
1096
1097static void
1098ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
1099{
1100 sc->curmode = mode;
1101
1102 if (mode == AR5K_MODE_11A) {
1103 sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ];
1104 } else {
1105 sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ];
1106 }
1107}
1108
1109static void
1110ath5k_mode_setup(struct ath5k_softc *sc)
1111{
1112 struct ath5k_hw *ah = sc->ah;
1113 u32 rfilt;
1114
1115 /* configure rx filter */
1116 rfilt = sc->filter_flags;
1117 ath5k_hw_set_rx_filter(ah, rfilt);
1118
1119 if (ath5k_hw_hasbssidmask(ah))
1120 ath5k_hw_set_bssid_mask(ah, sc->bssidmask);
1121
1122 /* configure operational mode */
1123 ath5k_hw_set_opmode(ah);
1124
1125 ath5k_hw_set_mcast_filter(ah, 0, 0);
1126 ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
1127}
1128
1129static inline int
1130ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
1131{
1132 int rix;
1133
1134 /* return base rate on errors */
1135 if (WARN(hw_rix < 0 || hw_rix >= AR5K_MAX_RATES,
1136 "hw_rix out of bounds: %x\n", hw_rix))
1137 return 0;
1138
1139 rix = sc->rate_idx[sc->curband->band][hw_rix];
1140 if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix))
1141 rix = 0;
1142
1143 return rix;
1144}
1145
1146/***************\
1147* Buffers setup *
1148\***************/
1149
1150static
1151struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
1152{
1153 struct sk_buff *skb;
1154 unsigned int off;
1155
1156 /*
1157 * Allocate buffer with headroom_needed space for the
1158 * fake physical layer header at the start.
1159 */
1160 skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
1161
1162 if (!skb) {
1163 ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
1164 sc->rxbufsize + sc->cachelsz - 1);
1165 return NULL;
1166 }
1167 /*
1168 * Cache-line-align. This is important (for the
1169 * 5210 at least) as not doing so causes bogus data
1170 * in rx'd frames.
1171 */
1172 off = ((unsigned long)skb->data) % sc->cachelsz;
1173 if (off != 0)
1174 skb_reserve(skb, sc->cachelsz - off);
1175
1176 *skb_addr = pci_map_single(sc->pdev,
1177 skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
1178 if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) {
1179 ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
1180 dev_kfree_skb(skb);
1181 return NULL;
1182 }
1183 return skb;
1184}
1185
1186static int
1187ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
1188{
1189 struct ath5k_hw *ah = sc->ah;
1190 struct sk_buff *skb = bf->skb;
1191 struct ath5k_desc *ds;
1192
1193 if (!skb) {
1194 skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
1195 if (!skb)
1196 return -ENOMEM;
1197 bf->skb = skb;
1198 }
1199
1200 /*
1201 * Setup descriptors. For receive we always terminate
1202 * the descriptor list with a self-linked entry so we'll
1203 * not get overrun under high load (as can happen with a
1204 * 5212 when ANI processing enables PHY error frames).
1205 *
1206 * To insure the last descriptor is self-linked we create
1207 * each descriptor as self-linked and add it to the end. As
1208 * each additional descriptor is added the previous self-linked
1209 * entry is ``fixed'' naturally. This should be safe even
1210 * if DMA is happening. When processing RX interrupts we
1211 * never remove/process the last, self-linked, entry on the
1212 * descriptor list. This insures the hardware always has
1213 * someplace to write a new frame.
1214 */
1215 ds = bf->desc;
1216 ds->ds_link = bf->daddr; /* link to self */
1217 ds->ds_data = bf->skbaddr;
1218 ah->ah_setup_rx_desc(ah, ds,
1219 skb_tailroom(skb), /* buffer size */
1220 0);
1221
1222 if (sc->rxlink != NULL)
1223 *sc->rxlink = bf->daddr;
1224 sc->rxlink = &ds->ds_link;
1225 return 0;
1226}
1227
1228static int
1229ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
1230{
1231 struct ath5k_hw *ah = sc->ah;
1232 struct ath5k_txq *txq = sc->txq;
1233 struct ath5k_desc *ds = bf->desc;
1234 struct sk_buff *skb = bf->skb;
1235 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1236 unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID;
1237 struct ieee80211_rate *rate;
1238 unsigned int mrr_rate[3], mrr_tries[3];
1239 int i, ret;
1240 u16 hw_rate;
1241 u16 cts_rate = 0;
1242 u16 duration = 0;
1243 u8 rc_flags;
1244
1245 flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
1246
1247 /* XXX endianness */
1248 bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
1249 PCI_DMA_TODEVICE);
1250
1251 rate = ieee80211_get_tx_rate(sc->hw, info);
1252
1253 if (info->flags & IEEE80211_TX_CTL_NO_ACK)
1254 flags |= AR5K_TXDESC_NOACK;
1255
1256 rc_flags = info->control.rates[0].flags;
1257 hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ?
1258 rate->hw_value_short : rate->hw_value;
1259
1260 pktlen = skb->len;
1261
1262 /* FIXME: If we are in g mode and rate is a CCK rate
1263 * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta
1264 * from tx power (value is in dB units already) */
1265 if (info->control.hw_key) {
1266 keyidx = info->control.hw_key->hw_key_idx;
1267 pktlen += info->control.hw_key->icv_len;
1268 }
1269 if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
1270 flags |= AR5K_TXDESC_RTSENA;
1271 cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
1272 duration = le16_to_cpu(ieee80211_rts_duration(sc->hw,
1273 sc->vif, pktlen, info));
1274 }
1275 if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
1276 flags |= AR5K_TXDESC_CTSENA;
1277 cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
1278 duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw,
1279 sc->vif, pktlen, info));
1280 }
1281 ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
1282 ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
1283 (sc->power_level * 2),
1284 hw_rate,
1285 info->control.rates[0].count, keyidx, 0, flags,
1286 cts_rate, duration);
1287 if (ret)
1288 goto err_unmap;
1289
1290 memset(mrr_rate, 0, sizeof(mrr_rate));
1291 memset(mrr_tries, 0, sizeof(mrr_tries));
1292 for (i = 0; i < 3; i++) {
1293 rate = ieee80211_get_alt_retry_rate(sc->hw, info, i);
1294 if (!rate)
1295 break;
1296
1297 mrr_rate[i] = rate->hw_value;
1298 mrr_tries[i] = info->control.rates[i + 1].count;
1299 }
1300
1301 ah->ah_setup_mrr_tx_desc(ah, ds,
1302 mrr_rate[0], mrr_tries[0],
1303 mrr_rate[1], mrr_tries[1],
1304 mrr_rate[2], mrr_tries[2]);
1305
1306 ds->ds_link = 0;
1307 ds->ds_data = bf->skbaddr;
1308
1309 spin_lock_bh(&txq->lock);
1310 list_add_tail(&bf->list, &txq->q);
1311 sc->tx_stats[txq->qnum].len++;
1312 if (txq->link == NULL) /* is this first packet? */
1313 ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr);
1314 else /* no, so only link it */
1315 *txq->link = bf->daddr;
1316
1317 txq->link = &ds->ds_link;
1318 ath5k_hw_start_tx_dma(ah, txq->qnum);
1319 mmiowb();
1320 spin_unlock_bh(&txq->lock);
1321
1322 return 0;
1323err_unmap:
1324 pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
1325 return ret;
1326}
1327
1328/*******************\
1329* Descriptors setup *
1330\*******************/
1331
1332static int
1333ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev)
1334{
1335 struct ath5k_desc *ds;
1336 struct ath5k_buf *bf;
1337 dma_addr_t da;
1338 unsigned int i;
1339 int ret;
1340
1341 /* allocate descriptors */
1342 sc->desc_len = sizeof(struct ath5k_desc) *
1343 (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1);
1344 sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr);
1345 if (sc->desc == NULL) {
1346 ATH5K_ERR(sc, "can't allocate descriptors\n");
1347 ret = -ENOMEM;
1348 goto err;
1349 }
1350 ds = sc->desc;
1351 da = sc->desc_daddr;
1352 ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n",
1353 ds, sc->desc_len, (unsigned long long)sc->desc_daddr);
1354
1355 bf = kcalloc(1 + ATH_TXBUF + ATH_RXBUF + ATH_BCBUF,
1356 sizeof(struct ath5k_buf), GFP_KERNEL);
1357 if (bf == NULL) {
1358 ATH5K_ERR(sc, "can't allocate bufptr\n");
1359 ret = -ENOMEM;
1360 goto err_free;
1361 }
1362 sc->bufptr = bf;
1363
1364 INIT_LIST_HEAD(&sc->rxbuf);
1365 for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
1366 bf->desc = ds;
1367 bf->daddr = da;
1368 list_add_tail(&bf->list, &sc->rxbuf);
1369 }
1370
1371 INIT_LIST_HEAD(&sc->txbuf);
1372 sc->txbuf_len = ATH_TXBUF;
1373 for (i = 0; i < ATH_TXBUF; i++, bf++, ds++,
1374 da += sizeof(*ds)) {
1375 bf->desc = ds;
1376 bf->daddr = da;
1377 list_add_tail(&bf->list, &sc->txbuf);
1378 }
1379
1380 /* beacon buffer */
1381 bf->desc = ds;
1382 bf->daddr = da;
1383 sc->bbuf = bf;
1384
1385 return 0;
1386err_free:
1387 pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
1388err:
1389 sc->desc = NULL;
1390 return ret;
1391}
1392
1393static void
1394ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev)
1395{
1396 struct ath5k_buf *bf;
1397
1398 ath5k_txbuf_free(sc, sc->bbuf);
1399 list_for_each_entry(bf, &sc->txbuf, list)
1400 ath5k_txbuf_free(sc, bf);
1401 list_for_each_entry(bf, &sc->rxbuf, list)
1402 ath5k_rxbuf_free(sc, bf);
1403
1404 /* Free memory associated with all descriptors */
1405 pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
1406
1407 kfree(sc->bufptr);
1408 sc->bufptr = NULL;
1409}
1410
1411
1412
1413
1414
1415/**************\
1416* Queues setup *
1417\**************/
1418
1419static struct ath5k_txq *
1420ath5k_txq_setup(struct ath5k_softc *sc,
1421 int qtype, int subtype)
1422{
1423 struct ath5k_hw *ah = sc->ah;
1424 struct ath5k_txq *txq;
1425 struct ath5k_txq_info qi = {
1426 .tqi_subtype = subtype,
1427 .tqi_aifs = AR5K_TXQ_USEDEFAULT,
1428 .tqi_cw_min = AR5K_TXQ_USEDEFAULT,
1429 .tqi_cw_max = AR5K_TXQ_USEDEFAULT
1430 };
1431 int qnum;
1432
1433 /*
1434 * Enable interrupts only for EOL and DESC conditions.
1435 * We mark tx descriptors to receive a DESC interrupt
1436 * when a tx queue gets deep; otherwise waiting for the
1437 * EOL to reap descriptors. Note that this is done to
1438 * reduce interrupt load and this only defers reaping
1439 * descriptors, never transmitting frames. Aside from
1440 * reducing interrupts this also permits more concurrency.
1441 * The only potential downside is if the tx queue backs
1442 * up in which case the top half of the kernel may backup
1443 * due to a lack of tx descriptors.
1444 */
1445 qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE |
1446 AR5K_TXQ_FLAG_TXDESCINT_ENABLE;
1447 qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi);
1448 if (qnum < 0) {
1449 /*
1450 * NB: don't print a message, this happens
1451 * normally on parts with too few tx queues
1452 */
1453 return ERR_PTR(qnum);
1454 }
1455 if (qnum >= ARRAY_SIZE(sc->txqs)) {
1456 ATH5K_ERR(sc, "hw qnum %u out of range, max %tu!\n",
1457 qnum, ARRAY_SIZE(sc->txqs));
1458 ath5k_hw_release_tx_queue(ah, qnum);
1459 return ERR_PTR(-EINVAL);
1460 }
1461 txq = &sc->txqs[qnum];
1462 if (!txq->setup) {
1463 txq->qnum = qnum;
1464 txq->link = NULL;
1465 INIT_LIST_HEAD(&txq->q);
1466 spin_lock_init(&txq->lock);
1467 txq->setup = true;
1468 }
1469 return &sc->txqs[qnum];
1470}
1471
1472static int
1473ath5k_beaconq_setup(struct ath5k_hw *ah)
1474{
1475 struct ath5k_txq_info qi = {
1476 .tqi_aifs = AR5K_TXQ_USEDEFAULT,
1477 .tqi_cw_min = AR5K_TXQ_USEDEFAULT,
1478 .tqi_cw_max = AR5K_TXQ_USEDEFAULT,
1479 /* NB: for dynamic turbo, don't enable any other interrupts */
1480 .tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE
1481 };
1482
1483 return ath5k_hw_setup_tx_queue(ah, AR5K_TX_QUEUE_BEACON, &qi);
1484}
1485
1486static int
1487ath5k_beaconq_config(struct ath5k_softc *sc)
1488{
1489 struct ath5k_hw *ah = sc->ah;
1490 struct ath5k_txq_info qi;
1491 int ret;
1492
1493 ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi);
1494 if (ret)
1495 return ret;
1496 if (sc->opmode == NL80211_IFTYPE_AP ||
1497 sc->opmode == NL80211_IFTYPE_MESH_POINT) {
1498 /*
1499 * Always burst out beacon and CAB traffic
1500 * (aifs = cwmin = cwmax = 0)
1501 */
1502 qi.tqi_aifs = 0;
1503 qi.tqi_cw_min = 0;
1504 qi.tqi_cw_max = 0;
1505 } else if (sc->opmode == NL80211_IFTYPE_ADHOC) {
1506 /*
1507 * Adhoc mode; backoff between 0 and (2 * cw_min).
1508 */
1509 qi.tqi_aifs = 0;
1510 qi.tqi_cw_min = 0;
1511 qi.tqi_cw_max = 2 * ah->ah_cw_min;
1512 }
1513
1514 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
1515 "beacon queueprops tqi_aifs:%d tqi_cw_min:%d tqi_cw_max:%d\n",
1516 qi.tqi_aifs, qi.tqi_cw_min, qi.tqi_cw_max);
1517
1518 ret = ath5k_hw_set_tx_queueprops(ah, sc->bhalq, &qi);
1519 if (ret) {
1520 ATH5K_ERR(sc, "%s: unable to update parameters for beacon "
1521 "hardware queue!\n", __func__);
1522 return ret;
1523 }
1524
1525 return ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */;
1526}
1527
1528static void
1529ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
1530{
1531 struct ath5k_buf *bf, *bf0;
1532
1533 /*
1534 * NB: this assumes output has been stopped and
1535 * we do not need to block ath5k_tx_tasklet
1536 */
1537 spin_lock_bh(&txq->lock);
1538 list_for_each_entry_safe(bf, bf0, &txq->q, list) {
1539 ath5k_debug_printtxbuf(sc, bf);
1540
1541 ath5k_txbuf_free(sc, bf);
1542
1543 spin_lock_bh(&sc->txbuflock);
1544 sc->tx_stats[txq->qnum].len--;
1545 list_move_tail(&bf->list, &sc->txbuf);
1546 sc->txbuf_len++;
1547 spin_unlock_bh(&sc->txbuflock);
1548 }
1549 txq->link = NULL;
1550 spin_unlock_bh(&txq->lock);
1551}
1552
1553/*
1554 * Drain the transmit queues and reclaim resources.
1555 */
1556static void
1557ath5k_txq_cleanup(struct ath5k_softc *sc)
1558{
1559 struct ath5k_hw *ah = sc->ah;
1560 unsigned int i;
1561
1562 /* XXX return value */
1563 if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) {
1564 /* don't touch the hardware if marked invalid */
1565 ath5k_hw_stop_tx_dma(ah, sc->bhalq);
1566 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n",
1567 ath5k_hw_get_txdp(ah, sc->bhalq));
1568 for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
1569 if (sc->txqs[i].setup) {
1570 ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum);
1571 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, "
1572 "link %p\n",
1573 sc->txqs[i].qnum,
1574 ath5k_hw_get_txdp(ah,
1575 sc->txqs[i].qnum),
1576 sc->txqs[i].link);
1577 }
1578 }
1579 ieee80211_wake_queues(sc->hw); /* XXX move to callers */
1580
1581 for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
1582 if (sc->txqs[i].setup)
1583 ath5k_txq_drainq(sc, &sc->txqs[i]);
1584}
1585
1586static void
1587ath5k_txq_release(struct ath5k_softc *sc)
1588{
1589 struct ath5k_txq *txq = sc->txqs;
1590 unsigned int i;
1591
1592 for (i = 0; i < ARRAY_SIZE(sc->txqs); i++, txq++)
1593 if (txq->setup) {
1594 ath5k_hw_release_tx_queue(sc->ah, txq->qnum);
1595 txq->setup = false;
1596 }
1597}
1598
1599
1600
1601
1602/*************\
1603* RX Handling *
1604\*************/
1605
1606/*
1607 * Enable the receive h/w following a reset.
1608 */
1609static int
1610ath5k_rx_start(struct ath5k_softc *sc)
1611{
1612 struct ath5k_hw *ah = sc->ah;
1613 struct ath5k_buf *bf;
1614 int ret;
1615
1616 sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->cachelsz);
1617
1618 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n",
1619 sc->cachelsz, sc->rxbufsize);
1620
1621 sc->rxlink = NULL;
1622
1623 spin_lock_bh(&sc->rxbuflock);
1624 list_for_each_entry(bf, &sc->rxbuf, list) {
1625 ret = ath5k_rxbuf_setup(sc, bf);
1626 if (ret != 0) {
1627 spin_unlock_bh(&sc->rxbuflock);
1628 goto err;
1629 }
1630 }
1631 bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
1632 spin_unlock_bh(&sc->rxbuflock);
1633
1634 ath5k_hw_set_rxdp(ah, bf->daddr);
1635 ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */
1636 ath5k_mode_setup(sc); /* set filters, etc. */
1637 ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */
1638
1639 return 0;
1640err:
1641 return ret;
1642}
1643
1644/*
1645 * Disable the receive h/w in preparation for a reset.
1646 */
1647static void
1648ath5k_rx_stop(struct ath5k_softc *sc)
1649{
1650 struct ath5k_hw *ah = sc->ah;
1651
1652 ath5k_hw_stop_rx_pcu(ah); /* disable PCU */
1653 ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */
1654 ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */
1655
1656 ath5k_debug_printrxbuffs(sc, ah);
1657
1658 sc->rxlink = NULL; /* just in case */
1659}
1660
1661static unsigned int
1662ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
1663 struct sk_buff *skb, struct ath5k_rx_status *rs)
1664{
1665 struct ieee80211_hdr *hdr = (void *)skb->data;
1666 unsigned int keyix, hlen;
1667
1668 if (!(rs->rs_status & AR5K_RXERR_DECRYPT) &&
1669 rs->rs_keyix != AR5K_RXKEYIX_INVALID)
1670 return RX_FLAG_DECRYPTED;
1671
1672 /* Apparently when a default key is used to decrypt the packet
1673 the hw does not set the index used to decrypt. In such cases
1674 get the index from the packet. */
1675 hlen = ieee80211_hdrlen(hdr->frame_control);
1676 if (ieee80211_has_protected(hdr->frame_control) &&
1677 !(rs->rs_status & AR5K_RXERR_DECRYPT) &&
1678 skb->len >= hlen + 4) {
1679 keyix = skb->data[hlen + 3] >> 6;
1680
1681 if (test_bit(keyix, sc->keymap))
1682 return RX_FLAG_DECRYPTED;
1683 }
1684
1685 return 0;
1686}
1687
1688
1689static void
1690ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
1691 struct ieee80211_rx_status *rxs)
1692{
1693 u64 tsf, bc_tstamp;
1694 u32 hw_tu;
1695 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
1696
1697 if (ieee80211_is_beacon(mgmt->frame_control) &&
1698 le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS &&
1699 memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
1700 /*
1701 * Received an IBSS beacon with the same BSSID. Hardware *must*
1702 * have updated the local TSF. We have to work around various
1703 * hardware bugs, though...
1704 */
1705 tsf = ath5k_hw_get_tsf64(sc->ah);
1706 bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
1707 hw_tu = TSF_TO_TU(tsf);
1708
1709 ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
1710 "beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
1711 (unsigned long long)bc_tstamp,
1712 (unsigned long long)rxs->mactime,
1713 (unsigned long long)(rxs->mactime - bc_tstamp),
1714 (unsigned long long)tsf);
1715
1716 /*
1717 * Sometimes the HW will give us a wrong tstamp in the rx
1718 * status, causing the timestamp extension to go wrong.
1719 * (This seems to happen especially with beacon frames bigger
1720 * than 78 byte (incl. FCS))
1721 * But we know that the receive timestamp must be later than the
1722 * timestamp of the beacon since HW must have synced to that.
1723 *
1724 * NOTE: here we assume mactime to be after the frame was
1725 * received, not like mac80211 which defines it at the start.
1726 */
1727 if (bc_tstamp > rxs->mactime) {
1728 ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
1729 "fixing mactime from %llx to %llx\n",
1730 (unsigned long long)rxs->mactime,
1731 (unsigned long long)tsf);
1732 rxs->mactime = tsf;
1733 }
1734
1735 /*
1736 * Local TSF might have moved higher than our beacon timers,
1737 * in that case we have to update them to continue sending
1738 * beacons. This also takes care of synchronizing beacon sending
1739 * times with other stations.
1740 */
1741 if (hw_tu >= sc->nexttbtt)
1742 ath5k_beacon_update_timers(sc, bc_tstamp);
1743 }
1744}
1745
1746static void ath5k_tasklet_beacon(unsigned long data)
1747{
1748 struct ath5k_softc *sc = (struct ath5k_softc *) data;
1749
1750 /*
1751 * Software beacon alert--time to send a beacon.
1752 *
1753 * In IBSS mode we use this interrupt just to
1754 * keep track of the next TBTT (target beacon
1755 * transmission time) in order to detect wether
1756 * automatic TSF updates happened.
1757 */
1758 if (sc->opmode == NL80211_IFTYPE_ADHOC) {
1759 /* XXX: only if VEOL suppported */
1760 u64 tsf = ath5k_hw_get_tsf64(sc->ah);
1761 sc->nexttbtt += sc->bintval;
1762 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
1763 "SWBA nexttbtt: %x hw_tu: %x "
1764 "TSF: %llx\n",
1765 sc->nexttbtt,
1766 TSF_TO_TU(tsf),
1767 (unsigned long long) tsf);
1768 } else {
1769 spin_lock(&sc->block);
1770 ath5k_beacon_send(sc);
1771 spin_unlock(&sc->block);
1772 }
1773}
1774
1775static void
1776ath5k_tasklet_rx(unsigned long data)
1777{
1778 struct ieee80211_rx_status rxs = {};
1779 struct ath5k_rx_status rs = {};
1780 struct sk_buff *skb, *next_skb;
1781 dma_addr_t next_skb_addr;
1782 struct ath5k_softc *sc = (void *)data;
1783 struct ath5k_buf *bf, *bf_last;
1784 struct ath5k_desc *ds;
1785 int ret;
1786 int hdrlen;
1787 int padsize;
1788
1789 spin_lock(&sc->rxbuflock);
1790 if (list_empty(&sc->rxbuf)) {
1791 ATH5K_WARN(sc, "empty rx buf pool\n");
1792 goto unlock;
1793 }
1794 bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list);
1795 do {
1796 rxs.flag = 0;
1797
1798 bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
1799 BUG_ON(bf->skb == NULL);
1800 skb = bf->skb;
1801 ds = bf->desc;
1802
1803 /*
1804 * last buffer must not be freed to ensure proper hardware
1805 * function. When the hardware finishes also a packet next to
1806 * it, we are sure, it doesn't use it anymore and we can go on.
1807 */
1808 if (bf_last == bf)
1809 bf->flags |= 1;
1810 if (bf->flags) {
1811 struct ath5k_buf *bf_next = list_entry(bf->list.next,
1812 struct ath5k_buf, list);
1813 ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc,
1814 &rs);
1815 if (ret)
1816 break;
1817 bf->flags &= ~1;
1818 /* skip the overwritten one (even status is martian) */
1819 goto next;
1820 }
1821
1822 ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
1823 if (unlikely(ret == -EINPROGRESS))
1824 break;
1825 else if (unlikely(ret)) {
1826 ATH5K_ERR(sc, "error in processing rx descriptor\n");
1827 spin_unlock(&sc->rxbuflock);
1828 return;
1829 }
1830
1831 if (unlikely(rs.rs_more)) {
1832 ATH5K_WARN(sc, "unsupported jumbo\n");
1833 goto next;
1834 }
1835
1836 if (unlikely(rs.rs_status)) {
1837 if (rs.rs_status & AR5K_RXERR_PHY)
1838 goto next;
1839 if (rs.rs_status & AR5K_RXERR_DECRYPT) {
1840 /*
1841 * Decrypt error. If the error occurred
1842 * because there was no hardware key, then
1843 * let the frame through so the upper layers
1844 * can process it. This is necessary for 5210
1845 * parts which have no way to setup a ``clear''
1846 * key cache entry.
1847 *
1848 * XXX do key cache faulting
1849 */
1850 if (rs.rs_keyix == AR5K_RXKEYIX_INVALID &&
1851 !(rs.rs_status & AR5K_RXERR_CRC))
1852 goto accept;
1853 }
1854 if (rs.rs_status & AR5K_RXERR_MIC) {
1855 rxs.flag |= RX_FLAG_MMIC_ERROR;
1856 goto accept;
1857 }
1858
1859 /* let crypto-error packets fall through in MNTR */
1860 if ((rs.rs_status &
1861 ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
1862 sc->opmode != NL80211_IFTYPE_MONITOR)
1863 goto next;
1864 }
1865accept:
1866 next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr);
1867
1868 /*
1869 * If we can't replace bf->skb with a new skb under memory
1870 * pressure, just skip this packet
1871 */
1872 if (!next_skb)
1873 goto next;
1874
1875 pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
1876 PCI_DMA_FROMDEVICE);
1877 skb_put(skb, rs.rs_datalen);
1878
1879 /* The MAC header is padded to have 32-bit boundary if the
1880 * packet payload is non-zero. The general calculation for
1881 * padsize would take into account odd header lengths:
1882 * padsize = (4 - hdrlen % 4) % 4; However, since only
1883 * even-length headers are used, padding can only be 0 or 2
1884 * bytes and we can optimize this a bit. In addition, we must
1885 * not try to remove padding from short control frames that do
1886 * not have payload. */
1887 hdrlen = ieee80211_get_hdrlen_from_skb(skb);
1888 padsize = ath5k_pad_size(hdrlen);
1889 if (padsize) {
1890 memmove(skb->data + padsize, skb->data, hdrlen);
1891 skb_pull(skb, padsize);
1892 }
1893
1894 /*
1895 * always extend the mac timestamp, since this information is
1896 * also needed for proper IBSS merging.
1897 *
1898 * XXX: it might be too late to do it here, since rs_tstamp is
1899 * 15bit only. that means TSF extension has to be done within
1900 * 32768usec (about 32ms). it might be necessary to move this to
1901 * the interrupt handler, like it is done in madwifi.
1902 *
1903 * Unfortunately we don't know when the hardware takes the rx
1904 * timestamp (beginning of phy frame, data frame, end of rx?).
1905 * The only thing we know is that it is hardware specific...
1906 * On AR5213 it seems the rx timestamp is at the end of the
1907 * frame, but i'm not sure.
1908 *
1909 * NOTE: mac80211 defines mactime at the beginning of the first
1910 * data symbol. Since we don't have any time references it's
1911 * impossible to comply to that. This affects IBSS merge only
1912 * right now, so it's not too bad...
1913 */
1914 rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp);
1915 rxs.flag |= RX_FLAG_TSFT;
1916
1917 rxs.freq = sc->curchan->center_freq;
1918 rxs.band = sc->curband->band;
1919
1920 rxs.noise = sc->ah->ah_noise_floor;
1921 rxs.signal = rxs.noise + rs.rs_rssi;
1922
1923 /* An rssi of 35 indicates you should be able use
1924 * 54 Mbps reliably. A more elaborate scheme can be used
1925 * here but it requires a map of SNR/throughput for each
1926 * possible mode used */
1927 rxs.qual = rs.rs_rssi * 100 / 35;
1928
1929 /* rssi can be more than 35 though, anything above that
1930 * should be considered at 100% */
1931 if (rxs.qual > 100)
1932 rxs.qual = 100;
1933
1934 rxs.antenna = rs.rs_antenna;
1935 rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
1936 rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
1937
1938 if (rxs.rate_idx >= 0 && rs.rs_rate ==
1939 sc->curband->bitrates[rxs.rate_idx].hw_value_short)
1940 rxs.flag |= RX_FLAG_SHORTPRE;
1941
1942 ath5k_debug_dump_skb(sc, skb, "RX ", 0);
1943
1944 /* check beacons in IBSS mode */
1945 if (sc->opmode == NL80211_IFTYPE_ADHOC)
1946 ath5k_check_ibss_tsf(sc, skb, &rxs);
1947
1948 __ieee80211_rx(sc->hw, skb, &rxs);
1949
1950 bf->skb = next_skb;
1951 bf->skbaddr = next_skb_addr;
1952next:
1953 list_move_tail(&bf->list, &sc->rxbuf);
1954 } while (ath5k_rxbuf_setup(sc, bf) == 0);
1955unlock:
1956 spin_unlock(&sc->rxbuflock);
1957}
1958
1959
1960
1961
1962/*************\
1963* TX Handling *
1964\*************/
1965
1966static void
1967ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
1968{
1969 struct ath5k_tx_status ts = {};
1970 struct ath5k_buf *bf, *bf0;
1971 struct ath5k_desc *ds;
1972 struct sk_buff *skb;
1973 struct ieee80211_tx_info *info;
1974 int i, ret;
1975
1976 spin_lock(&txq->lock);
1977 list_for_each_entry_safe(bf, bf0, &txq->q, list) {
1978 ds = bf->desc;
1979
1980 ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
1981 if (unlikely(ret == -EINPROGRESS))
1982 break;
1983 else if (unlikely(ret)) {
1984 ATH5K_ERR(sc, "error %d while processing queue %u\n",
1985 ret, txq->qnum);
1986 break;
1987 }
1988
1989 skb = bf->skb;
1990 info = IEEE80211_SKB_CB(skb);
1991 bf->skb = NULL;
1992
1993 pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
1994 PCI_DMA_TODEVICE);
1995
1996 ieee80211_tx_info_clear_status(info);
1997 for (i = 0; i < 4; i++) {
1998 struct ieee80211_tx_rate *r =
1999 &info->status.rates[i];
2000
2001 if (ts.ts_rate[i]) {
2002 r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]);
2003 r->count = ts.ts_retry[i];
2004 } else {
2005 r->idx = -1;
2006 r->count = 0;
2007 }
2008 }
2009
2010 /* count the successful attempt as well */
2011 info->status.rates[ts.ts_final_idx].count++;
2012
2013 if (unlikely(ts.ts_status)) {
2014 sc->ll_stats.dot11ACKFailureCount++;
2015 if (ts.ts_status & AR5K_TXERR_FILT)
2016 info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
2017 } else {
2018 info->flags |= IEEE80211_TX_STAT_ACK;
2019 info->status.ack_signal = ts.ts_rssi;
2020 }
2021
2022 ieee80211_tx_status(sc->hw, skb);
2023 sc->tx_stats[txq->qnum].count++;
2024
2025 spin_lock(&sc->txbuflock);
2026 sc->tx_stats[txq->qnum].len--;
2027 list_move_tail(&bf->list, &sc->txbuf);
2028 sc->txbuf_len++;
2029 spin_unlock(&sc->txbuflock);
2030 }
2031 if (likely(list_empty(&txq->q)))
2032 txq->link = NULL;
2033 spin_unlock(&txq->lock);
2034 if (sc->txbuf_len > ATH_TXBUF / 5)
2035 ieee80211_wake_queues(sc->hw);
2036}
2037
2038static void
2039ath5k_tasklet_tx(unsigned long data)
2040{
2041 struct ath5k_softc *sc = (void *)data;
2042
2043 ath5k_tx_processq(sc, sc->txq);
2044}
2045
2046
2047/*****************\
2048* Beacon handling *
2049\*****************/
2050
2051/*
2052 * Setup the beacon frame for transmit.
2053 */
2054static int
2055ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
2056{
2057 struct sk_buff *skb = bf->skb;
2058 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
2059 struct ath5k_hw *ah = sc->ah;
2060 struct ath5k_desc *ds;
2061 int ret, antenna = 0;
2062 u32 flags;
2063
2064 bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
2065 PCI_DMA_TODEVICE);
2066 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] "
2067 "skbaddr %llx\n", skb, skb->data, skb->len,
2068 (unsigned long long)bf->skbaddr);
2069 if (pci_dma_mapping_error(sc->pdev, bf->skbaddr)) {
2070 ATH5K_ERR(sc, "beacon DMA mapping failed\n");
2071 return -EIO;
2072 }
2073
2074 ds = bf->desc;
2075
2076 flags = AR5K_TXDESC_NOACK;
2077 if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) {
2078 ds->ds_link = bf->daddr; /* self-linked */
2079 flags |= AR5K_TXDESC_VEOL;
2080 /*
2081 * Let hardware handle antenna switching if txantenna is not set
2082 */
2083 } else {
2084 ds->ds_link = 0;
2085 /*
2086 * Switch antenna every 4 beacons if txantenna is not set
2087 * XXX assumes two antennas
2088 */
2089 if (antenna == 0)
2090 antenna = sc->bsent & 4 ? 2 : 1;
2091 }
2092
2093 /* FIXME: If we are in g mode and rate is a CCK rate
2094 * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta
2095 * from tx power (value is in dB units already) */
2096 ds->ds_data = bf->skbaddr;
2097 ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
2098 ieee80211_get_hdrlen_from_skb(skb),
2099 AR5K_PKT_TYPE_BEACON, (sc->power_level * 2),
2100 ieee80211_get_tx_rate(sc->hw, info)->hw_value,
2101 1, AR5K_TXKEYIX_INVALID,
2102 antenna, flags, 0, 0);
2103 if (ret)
2104 goto err_unmap;
2105
2106 return 0;
2107err_unmap:
2108 pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
2109 return ret;
2110}
2111
2112/*
2113 * Transmit a beacon frame at SWBA. Dynamic updates to the
2114 * frame contents are done as needed and the slot time is
2115 * also adjusted based on current state.
2116 *
2117 * This is called from software irq context (beacontq or restq
2118 * tasklets) or user context from ath5k_beacon_config.
2119 */
2120static void
2121ath5k_beacon_send(struct ath5k_softc *sc)
2122{
2123 struct ath5k_buf *bf = sc->bbuf;
2124 struct ath5k_hw *ah = sc->ah;
2125
2126 ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
2127
2128 if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
2129 sc->opmode == NL80211_IFTYPE_MONITOR)) {
2130 ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
2131 return;
2132 }
2133 /*
2134 * Check if the previous beacon has gone out. If
2135 * not don't don't try to post another, skip this
2136 * period and wait for the next. Missed beacons
2137 * indicate a problem and should not occur. If we
2138 * miss too many consecutive beacons reset the device.
2139 */
2140 if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) {
2141 sc->bmisscount++;
2142 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
2143 "missed %u consecutive beacons\n", sc->bmisscount);
2144 if (sc->bmisscount > 3) { /* NB: 3 is a guess */
2145 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
2146 "stuck beacon time (%u missed)\n",
2147 sc->bmisscount);
2148 tasklet_schedule(&sc->restq);
2149 }
2150 return;
2151 }
2152 if (unlikely(sc->bmisscount != 0)) {
2153 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
2154 "resume beacon xmit after %u misses\n",
2155 sc->bmisscount);
2156 sc->bmisscount = 0;
2157 }
2158
2159 /*
2160 * Stop any current dma and put the new frame on the queue.
2161 * This should never fail since we check above that no frames
2162 * are still pending on the queue.
2163 */
2164 if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) {
2165 ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq);
2166 /* NB: hw still stops DMA, so proceed */
2167 }
2168
2169 ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
2170 ath5k_hw_start_tx_dma(ah, sc->bhalq);
2171 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
2172 sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
2173
2174 sc->bsent++;
2175}
2176
2177
2178/**
2179 * ath5k_beacon_update_timers - update beacon timers
2180 *
2181 * @sc: struct ath5k_softc pointer we are operating on
2182 * @bc_tsf: the timestamp of the beacon. 0 to reset the TSF. -1 to perform a
2183 * beacon timer update based on the current HW TSF.
2184 *
2185 * Calculate the next target beacon transmit time (TBTT) based on the timestamp
2186 * of a received beacon or the current local hardware TSF and write it to the
2187 * beacon timer registers.
2188 *
2189 * This is called in a variety of situations, e.g. when a beacon is received,
2190 * when a TSF update has been detected, but also when an new IBSS is created or
2191 * when we otherwise know we have to update the timers, but we keep it in this
2192 * function to have it all together in one place.
2193 */
2194static void
2195ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
2196{
2197 struct ath5k_hw *ah = sc->ah;
2198 u32 nexttbtt, intval, hw_tu, bc_tu;
2199 u64 hw_tsf;
2200
2201 intval = sc->bintval & AR5K_BEACON_PERIOD;
2202 if (WARN_ON(!intval))
2203 return;
2204
2205 /* beacon TSF converted to TU */
2206 bc_tu = TSF_TO_TU(bc_tsf);
2207
2208 /* current TSF converted to TU */
2209 hw_tsf = ath5k_hw_get_tsf64(ah);
2210 hw_tu = TSF_TO_TU(hw_tsf);
2211
2212#define FUDGE 3
2213 /* we use FUDGE to make sure the next TBTT is ahead of the current TU */
2214 if (bc_tsf == -1) {
2215 /*
2216 * no beacons received, called internally.
2217 * just need to refresh timers based on HW TSF.
2218 */
2219 nexttbtt = roundup(hw_tu + FUDGE, intval);
2220 } else if (bc_tsf == 0) {
2221 /*
2222 * no beacon received, probably called by ath5k_reset_tsf().
2223 * reset TSF to start with 0.
2224 */
2225 nexttbtt = intval;
2226 intval |= AR5K_BEACON_RESET_TSF;
2227 } else if (bc_tsf > hw_tsf) {
2228 /*
2229 * beacon received, SW merge happend but HW TSF not yet updated.
2230 * not possible to reconfigure timers yet, but next time we
2231 * receive a beacon with the same BSSID, the hardware will
2232 * automatically update the TSF and then we need to reconfigure
2233 * the timers.
2234 */
2235 ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
2236 "need to wait for HW TSF sync\n");
2237 return;
2238 } else {
2239 /*
2240 * most important case for beacon synchronization between STA.
2241 *
2242 * beacon received and HW TSF has been already updated by HW.
2243 * update next TBTT based on the TSF of the beacon, but make
2244 * sure it is ahead of our local TSF timer.
2245 */
2246 nexttbtt = bc_tu + roundup(hw_tu + FUDGE - bc_tu, intval);
2247 }
2248#undef FUDGE
2249
2250 sc->nexttbtt = nexttbtt;
2251
2252 intval |= AR5K_BEACON_ENA;
2253 ath5k_hw_init_beacon(ah, nexttbtt, intval);
2254
2255 /*
2256 * debugging output last in order to preserve the time critical aspect
2257 * of this function
2258 */
2259 if (bc_tsf == -1)
2260 ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
2261 "reconfigured timers based on HW TSF\n");
2262 else if (bc_tsf == 0)
2263 ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
2264 "reset HW TSF and timers\n");
2265 else
2266 ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
2267 "updated timers based on beacon TSF\n");
2268
2269 ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
2270 "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n",
2271 (unsigned long long) bc_tsf,
2272 (unsigned long long) hw_tsf, bc_tu, hw_tu, nexttbtt);
2273 ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n",
2274 intval & AR5K_BEACON_PERIOD,
2275 intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "",
2276 intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : "");
2277}
2278
2279
2280/**
2281 * ath5k_beacon_config - Configure the beacon queues and interrupts
2282 *
2283 * @sc: struct ath5k_softc pointer we are operating on
2284 *
2285 * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
2286 * interrupts to detect TSF updates only.
2287 */
2288static void
2289ath5k_beacon_config(struct ath5k_softc *sc)
2290{
2291 struct ath5k_hw *ah = sc->ah;
2292 unsigned long flags;
2293
2294 ath5k_hw_set_imr(ah, 0);
2295 sc->bmisscount = 0;
2296 sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
2297
2298 if (sc->opmode == NL80211_IFTYPE_ADHOC ||
2299 sc->opmode == NL80211_IFTYPE_MESH_POINT ||
2300 sc->opmode == NL80211_IFTYPE_AP) {
2301 /*
2302 * In IBSS mode we use a self-linked tx descriptor and let the
2303 * hardware send the beacons automatically. We have to load it
2304 * only once here.
2305 * We use the SWBA interrupt only to keep track of the beacon
2306 * timers in order to detect automatic TSF updates.
2307 */
2308 ath5k_beaconq_config(sc);
2309
2310 sc->imask |= AR5K_INT_SWBA;
2311
2312 if (sc->opmode == NL80211_IFTYPE_ADHOC) {
2313 if (ath5k_hw_hasveol(ah)) {
2314 spin_lock_irqsave(&sc->block, flags);
2315 ath5k_beacon_send(sc);
2316 spin_unlock_irqrestore(&sc->block, flags);
2317 }
2318 } else
2319 ath5k_beacon_update_timers(sc, -1);
2320 }
2321
2322 ath5k_hw_set_imr(ah, sc->imask);
2323}
2324
2325
2326/********************\
2327* Interrupt handling *
2328\********************/
2329
2330static int
2331ath5k_init(struct ath5k_softc *sc)
2332{
2333 struct ath5k_hw *ah = sc->ah;
2334 int ret, i;
2335
2336 mutex_lock(&sc->lock);
2337
2338 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
2339
2340 /*
2341 * Stop anything previously setup. This is safe
2342 * no matter this is the first time through or not.
2343 */
2344 ath5k_stop_locked(sc);
2345
2346 /*
2347 * The basic interface to setting the hardware in a good
2348 * state is ``reset''. On return the hardware is known to
2349 * be powered up and with interrupts disabled. This must
2350 * be followed by initialization of the appropriate bits
2351 * and then setup of the interrupt mask.
2352 */
2353 sc->curchan = sc->hw->conf.channel;
2354 sc->curband = &sc->sbands[sc->curchan->band];
2355 sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
2356 AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
2357 AR5K_INT_FATAL | AR5K_INT_GLOBAL;
2358 ret = ath5k_reset(sc, false, false);
2359 if (ret)
2360 goto done;
2361
2362 /*
2363 * Reset the key cache since some parts do not reset the
2364 * contents on initial power up or resume from suspend.
2365 */
2366 for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
2367 ath5k_hw_reset_key(ah, i);
2368
2369 /* Set ack to be sent at low bit-rates */
2370 ath5k_hw_set_ack_bitrate_high(ah, false);
2371
2372 mod_timer(&sc->calib_tim, round_jiffies(jiffies +
2373 msecs_to_jiffies(ath5k_calinterval * 1000)));
2374
2375 ret = 0;
2376done:
2377 mmiowb();
2378 mutex_unlock(&sc->lock);
2379 return ret;
2380}
2381
2382static int
2383ath5k_stop_locked(struct ath5k_softc *sc)
2384{
2385 struct ath5k_hw *ah = sc->ah;
2386
2387 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n",
2388 test_bit(ATH_STAT_INVALID, sc->status));
2389
2390 /*
2391 * Shutdown the hardware and driver:
2392 * stop output from above
2393 * disable interrupts
2394 * turn off timers
2395 * turn off the radio
2396 * clear transmit machinery
2397 * clear receive machinery
2398 * drain and release tx queues
2399 * reclaim beacon resources
2400 * power down hardware
2401 *
2402 * Note that some of this work is not possible if the
2403 * hardware is gone (invalid).
2404 */
2405 ieee80211_stop_queues(sc->hw);
2406
2407 if (!test_bit(ATH_STAT_INVALID, sc->status)) {
2408 ath5k_led_off(sc);
2409 ath5k_hw_set_imr(ah, 0);
2410 synchronize_irq(sc->pdev->irq);
2411 }
2412 ath5k_txq_cleanup(sc);
2413 if (!test_bit(ATH_STAT_INVALID, sc->status)) {
2414 ath5k_rx_stop(sc);
2415 ath5k_hw_phy_disable(ah);
2416 } else
2417 sc->rxlink = NULL;
2418
2419 return 0;
2420}
2421
2422/*
2423 * Stop the device, grabbing the top-level lock to protect
2424 * against concurrent entry through ath5k_init (which can happen
2425 * if another thread does a system call and the thread doing the
2426 * stop is preempted).
2427 */
2428static int
2429ath5k_stop_hw(struct ath5k_softc *sc)
2430{
2431 int ret;
2432
2433 mutex_lock(&sc->lock);
2434 ret = ath5k_stop_locked(sc);
2435 if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
2436 /*
2437 * Set the chip in full sleep mode. Note that we are
2438 * careful to do this only when bringing the interface
2439 * completely to a stop. When the chip is in this state
2440 * it must be carefully woken up or references to
2441 * registers in the PCI clock domain may freeze the bus
2442 * (and system). This varies by chip and is mostly an
2443 * issue with newer parts that go to sleep more quickly.
2444 */
2445 if (sc->ah->ah_mac_srev >= 0x78) {
2446 /*
2447 * XXX
2448 * don't put newer MAC revisions > 7.8 to sleep because
2449 * of the above mentioned problems
2450 */
2451 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mac version > 7.8, "
2452 "not putting device to sleep\n");
2453 } else {
2454 ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
2455 "putting device to full sleep\n");
2456 ath5k_hw_set_power(sc->ah, AR5K_PM_FULL_SLEEP, true, 0);
2457 }
2458 }
2459 ath5k_txbuf_free(sc, sc->bbuf);
2460
2461 mmiowb();
2462 mutex_unlock(&sc->lock);
2463
2464 del_timer_sync(&sc->calib_tim);
2465 tasklet_kill(&sc->rxtq);
2466 tasklet_kill(&sc->txtq);
2467 tasklet_kill(&sc->restq);
2468 tasklet_kill(&sc->beacontq);
2469
2470 return ret;
2471}
2472
2473static irqreturn_t
2474ath5k_intr(int irq, void *dev_id)
2475{
2476 struct ath5k_softc *sc = dev_id;
2477 struct ath5k_hw *ah = sc->ah;
2478 enum ath5k_int status;
2479 unsigned int counter = 1000;
2480
2481 if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) ||
2482 !ath5k_hw_is_intr_pending(ah)))
2483 return IRQ_NONE;
2484
2485 do {
2486 ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */
2487 ATH5K_DBG(sc, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n",
2488 status, sc->imask);
2489 if (unlikely(status & AR5K_INT_FATAL)) {
2490 /*
2491 * Fatal errors are unrecoverable.
2492 * Typically these are caused by DMA errors.
2493 */
2494 tasklet_schedule(&sc->restq);
2495 } else if (unlikely(status & AR5K_INT_RXORN)) {
2496 tasklet_schedule(&sc->restq);
2497 } else {
2498 if (status & AR5K_INT_SWBA) {
2499 tasklet_schedule(&sc->beacontq);
2500 }
2501 if (status & AR5K_INT_RXEOL) {
2502 /*
2503 * NB: the hardware should re-read the link when
2504 * RXE bit is written, but it doesn't work at
2505 * least on older hardware revs.
2506 */
2507 sc->rxlink = NULL;
2508 }
2509 if (status & AR5K_INT_TXURN) {
2510 /* bump tx trigger level */
2511 ath5k_hw_update_tx_triglevel(ah, true);
2512 }
2513 if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
2514 tasklet_schedule(&sc->rxtq);
2515 if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
2516 | AR5K_INT_TXERR | AR5K_INT_TXEOL))
2517 tasklet_schedule(&sc->txtq);
2518 if (status & AR5K_INT_BMISS) {
2519 /* TODO */
2520 }
2521 if (status & AR5K_INT_MIB) {
2522 /*
2523 * These stats are also used for ANI i think
2524 * so how about updating them more often ?
2525 */
2526 ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
2527 }
2528 }
2529 } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0);
2530
2531 if (unlikely(!counter))
2532 ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
2533
2534 return IRQ_HANDLED;
2535}
2536
2537static void
2538ath5k_tasklet_reset(unsigned long data)
2539{
2540 struct ath5k_softc *sc = (void *)data;
2541
2542 ath5k_reset_wake(sc);
2543}
2544
2545/*
2546 * Periodically recalibrate the PHY to account
2547 * for temperature/environment changes.
2548 */
2549static void
2550ath5k_calibrate(unsigned long data)
2551{
2552 struct ath5k_softc *sc = (void *)data;
2553 struct ath5k_hw *ah = sc->ah;
2554
2555 ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
2556 ieee80211_frequency_to_channel(sc->curchan->center_freq),
2557 sc->curchan->hw_value);
2558
2559 if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) {
2560 /*
2561 * Rfgain is out of bounds, reset the chip
2562 * to load new gain values.
2563 */
2564 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n");
2565 ath5k_reset_wake(sc);
2566 }
2567 if (ath5k_hw_phy_calibrate(ah, sc->curchan))
2568 ATH5K_ERR(sc, "calibration of channel %u failed\n",
2569 ieee80211_frequency_to_channel(
2570 sc->curchan->center_freq));
2571
2572 mod_timer(&sc->calib_tim, round_jiffies(jiffies +
2573 msecs_to_jiffies(ath5k_calinterval * 1000)));
2574}
2575
2576
2577/********************\
2578* Mac80211 functions *
2579\********************/
2580
2581static int
2582ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
2583{
2584 struct ath5k_softc *sc = hw->priv;
2585 struct ath5k_buf *bf;
2586 unsigned long flags;
2587 int hdrlen;
2588 int padsize;
2589
2590 ath5k_debug_dump_skb(sc, skb, "TX ", 1);
2591
2592 if (sc->opmode == NL80211_IFTYPE_MONITOR)
2593 ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n");
2594
2595 /*
2596 * the hardware expects the header padded to 4 byte boundaries
2597 * if this is not the case we add the padding after the header
2598 */
2599 hdrlen = ieee80211_get_hdrlen_from_skb(skb);
2600 padsize = ath5k_pad_size(hdrlen);
2601 if (padsize) {
2602
2603 if (skb_headroom(skb) < padsize) {
2604 ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough"
2605 " headroom to pad %d\n", hdrlen, padsize);
2606 goto drop_packet;
2607 }
2608 skb_push(skb, padsize);
2609 memmove(skb->data, skb->data+padsize, hdrlen);
2610 }
2611
2612 spin_lock_irqsave(&sc->txbuflock, flags);
2613 if (list_empty(&sc->txbuf)) {
2614 ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
2615 spin_unlock_irqrestore(&sc->txbuflock, flags);
2616 ieee80211_stop_queue(hw, skb_get_queue_mapping(skb));
2617 goto drop_packet;
2618 }
2619 bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
2620 list_del(&bf->list);
2621 sc->txbuf_len--;
2622 if (list_empty(&sc->txbuf))
2623 ieee80211_stop_queues(hw);
2624 spin_unlock_irqrestore(&sc->txbuflock, flags);
2625
2626 bf->skb = skb;
2627
2628 if (ath5k_txbuf_setup(sc, bf)) {
2629 bf->skb = NULL;
2630 spin_lock_irqsave(&sc->txbuflock, flags);
2631 list_add_tail(&bf->list, &sc->txbuf);
2632 sc->txbuf_len++;
2633 spin_unlock_irqrestore(&sc->txbuflock, flags);
2634 goto drop_packet;
2635 }
2636 return NETDEV_TX_OK;
2637
2638drop_packet:
2639 dev_kfree_skb_any(skb);
2640 return NETDEV_TX_OK;
2641}
2642
2643static int
2644ath5k_reset(struct ath5k_softc *sc, bool stop, bool change_channel)
2645{
2646 struct ath5k_hw *ah = sc->ah;
2647 int ret;
2648
2649 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
2650
2651 if (stop) {
2652 ath5k_hw_set_imr(ah, 0);
2653 ath5k_txq_cleanup(sc);
2654 ath5k_rx_stop(sc);
2655 }
2656 ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
2657 if (ret) {
2658 ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
2659 goto err;
2660 }
2661
2662 ret = ath5k_rx_start(sc);
2663 if (ret) {
2664 ATH5K_ERR(sc, "can't start recv logic\n");
2665 goto err;
2666 }
2667
2668 /*
2669 * Change channels and update the h/w rate map if we're switching;
2670 * e.g. 11a to 11b/g.
2671 *
2672 * We may be doing a reset in response to an ioctl that changes the
2673 * channel so update any state that might change as a result.
2674 *
2675 * XXX needed?
2676 */
2677/* ath5k_chan_change(sc, c); */
2678
2679 ath5k_beacon_config(sc);
2680 /* intrs are enabled by ath5k_beacon_config */
2681
2682 return 0;
2683err:
2684 return ret;
2685}
2686
2687static int
2688ath5k_reset_wake(struct ath5k_softc *sc)
2689{
2690 int ret;
2691
2692 ret = ath5k_reset(sc, true, true);
2693 if (!ret)
2694 ieee80211_wake_queues(sc->hw);
2695
2696 return ret;
2697}
2698
2699static int ath5k_start(struct ieee80211_hw *hw)
2700{
2701 return ath5k_init(hw->priv);
2702}
2703
2704static void ath5k_stop(struct ieee80211_hw *hw)
2705{
2706 ath5k_stop_hw(hw->priv);
2707}
2708
2709static int ath5k_add_interface(struct ieee80211_hw *hw,
2710 struct ieee80211_if_init_conf *conf)
2711{
2712 struct ath5k_softc *sc = hw->priv;
2713 int ret;
2714
2715 mutex_lock(&sc->lock);
2716 if (sc->vif) {
2717 ret = 0;
2718 goto end;
2719 }
2720
2721 sc->vif = conf->vif;
2722
2723 switch (conf->type) {
2724 case NL80211_IFTYPE_AP:
2725 case NL80211_IFTYPE_STATION:
2726 case NL80211_IFTYPE_ADHOC:
2727 case NL80211_IFTYPE_MESH_POINT:
2728 case NL80211_IFTYPE_MONITOR:
2729 sc->opmode = conf->type;
2730 break;
2731 default:
2732 ret = -EOPNOTSUPP;
2733 goto end;
2734 }
2735
2736 /* Set to a reasonable value. Note that this will
2737 * be set to mac80211's value at ath5k_config(). */
2738 sc->bintval = 1000;
2739 ath5k_hw_set_lladdr(sc->ah, conf->mac_addr);
2740
2741 ret = 0;
2742end:
2743 mutex_unlock(&sc->lock);
2744 return ret;
2745}
2746
2747static void
2748ath5k_remove_interface(struct ieee80211_hw *hw,
2749 struct ieee80211_if_init_conf *conf)
2750{
2751 struct ath5k_softc *sc = hw->priv;
2752 u8 mac[ETH_ALEN] = {};
2753
2754 mutex_lock(&sc->lock);
2755 if (sc->vif != conf->vif)
2756 goto end;
2757
2758 ath5k_hw_set_lladdr(sc->ah, mac);
2759 sc->vif = NULL;
2760end:
2761 mutex_unlock(&sc->lock);
2762}
2763
2764/*
2765 * TODO: Phy disable/diversity etc
2766 */
2767static int
2768ath5k_config(struct ieee80211_hw *hw, u32 changed)
2769{
2770 struct ath5k_softc *sc = hw->priv;
2771 struct ieee80211_conf *conf = &hw->conf;
2772 int ret;
2773
2774 mutex_lock(&sc->lock);
2775
2776 sc->bintval = conf->beacon_int;
2777 sc->power_level = conf->power_level;
2778
2779 ret = ath5k_chan_set(sc, conf->channel);
2780
2781 mutex_unlock(&sc->lock);
2782 return ret;
2783}
2784
2785static int
2786ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2787 struct ieee80211_if_conf *conf)
2788{
2789 struct ath5k_softc *sc = hw->priv;
2790 struct ath5k_hw *ah = sc->ah;
2791 int ret = 0;
2792
2793 mutex_lock(&sc->lock);
2794 if (sc->vif != vif) {
2795 ret = -EIO;
2796 goto unlock;
2797 }
2798 if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) {
2799 /* Cache for later use during resets */
2800 memcpy(ah->ah_bssid, conf->bssid, ETH_ALEN);
2801 /* XXX: assoc id is set to 0 for now, mac80211 doesn't have
2802 * a clean way of letting us retrieve this yet. */
2803 ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
2804 mmiowb();
2805 }
2806 if (conf->changed & IEEE80211_IFCC_BEACON &&
2807 (vif->type == NL80211_IFTYPE_ADHOC ||
2808 vif->type == NL80211_IFTYPE_MESH_POINT ||
2809 vif->type == NL80211_IFTYPE_AP)) {
2810 struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
2811 if (!beacon) {
2812 ret = -ENOMEM;
2813 goto unlock;
2814 }
2815 ath5k_beacon_update(sc, beacon);
2816 }
2817
2818unlock:
2819 mutex_unlock(&sc->lock);
2820 return ret;
2821}
2822
2823#define SUPPORTED_FIF_FLAGS \
2824 FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \
2825 FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
2826 FIF_BCN_PRBRESP_PROMISC
2827/*
2828 * o always accept unicast, broadcast, and multicast traffic
2829 * o multicast traffic for all BSSIDs will be enabled if mac80211
2830 * says it should be
2831 * o maintain current state of phy ofdm or phy cck error reception.
2832 * If the hardware detects any of these type of errors then
2833 * ath5k_hw_get_rx_filter() will pass to us the respective
2834 * hardware filters to be able to receive these type of frames.
2835 * o probe request frames are accepted only when operating in
2836 * hostap, adhoc, or monitor modes
2837 * o enable promiscuous mode according to the interface state
2838 * o accept beacons:
2839 * - when operating in adhoc mode so the 802.11 layer creates
2840 * node table entries for peers,
2841 * - when operating in station mode for collecting rssi data when
2842 * the station is otherwise quiet, or
2843 * - when scanning
2844 */
2845static void ath5k_configure_filter(struct ieee80211_hw *hw,
2846 unsigned int changed_flags,
2847 unsigned int *new_flags,
2848 int mc_count, struct dev_mc_list *mclist)
2849{
2850 struct ath5k_softc *sc = hw->priv;
2851 struct ath5k_hw *ah = sc->ah;
2852 u32 mfilt[2], val, rfilt;
2853 u8 pos;
2854 int i;
2855
2856 mfilt[0] = 0;
2857 mfilt[1] = 0;
2858
2859 /* Only deal with supported flags */
2860 changed_flags &= SUPPORTED_FIF_FLAGS;
2861 *new_flags &= SUPPORTED_FIF_FLAGS;
2862
2863 /* If HW detects any phy or radar errors, leave those filters on.
2864 * Also, always enable Unicast, Broadcasts and Multicast
2865 * XXX: move unicast, bssid broadcasts and multicast to mac80211 */
2866 rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) |
2867 (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST |
2868 AR5K_RX_FILTER_MCAST);
2869
2870 if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
2871 if (*new_flags & FIF_PROMISC_IN_BSS) {
2872 rfilt |= AR5K_RX_FILTER_PROM;
2873 __set_bit(ATH_STAT_PROMISC, sc->status);
2874 } else {
2875 __clear_bit(ATH_STAT_PROMISC, sc->status);
2876 }
2877 }
2878
2879 /* Note, AR5K_RX_FILTER_MCAST is already enabled */
2880 if (*new_flags & FIF_ALLMULTI) {
2881 mfilt[0] = ~0;
2882 mfilt[1] = ~0;
2883 } else {
2884 for (i = 0; i < mc_count; i++) {
2885 if (!mclist)
2886 break;
2887 /* calculate XOR of eight 6-bit values */
2888 val = get_unaligned_le32(mclist->dmi_addr + 0);
2889 pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
2890 val = get_unaligned_le32(mclist->dmi_addr + 3);
2891 pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
2892 pos &= 0x3f;
2893 mfilt[pos / 32] |= (1 << (pos % 32));
2894 /* XXX: we might be able to just do this instead,
2895 * but not sure, needs testing, if we do use this we'd
2896 * neet to inform below to not reset the mcast */
2897 /* ath5k_hw_set_mcast_filterindex(ah,
2898 * mclist->dmi_addr[5]); */
2899 mclist = mclist->next;
2900 }
2901 }
2902
2903 /* This is the best we can do */
2904 if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))
2905 rfilt |= AR5K_RX_FILTER_PHYERR;
2906
2907 /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
2908 * and probes for any BSSID, this needs testing */
2909 if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
2910 rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ;
2911
2912 /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
2913 * set we should only pass on control frames for this
2914 * station. This needs testing. I believe right now this
2915 * enables *all* control frames, which is OK.. but
2916 * but we should see if we can improve on granularity */
2917 if (*new_flags & FIF_CONTROL)
2918 rfilt |= AR5K_RX_FILTER_CONTROL;
2919
2920 /* Additional settings per mode -- this is per ath5k */
2921
2922 /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
2923
2924 if (sc->opmode == NL80211_IFTYPE_MONITOR)
2925 rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
2926 AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
2927 if (sc->opmode != NL80211_IFTYPE_STATION)
2928 rfilt |= AR5K_RX_FILTER_PROBEREQ;
2929 if (sc->opmode != NL80211_IFTYPE_AP &&
2930 sc->opmode != NL80211_IFTYPE_MESH_POINT &&
2931 test_bit(ATH_STAT_PROMISC, sc->status))
2932 rfilt |= AR5K_RX_FILTER_PROM;
2933 if ((sc->opmode == NL80211_IFTYPE_STATION && sc->assoc) ||
2934 sc->opmode == NL80211_IFTYPE_ADHOC ||
2935 sc->opmode == NL80211_IFTYPE_AP)
2936 rfilt |= AR5K_RX_FILTER_BEACON;
2937 if (sc->opmode == NL80211_IFTYPE_MESH_POINT)
2938 rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
2939 AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
2940
2941 /* Set filters */
2942 ath5k_hw_set_rx_filter(ah, rfilt);
2943
2944 /* Set multicast bits */
2945 ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
2946 /* Set the cached hw filter flags, this will alter actually
2947 * be set in HW */
2948 sc->filter_flags = rfilt;
2949}
2950
2951static int
2952ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
2953 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
2954 struct ieee80211_key_conf *key)
2955{
2956 struct ath5k_softc *sc = hw->priv;
2957 int ret = 0;
2958
2959 if (modparam_nohwcrypt)
2960 return -EOPNOTSUPP;
2961
2962 switch (key->alg) {
2963 case ALG_WEP:
2964 case ALG_TKIP:
2965 break;
2966 case ALG_CCMP:
2967 return -EOPNOTSUPP;
2968 default:
2969 WARN_ON(1);
2970 return -EINVAL;
2971 }
2972
2973 mutex_lock(&sc->lock);
2974
2975 switch (cmd) {
2976 case SET_KEY:
2977 ret = ath5k_hw_set_key(sc->ah, key->keyidx, key,
2978 sta ? sta->addr : NULL);
2979 if (ret) {
2980 ATH5K_ERR(sc, "can't set the key\n");
2981 goto unlock;
2982 }
2983 __set_bit(key->keyidx, sc->keymap);
2984 key->hw_key_idx = key->keyidx;
2985 key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV |
2986 IEEE80211_KEY_FLAG_GENERATE_MMIC);
2987 break;
2988 case DISABLE_KEY:
2989 ath5k_hw_reset_key(sc->ah, key->keyidx);
2990 __clear_bit(key->keyidx, sc->keymap);
2991 break;
2992 default:
2993 ret = -EINVAL;
2994 goto unlock;
2995 }
2996
2997unlock:
2998 mmiowb();
2999 mutex_unlock(&sc->lock);
3000 return ret;
3001}
3002
3003static int
3004ath5k_get_stats(struct ieee80211_hw *hw,
3005 struct ieee80211_low_level_stats *stats)
3006{
3007 struct ath5k_softc *sc = hw->priv;
3008 struct ath5k_hw *ah = sc->ah;
3009
3010 /* Force update */
3011 ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
3012
3013 memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats));
3014
3015 return 0;
3016}
3017
3018static int
3019ath5k_get_tx_stats(struct ieee80211_hw *hw,
3020 struct ieee80211_tx_queue_stats *stats)
3021{
3022 struct ath5k_softc *sc = hw->priv;
3023
3024 memcpy(stats, &sc->tx_stats, sizeof(sc->tx_stats));
3025
3026 return 0;
3027}
3028
3029static u64
3030ath5k_get_tsf(struct ieee80211_hw *hw)
3031{
3032 struct ath5k_softc *sc = hw->priv;
3033
3034 return ath5k_hw_get_tsf64(sc->ah);
3035}
3036
3037static void
3038ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
3039{
3040 struct ath5k_softc *sc = hw->priv;
3041
3042 ath5k_hw_set_tsf64(sc->ah, tsf);
3043}
3044
3045static void
3046ath5k_reset_tsf(struct ieee80211_hw *hw)
3047{
3048 struct ath5k_softc *sc = hw->priv;
3049
3050 /*
3051 * in IBSS mode we need to update the beacon timers too.
3052 * this will also reset the TSF if we call it with 0
3053 */
3054 if (sc->opmode == NL80211_IFTYPE_ADHOC)
3055 ath5k_beacon_update_timers(sc, 0);
3056 else
3057 ath5k_hw_reset_tsf(sc->ah);
3058}
3059
3060static int
3061ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb)
3062{
3063 unsigned long flags;
3064 int ret;
3065
3066 ath5k_debug_dump_skb(sc, skb, "BC ", 1);
3067
3068 spin_lock_irqsave(&sc->block, flags);
3069 ath5k_txbuf_free(sc, sc->bbuf);
3070 sc->bbuf->skb = skb;
3071 ret = ath5k_beacon_setup(sc, sc->bbuf);
3072 if (ret)
3073 sc->bbuf->skb = NULL;
3074 spin_unlock_irqrestore(&sc->block, flags);
3075 if (!ret) {
3076 ath5k_beacon_config(sc);
3077 mmiowb();
3078 }
3079
3080 return ret;
3081}
3082static void
3083set_beacon_filter(struct ieee80211_hw *hw, bool enable)
3084{
3085 struct ath5k_softc *sc = hw->priv;
3086 struct ath5k_hw *ah = sc->ah;
3087 u32 rfilt;
3088 rfilt = ath5k_hw_get_rx_filter(ah);
3089 if (enable)
3090 rfilt |= AR5K_RX_FILTER_BEACON;
3091 else
3092 rfilt &= ~AR5K_RX_FILTER_BEACON;
3093 ath5k_hw_set_rx_filter(ah, rfilt);
3094 sc->filter_flags = rfilt;
3095}
3096
3097static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
3098 struct ieee80211_vif *vif,
3099 struct ieee80211_bss_conf *bss_conf,
3100 u32 changes)
3101{
3102 struct ath5k_softc *sc = hw->priv;
3103 if (changes & BSS_CHANGED_ASSOC) {
3104 mutex_lock(&sc->lock);
3105 sc->assoc = bss_conf->assoc;
3106 if (sc->opmode == NL80211_IFTYPE_STATION)
3107 set_beacon_filter(hw, sc->assoc);
3108 mutex_unlock(&sc->lock);
3109 }
3110}
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
new file mode 100644
index 000000000000..822956114cd7
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -0,0 +1,190 @@
1/*-
2 * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 * redistribution must be conditioned upon including a substantially
14 * similar Disclaimer requirement for further binary redistribution.
15 * 3. Neither the names of the above-listed copyright holders nor the names
16 * of any contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * Alternatively, this software may be distributed under the terms of the
20 * GNU General Public License ("GPL") version 2 as published by the Free
21 * Software Foundation.
22 *
23 * NO WARRANTY
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
28 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
29 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
32 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34 * THE POSSIBILITY OF SUCH DAMAGES.
35 *
36 */
37
38/*
39 * Defintions for the Atheros Wireless LAN controller driver.
40 */
41#ifndef _DEV_ATH_ATHVAR_H
42#define _DEV_ATH_ATHVAR_H
43
44#include <linux/interrupt.h>
45#include <linux/list.h>
46#include <linux/wireless.h>
47#include <linux/if_ether.h>
48#include <linux/leds.h>
49
50#include "ath5k.h"
51#include "debug.h"
52
53#define ATH_RXBUF 40 /* number of RX buffers */
54#define ATH_TXBUF 200 /* number of TX buffers */
55#define ATH_BCBUF 1 /* number of beacon buffers */
56
57struct ath5k_buf {
58 struct list_head list;
59 unsigned int flags; /* rx descriptor flags */
60 struct ath5k_desc *desc; /* virtual addr of desc */
61 dma_addr_t daddr; /* physical addr of desc */
62 struct sk_buff *skb; /* skbuff for buf */
63 dma_addr_t skbaddr;/* physical addr of skb data */
64};
65
66/*
67 * Data transmit queue state. One of these exists for each
68 * hardware transmit queue. Packets sent to us from above
69 * are assigned to queues based on their priority. Not all
70 * devices support a complete set of hardware transmit queues.
71 * For those devices the array sc_ac2q will map multiple
72 * priorities to fewer hardware queues (typically all to one
73 * hardware queue).
74 */
75struct ath5k_txq {
76 unsigned int qnum; /* hardware q number */
77 u32 *link; /* link ptr in last TX desc */
78 struct list_head q; /* transmit queue */
79 spinlock_t lock; /* lock on q and link */
80 bool setup;
81};
82
83#define ATH5K_LED_MAX_NAME_LEN 31
84
85/*
86 * State for LED triggers
87 */
88struct ath5k_led
89{
90 char name[ATH5K_LED_MAX_NAME_LEN + 1]; /* name of the LED in sysfs */
91 struct ath5k_softc *sc; /* driver state */
92 struct led_classdev led_dev; /* led classdev */
93};
94
95
96#if CHAN_DEBUG
97#define ATH_CHAN_MAX (26+26+26+200+200)
98#else
99#define ATH_CHAN_MAX (14+14+14+252+20)
100#endif
101
102/* Software Carrier, keeps track of the driver state
103 * associated with an instance of a device */
104struct ath5k_softc {
105 struct pci_dev *pdev; /* for dma mapping */
106 void __iomem *iobase; /* address of the device */
107 struct mutex lock; /* dev-level lock */
108 /* FIXME: how many does it really need? */
109 struct ieee80211_tx_queue_stats tx_stats[16];
110 struct ieee80211_low_level_stats ll_stats;
111 struct ieee80211_hw *hw; /* IEEE 802.11 common */
112 struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
113 struct ieee80211_channel channels[ATH_CHAN_MAX];
114 struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
115 s8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
116 enum nl80211_iftype opmode;
117 struct ath5k_hw *ah; /* Atheros HW */
118
119 struct ieee80211_supported_band *curband;
120
121#ifdef CONFIG_ATH5K_DEBUG
122 struct ath5k_dbg_info debug; /* debug info */
123#endif /* CONFIG_ATH5K_DEBUG */
124
125 struct ath5k_buf *bufptr; /* allocated buffer ptr */
126 struct ath5k_desc *desc; /* TX/RX descriptors */
127 dma_addr_t desc_daddr; /* DMA (physical) address */
128 size_t desc_len; /* size of TX/RX descriptors */
129 u16 cachelsz; /* cache line size */
130
131 DECLARE_BITMAP(status, 5);
132#define ATH_STAT_INVALID 0 /* disable hardware accesses */
133#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */
134#define ATH_STAT_PROMISC 2
135#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */
136#define ATH_STAT_STARTED 4 /* opened & irqs enabled */
137
138 unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
139 unsigned int curmode; /* current phy mode */
140 struct ieee80211_channel *curchan; /* current h/w channel */
141
142 struct ieee80211_vif *vif;
143
144 enum ath5k_int imask; /* interrupt mask copy */
145
146 DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */
147
148 u8 bssidmask[ETH_ALEN];
149
150 unsigned int led_pin, /* GPIO pin for driving LED */
151 led_on; /* pin setting for LED on */
152
153 struct tasklet_struct restq; /* reset tasklet */
154
155 unsigned int rxbufsize; /* rx size based on mtu */
156 struct list_head rxbuf; /* receive buffer */
157 spinlock_t rxbuflock;
158 u32 *rxlink; /* link ptr in last RX desc */
159 struct tasklet_struct rxtq; /* rx intr tasklet */
160 struct ath5k_led rx_led; /* rx led */
161
162 struct list_head txbuf; /* transmit buffer */
163 spinlock_t txbuflock;
164 unsigned int txbuf_len; /* buf count in txbuf list */
165 struct ath5k_txq txqs[2]; /* beacon and tx */
166
167 struct ath5k_txq *txq; /* beacon and tx*/
168 struct tasklet_struct txtq; /* tx intr tasklet */
169 struct ath5k_led tx_led; /* tx led */
170
171 spinlock_t block; /* protects beacon */
172 struct tasklet_struct beacontq; /* beacon intr tasklet */
173 struct ath5k_buf *bbuf; /* beacon buffer */
174 unsigned int bhalq, /* SW q for outgoing beacons */
175 bmisscount, /* missed beacon transmits */
176 bintval, /* beacon interval in TU */
177 bsent;
178 unsigned int nexttbtt; /* next beacon time in TU */
179
180 struct timer_list calib_tim; /* calibration timer */
181 int power_level; /* Requested tx power in dbm */
182 bool assoc; /* assocate state */
183};
184
185#define ath5k_hw_hasbssidmask(_ah) \
186 (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0)
187#define ath5k_hw_hasveol(_ah) \
188 (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0)
189
190#endif
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c
new file mode 100644
index 000000000000..367a6c7d3cc7
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/caps.c
@@ -0,0 +1,195 @@
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4 * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20/**************\
21* Capabilities *
22\**************/
23
24#include "ath5k.h"
25#include "reg.h"
26#include "debug.h"
27#include "base.h"
28
29/*
30 * Fill the capabilities struct
31 * TODO: Merge this with EEPROM code when we are done with it
32 */
33int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
34{
35 u16 ee_header;
36
37 ATH5K_TRACE(ah->ah_sc);
38 /* Capabilities stored in the EEPROM */
39 ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
40
41 if (ah->ah_version == AR5K_AR5210) {
42 /*
43 * Set radio capabilities
44 * (The AR5110 only supports the middle 5GHz band)
45 */
46 ah->ah_capabilities.cap_range.range_5ghz_min = 5120;
47 ah->ah_capabilities.cap_range.range_5ghz_max = 5430;
48 ah->ah_capabilities.cap_range.range_2ghz_min = 0;
49 ah->ah_capabilities.cap_range.range_2ghz_max = 0;
50
51 /* Set supported modes */
52 __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
53 __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode);
54 } else {
55 /*
56 * XXX The tranceiver supports frequencies from 4920 to 6100GHz
57 * XXX and from 2312 to 2732GHz. There are problems with the
58 * XXX current ieee80211 implementation because the IEEE
59 * XXX channel mapping does not support negative channel
60 * XXX numbers (2312MHz is channel -19). Of course, this
61 * XXX doesn't matter because these channels are out of range
62 * XXX but some regulation domains like MKK (Japan) will
63 * XXX support frequencies somewhere around 4.8GHz.
64 */
65
66 /*
67 * Set radio capabilities
68 */
69
70 if (AR5K_EEPROM_HDR_11A(ee_header)) {
71 /* 4920 */
72 ah->ah_capabilities.cap_range.range_5ghz_min = 5005;
73 ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
74
75 /* Set supported modes */
76 __set_bit(AR5K_MODE_11A,
77 ah->ah_capabilities.cap_mode);
78 __set_bit(AR5K_MODE_11A_TURBO,
79 ah->ah_capabilities.cap_mode);
80 if (ah->ah_version == AR5K_AR5212)
81 __set_bit(AR5K_MODE_11G_TURBO,
82 ah->ah_capabilities.cap_mode);
83 }
84
85 /* Enable 802.11b if a 2GHz capable radio (2111/5112) is
86 * connected */
87 if (AR5K_EEPROM_HDR_11B(ee_header) ||
88 (AR5K_EEPROM_HDR_11G(ee_header) &&
89 ah->ah_version != AR5K_AR5211)) {
90 /* 2312 */
91 ah->ah_capabilities.cap_range.range_2ghz_min = 2412;
92 ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
93
94 if (AR5K_EEPROM_HDR_11B(ee_header))
95 __set_bit(AR5K_MODE_11B,
96 ah->ah_capabilities.cap_mode);
97
98 if (AR5K_EEPROM_HDR_11G(ee_header) &&
99 ah->ah_version != AR5K_AR5211)
100 __set_bit(AR5K_MODE_11G,
101 ah->ah_capabilities.cap_mode);
102 }
103 }
104
105 /* GPIO */
106 ah->ah_gpio_npins = AR5K_NUM_GPIO;
107
108 /* Set number of supported TX queues */
109 if (ah->ah_version == AR5K_AR5210)
110 ah->ah_capabilities.cap_queues.q_tx_num =
111 AR5K_NUM_TX_QUEUES_NOQCU;
112 else
113 ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES;
114
115 return 0;
116}
117
118/* Main function used by the driver part to check caps */
119int ath5k_hw_get_capability(struct ath5k_hw *ah,
120 enum ath5k_capability_type cap_type,
121 u32 capability, u32 *result)
122{
123 ATH5K_TRACE(ah->ah_sc);
124
125 switch (cap_type) {
126 case AR5K_CAP_NUM_TXQUEUES:
127 if (result) {
128 if (ah->ah_version == AR5K_AR5210)
129 *result = AR5K_NUM_TX_QUEUES_NOQCU;
130 else
131 *result = AR5K_NUM_TX_QUEUES;
132 goto yes;
133 }
134 case AR5K_CAP_VEOL:
135 goto yes;
136 case AR5K_CAP_COMPRESSION:
137 if (ah->ah_version == AR5K_AR5212)
138 goto yes;
139 else
140 goto no;
141 case AR5K_CAP_BURST:
142 goto yes;
143 case AR5K_CAP_TPC:
144 goto yes;
145 case AR5K_CAP_BSSIDMASK:
146 if (ah->ah_version == AR5K_AR5212)
147 goto yes;
148 else
149 goto no;
150 case AR5K_CAP_XR:
151 if (ah->ah_version == AR5K_AR5212)
152 goto yes;
153 else
154 goto no;
155 default:
156 goto no;
157 }
158
159no:
160 return -EINVAL;
161yes:
162 return 0;
163}
164
165/*
166 * TODO: Following functions should be part of a new function
167 * set_capability
168 */
169
170int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid,
171 u16 assoc_id)
172{
173 ATH5K_TRACE(ah->ah_sc);
174
175 if (ah->ah_version == AR5K_AR5210) {
176 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
177 AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
178 return 0;
179 }
180
181 return -EIO;
182}
183
184int ath5k_hw_disable_pspoll(struct ath5k_hw *ah)
185{
186 ATH5K_TRACE(ah->ah_sc);
187
188 if (ah->ah_version == AR5K_AR5210) {
189 AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
190 AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
191 return 0;
192 }
193
194 return -EIO;
195}
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
new file mode 100644
index 000000000000..9770bb3d40f9
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -0,0 +1,538 @@
1/*
2 * Copyright (c) 2007-2008 Bruno Randolf <bruno@thinktube.com>
3 *
4 * This file is free software: you may copy, redistribute and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation, either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This file is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 *
18 * This file incorporates work covered by the following copyright and
19 * permission notice:
20 *
21 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
22 * Copyright (c) 2004-2005 Atheros Communications, Inc.
23 * Copyright (c) 2006 Devicescape Software, Inc.
24 * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
25 * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
26 *
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer,
34 * without modification.
35 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
36 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
37 * redistribution must be conditioned upon including a substantially
38 * similar Disclaimer requirement for further binary redistribution.
39 * 3. Neither the names of the above-listed copyright holders nor the names
40 * of any contributors may be used to endorse or promote products derived
41 * from this software without specific prior written permission.
42 *
43 * Alternatively, this software may be distributed under the terms of the
44 * GNU General Public License ("GPL") version 2 as published by the Free
45 * Software Foundation.
46 *
47 * NO WARRANTY
48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
51 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
52 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
53 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
56 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
58 * THE POSSIBILITY OF SUCH DAMAGES.
59 */
60
61#include "base.h"
62#include "debug.h"
63
64static unsigned int ath5k_debug;
65module_param_named(debug, ath5k_debug, uint, 0);
66
67
68#ifdef CONFIG_ATH5K_DEBUG
69
70#include <linux/seq_file.h>
71#include "reg.h"
72
73static struct dentry *ath5k_global_debugfs;
74
75static int ath5k_debugfs_open(struct inode *inode, struct file *file)
76{
77 file->private_data = inode->i_private;
78 return 0;
79}
80
81
82/* debugfs: registers */
83
84struct reg {
85 const char *name;
86 int addr;
87};
88
89#define REG_STRUCT_INIT(r) { #r, r }
90
91/* just a few random registers, might want to add more */
92static const struct reg regs[] = {
93 REG_STRUCT_INIT(AR5K_CR),
94 REG_STRUCT_INIT(AR5K_RXDP),
95 REG_STRUCT_INIT(AR5K_CFG),
96 REG_STRUCT_INIT(AR5K_IER),
97 REG_STRUCT_INIT(AR5K_BCR),
98 REG_STRUCT_INIT(AR5K_RTSD0),
99 REG_STRUCT_INIT(AR5K_RTSD1),
100 REG_STRUCT_INIT(AR5K_TXCFG),
101 REG_STRUCT_INIT(AR5K_RXCFG),
102 REG_STRUCT_INIT(AR5K_RXJLA),
103 REG_STRUCT_INIT(AR5K_MIBC),
104 REG_STRUCT_INIT(AR5K_TOPS),
105 REG_STRUCT_INIT(AR5K_RXNOFRM),
106 REG_STRUCT_INIT(AR5K_TXNOFRM),
107 REG_STRUCT_INIT(AR5K_RPGTO),
108 REG_STRUCT_INIT(AR5K_RFCNT),
109 REG_STRUCT_INIT(AR5K_MISC),
110 REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT),
111 REG_STRUCT_INIT(AR5K_ISR),
112 REG_STRUCT_INIT(AR5K_PISR),
113 REG_STRUCT_INIT(AR5K_SISR0),
114 REG_STRUCT_INIT(AR5K_SISR1),
115 REG_STRUCT_INIT(AR5K_SISR2),
116 REG_STRUCT_INIT(AR5K_SISR3),
117 REG_STRUCT_INIT(AR5K_SISR4),
118 REG_STRUCT_INIT(AR5K_IMR),
119 REG_STRUCT_INIT(AR5K_PIMR),
120 REG_STRUCT_INIT(AR5K_SIMR0),
121 REG_STRUCT_INIT(AR5K_SIMR1),
122 REG_STRUCT_INIT(AR5K_SIMR2),
123 REG_STRUCT_INIT(AR5K_SIMR3),
124 REG_STRUCT_INIT(AR5K_SIMR4),
125 REG_STRUCT_INIT(AR5K_DCM_ADDR),
126 REG_STRUCT_INIT(AR5K_DCCFG),
127 REG_STRUCT_INIT(AR5K_CCFG),
128 REG_STRUCT_INIT(AR5K_CPC0),
129 REG_STRUCT_INIT(AR5K_CPC1),
130 REG_STRUCT_INIT(AR5K_CPC2),
131 REG_STRUCT_INIT(AR5K_CPC3),
132 REG_STRUCT_INIT(AR5K_CPCOVF),
133 REG_STRUCT_INIT(AR5K_RESET_CTL),
134 REG_STRUCT_INIT(AR5K_SLEEP_CTL),
135 REG_STRUCT_INIT(AR5K_INTPEND),
136 REG_STRUCT_INIT(AR5K_SFR),
137 REG_STRUCT_INIT(AR5K_PCICFG),
138 REG_STRUCT_INIT(AR5K_GPIOCR),
139 REG_STRUCT_INIT(AR5K_GPIODO),
140 REG_STRUCT_INIT(AR5K_SREV),
141};
142
143static void *reg_start(struct seq_file *seq, loff_t *pos)
144{
145 return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
146}
147
148static void reg_stop(struct seq_file *seq, void *p)
149{
150 /* nothing to do */
151}
152
153static void *reg_next(struct seq_file *seq, void *p, loff_t *pos)
154{
155 ++*pos;
156 return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
157}
158
159static int reg_show(struct seq_file *seq, void *p)
160{
161 struct ath5k_softc *sc = seq->private;
162 struct reg *r = p;
163 seq_printf(seq, "%-25s0x%08x\n", r->name,
164 ath5k_hw_reg_read(sc->ah, r->addr));
165 return 0;
166}
167
168static const struct seq_operations register_seq_ops = {
169 .start = reg_start,
170 .next = reg_next,
171 .stop = reg_stop,
172 .show = reg_show
173};
174
175static int open_file_registers(struct inode *inode, struct file *file)
176{
177 struct seq_file *s;
178 int res;
179 res = seq_open(file, &register_seq_ops);
180 if (res == 0) {
181 s = file->private_data;
182 s->private = inode->i_private;
183 }
184 return res;
185}
186
187static const struct file_operations fops_registers = {
188 .open = open_file_registers,
189 .read = seq_read,
190 .llseek = seq_lseek,
191 .release = seq_release,
192 .owner = THIS_MODULE,
193};
194
195
196/* debugfs: beacons */
197
198static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
199 size_t count, loff_t *ppos)
200{
201 struct ath5k_softc *sc = file->private_data;
202 struct ath5k_hw *ah = sc->ah;
203 char buf[500];
204 unsigned int len = 0;
205 unsigned int v;
206 u64 tsf;
207
208 v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON);
209 len += snprintf(buf+len, sizeof(buf)-len,
210 "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
211 "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
212 (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
213
214 len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n",
215 "AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP));
216
217 len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n",
218 "AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT));
219
220 v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0);
221 len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
222 "AR5K_TIMER0 (TBTT)", v, v);
223
224 v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1);
225 len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
226 "AR5K_TIMER1 (DMA)", v, v >> 3);
227
228 v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2);
229 len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
230 "AR5K_TIMER2 (SWBA)", v, v >> 3);
231
232 v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3);
233 len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
234 "AR5K_TIMER3 (ATIM)", v, v);
235
236 tsf = ath5k_hw_get_tsf64(sc->ah);
237 len += snprintf(buf+len, sizeof(buf)-len,
238 "TSF\t\t0x%016llx\tTU: %08x\n",
239 (unsigned long long)tsf, TSF_TO_TU(tsf));
240
241 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
242}
243
244static ssize_t write_file_beacon(struct file *file,
245 const char __user *userbuf,
246 size_t count, loff_t *ppos)
247{
248 struct ath5k_softc *sc = file->private_data;
249 struct ath5k_hw *ah = sc->ah;
250 char buf[20];
251
252 if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
253 return -EFAULT;
254
255 if (strncmp(buf, "disable", 7) == 0) {
256 AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
257 printk(KERN_INFO "debugfs disable beacons\n");
258 } else if (strncmp(buf, "enable", 6) == 0) {
259 AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
260 printk(KERN_INFO "debugfs enable beacons\n");
261 }
262 return count;
263}
264
265static const struct file_operations fops_beacon = {
266 .read = read_file_beacon,
267 .write = write_file_beacon,
268 .open = ath5k_debugfs_open,
269 .owner = THIS_MODULE,
270};
271
272
273/* debugfs: reset */
274
275static ssize_t write_file_reset(struct file *file,
276 const char __user *userbuf,
277 size_t count, loff_t *ppos)
278{
279 struct ath5k_softc *sc = file->private_data;
280 tasklet_schedule(&sc->restq);
281 return count;
282}
283
284static const struct file_operations fops_reset = {
285 .write = write_file_reset,
286 .open = ath5k_debugfs_open,
287 .owner = THIS_MODULE,
288};
289
290
291/* debugfs: debug level */
292
293static const struct {
294 enum ath5k_debug_level level;
295 const char *name;
296 const char *desc;
297} dbg_info[] = {
298 { ATH5K_DEBUG_RESET, "reset", "reset and initialization" },
299 { ATH5K_DEBUG_INTR, "intr", "interrupt handling" },
300 { ATH5K_DEBUG_MODE, "mode", "mode init/setup" },
301 { ATH5K_DEBUG_XMIT, "xmit", "basic xmit operation" },
302 { ATH5K_DEBUG_BEACON, "beacon", "beacon handling" },
303 { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" },
304 { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" },
305 { ATH5K_DEBUG_LED, "led", "LED management" },
306 { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" },
307 { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" },
308 { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" },
309 { ATH5K_DEBUG_TRACE, "trace", "trace function calls" },
310 { ATH5K_DEBUG_ANY, "all", "show all debug levels" },
311};
312
313static ssize_t read_file_debug(struct file *file, char __user *user_buf,
314 size_t count, loff_t *ppos)
315{
316 struct ath5k_softc *sc = file->private_data;
317 char buf[700];
318 unsigned int len = 0;
319 unsigned int i;
320
321 len += snprintf(buf+len, sizeof(buf)-len,
322 "DEBUG LEVEL: 0x%08x\n\n", sc->debug.level);
323
324 for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
325 len += snprintf(buf+len, sizeof(buf)-len,
326 "%10s %c 0x%08x - %s\n", dbg_info[i].name,
327 sc->debug.level & dbg_info[i].level ? '+' : ' ',
328 dbg_info[i].level, dbg_info[i].desc);
329 }
330 len += snprintf(buf+len, sizeof(buf)-len,
331 "%10s %c 0x%08x - %s\n", dbg_info[i].name,
332 sc->debug.level == dbg_info[i].level ? '+' : ' ',
333 dbg_info[i].level, dbg_info[i].desc);
334
335 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
336}
337
338static ssize_t write_file_debug(struct file *file,
339 const char __user *userbuf,
340 size_t count, loff_t *ppos)
341{
342 struct ath5k_softc *sc = file->private_data;
343 unsigned int i;
344 char buf[20];
345
346 if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
347 return -EFAULT;
348
349 for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
350 if (strncmp(buf, dbg_info[i].name,
351 strlen(dbg_info[i].name)) == 0) {
352 sc->debug.level ^= dbg_info[i].level; /* toggle bit */
353 break;
354 }
355 }
356 return count;
357}
358
359static const struct file_operations fops_debug = {
360 .read = read_file_debug,
361 .write = write_file_debug,
362 .open = ath5k_debugfs_open,
363 .owner = THIS_MODULE,
364};
365
366
367/* init */
368
369void
370ath5k_debug_init(void)
371{
372 ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL);
373}
374
375void
376ath5k_debug_init_device(struct ath5k_softc *sc)
377{
378 sc->debug.level = ath5k_debug;
379
380 sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
381 ath5k_global_debugfs);
382
383 sc->debug.debugfs_debug = debugfs_create_file("debug", S_IWUSR | S_IRUGO,
384 sc->debug.debugfs_phydir, sc, &fops_debug);
385
386 sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO,
387 sc->debug.debugfs_phydir, sc, &fops_registers);
388
389 sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO,
390 sc->debug.debugfs_phydir, sc, &fops_beacon);
391
392 sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR,
393 sc->debug.debugfs_phydir, sc, &fops_reset);
394}
395
396void
397ath5k_debug_finish(void)
398{
399 debugfs_remove(ath5k_global_debugfs);
400}
401
402void
403ath5k_debug_finish_device(struct ath5k_softc *sc)
404{
405 debugfs_remove(sc->debug.debugfs_debug);
406 debugfs_remove(sc->debug.debugfs_registers);
407 debugfs_remove(sc->debug.debugfs_beacon);
408 debugfs_remove(sc->debug.debugfs_reset);
409 debugfs_remove(sc->debug.debugfs_phydir);
410}
411
412
413/* functions used in other places */
414
415void
416ath5k_debug_dump_bands(struct ath5k_softc *sc)
417{
418 unsigned int b, i;
419
420 if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS)))
421 return;
422
423 BUG_ON(!sc->sbands);
424
425 for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
426 struct ieee80211_supported_band *band = &sc->sbands[b];
427 char bname[5];
428 switch (band->band) {
429 case IEEE80211_BAND_2GHZ:
430 strcpy(bname, "2 GHz");
431 break;
432 case IEEE80211_BAND_5GHZ:
433 strcpy(bname, "5 GHz");
434 break;
435 default:
436 printk(KERN_DEBUG "Band not supported: %d\n",
437 band->band);
438 return;
439 }
440 printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname,
441 band->n_channels, band->n_bitrates);
442 printk(KERN_DEBUG " channels:\n");
443 for (i = 0; i < band->n_channels; i++)
444 printk(KERN_DEBUG " %3d %d %.4x %.4x\n",
445 ieee80211_frequency_to_channel(
446 band->channels[i].center_freq),
447 band->channels[i].center_freq,
448 band->channels[i].hw_value,
449 band->channels[i].flags);
450 printk(KERN_DEBUG " rates:\n");
451 for (i = 0; i < band->n_bitrates; i++)
452 printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n",
453 band->bitrates[i].bitrate,
454 band->bitrates[i].hw_value,
455 band->bitrates[i].flags,
456 band->bitrates[i].hw_value_short);
457 }
458}
459
460static inline void
461ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
462 struct ath5k_rx_status *rs)
463{
464 struct ath5k_desc *ds = bf->desc;
465 struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
466
467 printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
468 ds, (unsigned long long)bf->daddr,
469 ds->ds_link, ds->ds_data,
470 rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
471 rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0,
472 !done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
473}
474
475void
476ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
477{
478 struct ath5k_desc *ds;
479 struct ath5k_buf *bf;
480 struct ath5k_rx_status rs = {};
481 int status;
482
483 if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
484 return;
485
486 printk(KERN_DEBUG "rx queue %x, link %p\n",
487 ath5k_hw_get_rxdp(ah), sc->rxlink);
488
489 spin_lock_bh(&sc->rxbuflock);
490 list_for_each_entry(bf, &sc->rxbuf, list) {
491 ds = bf->desc;
492 status = ah->ah_proc_rx_desc(ah, ds, &rs);
493 if (!status)
494 ath5k_debug_printrxbuf(bf, status == 0, &rs);
495 }
496 spin_unlock_bh(&sc->rxbuflock);
497}
498
499void
500ath5k_debug_dump_skb(struct ath5k_softc *sc,
501 struct sk_buff *skb, const char *prefix, int tx)
502{
503 char buf[16];
504
505 if (likely(!((tx && (sc->debug.level & ATH5K_DEBUG_DUMP_TX)) ||
506 (!tx && (sc->debug.level & ATH5K_DEBUG_DUMP_RX)))))
507 return;
508
509 snprintf(buf, sizeof(buf), "%s %s", wiphy_name(sc->hw->wiphy), prefix);
510
511 print_hex_dump_bytes(buf, DUMP_PREFIX_NONE, skb->data,
512 min(200U, skb->len));
513
514 printk(KERN_DEBUG "\n");
515}
516
517void
518ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
519{
520 struct ath5k_desc *ds = bf->desc;
521 struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
522 struct ath5k_tx_status ts = {};
523 int done;
524
525 if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
526 return;
527
528 done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts);
529
530 printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
531 "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
532 ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
533 td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
534 td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
535 done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
536}
537
538#endif /* ifdef CONFIG_ATH5K_DEBUG */
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h
new file mode 100644
index 000000000000..66f69f04e55e
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/debug.h
@@ -0,0 +1,203 @@
1/*
2 * Copyright (c) 2007 Bruno Randolf <bruno@thinktube.com>
3 *
4 * This file is free software: you may copy, redistribute and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation, either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This file is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 *
18 * This file incorporates work covered by the following copyright and
19 * permission notice:
20 *
21 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
22 * Copyright (c) 2004-2005 Atheros Communications, Inc.
23 * Copyright (c) 2006 Devicescape Software, Inc.
24 * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
25 * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
26 *
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer,
34 * without modification.
35 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
36 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
37 * redistribution must be conditioned upon including a substantially
38 * similar Disclaimer requirement for further binary redistribution.
39 * 3. Neither the names of the above-listed copyright holders nor the names
40 * of any contributors may be used to endorse or promote products derived
41 * from this software without specific prior written permission.
42 *
43 * Alternatively, this software may be distributed under the terms of the
44 * GNU General Public License ("GPL") version 2 as published by the Free
45 * Software Foundation.
46 *
47 * NO WARRANTY
48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
51 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
52 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
53 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
56 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
58 * THE POSSIBILITY OF SUCH DAMAGES.
59 */
60
61#ifndef _ATH5K_DEBUG_H
62#define _ATH5K_DEBUG_H
63
64struct ath5k_softc;
65struct ath5k_hw;
66struct sk_buff;
67struct ath5k_buf;
68
69struct ath5k_dbg_info {
70 unsigned int level; /* debug level */
71 /* debugfs entries */
72 struct dentry *debugfs_phydir;
73 struct dentry *debugfs_debug;
74 struct dentry *debugfs_registers;
75 struct dentry *debugfs_beacon;
76 struct dentry *debugfs_reset;
77};
78
79/**
80 * enum ath5k_debug_level - ath5k debug level
81 *
82 * @ATH5K_DEBUG_RESET: reset processing
83 * @ATH5K_DEBUG_INTR: interrupt handling
84 * @ATH5K_DEBUG_MODE: mode init/setup
85 * @ATH5K_DEBUG_XMIT: basic xmit operation
86 * @ATH5K_DEBUG_BEACON: beacon handling
87 * @ATH5K_DEBUG_CALIBRATE: periodic calibration
88 * @ATH5K_DEBUG_TXPOWER: transmit power setting
89 * @ATH5K_DEBUG_LED: led management
90 * @ATH5K_DEBUG_DUMP_RX: print received skb content
91 * @ATH5K_DEBUG_DUMP_TX: print transmit skb content
92 * @ATH5K_DEBUG_DUMPBANDS: dump bands
93 * @ATH5K_DEBUG_TRACE: trace function calls
94 * @ATH5K_DEBUG_ANY: show at any debug level
95 *
96 * The debug level is used to control the amount and type of debugging output
97 * we want to see. The debug level is given in calls to ATH5K_DBG to specify
98 * where the message should appear, and the user can control the debugging
99 * messages he wants to see, either by the module parameter 'debug' on module
100 * load, or dynamically by using debugfs 'ath5k/phyX/debug'. these levels can
101 * be combined together by bitwise OR.
102 */
103enum ath5k_debug_level {
104 ATH5K_DEBUG_RESET = 0x00000001,
105 ATH5K_DEBUG_INTR = 0x00000002,
106 ATH5K_DEBUG_MODE = 0x00000004,
107 ATH5K_DEBUG_XMIT = 0x00000008,
108 ATH5K_DEBUG_BEACON = 0x00000010,
109 ATH5K_DEBUG_CALIBRATE = 0x00000020,
110 ATH5K_DEBUG_TXPOWER = 0x00000040,
111 ATH5K_DEBUG_LED = 0x00000080,
112 ATH5K_DEBUG_DUMP_RX = 0x00000100,
113 ATH5K_DEBUG_DUMP_TX = 0x00000200,
114 ATH5K_DEBUG_DUMPBANDS = 0x00000400,
115 ATH5K_DEBUG_TRACE = 0x00001000,
116 ATH5K_DEBUG_ANY = 0xffffffff
117};
118
119#ifdef CONFIG_ATH5K_DEBUG
120
121#define ATH5K_TRACE(_sc) do { \
122 if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \
123 printk(KERN_DEBUG "ath5k trace %s:%d\n", __func__, __LINE__); \
124 } while (0)
125
126#define ATH5K_DBG(_sc, _m, _fmt, ...) do { \
127 if (unlikely((_sc)->debug.level & (_m) && net_ratelimit())) \
128 ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \
129 __func__, __LINE__, ##__VA_ARGS__); \
130 } while (0)
131
132#define ATH5K_DBG_UNLIMIT(_sc, _m, _fmt, ...) do { \
133 if (unlikely((_sc)->debug.level & (_m))) \
134 ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \
135 __func__, __LINE__, ##__VA_ARGS__); \
136 } while (0)
137
138void
139ath5k_debug_init(void);
140
141void
142ath5k_debug_init_device(struct ath5k_softc *sc);
143
144void
145ath5k_debug_finish(void);
146
147void
148ath5k_debug_finish_device(struct ath5k_softc *sc);
149
150void
151ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
152
153void
154ath5k_debug_dump_bands(struct ath5k_softc *sc);
155
156void
157ath5k_debug_dump_skb(struct ath5k_softc *sc,
158 struct sk_buff *skb, const char *prefix, int tx);
159
160void
161ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf);
162
163#else /* no debugging */
164
165#include <linux/compiler.h>
166
167#define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc))
168
169static inline void __attribute__ ((format (printf, 3, 4)))
170ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {}
171
172static inline void __attribute__ ((format (printf, 3, 4)))
173ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...)
174{}
175
176static inline void
177ath5k_debug_init(void) {}
178
179static inline void
180ath5k_debug_init_device(struct ath5k_softc *sc) {}
181
182static inline void
183ath5k_debug_finish(void) {}
184
185static inline void
186ath5k_debug_finish_device(struct ath5k_softc *sc) {}
187
188static inline void
189ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
190
191static inline void
192ath5k_debug_dump_bands(struct ath5k_softc *sc) {}
193
194static inline void
195ath5k_debug_dump_skb(struct ath5k_softc *sc,
196 struct sk_buff *skb, const char *prefix, int tx) {}
197
198static inline void
199ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {}
200
201#endif /* ifdef CONFIG_ATH5K_DEBUG */
202
203#endif /* ifndef _ATH5K_DEBUG_H */
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c
new file mode 100644
index 000000000000..dc30a2b70a6b
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/desc.c
@@ -0,0 +1,696 @@
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4 * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20/******************************\
21 Hardware Descriptor Functions
22\******************************/
23
24#include "ath5k.h"
25#include "reg.h"
26#include "debug.h"
27#include "base.h"
28
29/*
30 * TX Descriptors
31 */
32
33/*
34 * Initialize the 2-word tx control descriptor on 5210/5211
35 */
36static int
37ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
38 unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
39 unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0,
40 unsigned int key_index, unsigned int antenna_mode, unsigned int flags,
41 unsigned int rtscts_rate, unsigned int rtscts_duration)
42{
43 u32 frame_type;
44 struct ath5k_hw_2w_tx_ctl *tx_ctl;
45 unsigned int frame_len;
46
47 tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
48
49 /*
50 * Validate input
51 * - Zero retries don't make sense.
52 * - A zero rate will put the HW into a mode where it continously sends
53 * noise on the channel, so it is important to avoid this.
54 */
55 if (unlikely(tx_tries0 == 0)) {
56 ATH5K_ERR(ah->ah_sc, "zero retries\n");
57 WARN_ON(1);
58 return -EINVAL;
59 }
60 if (unlikely(tx_rate0 == 0)) {
61 ATH5K_ERR(ah->ah_sc, "zero rate\n");
62 WARN_ON(1);
63 return -EINVAL;
64 }
65
66 /* Clear descriptor */
67 memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
68
69 /* Setup control descriptor */
70
71 /* Verify and set frame length */
72
73 /* remove padding we might have added before */
74 frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN;
75
76 if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
77 return -EINVAL;
78
79 tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
80
81 /* Verify and set buffer length */
82
83 /* NB: beacon's BufLen must be a multiple of 4 bytes */
84 if (type == AR5K_PKT_TYPE_BEACON)
85 pkt_len = roundup(pkt_len, 4);
86
87 if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
88 return -EINVAL;
89
90 tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
91
92 /*
93 * Verify and set header length
94 * XXX: I only found that on 5210 code, does it work on 5211 ?
95 */
96 if (ah->ah_version == AR5K_AR5210) {
97 if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
98 return -EINVAL;
99 tx_ctl->tx_control_0 |=
100 AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
101 }
102
103 /*Diferences between 5210-5211*/
104 if (ah->ah_version == AR5K_AR5210) {
105 switch (type) {
106 case AR5K_PKT_TYPE_BEACON:
107 case AR5K_PKT_TYPE_PROBE_RESP:
108 frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
109 case AR5K_PKT_TYPE_PIFS:
110 frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
111 default:
112 frame_type = type /*<< 2 ?*/;
113 }
114
115 tx_ctl->tx_control_0 |=
116 AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
117 AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
118
119 } else {
120 tx_ctl->tx_control_0 |=
121 AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
122 AR5K_REG_SM(antenna_mode,
123 AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
124 tx_ctl->tx_control_1 |=
125 AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
126 }
127#define _TX_FLAGS(_c, _flag) \
128 if (flags & AR5K_TXDESC_##_flag) { \
129 tx_ctl->tx_control_##_c |= \
130 AR5K_2W_TX_DESC_CTL##_c##_##_flag; \
131 }
132
133 _TX_FLAGS(0, CLRDMASK);
134 _TX_FLAGS(0, VEOL);
135 _TX_FLAGS(0, INTREQ);
136 _TX_FLAGS(0, RTSENA);
137 _TX_FLAGS(1, NOACK);
138
139#undef _TX_FLAGS
140
141 /*
142 * WEP crap
143 */
144 if (key_index != AR5K_TXKEYIX_INVALID) {
145 tx_ctl->tx_control_0 |=
146 AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
147 tx_ctl->tx_control_1 |=
148 AR5K_REG_SM(key_index,
149 AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
150 }
151
152 /*
153 * RTS/CTS Duration [5210 ?]
154 */
155 if ((ah->ah_version == AR5K_AR5210) &&
156 (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
157 tx_ctl->tx_control_1 |= rtscts_duration &
158 AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
159
160 return 0;
161}
162
163/*
164 * Initialize the 4-word tx control descriptor on 5212
165 */
166static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
167 struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len,
168 enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
169 unsigned int tx_tries0, unsigned int key_index,
170 unsigned int antenna_mode, unsigned int flags,
171 unsigned int rtscts_rate,
172 unsigned int rtscts_duration)
173{
174 struct ath5k_hw_4w_tx_ctl *tx_ctl;
175 unsigned int frame_len;
176
177 ATH5K_TRACE(ah->ah_sc);
178 tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
179
180 /*
181 * Validate input
182 * - Zero retries don't make sense.
183 * - A zero rate will put the HW into a mode where it continously sends
184 * noise on the channel, so it is important to avoid this.
185 */
186 if (unlikely(tx_tries0 == 0)) {
187 ATH5K_ERR(ah->ah_sc, "zero retries\n");
188 WARN_ON(1);
189 return -EINVAL;
190 }
191 if (unlikely(tx_rate0 == 0)) {
192 ATH5K_ERR(ah->ah_sc, "zero rate\n");
193 WARN_ON(1);
194 return -EINVAL;
195 }
196
197 tx_power += ah->ah_txpower.txp_offset;
198 if (tx_power > AR5K_TUNE_MAX_TXPOWER)
199 tx_power = AR5K_TUNE_MAX_TXPOWER;
200
201 /* Clear descriptor */
202 memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
203
204 /* Setup control descriptor */
205
206 /* Verify and set frame length */
207
208 /* remove padding we might have added before */
209 frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN;
210
211 if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
212 return -EINVAL;
213
214 tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
215
216 /* Verify and set buffer length */
217
218 /* NB: beacon's BufLen must be a multiple of 4 bytes */
219 if (type == AR5K_PKT_TYPE_BEACON)
220 pkt_len = roundup(pkt_len, 4);
221
222 if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
223 return -EINVAL;
224
225 tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
226
227 tx_ctl->tx_control_0 |=
228 AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
229 AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
230 tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
231 AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
232 tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
233 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
234 tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
235
236#define _TX_FLAGS(_c, _flag) \
237 if (flags & AR5K_TXDESC_##_flag) { \
238 tx_ctl->tx_control_##_c |= \
239 AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
240 }
241
242 _TX_FLAGS(0, CLRDMASK);
243 _TX_FLAGS(0, VEOL);
244 _TX_FLAGS(0, INTREQ);
245 _TX_FLAGS(0, RTSENA);
246 _TX_FLAGS(0, CTSENA);
247 _TX_FLAGS(1, NOACK);
248
249#undef _TX_FLAGS
250
251 /*
252 * WEP crap
253 */
254 if (key_index != AR5K_TXKEYIX_INVALID) {
255 tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
256 tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
257 AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
258 }
259
260 /*
261 * RTS/CTS
262 */
263 if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
264 if ((flags & AR5K_TXDESC_RTSENA) &&
265 (flags & AR5K_TXDESC_CTSENA))
266 return -EINVAL;
267 tx_ctl->tx_control_2 |= rtscts_duration &
268 AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
269 tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
270 AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
271 }
272
273 return 0;
274}
275
276/*
277 * Initialize a 4-word multi rate retry tx control descriptor on 5212
278 */
279static int
280ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
281 unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
282 u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3)
283{
284 struct ath5k_hw_4w_tx_ctl *tx_ctl;
285
286 /*
287 * Rates can be 0 as long as the retry count is 0 too.
288 * A zero rate and nonzero retry count will put the HW into a mode where
289 * it continously sends noise on the channel, so it is important to
290 * avoid this.
291 */
292 if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
293 (tx_rate2 == 0 && tx_tries2 != 0) ||
294 (tx_rate3 == 0 && tx_tries3 != 0))) {
295 ATH5K_ERR(ah->ah_sc, "zero rate\n");
296 WARN_ON(1);
297 return -EINVAL;
298 }
299
300 if (ah->ah_version == AR5K_AR5212) {
301 tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
302
303#define _XTX_TRIES(_n) \
304 if (tx_tries##_n) { \
305 tx_ctl->tx_control_2 |= \
306 AR5K_REG_SM(tx_tries##_n, \
307 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \
308 tx_ctl->tx_control_3 |= \
309 AR5K_REG_SM(tx_rate##_n, \
310 AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \
311 }
312
313 _XTX_TRIES(1);
314 _XTX_TRIES(2);
315 _XTX_TRIES(3);
316
317#undef _XTX_TRIES
318
319 return 1;
320 }
321
322 return 0;
323}
324
325/* no mrr support for cards older than 5212 */
326static int
327ath5k_hw_setup_no_mrr(struct ath5k_hw *ah, struct ath5k_desc *desc,
328 unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
329 u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3)
330{
331 return 0;
332}
333
334/*
335 * Proccess the tx status descriptor on 5210/5211
336 */
337static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
338 struct ath5k_desc *desc, struct ath5k_tx_status *ts)
339{
340 struct ath5k_hw_2w_tx_ctl *tx_ctl;
341 struct ath5k_hw_tx_status *tx_status;
342
343 ATH5K_TRACE(ah->ah_sc);
344
345 tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
346 tx_status = &desc->ud.ds_tx5210.tx_stat;
347
348 /* No frame has been send or error */
349 if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
350 return -EINPROGRESS;
351
352 /*
353 * Get descriptor status
354 */
355 ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
356 AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
357 ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
358 AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
359 ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
360 AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
361 /*TODO: ts->ts_virtcol + test*/
362 ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
363 AR5K_DESC_TX_STATUS1_SEQ_NUM);
364 ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
365 AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
366 ts->ts_antenna = 1;
367 ts->ts_status = 0;
368 ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
369 AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
370 ts->ts_retry[0] = ts->ts_longretry;
371 ts->ts_final_idx = 0;
372
373 if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
374 if (tx_status->tx_status_0 &
375 AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
376 ts->ts_status |= AR5K_TXERR_XRETRY;
377
378 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
379 ts->ts_status |= AR5K_TXERR_FIFO;
380
381 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
382 ts->ts_status |= AR5K_TXERR_FILT;
383 }
384
385 return 0;
386}
387
388/*
389 * Proccess a tx status descriptor on 5212
390 */
391static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
392 struct ath5k_desc *desc, struct ath5k_tx_status *ts)
393{
394 struct ath5k_hw_4w_tx_ctl *tx_ctl;
395 struct ath5k_hw_tx_status *tx_status;
396
397 ATH5K_TRACE(ah->ah_sc);
398
399 tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
400 tx_status = &desc->ud.ds_tx5212.tx_stat;
401
402 /* No frame has been send or error */
403 if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE)))
404 return -EINPROGRESS;
405
406 /*
407 * Get descriptor status
408 */
409 ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
410 AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
411 ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
412 AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
413 ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
414 AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
415 ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
416 AR5K_DESC_TX_STATUS1_SEQ_NUM);
417 ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
418 AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
419 ts->ts_antenna = (tx_status->tx_status_1 &
420 AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
421 ts->ts_status = 0;
422
423 ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
424 AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX);
425
426 /* The longretry counter has the number of un-acked retries
427 * for the final rate. To get the total number of retries
428 * we have to add the retry counters for the other rates
429 * as well
430 */
431 ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry;
432 switch (ts->ts_final_idx) {
433 case 3:
434 ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3,
435 AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
436
437 ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2,
438 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
439 ts->ts_longretry += ts->ts_retry[2];
440 /* fall through */
441 case 2:
442 ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3,
443 AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
444
445 ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2,
446 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
447 ts->ts_longretry += ts->ts_retry[1];
448 /* fall through */
449 case 1:
450 ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3,
451 AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
452
453 ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2,
454 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
455 ts->ts_longretry += ts->ts_retry[0];
456 /* fall through */
457 case 0:
458 ts->ts_rate[0] = tx_ctl->tx_control_3 &
459 AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
460 break;
461 }
462
463 /* TX error */
464 if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
465 if (tx_status->tx_status_0 &
466 AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
467 ts->ts_status |= AR5K_TXERR_XRETRY;
468
469 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
470 ts->ts_status |= AR5K_TXERR_FIFO;
471
472 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
473 ts->ts_status |= AR5K_TXERR_FILT;
474 }
475
476 return 0;
477}
478
479/*
480 * RX Descriptors
481 */
482
483/*
484 * Initialize an rx control descriptor
485 */
486static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
487 u32 size, unsigned int flags)
488{
489 struct ath5k_hw_rx_ctl *rx_ctl;
490
491 ATH5K_TRACE(ah->ah_sc);
492 rx_ctl = &desc->ud.ds_rx.rx_ctl;
493
494 /*
495 * Clear the descriptor
496 * If we don't clean the status descriptor,
497 * while scanning we get too many results,
498 * most of them virtual, after some secs
499 * of scanning system hangs. M.F.
500 */
501 memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
502
503 /* Setup descriptor */
504 rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
505 if (unlikely(rx_ctl->rx_control_1 != size))
506 return -EINVAL;
507
508 if (flags & AR5K_RXDESC_INTREQ)
509 rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
510
511 return 0;
512}
513
514/*
515 * Proccess the rx status descriptor on 5210/5211
516 */
517static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
518 struct ath5k_desc *desc, struct ath5k_rx_status *rs)
519{
520 struct ath5k_hw_rx_status *rx_status;
521
522 rx_status = &desc->ud.ds_rx.u.rx_stat;
523
524 /* No frame received / not ready */
525 if (unlikely(!(rx_status->rx_status_1 &
526 AR5K_5210_RX_DESC_STATUS1_DONE)))
527 return -EINPROGRESS;
528
529 /*
530 * Frame receive status
531 */
532 rs->rs_datalen = rx_status->rx_status_0 &
533 AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
534 rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
535 AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
536 rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
537 AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
538 rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
539 AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA);
540 rs->rs_more = !!(rx_status->rx_status_0 &
541 AR5K_5210_RX_DESC_STATUS0_MORE);
542 /* TODO: this timestamp is 13 bit, later on we assume 15 bit */
543 rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
544 AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
545 rs->rs_status = 0;
546 rs->rs_phyerr = 0;
547
548 /*
549 * Key table status
550 */
551 if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
552 rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
553 AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
554 else
555 rs->rs_keyix = AR5K_RXKEYIX_INVALID;
556
557 /*
558 * Receive/descriptor errors
559 */
560 if (!(rx_status->rx_status_1 &
561 AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
562 if (rx_status->rx_status_1 &
563 AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
564 rs->rs_status |= AR5K_RXERR_CRC;
565
566 if (rx_status->rx_status_1 &
567 AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
568 rs->rs_status |= AR5K_RXERR_FIFO;
569
570 if (rx_status->rx_status_1 &
571 AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
572 rs->rs_status |= AR5K_RXERR_PHY;
573 rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1,
574 AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
575 }
576
577 if (rx_status->rx_status_1 &
578 AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
579 rs->rs_status |= AR5K_RXERR_DECRYPT;
580 }
581
582 return 0;
583}
584
585/*
586 * Proccess the rx status descriptor on 5212
587 */
588static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
589 struct ath5k_desc *desc, struct ath5k_rx_status *rs)
590{
591 struct ath5k_hw_rx_status *rx_status;
592 struct ath5k_hw_rx_error *rx_err;
593
594 ATH5K_TRACE(ah->ah_sc);
595 rx_status = &desc->ud.ds_rx.u.rx_stat;
596
597 /* Overlay on error */
598 rx_err = &desc->ud.ds_rx.u.rx_err;
599
600 /* No frame received / not ready */
601 if (unlikely(!(rx_status->rx_status_1 &
602 AR5K_5212_RX_DESC_STATUS1_DONE)))
603 return -EINPROGRESS;
604
605 /*
606 * Frame receive status
607 */
608 rs->rs_datalen = rx_status->rx_status_0 &
609 AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
610 rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
611 AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
612 rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
613 AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
614 rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
615 AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
616 rs->rs_more = !!(rx_status->rx_status_0 &
617 AR5K_5212_RX_DESC_STATUS0_MORE);
618 rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
619 AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
620 rs->rs_status = 0;
621 rs->rs_phyerr = 0;
622
623 /*
624 * Key table status
625 */
626 if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
627 rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
628 AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
629 else
630 rs->rs_keyix = AR5K_RXKEYIX_INVALID;
631
632 /*
633 * Receive/descriptor errors
634 */
635 if (!(rx_status->rx_status_1 &
636 AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
637 if (rx_status->rx_status_1 &
638 AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
639 rs->rs_status |= AR5K_RXERR_CRC;
640
641 if (rx_status->rx_status_1 &
642 AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
643 rs->rs_status |= AR5K_RXERR_PHY;
644 rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1,
645 AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
646 }
647
648 if (rx_status->rx_status_1 &
649 AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
650 rs->rs_status |= AR5K_RXERR_DECRYPT;
651
652 if (rx_status->rx_status_1 &
653 AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
654 rs->rs_status |= AR5K_RXERR_MIC;
655 }
656
657 return 0;
658}
659
660/*
661 * Init function pointers inside ath5k_hw struct
662 */
663int ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
664{
665
666 if (ah->ah_version != AR5K_AR5210 &&
667 ah->ah_version != AR5K_AR5211 &&
668 ah->ah_version != AR5K_AR5212)
669 return -ENOTSUPP;
670
671 /* XXX: What is this magic value and where is it used ? */
672 if (ah->ah_version == AR5K_AR5212)
673 ah->ah_magic = AR5K_EEPROM_MAGIC_5212;
674 else if (ah->ah_version == AR5K_AR5211)
675 ah->ah_magic = AR5K_EEPROM_MAGIC_5211;
676
677 if (ah->ah_version == AR5K_AR5212) {
678 ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
679 ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
680 ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc;
681 ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
682 } else {
683 ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
684 ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
685 ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr;
686 ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
687 }
688
689 if (ah->ah_version == AR5K_AR5212)
690 ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
691 else if (ah->ah_version <= AR5K_AR5211)
692 ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
693
694 return 0;
695}
696
diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h
new file mode 100644
index 000000000000..56158c804e3e
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/desc.h
@@ -0,0 +1,332 @@
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 */
18
19/*
20 * Internal RX/TX descriptor structures
21 * (rX: reserved fields possibily used by future versions of the ar5k chipset)
22 */
23
24/*
25 * common hardware RX control descriptor
26 */
27struct ath5k_hw_rx_ctl {
28 u32 rx_control_0; /* RX control word 0 */
29 u32 rx_control_1; /* RX control word 1 */
30} __packed;
31
32/* RX control word 0 field/sflags */
33#define AR5K_DESC_RX_CTL0 0x00000000
34
35/* RX control word 1 fields/flags */
36#define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff
37#define AR5K_DESC_RX_CTL1_INTREQ 0x00002000
38
39/*
40 * common hardware RX status descriptor
41 * 5210/11 and 5212 differ only in the flags defined below
42 */
43struct ath5k_hw_rx_status {
44 u32 rx_status_0; /* RX status word 0 */
45 u32 rx_status_1; /* RX status word 1 */
46} __packed;
47
48/* 5210/5211 */
49/* RX status word 0 fields/flags */
50#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff
51#define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000
52#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000
53#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15
54#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000
55#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19
56#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000
57#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27
58
59/* RX status word 1 fields/flags */
60#define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001
61#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
62#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004
63#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008
64#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010
65#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0
66#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5
67#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
68#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00
69#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9
70#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000
71#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15
72#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000
73
74/* 5212 */
75/* RX status word 0 fields/flags */
76#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff
77#define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000
78#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000
79#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000
80#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15
81#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000
82#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20
83#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000
84#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28
85
86/* RX status word 1 fields/flags */
87#define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001
88#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
89#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004
90#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008
91#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010
92#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020
93#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
94#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00
95#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9
96#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000
97#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16
98#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000
99
100/*
101 * common hardware RX error descriptor
102 */
103struct ath5k_hw_rx_error {
104 u32 rx_error_0; /* RX status word 0 */
105 u32 rx_error_1; /* RX status word 1 */
106} __packed;
107
108/* RX error word 0 fields/flags */
109#define AR5K_RX_DESC_ERROR0 0x00000000
110
111/* RX error word 1 fields/flags */
112#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00
113#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8
114
115/* PHY Error codes */
116#define AR5K_DESC_RX_PHY_ERROR_NONE 0x00
117#define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20
118#define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40
119#define AR5K_DESC_RX_PHY_ERROR_RATE 0x60
120#define AR5K_DESC_RX_PHY_ERROR_LENGTH 0x80
121#define AR5K_DESC_RX_PHY_ERROR_64QAM 0xa0
122#define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0
123#define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0
124
125/*
126 * 5210/5211 hardware 2-word TX control descriptor
127 */
128struct ath5k_hw_2w_tx_ctl {
129 u32 tx_control_0; /* TX control word 0 */
130 u32 tx_control_1; /* TX control word 1 */
131} __packed;
132
133/* TX control word 0 fields/flags */
134#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
135#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/
136#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12
137#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000
138#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S 18
139#define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000
140#define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000
141#define AR5K_2W_TX_DESC_CTL0_LONG_PACKET 0x00800000 /*[5210]*/
142#define AR5K_2W_TX_DESC_CTL0_VEOL 0x00800000 /*[5211]*/
143#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE 0x1c000000 /*[5210]*/
144#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26
145#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000
146#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000
147
148#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT \
149 (ah->ah_version == AR5K_AR5210 ? \
150 AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \
151 AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211)
152
153#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25
154#define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000
155#define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000
156
157/* TX control word 1 fields/flags */
158#define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff
159#define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000
160#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000
161#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000
162
163#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX \
164 (ah->ah_version == AR5K_AR5210 ? \
165 AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \
166 AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211)
167
168#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13
169#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/
170#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20
171#define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/
172#define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/
173
174/* Frame types */
175#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00
176#define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04
177#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08
178#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c
179#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10
180
181/*
182 * 5212 hardware 4-word TX control descriptor
183 */
184struct ath5k_hw_4w_tx_ctl {
185 u32 tx_control_0; /* TX control word 0 */
186
187#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
188#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000
189#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S 16
190#define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000
191#define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000
192#define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000
193#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000
194#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25
195#define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000
196#define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000
197#define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000
198
199 u32 tx_control_1; /* TX control word 1 */
200
201#define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff
202#define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000
203#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX 0x000fe000
204#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13
205#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000
206#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S 20
207#define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000
208#define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000
209#define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S 25
210#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000
211#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S 27
212#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000
213#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S 29
214
215 u32 tx_control_2; /* TX control word 2 */
216
217#define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff
218#define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE 0x00008000
219#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000
220#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16
221#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000
222#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20
223#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000
224#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24
225#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000
226#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28
227
228 u32 tx_control_3; /* TX control word 3 */
229
230#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f
231#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0
232#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S 5
233#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00
234#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S 10
235#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000
236#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S 15
237#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000
238#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20
239} __packed;
240
241/*
242 * Common TX status descriptor
243 */
244struct ath5k_hw_tx_status {
245 u32 tx_status_0; /* TX status word 0 */
246 u32 tx_status_1; /* TX status word 1 */
247} __packed;
248
249/* TX status word 0 fields/flags */
250#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001
251#define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002
252#define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004
253#define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008
254/*???
255#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT 0x000000f0
256#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S 4
257*/
258#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0
259#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S 4
260/*???
261#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT 0x00000f00
262#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S 8
263*/
264#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00
265#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S 8
266#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT 0x0000f000
267#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S 12
268#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000
269#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16
270
271/* TX status word 1 fields/flags */
272#define AR5K_DESC_TX_STATUS1_DONE 0x00000001
273#define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe
274#define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1
275#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000
276#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S 13
277#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX 0x00600000
278#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21
279#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000
280#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000
281
282/*
283 * 5210/5211 hardware TX descriptor
284 */
285struct ath5k_hw_5210_tx_desc {
286 struct ath5k_hw_2w_tx_ctl tx_ctl;
287 struct ath5k_hw_tx_status tx_stat;
288} __packed;
289
290/*
291 * 5212 hardware TX descriptor
292 */
293struct ath5k_hw_5212_tx_desc {
294 struct ath5k_hw_4w_tx_ctl tx_ctl;
295 struct ath5k_hw_tx_status tx_stat;
296} __packed;
297
298/*
299 * common hardware RX descriptor
300 */
301struct ath5k_hw_all_rx_desc {
302 struct ath5k_hw_rx_ctl rx_ctl;
303 union {
304 struct ath5k_hw_rx_status rx_stat;
305 struct ath5k_hw_rx_error rx_err;
306 } u;
307} __packed;
308
309/*
310 * Atheros hardware descriptor
311 * This is read and written to by the hardware
312 */
313struct ath5k_desc {
314 u32 ds_link; /* physical address of the next descriptor */
315 u32 ds_data; /* physical address of data buffer (skb) */
316
317 union {
318 struct ath5k_hw_5210_tx_desc ds_tx5210;
319 struct ath5k_hw_5212_tx_desc ds_tx5212;
320 struct ath5k_hw_all_rx_desc ds_rx;
321 } ud;
322} __packed;
323
324#define AR5K_RXDESC_INTREQ 0x0020
325
326#define AR5K_TXDESC_CLRDMASK 0x0001
327#define AR5K_TXDESC_NOACK 0x0002 /*[5211+]*/
328#define AR5K_TXDESC_RTSENA 0x0004
329#define AR5K_TXDESC_CTSENA 0x0008
330#define AR5K_TXDESC_INTREQ 0x0010
331#define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/
332
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c
new file mode 100644
index 000000000000..b65b4feb2d28
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -0,0 +1,705 @@
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 */
18
19/*************************************\
20* DMA and interrupt masking functions *
21\*************************************/
22
23/*
24 * dma.c - DMA and interrupt masking functions
25 *
26 * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and
27 * handle queue setup for 5210 chipset (rest are handled on qcu.c).
28 * Also we setup interrupt mask register (IMR) and read the various iterrupt
29 * status registers (ISR).
30 *
31 * TODO: Handle SISR on 5211+ and introduce a function to return the queue
32 * number that resulted the interrupt.
33 */
34
35#include "ath5k.h"
36#include "reg.h"
37#include "debug.h"
38#include "base.h"
39
40/*********\
41* Receive *
42\*********/
43
44/**
45 * ath5k_hw_start_rx_dma - Start DMA receive
46 *
47 * @ah: The &struct ath5k_hw
48 */
49void ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
50{
51 ATH5K_TRACE(ah->ah_sc);
52 ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
53 ath5k_hw_reg_read(ah, AR5K_CR);
54}
55
56/**
57 * ath5k_hw_stop_rx_dma - Stop DMA receive
58 *
59 * @ah: The &struct ath5k_hw
60 */
61int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
62{
63 unsigned int i;
64
65 ATH5K_TRACE(ah->ah_sc);
66 ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
67
68 /*
69 * It may take some time to disable the DMA receive unit
70 */
71 for (i = 1000; i > 0 &&
72 (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
73 i--)
74 udelay(10);
75
76 return i ? 0 : -EBUSY;
77}
78
79/**
80 * ath5k_hw_get_rxdp - Get RX Descriptor's address
81 *
82 * @ah: The &struct ath5k_hw
83 *
84 * XXX: Is RXDP read and clear ?
85 */
86u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
87{
88 return ath5k_hw_reg_read(ah, AR5K_RXDP);
89}
90
91/**
92 * ath5k_hw_set_rxdp - Set RX Descriptor's address
93 *
94 * @ah: The &struct ath5k_hw
95 * @phys_addr: RX descriptor address
96 *
97 * XXX: Should we check if rx is enabled before setting rxdp ?
98 */
99void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
100{
101 ATH5K_TRACE(ah->ah_sc);
102
103 ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
104}
105
106
107/**********\
108* Transmit *
109\**********/
110
111/**
112 * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue
113 *
114 * @ah: The &struct ath5k_hw
115 * @queue: The hw queue number
116 *
117 * Start DMA transmit for a specific queue and since 5210 doesn't have
118 * QCU/DCU, set up queue parameters for 5210 here based on queue type (one
119 * queue for normal data and one queue for beacons). For queue setup
120 * on newer chips check out qcu.c. Returns -EINVAL if queue number is out
121 * of range or if queue is already disabled.
122 *
123 * NOTE: Must be called after setting up tx control descriptor for that
124 * queue (see below).
125 */
126int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
127{
128 u32 tx_queue;
129
130 ATH5K_TRACE(ah->ah_sc);
131 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
132
133 /* Return if queue is declared inactive */
134 if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
135 return -EIO;
136
137 if (ah->ah_version == AR5K_AR5210) {
138 tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
139
140 /*
141 * Set the queue by type on 5210
142 */
143 switch (ah->ah_txq[queue].tqi_type) {
144 case AR5K_TX_QUEUE_DATA:
145 tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0;
146 break;
147 case AR5K_TX_QUEUE_BEACON:
148 tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
149 ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
150 AR5K_BSR);
151 break;
152 case AR5K_TX_QUEUE_CAB:
153 tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
154 ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V |
155 AR5K_BCR_BDMAE, AR5K_BSR);
156 break;
157 default:
158 return -EINVAL;
159 }
160 /* Start queue */
161 ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
162 ath5k_hw_reg_read(ah, AR5K_CR);
163 } else {
164 /* Return if queue is disabled */
165 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue))
166 return -EIO;
167
168 /* Start queue */
169 AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue);
170 }
171
172 return 0;
173}
174
175/**
176 * ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue
177 *
178 * @ah: The &struct ath5k_hw
179 * @queue: The hw queue number
180 *
181 * Stop DMA transmit on a specific hw queue and drain queue so we don't
182 * have any pending frames. Returns -EBUSY if we still have pending frames,
183 * -EINVAL if queue number is out of range.
184 *
185 */
186int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
187{
188 unsigned int i = 40;
189 u32 tx_queue, pending;
190
191 ATH5K_TRACE(ah->ah_sc);
192 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
193
194 /* Return if queue is declared inactive */
195 if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
196 return -EIO;
197
198 if (ah->ah_version == AR5K_AR5210) {
199 tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
200
201 /*
202 * Set by queue type
203 */
204 switch (ah->ah_txq[queue].tqi_type) {
205 case AR5K_TX_QUEUE_DATA:
206 tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0;
207 break;
208 case AR5K_TX_QUEUE_BEACON:
209 case AR5K_TX_QUEUE_CAB:
210 /* XXX Fix me... */
211 tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1;
212 ath5k_hw_reg_write(ah, 0, AR5K_BSR);
213 break;
214 default:
215 return -EINVAL;
216 }
217
218 /* Stop queue */
219 ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
220 ath5k_hw_reg_read(ah, AR5K_CR);
221 } else {
222 /*
223 * Schedule TX disable and wait until queue is empty
224 */
225 AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
226
227 /*Check for pending frames*/
228 do {
229 pending = ath5k_hw_reg_read(ah,
230 AR5K_QUEUE_STATUS(queue)) &
231 AR5K_QCU_STS_FRMPENDCNT;
232 udelay(100);
233 } while (--i && pending);
234
235 /* For 2413+ order PCU to drop packets using
236 * QUIET mechanism */
237 if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) &&
238 pending){
239 /* Set periodicity and duration */
240 ath5k_hw_reg_write(ah,
241 AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)|
242 AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR),
243 AR5K_QUIET_CTL2);
244
245 /* Enable quiet period for current TSF */
246 ath5k_hw_reg_write(ah,
247 AR5K_QUIET_CTL1_QT_EN |
248 AR5K_REG_SM(ath5k_hw_reg_read(ah,
249 AR5K_TSF_L32_5211) >> 10,
250 AR5K_QUIET_CTL1_NEXT_QT_TSF),
251 AR5K_QUIET_CTL1);
252
253 /* Force channel idle high */
254 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
255 AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
256
257 /* Wait a while and disable mechanism */
258 udelay(200);
259 AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1,
260 AR5K_QUIET_CTL1_QT_EN);
261
262 /* Re-check for pending frames */
263 i = 40;
264 do {
265 pending = ath5k_hw_reg_read(ah,
266 AR5K_QUEUE_STATUS(queue)) &
267 AR5K_QCU_STS_FRMPENDCNT;
268 udelay(100);
269 } while (--i && pending);
270
271 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
272 AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
273 }
274
275 /* Clear register */
276 ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
277 if (pending)
278 return -EBUSY;
279 }
280
281 /* TODO: Check for success on 5210 else return error */
282 return 0;
283}
284
285/**
286 * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue
287 *
288 * @ah: The &struct ath5k_hw
289 * @queue: The hw queue number
290 *
291 * Get TX descriptor's address for a specific queue. For 5210 we ignore
292 * the queue number and use tx queue type since we only have 2 queues.
293 * We use TXDP0 for normal data queue and TXDP1 for beacon queue.
294 * For newer chips with QCU/DCU we just read the corresponding TXDP register.
295 *
296 * XXX: Is TXDP read and clear ?
297 */
298u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
299{
300 u16 tx_reg;
301
302 ATH5K_TRACE(ah->ah_sc);
303 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
304
305 /*
306 * Get the transmit queue descriptor pointer from the selected queue
307 */
308 /*5210 doesn't have QCU*/
309 if (ah->ah_version == AR5K_AR5210) {
310 switch (ah->ah_txq[queue].tqi_type) {
311 case AR5K_TX_QUEUE_DATA:
312 tx_reg = AR5K_NOQCU_TXDP0;
313 break;
314 case AR5K_TX_QUEUE_BEACON:
315 case AR5K_TX_QUEUE_CAB:
316 tx_reg = AR5K_NOQCU_TXDP1;
317 break;
318 default:
319 return 0xffffffff;
320 }
321 } else {
322 tx_reg = AR5K_QUEUE_TXDP(queue);
323 }
324
325 return ath5k_hw_reg_read(ah, tx_reg);
326}
327
328/**
329 * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue
330 *
331 * @ah: The &struct ath5k_hw
332 * @queue: The hw queue number
333 *
334 * Set TX descriptor's address for a specific queue. For 5210 we ignore
335 * the queue number and we use tx queue type since we only have 2 queues
336 * so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue.
337 * For newer chips with QCU/DCU we just set the corresponding TXDP register.
338 * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still
339 * active.
340 */
341int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
342{
343 u16 tx_reg;
344
345 ATH5K_TRACE(ah->ah_sc);
346 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
347
348 /*
349 * Set the transmit queue descriptor pointer register by type
350 * on 5210
351 */
352 if (ah->ah_version == AR5K_AR5210) {
353 switch (ah->ah_txq[queue].tqi_type) {
354 case AR5K_TX_QUEUE_DATA:
355 tx_reg = AR5K_NOQCU_TXDP0;
356 break;
357 case AR5K_TX_QUEUE_BEACON:
358 case AR5K_TX_QUEUE_CAB:
359 tx_reg = AR5K_NOQCU_TXDP1;
360 break;
361 default:
362 return -EINVAL;
363 }
364 } else {
365 /*
366 * Set the transmit queue descriptor pointer for
367 * the selected queue on QCU for 5211+
368 * (this won't work if the queue is still active)
369 */
370 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
371 return -EIO;
372
373 tx_reg = AR5K_QUEUE_TXDP(queue);
374 }
375
376 /* Set descriptor pointer */
377 ath5k_hw_reg_write(ah, phys_addr, tx_reg);
378
379 return 0;
380}
381
382/**
383 * ath5k_hw_update_tx_triglevel - Update tx trigger level
384 *
385 * @ah: The &struct ath5k_hw
386 * @increase: Flag to force increase of trigger level
387 *
388 * This function increases/decreases the tx trigger level for the tx fifo
389 * buffer (aka FIFO threshold) that is used to indicate when PCU flushes
390 * the buffer and transmits it's data. Lowering this results sending small
391 * frames more quickly but can lead to tx underruns, raising it a lot can
392 * result other problems (i think bmiss is related). Right now we start with
393 * the lowest possible (64Bytes) and if we get tx underrun we increase it using
394 * the increase flag. Returns -EIO if we have have reached maximum/minimum.
395 *
396 * XXX: Link this with tx DMA size ?
397 * XXX: Use it to save interrupts ?
398 * TODO: Needs testing, i think it's related to bmiss...
399 */
400int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
401{
402 u32 trigger_level, imr;
403 int ret = -EIO;
404
405 ATH5K_TRACE(ah->ah_sc);
406
407 /*
408 * Disable interrupts by setting the mask
409 */
410 imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL);
411
412 trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
413 AR5K_TXCFG_TXFULL);
414
415 if (!increase) {
416 if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
417 goto done;
418 } else
419 trigger_level +=
420 ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
421
422 /*
423 * Update trigger level on success
424 */
425 if (ah->ah_version == AR5K_AR5210)
426 ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL);
427 else
428 AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
429 AR5K_TXCFG_TXFULL, trigger_level);
430
431 ret = 0;
432
433done:
434 /*
435 * Restore interrupt mask
436 */
437 ath5k_hw_set_imr(ah, imr);
438
439 return ret;
440}
441
442/*******************\
443* Interrupt masking *
444\*******************/
445
446/**
447 * ath5k_hw_is_intr_pending - Check if we have pending interrupts
448 *
449 * @ah: The &struct ath5k_hw
450 *
451 * Check if we have pending interrupts to process. Returns 1 if we
452 * have pending interrupts and 0 if we haven't.
453 */
454bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
455{
456 ATH5K_TRACE(ah->ah_sc);
457 return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0;
458}
459
460/**
461 * ath5k_hw_get_isr - Get interrupt status
462 *
463 * @ah: The @struct ath5k_hw
464 * @interrupt_mask: Driver's interrupt mask used to filter out
465 * interrupts in sw.
466 *
467 * This function is used inside our interrupt handler to determine the reason
468 * for the interrupt by reading Primary Interrupt Status Register. Returns an
469 * abstract interrupt status mask which is mostly ISR with some uncommon bits
470 * being mapped on some standard non hw-specific positions
471 * (check out &ath5k_int).
472 *
473 * NOTE: We use read-and-clear register, so after this function is called ISR
474 * is zeroed.
475 */
476int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
477{
478 u32 data;
479
480 ATH5K_TRACE(ah->ah_sc);
481
482 /*
483 * Read interrupt status from the Interrupt Status register
484 * on 5210
485 */
486 if (ah->ah_version == AR5K_AR5210) {
487 data = ath5k_hw_reg_read(ah, AR5K_ISR);
488 if (unlikely(data == AR5K_INT_NOCARD)) {
489 *interrupt_mask = data;
490 return -ENODEV;
491 }
492 } else {
493 /*
494 * Read interrupt status from Interrupt
495 * Status Register shadow copy (Read And Clear)
496 *
497 * Note: PISR/SISR Not available on 5210
498 */
499 data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
500 if (unlikely(data == AR5K_INT_NOCARD)) {
501 *interrupt_mask = data;
502 return -ENODEV;
503 }
504 }
505
506 /*
507 * Get abstract interrupt mask (driver-compatible)
508 */
509 *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
510
511 if (ah->ah_version != AR5K_AR5210) {
512 u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2);
513
514 /*HIU = Host Interface Unit (PCI etc)*/
515 if (unlikely(data & (AR5K_ISR_HIUERR)))
516 *interrupt_mask |= AR5K_INT_FATAL;
517
518 /*Beacon Not Ready*/
519 if (unlikely(data & (AR5K_ISR_BNR)))
520 *interrupt_mask |= AR5K_INT_BNR;
521
522 if (unlikely(sisr2 & (AR5K_SISR2_SSERR |
523 AR5K_SISR2_DPERR |
524 AR5K_SISR2_MCABT)))
525 *interrupt_mask |= AR5K_INT_FATAL;
526
527 if (data & AR5K_ISR_TIM)
528 *interrupt_mask |= AR5K_INT_TIM;
529
530 if (data & AR5K_ISR_BCNMISC) {
531 if (sisr2 & AR5K_SISR2_TIM)
532 *interrupt_mask |= AR5K_INT_TIM;
533 if (sisr2 & AR5K_SISR2_DTIM)
534 *interrupt_mask |= AR5K_INT_DTIM;
535 if (sisr2 & AR5K_SISR2_DTIM_SYNC)
536 *interrupt_mask |= AR5K_INT_DTIM_SYNC;
537 if (sisr2 & AR5K_SISR2_BCN_TIMEOUT)
538 *interrupt_mask |= AR5K_INT_BCN_TIMEOUT;
539 if (sisr2 & AR5K_SISR2_CAB_TIMEOUT)
540 *interrupt_mask |= AR5K_INT_CAB_TIMEOUT;
541 }
542
543 if (data & AR5K_ISR_RXDOPPLER)
544 *interrupt_mask |= AR5K_INT_RX_DOPPLER;
545 if (data & AR5K_ISR_QCBRORN) {
546 *interrupt_mask |= AR5K_INT_QCBRORN;
547 ah->ah_txq_isr |= AR5K_REG_MS(
548 ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
549 AR5K_SISR3_QCBRORN);
550 }
551 if (data & AR5K_ISR_QCBRURN) {
552 *interrupt_mask |= AR5K_INT_QCBRURN;
553 ah->ah_txq_isr |= AR5K_REG_MS(
554 ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
555 AR5K_SISR3_QCBRURN);
556 }
557 if (data & AR5K_ISR_QTRIG) {
558 *interrupt_mask |= AR5K_INT_QTRIG;
559 ah->ah_txq_isr |= AR5K_REG_MS(
560 ath5k_hw_reg_read(ah, AR5K_RAC_SISR4),
561 AR5K_SISR4_QTRIG);
562 }
563
564 if (data & AR5K_ISR_TXOK)
565 ah->ah_txq_isr |= AR5K_REG_MS(
566 ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
567 AR5K_SISR0_QCU_TXOK);
568
569 if (data & AR5K_ISR_TXDESC)
570 ah->ah_txq_isr |= AR5K_REG_MS(
571 ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
572 AR5K_SISR0_QCU_TXDESC);
573
574 if (data & AR5K_ISR_TXERR)
575 ah->ah_txq_isr |= AR5K_REG_MS(
576 ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
577 AR5K_SISR1_QCU_TXERR);
578
579 if (data & AR5K_ISR_TXEOL)
580 ah->ah_txq_isr |= AR5K_REG_MS(
581 ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
582 AR5K_SISR1_QCU_TXEOL);
583
584 if (data & AR5K_ISR_TXURN)
585 ah->ah_txq_isr |= AR5K_REG_MS(
586 ath5k_hw_reg_read(ah, AR5K_RAC_SISR2),
587 AR5K_SISR2_QCU_TXURN);
588 } else {
589 if (unlikely(data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT
590 | AR5K_ISR_HIUERR | AR5K_ISR_DPERR)))
591 *interrupt_mask |= AR5K_INT_FATAL;
592
593 /*
594 * XXX: BMISS interrupts may occur after association.
595 * I found this on 5210 code but it needs testing. If this is
596 * true we should disable them before assoc and re-enable them
597 * after a successful assoc + some jiffies.
598 interrupt_mask &= ~AR5K_INT_BMISS;
599 */
600 }
601
602 /*
603 * In case we didn't handle anything,
604 * print the register value.
605 */
606 if (unlikely(*interrupt_mask == 0 && net_ratelimit()))
607 ATH5K_PRINTF("ISR: 0x%08x IMR: 0x%08x\n", data, ah->ah_imr);
608
609 return 0;
610}
611
612/**
613 * ath5k_hw_set_imr - Set interrupt mask
614 *
615 * @ah: The &struct ath5k_hw
616 * @new_mask: The new interrupt mask to be set
617 *
618 * Set the interrupt mask in hw to save interrupts. We do that by mapping
619 * ath5k_int bits to hw-specific bits to remove abstraction and writing
620 * Interrupt Mask Register.
621 */
622enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
623{
624 enum ath5k_int old_mask, int_mask;
625
626 old_mask = ah->ah_imr;
627
628 /*
629 * Disable card interrupts to prevent any race conditions
630 * (they will be re-enabled afterwards if AR5K_INT GLOBAL
631 * is set again on the new mask).
632 */
633 if (old_mask & AR5K_INT_GLOBAL) {
634 ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
635 ath5k_hw_reg_read(ah, AR5K_IER);
636 }
637
638 /*
639 * Add additional, chipset-dependent interrupt mask flags
640 * and write them to the IMR (interrupt mask register).
641 */
642 int_mask = new_mask & AR5K_INT_COMMON;
643
644 if (ah->ah_version != AR5K_AR5210) {
645 /* Preserve per queue TXURN interrupt mask */
646 u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2)
647 & AR5K_SIMR2_QCU_TXURN;
648
649 if (new_mask & AR5K_INT_FATAL) {
650 int_mask |= AR5K_IMR_HIUERR;
651 simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR
652 | AR5K_SIMR2_DPERR);
653 }
654
655 /*Beacon Not Ready*/
656 if (new_mask & AR5K_INT_BNR)
657 int_mask |= AR5K_INT_BNR;
658
659 if (new_mask & AR5K_INT_TIM)
660 int_mask |= AR5K_IMR_TIM;
661
662 if (new_mask & AR5K_INT_TIM)
663 simr2 |= AR5K_SISR2_TIM;
664 if (new_mask & AR5K_INT_DTIM)
665 simr2 |= AR5K_SISR2_DTIM;
666 if (new_mask & AR5K_INT_DTIM_SYNC)
667 simr2 |= AR5K_SISR2_DTIM_SYNC;
668 if (new_mask & AR5K_INT_BCN_TIMEOUT)
669 simr2 |= AR5K_SISR2_BCN_TIMEOUT;
670 if (new_mask & AR5K_INT_CAB_TIMEOUT)
671 simr2 |= AR5K_SISR2_CAB_TIMEOUT;
672
673 if (new_mask & AR5K_INT_RX_DOPPLER)
674 int_mask |= AR5K_IMR_RXDOPPLER;
675
676 /* Note: Per queue interrupt masks
677 * are set via reset_tx_queue (qcu.c) */
678 ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
679 ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
680
681 } else {
682 if (new_mask & AR5K_INT_FATAL)
683 int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT
684 | AR5K_IMR_HIUERR | AR5K_IMR_DPERR);
685
686 ath5k_hw_reg_write(ah, int_mask, AR5K_IMR);
687 }
688
689 /* If RXNOFRM interrupt is masked disable it
690 * by setting AR5K_RXNOFRM to zero */
691 if (!(new_mask & AR5K_INT_RXNOFRM))
692 ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM);
693
694 /* Store new interrupt mask */
695 ah->ah_imr = new_mask;
696
697 /* ..re-enable interrupts if AR5K_INT_GLOBAL is set */
698 if (new_mask & AR5K_INT_GLOBAL) {
699 ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER);
700 ath5k_hw_reg_read(ah, AR5K_IER);
701 }
702
703 return old_mask;
704}
705
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
new file mode 100644
index 000000000000..c0fb3b09ba45
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -0,0 +1,1769 @@
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
4 * Copyright (c) 2008-2009 Felix Fietkau <nbd@openwrt.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20/*************************************\
21* EEPROM access functions and helpers *
22\*************************************/
23
24#include "ath5k.h"
25#include "reg.h"
26#include "debug.h"
27#include "base.h"
28
29/*
30 * Read from eeprom
31 */
32static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
33{
34 u32 status, timeout;
35
36 ATH5K_TRACE(ah->ah_sc);
37 /*
38 * Initialize EEPROM access
39 */
40 if (ah->ah_version == AR5K_AR5210) {
41 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
42 (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
43 } else {
44 ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
45 AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
46 AR5K_EEPROM_CMD_READ);
47 }
48
49 for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
50 status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
51 if (status & AR5K_EEPROM_STAT_RDDONE) {
52 if (status & AR5K_EEPROM_STAT_RDERR)
53 return -EIO;
54 *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
55 0xffff);
56 return 0;
57 }
58 udelay(15);
59 }
60
61 return -ETIMEDOUT;
62}
63
64/*
65 * Translate binary channel representation in EEPROM to frequency
66 */
67static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin,
68 unsigned int mode)
69{
70 u16 val;
71
72 if (bin == AR5K_EEPROM_CHANNEL_DIS)
73 return bin;
74
75 if (mode == AR5K_EEPROM_MODE_11A) {
76 if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
77 val = (5 * bin) + 4800;
78 else
79 val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
80 (bin * 10) + 5100;
81 } else {
82 if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
83 val = bin + 2300;
84 else
85 val = bin + 2400;
86 }
87
88 return val;
89}
90
91/*
92 * Initialize eeprom & capabilities structs
93 */
94static int
95ath5k_eeprom_init_header(struct ath5k_hw *ah)
96{
97 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
98 int ret;
99 u16 val;
100
101 /*
102 * Read values from EEPROM and store them in the capability structure
103 */
104 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
105 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
106 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
107 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
108 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
109
110 /* Return if we have an old EEPROM */
111 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
112 return 0;
113
114#ifdef notyet
115 /*
116 * Validate the checksum of the EEPROM date. There are some
117 * devices with invalid EEPROMs.
118 */
119 for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
120 AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
121 cksum ^= val;
122 }
123 if (cksum != AR5K_EEPROM_INFO_CKSUM) {
124 ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
125 return -EIO;
126 }
127#endif
128
129 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
130 ee_ant_gain);
131
132 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
133 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
134 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
135
136 /* XXX: Don't know which versions include these two */
137 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2);
138
139 if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3)
140 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3);
141
142 if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) {
143 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4);
144 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5);
145 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6);
146 }
147 }
148
149 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
150 AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
151 ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
152 ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
153
154 AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
155 ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
156 ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
157 }
158
159 return 0;
160}
161
162
163/*
164 * Read antenna infos from eeprom
165 */
166static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
167 unsigned int mode)
168{
169 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
170 u32 o = *offset;
171 u16 val;
172 int ret, i = 0;
173
174 AR5K_EEPROM_READ(o++, val);
175 ee->ee_switch_settling[mode] = (val >> 8) & 0x7f;
176 ee->ee_atn_tx_rx[mode] = (val >> 2) & 0x3f;
177 ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
178
179 AR5K_EEPROM_READ(o++, val);
180 ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
181 ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
182 ee->ee_ant_control[mode][i++] = val & 0x3f;
183
184 AR5K_EEPROM_READ(o++, val);
185 ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f;
186 ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f;
187 ee->ee_ant_control[mode][i] = (val << 2) & 0x3f;
188
189 AR5K_EEPROM_READ(o++, val);
190 ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3;
191 ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f;
192 ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f;
193 ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
194
195 AR5K_EEPROM_READ(o++, val);
196 ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
197 ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
198 ee->ee_ant_control[mode][i++] = val & 0x3f;
199
200 /* Get antenna modes */
201 ah->ah_antenna[mode][0] =
202 (ee->ee_ant_control[mode][0] << 4);
203 ah->ah_antenna[mode][AR5K_ANT_FIXED_A] =
204 ee->ee_ant_control[mode][1] |
205 (ee->ee_ant_control[mode][2] << 6) |
206 (ee->ee_ant_control[mode][3] << 12) |
207 (ee->ee_ant_control[mode][4] << 18) |
208 (ee->ee_ant_control[mode][5] << 24);
209 ah->ah_antenna[mode][AR5K_ANT_FIXED_B] =
210 ee->ee_ant_control[mode][6] |
211 (ee->ee_ant_control[mode][7] << 6) |
212 (ee->ee_ant_control[mode][8] << 12) |
213 (ee->ee_ant_control[mode][9] << 18) |
214 (ee->ee_ant_control[mode][10] << 24);
215
216 /* return new offset */
217 *offset = o;
218
219 return 0;
220}
221
222/*
223 * Read supported modes and some mode-specific calibration data
224 * from eeprom
225 */
226static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
227 unsigned int mode)
228{
229 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
230 u32 o = *offset;
231 u16 val;
232 int ret;
233
234 ee->ee_n_piers[mode] = 0;
235 AR5K_EEPROM_READ(o++, val);
236 ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
237 switch(mode) {
238 case AR5K_EEPROM_MODE_11A:
239 ee->ee_ob[mode][3] = (val >> 5) & 0x7;
240 ee->ee_db[mode][3] = (val >> 2) & 0x7;
241 ee->ee_ob[mode][2] = (val << 1) & 0x7;
242
243 AR5K_EEPROM_READ(o++, val);
244 ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
245 ee->ee_db[mode][2] = (val >> 12) & 0x7;
246 ee->ee_ob[mode][1] = (val >> 9) & 0x7;
247 ee->ee_db[mode][1] = (val >> 6) & 0x7;
248 ee->ee_ob[mode][0] = (val >> 3) & 0x7;
249 ee->ee_db[mode][0] = val & 0x7;
250 break;
251 case AR5K_EEPROM_MODE_11G:
252 case AR5K_EEPROM_MODE_11B:
253 ee->ee_ob[mode][1] = (val >> 4) & 0x7;
254 ee->ee_db[mode][1] = val & 0x7;
255 break;
256 }
257
258 AR5K_EEPROM_READ(o++, val);
259 ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
260 ee->ee_thr_62[mode] = val & 0xff;
261
262 if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
263 ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
264
265 AR5K_EEPROM_READ(o++, val);
266 ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
267 ee->ee_tx_frm2xpa_enable[mode] = val & 0xff;
268
269 AR5K_EEPROM_READ(o++, val);
270 ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff;
271
272 if ((val & 0xff) & 0x80)
273 ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
274 else
275 ee->ee_noise_floor_thr[mode] = val & 0xff;
276
277 if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
278 ee->ee_noise_floor_thr[mode] =
279 mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
280
281 AR5K_EEPROM_READ(o++, val);
282 ee->ee_xlna_gain[mode] = (val >> 5) & 0xff;
283 ee->ee_x_gain[mode] = (val >> 1) & 0xf;
284 ee->ee_xpd[mode] = val & 0x1;
285
286 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
287 ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
288
289 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
290 AR5K_EEPROM_READ(o++, val);
291 ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
292
293 if (mode == AR5K_EEPROM_MODE_11A)
294 ee->ee_xr_power[mode] = val & 0x3f;
295 else {
296 ee->ee_ob[mode][0] = val & 0x7;
297 ee->ee_db[mode][0] = (val >> 3) & 0x7;
298 }
299 }
300
301 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
302 ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
303 ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
304 } else {
305 ee->ee_i_gain[mode] = (val >> 13) & 0x7;
306
307 AR5K_EEPROM_READ(o++, val);
308 ee->ee_i_gain[mode] |= (val << 3) & 0x38;
309
310 if (mode == AR5K_EEPROM_MODE_11G) {
311 ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
312 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6)
313 ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
314 }
315 }
316
317 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
318 mode == AR5K_EEPROM_MODE_11A) {
319 ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
320 ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
321 }
322
323 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0)
324 goto done;
325
326 /* Note: >= v5 have bg freq piers on another location
327 * so these freq piers are ignored for >= v5 (should be 0xff
328 * anyway) */
329 switch(mode) {
330 case AR5K_EEPROM_MODE_11A:
331 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1)
332 break;
333
334 AR5K_EEPROM_READ(o++, val);
335 ee->ee_margin_tx_rx[mode] = val & 0x3f;
336 break;
337 case AR5K_EEPROM_MODE_11B:
338 AR5K_EEPROM_READ(o++, val);
339
340 ee->ee_pwr_cal_b[0].freq =
341 ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
342 if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS)
343 ee->ee_n_piers[mode]++;
344
345 ee->ee_pwr_cal_b[1].freq =
346 ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
347 if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS)
348 ee->ee_n_piers[mode]++;
349
350 AR5K_EEPROM_READ(o++, val);
351 ee->ee_pwr_cal_b[2].freq =
352 ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
353 if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS)
354 ee->ee_n_piers[mode]++;
355
356 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
357 ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
358 break;
359 case AR5K_EEPROM_MODE_11G:
360 AR5K_EEPROM_READ(o++, val);
361
362 ee->ee_pwr_cal_g[0].freq =
363 ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
364 if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS)
365 ee->ee_n_piers[mode]++;
366
367 ee->ee_pwr_cal_g[1].freq =
368 ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
369 if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS)
370 ee->ee_n_piers[mode]++;
371
372 AR5K_EEPROM_READ(o++, val);
373 ee->ee_turbo_max_power[mode] = val & 0x7f;
374 ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
375
376 AR5K_EEPROM_READ(o++, val);
377 ee->ee_pwr_cal_g[2].freq =
378 ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
379 if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS)
380 ee->ee_n_piers[mode]++;
381
382 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
383 ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
384
385 AR5K_EEPROM_READ(o++, val);
386 ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
387 ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
388
389 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
390 AR5K_EEPROM_READ(o++, val);
391 ee->ee_cck_ofdm_gain_delta = val & 0xff;
392 }
393 break;
394 }
395
396done:
397 /* return new offset */
398 *offset = o;
399
400 return 0;
401}
402
403/*
404 * Read turbo mode information on newer EEPROM versions
405 */
406static int
407ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah,
408 u32 *offset, unsigned int mode)
409{
410 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
411 u32 o = *offset;
412 u16 val;
413 int ret;
414
415 if (ee->ee_version < AR5K_EEPROM_VERSION_5_0)
416 return 0;
417
418 switch (mode){
419 case AR5K_EEPROM_MODE_11A:
420 ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f;
421
422 ee->ee_atn_tx_rx_turbo[mode] = (val >> 13) & 0x7;
423 AR5K_EEPROM_READ(o++, val);
424 ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x7) << 3;
425 ee->ee_margin_tx_rx_turbo[mode] = (val >> 3) & 0x3f;
426
427 ee->ee_adc_desired_size_turbo[mode] = (val >> 9) & 0x7f;
428 AR5K_EEPROM_READ(o++, val);
429 ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7;
430 ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff;
431
432 if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2)
433 ee->ee_pd_gain_overlap = (val >> 9) & 0xf;
434 break;
435 case AR5K_EEPROM_MODE_11G:
436 ee->ee_switch_settling_turbo[mode] = (val >> 8) & 0x7f;
437
438 ee->ee_atn_tx_rx_turbo[mode] = (val >> 15) & 0x7;
439 AR5K_EEPROM_READ(o++, val);
440 ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x1f) << 1;
441 ee->ee_margin_tx_rx_turbo[mode] = (val >> 5) & 0x3f;
442
443 ee->ee_adc_desired_size_turbo[mode] = (val >> 11) & 0x7f;
444 AR5K_EEPROM_READ(o++, val);
445 ee->ee_adc_desired_size_turbo[mode] |= (val & 0x7) << 5;
446 ee->ee_pga_desired_size_turbo[mode] = (val >> 3) & 0xff;
447 break;
448 }
449
450 /* return new offset */
451 *offset = o;
452
453 return 0;
454}
455
456/* Read mode-specific data (except power calibration data) */
457static int
458ath5k_eeprom_init_modes(struct ath5k_hw *ah)
459{
460 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
461 u32 mode_offset[3];
462 unsigned int mode;
463 u32 offset;
464 int ret;
465
466 /*
467 * Get values for all modes
468 */
469 mode_offset[AR5K_EEPROM_MODE_11A] = AR5K_EEPROM_MODES_11A(ah->ah_ee_version);
470 mode_offset[AR5K_EEPROM_MODE_11B] = AR5K_EEPROM_MODES_11B(ah->ah_ee_version);
471 mode_offset[AR5K_EEPROM_MODE_11G] = AR5K_EEPROM_MODES_11G(ah->ah_ee_version);
472
473 ee->ee_turbo_max_power[AR5K_EEPROM_MODE_11A] =
474 AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
475
476 for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) {
477 offset = mode_offset[mode];
478
479 ret = ath5k_eeprom_read_ants(ah, &offset, mode);
480 if (ret)
481 return ret;
482
483 ret = ath5k_eeprom_read_modes(ah, &offset, mode);
484 if (ret)
485 return ret;
486
487 ret = ath5k_eeprom_read_turbo_modes(ah, &offset, mode);
488 if (ret)
489 return ret;
490 }
491
492 /* override for older eeprom versions for better performance */
493 if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) {
494 ee->ee_thr_62[AR5K_EEPROM_MODE_11A] = 15;
495 ee->ee_thr_62[AR5K_EEPROM_MODE_11B] = 28;
496 ee->ee_thr_62[AR5K_EEPROM_MODE_11G] = 28;
497 }
498
499 return 0;
500}
501
502/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff
503 * frequency mask) */
504static inline int
505ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
506 struct ath5k_chan_pcal_info *pc, unsigned int mode)
507{
508 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
509 int o = *offset;
510 int i = 0;
511 u8 freq1, freq2;
512 int ret;
513 u16 val;
514
515 ee->ee_n_piers[mode] = 0;
516 while(i < max) {
517 AR5K_EEPROM_READ(o++, val);
518
519 freq1 = val & 0xff;
520 if (!freq1)
521 break;
522
523 pc[i++].freq = ath5k_eeprom_bin2freq(ee,
524 freq1, mode);
525 ee->ee_n_piers[mode]++;
526
527 freq2 = (val >> 8) & 0xff;
528 if (!freq2)
529 break;
530
531 pc[i++].freq = ath5k_eeprom_bin2freq(ee,
532 freq2, mode);
533 ee->ee_n_piers[mode]++;
534 }
535
536 /* return new offset */
537 *offset = o;
538
539 return 0;
540}
541
542/* Read frequency piers for 802.11a */
543static int
544ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
545{
546 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
547 struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a;
548 int i, ret;
549 u16 val;
550 u8 mask;
551
552 if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
553 ath5k_eeprom_read_freq_list(ah, &offset,
554 AR5K_EEPROM_N_5GHZ_CHAN, pcal,
555 AR5K_EEPROM_MODE_11A);
556 } else {
557 mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version);
558
559 AR5K_EEPROM_READ(offset++, val);
560 pcal[0].freq = (val >> 9) & mask;
561 pcal[1].freq = (val >> 2) & mask;
562 pcal[2].freq = (val << 5) & mask;
563
564 AR5K_EEPROM_READ(offset++, val);
565 pcal[2].freq |= (val >> 11) & 0x1f;
566 pcal[3].freq = (val >> 4) & mask;
567 pcal[4].freq = (val << 3) & mask;
568
569 AR5K_EEPROM_READ(offset++, val);
570 pcal[4].freq |= (val >> 13) & 0x7;
571 pcal[5].freq = (val >> 6) & mask;
572 pcal[6].freq = (val << 1) & mask;
573
574 AR5K_EEPROM_READ(offset++, val);
575 pcal[6].freq |= (val >> 15) & 0x1;
576 pcal[7].freq = (val >> 8) & mask;
577 pcal[8].freq = (val >> 1) & mask;
578 pcal[9].freq = (val << 6) & mask;
579
580 AR5K_EEPROM_READ(offset++, val);
581 pcal[9].freq |= (val >> 10) & 0x3f;
582
583 /* Fixed number of piers */
584 ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10;
585
586 for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) {
587 pcal[i].freq = ath5k_eeprom_bin2freq(ee,
588 pcal[i].freq, AR5K_EEPROM_MODE_11A);
589 }
590 }
591
592 return 0;
593}
594
595/* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */
596static inline int
597ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
598{
599 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
600 struct ath5k_chan_pcal_info *pcal;
601
602 switch(mode) {
603 case AR5K_EEPROM_MODE_11B:
604 pcal = ee->ee_pwr_cal_b;
605 break;
606 case AR5K_EEPROM_MODE_11G:
607 pcal = ee->ee_pwr_cal_g;
608 break;
609 default:
610 return -EINVAL;
611 }
612
613 ath5k_eeprom_read_freq_list(ah, &offset,
614 AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal,
615 mode);
616
617 return 0;
618}
619
620/*
621 * Read power calibration for RF5111 chips
622 *
623 * For RF5111 we have an XPD -eXternal Power Detector- curve
624 * for each calibrated channel. Each curve has 0,5dB Power steps
625 * on x axis and PCDAC steps (offsets) on y axis and looks like an
626 * exponential function. To recreate the curve we read 11 points
627 * here and interpolate later.
628 */
629
630/* Used to match PCDAC steps with power values on RF5111 chips
631 * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC
632 * steps that match with the power values we read from eeprom. On
633 * older eeprom versions (< 3.2) these steps are equaly spaced at
634 * 10% of the pcdac curve -until the curve reaches it's maximum-
635 * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
636 * these 11 steps are spaced in a different way. This function returns
637 * the pcdac steps based on eeprom version and curve min/max so that we
638 * can have pcdac/pwr points.
639 */
640static inline void
641ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
642{
643 const static u16 intercepts3[] =
644 { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
645 const static u16 intercepts3_2[] =
646 { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
647 const u16 *ip;
648 int i;
649
650 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2)
651 ip = intercepts3_2;
652 else
653 ip = intercepts3;
654
655 for (i = 0; i < ARRAY_SIZE(intercepts3); i++)
656 vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100;
657}
658
659/* Convert RF5111 specific data to generic raw data
660 * used by interpolation code */
661static int
662ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
663 struct ath5k_chan_pcal_info *chinfo)
664{
665 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
666 struct ath5k_chan_pcal_info_rf5111 *pcinfo;
667 struct ath5k_pdgain_info *pd;
668 u8 pier, point, idx;
669 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
670
671 /* Fill raw data for each calibration pier */
672 for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
673
674 pcinfo = &chinfo[pier].rf5111_info;
675
676 /* Allocate pd_curves for this cal pier */
677 chinfo[pier].pd_curves =
678 kcalloc(AR5K_EEPROM_N_PD_CURVES,
679 sizeof(struct ath5k_pdgain_info),
680 GFP_KERNEL);
681
682 if (!chinfo[pier].pd_curves)
683 return -ENOMEM;
684
685 /* Only one curve for RF5111
686 * find out which one and place
687 * in in pd_curves.
688 * Note: ee_x_gain is reversed here */
689 for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) {
690
691 if (!((ee->ee_x_gain[mode] >> idx) & 0x1)) {
692 pdgain_idx[0] = idx;
693 break;
694 }
695 }
696
697 ee->ee_pd_gains[mode] = 1;
698
699 pd = &chinfo[pier].pd_curves[idx];
700
701 pd->pd_points = AR5K_EEPROM_N_PWR_POINTS_5111;
702
703 /* Allocate pd points for this curve */
704 pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
705 sizeof(u8), GFP_KERNEL);
706 if (!pd->pd_step)
707 return -ENOMEM;
708
709 pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
710 sizeof(s16), GFP_KERNEL);
711 if (!pd->pd_pwr)
712 return -ENOMEM;
713
714 /* Fill raw dataset
715 * (convert power to 0.25dB units
716 * for RF5112 combatibility) */
717 for (point = 0; point < pd->pd_points; point++) {
718
719 /* Absolute values */
720 pd->pd_pwr[point] = 2 * pcinfo->pwr[point];
721
722 /* Already sorted */
723 pd->pd_step[point] = pcinfo->pcdac[point];
724 }
725
726 /* Set min/max pwr */
727 chinfo[pier].min_pwr = pd->pd_pwr[0];
728 chinfo[pier].max_pwr = pd->pd_pwr[10];
729
730 }
731
732 return 0;
733}
734
735/* Parse EEPROM data */
736static int
737ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
738{
739 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
740 struct ath5k_chan_pcal_info *pcal;
741 int offset, ret;
742 int i;
743 u16 val;
744
745 offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
746 switch(mode) {
747 case AR5K_EEPROM_MODE_11A:
748 if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
749 return 0;
750
751 ret = ath5k_eeprom_init_11a_pcal_freq(ah,
752 offset + AR5K_EEPROM_GROUP1_OFFSET);
753 if (ret < 0)
754 return ret;
755
756 offset += AR5K_EEPROM_GROUP2_OFFSET;
757 pcal = ee->ee_pwr_cal_a;
758 break;
759 case AR5K_EEPROM_MODE_11B:
760 if (!AR5K_EEPROM_HDR_11B(ee->ee_header) &&
761 !AR5K_EEPROM_HDR_11G(ee->ee_header))
762 return 0;
763
764 pcal = ee->ee_pwr_cal_b;
765 offset += AR5K_EEPROM_GROUP3_OFFSET;
766
767 /* fixed piers */
768 pcal[0].freq = 2412;
769 pcal[1].freq = 2447;
770 pcal[2].freq = 2484;
771 ee->ee_n_piers[mode] = 3;
772 break;
773 case AR5K_EEPROM_MODE_11G:
774 if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
775 return 0;
776
777 pcal = ee->ee_pwr_cal_g;
778 offset += AR5K_EEPROM_GROUP4_OFFSET;
779
780 /* fixed piers */
781 pcal[0].freq = 2312;
782 pcal[1].freq = 2412;
783 pcal[2].freq = 2484;
784 ee->ee_n_piers[mode] = 3;
785 break;
786 default:
787 return -EINVAL;
788 }
789
790 for (i = 0; i < ee->ee_n_piers[mode]; i++) {
791 struct ath5k_chan_pcal_info_rf5111 *cdata =
792 &pcal[i].rf5111_info;
793
794 AR5K_EEPROM_READ(offset++, val);
795 cdata->pcdac_max = ((val >> 10) & AR5K_EEPROM_PCDAC_M);
796 cdata->pcdac_min = ((val >> 4) & AR5K_EEPROM_PCDAC_M);
797 cdata->pwr[0] = ((val << 2) & AR5K_EEPROM_POWER_M);
798
799 AR5K_EEPROM_READ(offset++, val);
800 cdata->pwr[0] |= ((val >> 14) & 0x3);
801 cdata->pwr[1] = ((val >> 8) & AR5K_EEPROM_POWER_M);
802 cdata->pwr[2] = ((val >> 2) & AR5K_EEPROM_POWER_M);
803 cdata->pwr[3] = ((val << 4) & AR5K_EEPROM_POWER_M);
804
805 AR5K_EEPROM_READ(offset++, val);
806 cdata->pwr[3] |= ((val >> 12) & 0xf);
807 cdata->pwr[4] = ((val >> 6) & AR5K_EEPROM_POWER_M);
808 cdata->pwr[5] = (val & AR5K_EEPROM_POWER_M);
809
810 AR5K_EEPROM_READ(offset++, val);
811 cdata->pwr[6] = ((val >> 10) & AR5K_EEPROM_POWER_M);
812 cdata->pwr[7] = ((val >> 4) & AR5K_EEPROM_POWER_M);
813 cdata->pwr[8] = ((val << 2) & AR5K_EEPROM_POWER_M);
814
815 AR5K_EEPROM_READ(offset++, val);
816 cdata->pwr[8] |= ((val >> 14) & 0x3);
817 cdata->pwr[9] = ((val >> 8) & AR5K_EEPROM_POWER_M);
818 cdata->pwr[10] = ((val >> 2) & AR5K_EEPROM_POWER_M);
819
820 ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min,
821 cdata->pcdac_max, cdata->pcdac);
822 }
823
824 return ath5k_eeprom_convert_pcal_info_5111(ah, mode, pcal);
825}
826
827
828/*
829 * Read power calibration for RF5112 chips
830 *
831 * For RF5112 we have 4 XPD -eXternal Power Detector- curves
832 * for each calibrated channel on 0, -6, -12 and -18dbm but we only
833 * use the higher (3) and the lower (0) curves. Each curve has 0.5dB
834 * power steps on x axis and PCDAC steps on y axis and looks like a
835 * linear function. To recreate the curve and pass the power values
836 * on hw, we read 4 points for xpd 0 (lower gain -> max power)
837 * and 3 points for xpd 3 (higher gain -> lower power) here and
838 * interpolate later.
839 *
840 * Note: Many vendors just use xpd 0 so xpd 3 is zeroed.
841 */
842
843/* Convert RF5112 specific data to generic raw data
844 * used by interpolation code */
845static int
846ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
847 struct ath5k_chan_pcal_info *chinfo)
848{
849 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
850 struct ath5k_chan_pcal_info_rf5112 *pcinfo;
851 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
852 unsigned int pier, pdg, point;
853
854 /* Fill raw data for each calibration pier */
855 for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
856
857 pcinfo = &chinfo[pier].rf5112_info;
858
859 /* Allocate pd_curves for this cal pier */
860 chinfo[pier].pd_curves =
861 kcalloc(AR5K_EEPROM_N_PD_CURVES,
862 sizeof(struct ath5k_pdgain_info),
863 GFP_KERNEL);
864
865 if (!chinfo[pier].pd_curves)
866 return -ENOMEM;
867
868 /* Fill pd_curves */
869 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
870
871 u8 idx = pdgain_idx[pdg];
872 struct ath5k_pdgain_info *pd =
873 &chinfo[pier].pd_curves[idx];
874
875 /* Lowest gain curve (max power) */
876 if (pdg == 0) {
877 /* One more point for better accuracy */
878 pd->pd_points = AR5K_EEPROM_N_XPD0_POINTS;
879
880 /* Allocate pd points for this curve */
881 pd->pd_step = kcalloc(pd->pd_points,
882 sizeof(u8), GFP_KERNEL);
883
884 if (!pd->pd_step)
885 return -ENOMEM;
886
887 pd->pd_pwr = kcalloc(pd->pd_points,
888 sizeof(s16), GFP_KERNEL);
889
890 if (!pd->pd_pwr)
891 return -ENOMEM;
892
893
894 /* Fill raw dataset
895 * (all power levels are in 0.25dB units) */
896 pd->pd_step[0] = pcinfo->pcdac_x0[0];
897 pd->pd_pwr[0] = pcinfo->pwr_x0[0];
898
899 for (point = 1; point < pd->pd_points;
900 point++) {
901 /* Absolute values */
902 pd->pd_pwr[point] =
903 pcinfo->pwr_x0[point];
904
905 /* Deltas */
906 pd->pd_step[point] =
907 pd->pd_step[point - 1] +
908 pcinfo->pcdac_x0[point];
909 }
910
911 /* Set min power for this frequency */
912 chinfo[pier].min_pwr = pd->pd_pwr[0];
913
914 /* Highest gain curve (min power) */
915 } else if (pdg == 1) {
916
917 pd->pd_points = AR5K_EEPROM_N_XPD3_POINTS;
918
919 /* Allocate pd points for this curve */
920 pd->pd_step = kcalloc(pd->pd_points,
921 sizeof(u8), GFP_KERNEL);
922
923 if (!pd->pd_step)
924 return -ENOMEM;
925
926 pd->pd_pwr = kcalloc(pd->pd_points,
927 sizeof(s16), GFP_KERNEL);
928
929 if (!pd->pd_pwr)
930 return -ENOMEM;
931
932 /* Fill raw dataset
933 * (all power levels are in 0.25dB units) */
934 for (point = 0; point < pd->pd_points;
935 point++) {
936 /* Absolute values */
937 pd->pd_pwr[point] =
938 pcinfo->pwr_x3[point];
939
940 /* Fixed points */
941 pd->pd_step[point] =
942 pcinfo->pcdac_x3[point];
943 }
944
945 /* Since we have a higher gain curve
946 * override min power */
947 chinfo[pier].min_pwr = pd->pd_pwr[0];
948 }
949 }
950 }
951
952 return 0;
953}
954
955/* Parse EEPROM data */
956static int
957ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
958{
959 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
960 struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info;
961 struct ath5k_chan_pcal_info *gen_chan_info;
962 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
963 u32 offset;
964 u8 i, c;
965 u16 val;
966 int ret;
967 u8 pd_gains = 0;
968
969 /* Count how many curves we have and
970 * identify them (which one of the 4
971 * available curves we have on each count).
972 * Curves are stored from lower (x0) to
973 * higher (x3) gain */
974 for (i = 0; i < AR5K_EEPROM_N_PD_CURVES; i++) {
975 /* ee_x_gain[mode] is x gain mask */
976 if ((ee->ee_x_gain[mode] >> i) & 0x1)
977 pdgain_idx[pd_gains++] = i;
978 }
979 ee->ee_pd_gains[mode] = pd_gains;
980
981 if (pd_gains == 0 || pd_gains > 2)
982 return -EINVAL;
983
984 switch (mode) {
985 case AR5K_EEPROM_MODE_11A:
986 /*
987 * Read 5GHz EEPROM channels
988 */
989 offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
990 ath5k_eeprom_init_11a_pcal_freq(ah, offset);
991
992 offset += AR5K_EEPROM_GROUP2_OFFSET;
993 gen_chan_info = ee->ee_pwr_cal_a;
994 break;
995 case AR5K_EEPROM_MODE_11B:
996 offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
997 if (AR5K_EEPROM_HDR_11A(ee->ee_header))
998 offset += AR5K_EEPROM_GROUP3_OFFSET;
999
1000 /* NB: frequency piers parsed during mode init */
1001 gen_chan_info = ee->ee_pwr_cal_b;
1002 break;
1003 case AR5K_EEPROM_MODE_11G:
1004 offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
1005 if (AR5K_EEPROM_HDR_11A(ee->ee_header))
1006 offset += AR5K_EEPROM_GROUP4_OFFSET;
1007 else if (AR5K_EEPROM_HDR_11B(ee->ee_header))
1008 offset += AR5K_EEPROM_GROUP2_OFFSET;
1009
1010 /* NB: frequency piers parsed during mode init */
1011 gen_chan_info = ee->ee_pwr_cal_g;
1012 break;
1013 default:
1014 return -EINVAL;
1015 }
1016
1017 for (i = 0; i < ee->ee_n_piers[mode]; i++) {
1018 chan_pcal_info = &gen_chan_info[i].rf5112_info;
1019
1020 /* Power values in quarter dB
1021 * for the lower xpd gain curve
1022 * (0 dBm -> higher output power) */
1023 for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
1024 AR5K_EEPROM_READ(offset++, val);
1025 chan_pcal_info->pwr_x0[c] = (s8) (val & 0xff);
1026 chan_pcal_info->pwr_x0[++c] = (s8) ((val >> 8) & 0xff);
1027 }
1028
1029 /* PCDAC steps
1030 * corresponding to the above power
1031 * measurements */
1032 AR5K_EEPROM_READ(offset++, val);
1033 chan_pcal_info->pcdac_x0[1] = (val & 0x1f);
1034 chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f);
1035 chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f);
1036
1037 /* Power values in quarter dB
1038 * for the higher xpd gain curve
1039 * (18 dBm -> lower output power) */
1040 AR5K_EEPROM_READ(offset++, val);
1041 chan_pcal_info->pwr_x3[0] = (s8) (val & 0xff);
1042 chan_pcal_info->pwr_x3[1] = (s8) ((val >> 8) & 0xff);
1043
1044 AR5K_EEPROM_READ(offset++, val);
1045 chan_pcal_info->pwr_x3[2] = (val & 0xff);
1046
1047 /* PCDAC steps
1048 * corresponding to the above power
1049 * measurements (fixed) */
1050 chan_pcal_info->pcdac_x3[0] = 20;
1051 chan_pcal_info->pcdac_x3[1] = 35;
1052 chan_pcal_info->pcdac_x3[2] = 63;
1053
1054 if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) {
1055 chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0x3f);
1056
1057 /* Last xpd0 power level is also channel maximum */
1058 gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3];
1059 } else {
1060 chan_pcal_info->pcdac_x0[0] = 1;
1061 gen_chan_info[i].max_pwr = (s8) ((val >> 8) & 0xff);
1062 }
1063
1064 }
1065
1066 return ath5k_eeprom_convert_pcal_info_5112(ah, mode, gen_chan_info);
1067}
1068
1069
1070/*
1071 * Read power calibration for RF2413 chips
1072 *
1073 * For RF2413 we have a Power to PDDAC table (Power Detector)
1074 * instead of a PCDAC and 4 pd gain curves for each calibrated channel.
1075 * Each curve has power on x axis in 0.5 db steps and PDDADC steps on y
1076 * axis and looks like an exponential function like the RF5111 curve.
1077 *
1078 * To recreate the curves we read here the points and interpolate
1079 * later. Note that in most cases only 2 (higher and lower) curves are
1080 * used (like RF5112) but vendors have the oportunity to include all
1081 * 4 curves on eeprom. The final curve (higher power) has an extra
1082 * point for better accuracy like RF5112.
1083 */
1084
1085/* For RF2413 power calibration data doesn't start on a fixed location and
1086 * if a mode is not supported, it's section is missing -not zeroed-.
1087 * So we need to calculate the starting offset for each section by using
1088 * these two functions */
1089
1090/* Return the size of each section based on the mode and the number of pd
1091 * gains available (maximum 4). */
1092static inline unsigned int
1093ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode)
1094{
1095 static const unsigned int pdgains_size[] = { 4, 6, 9, 12 };
1096 unsigned int sz;
1097
1098 sz = pdgains_size[ee->ee_pd_gains[mode] - 1];
1099 sz *= ee->ee_n_piers[mode];
1100
1101 return sz;
1102}
1103
1104/* Return the starting offset for a section based on the modes supported
1105 * and each section's size. */
1106static unsigned int
1107ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
1108{
1109 u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4);
1110
1111 switch(mode) {
1112 case AR5K_EEPROM_MODE_11G:
1113 if (AR5K_EEPROM_HDR_11B(ee->ee_header))
1114 offset += ath5k_pdgains_size_2413(ee,
1115 AR5K_EEPROM_MODE_11B) +
1116 AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
1117 /* fall through */
1118 case AR5K_EEPROM_MODE_11B:
1119 if (AR5K_EEPROM_HDR_11A(ee->ee_header))
1120 offset += ath5k_pdgains_size_2413(ee,
1121 AR5K_EEPROM_MODE_11A) +
1122 AR5K_EEPROM_N_5GHZ_CHAN / 2;
1123 /* fall through */
1124 case AR5K_EEPROM_MODE_11A:
1125 break;
1126 default:
1127 break;
1128 }
1129
1130 return offset;
1131}
1132
1133/* Convert RF2413 specific data to generic raw data
1134 * used by interpolation code */
1135static int
1136ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
1137 struct ath5k_chan_pcal_info *chinfo)
1138{
1139 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1140 struct ath5k_chan_pcal_info_rf2413 *pcinfo;
1141 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
1142 unsigned int pier, pdg, point;
1143
1144 /* Fill raw data for each calibration pier */
1145 for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
1146
1147 pcinfo = &chinfo[pier].rf2413_info;
1148
1149 /* Allocate pd_curves for this cal pier */
1150 chinfo[pier].pd_curves =
1151 kcalloc(AR5K_EEPROM_N_PD_CURVES,
1152 sizeof(struct ath5k_pdgain_info),
1153 GFP_KERNEL);
1154
1155 if (!chinfo[pier].pd_curves)
1156 return -ENOMEM;
1157
1158 /* Fill pd_curves */
1159 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
1160
1161 u8 idx = pdgain_idx[pdg];
1162 struct ath5k_pdgain_info *pd =
1163 &chinfo[pier].pd_curves[idx];
1164
1165 /* One more point for the highest power
1166 * curve (lowest gain) */
1167 if (pdg == ee->ee_pd_gains[mode] - 1)
1168 pd->pd_points = AR5K_EEPROM_N_PD_POINTS;
1169 else
1170 pd->pd_points = AR5K_EEPROM_N_PD_POINTS - 1;
1171
1172 /* Allocate pd points for this curve */
1173 pd->pd_step = kcalloc(pd->pd_points,
1174 sizeof(u8), GFP_KERNEL);
1175
1176 if (!pd->pd_step)
1177 return -ENOMEM;
1178
1179 pd->pd_pwr = kcalloc(pd->pd_points,
1180 sizeof(s16), GFP_KERNEL);
1181
1182 if (!pd->pd_pwr)
1183 return -ENOMEM;
1184
1185 /* Fill raw dataset
1186 * convert all pwr levels to
1187 * quarter dB for RF5112 combatibility */
1188 pd->pd_step[0] = pcinfo->pddac_i[pdg];
1189 pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg];
1190
1191 for (point = 1; point < pd->pd_points; point++) {
1192
1193 pd->pd_pwr[point] = pd->pd_pwr[point - 1] +
1194 2 * pcinfo->pwr[pdg][point - 1];
1195
1196 pd->pd_step[point] = pd->pd_step[point - 1] +
1197 pcinfo->pddac[pdg][point - 1];
1198
1199 }
1200
1201 /* Highest gain curve -> min power */
1202 if (pdg == 0)
1203 chinfo[pier].min_pwr = pd->pd_pwr[0];
1204
1205 /* Lowest gain curve -> max power */
1206 if (pdg == ee->ee_pd_gains[mode] - 1)
1207 chinfo[pier].max_pwr =
1208 pd->pd_pwr[pd->pd_points - 1];
1209 }
1210 }
1211
1212 return 0;
1213}
1214
1215/* Parse EEPROM data */
1216static int
1217ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
1218{
1219 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1220 struct ath5k_chan_pcal_info_rf2413 *pcinfo;
1221 struct ath5k_chan_pcal_info *chinfo;
1222 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
1223 u32 offset;
1224 int idx, i, ret;
1225 u16 val;
1226 u8 pd_gains = 0;
1227
1228 /* Count how many curves we have and
1229 * identify them (which one of the 4
1230 * available curves we have on each count).
1231 * Curves are stored from higher to
1232 * lower gain so we go backwards */
1233 for (idx = AR5K_EEPROM_N_PD_CURVES - 1; idx >= 0; idx--) {
1234 /* ee_x_gain[mode] is x gain mask */
1235 if ((ee->ee_x_gain[mode] >> idx) & 0x1)
1236 pdgain_idx[pd_gains++] = idx;
1237
1238 }
1239 ee->ee_pd_gains[mode] = pd_gains;
1240
1241 if (pd_gains == 0)
1242 return -EINVAL;
1243
1244 offset = ath5k_cal_data_offset_2413(ee, mode);
1245 switch (mode) {
1246 case AR5K_EEPROM_MODE_11A:
1247 if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
1248 return 0;
1249
1250 ath5k_eeprom_init_11a_pcal_freq(ah, offset);
1251 offset += AR5K_EEPROM_N_5GHZ_CHAN / 2;
1252 chinfo = ee->ee_pwr_cal_a;
1253 break;
1254 case AR5K_EEPROM_MODE_11B:
1255 if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
1256 return 0;
1257
1258 ath5k_eeprom_init_11bg_2413(ah, mode, offset);
1259 offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
1260 chinfo = ee->ee_pwr_cal_b;
1261 break;
1262 case AR5K_EEPROM_MODE_11G:
1263 if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
1264 return 0;
1265
1266 ath5k_eeprom_init_11bg_2413(ah, mode, offset);
1267 offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
1268 chinfo = ee->ee_pwr_cal_g;
1269 break;
1270 default:
1271 return -EINVAL;
1272 }
1273
1274 for (i = 0; i < ee->ee_n_piers[mode]; i++) {
1275 pcinfo = &chinfo[i].rf2413_info;
1276
1277 /*
1278 * Read pwr_i, pddac_i and the first
1279 * 2 pd points (pwr, pddac)
1280 */
1281 AR5K_EEPROM_READ(offset++, val);
1282 pcinfo->pwr_i[0] = val & 0x1f;
1283 pcinfo->pddac_i[0] = (val >> 5) & 0x7f;
1284 pcinfo->pwr[0][0] = (val >> 12) & 0xf;
1285
1286 AR5K_EEPROM_READ(offset++, val);
1287 pcinfo->pddac[0][0] = val & 0x3f;
1288 pcinfo->pwr[0][1] = (val >> 6) & 0xf;
1289 pcinfo->pddac[0][1] = (val >> 10) & 0x3f;
1290
1291 AR5K_EEPROM_READ(offset++, val);
1292 pcinfo->pwr[0][2] = val & 0xf;
1293 pcinfo->pddac[0][2] = (val >> 4) & 0x3f;
1294
1295 pcinfo->pwr[0][3] = 0;
1296 pcinfo->pddac[0][3] = 0;
1297
1298 if (pd_gains > 1) {
1299 /*
1300 * Pd gain 0 is not the last pd gain
1301 * so it only has 2 pd points.
1302 * Continue wih pd gain 1.
1303 */
1304 pcinfo->pwr_i[1] = (val >> 10) & 0x1f;
1305
1306 pcinfo->pddac_i[1] = (val >> 15) & 0x1;
1307 AR5K_EEPROM_READ(offset++, val);
1308 pcinfo->pddac_i[1] |= (val & 0x3F) << 1;
1309
1310 pcinfo->pwr[1][0] = (val >> 6) & 0xf;
1311 pcinfo->pddac[1][0] = (val >> 10) & 0x3f;
1312
1313 AR5K_EEPROM_READ(offset++, val);
1314 pcinfo->pwr[1][1] = val & 0xf;
1315 pcinfo->pddac[1][1] = (val >> 4) & 0x3f;
1316 pcinfo->pwr[1][2] = (val >> 10) & 0xf;
1317
1318 pcinfo->pddac[1][2] = (val >> 14) & 0x3;
1319 AR5K_EEPROM_READ(offset++, val);
1320 pcinfo->pddac[1][2] |= (val & 0xF) << 2;
1321
1322 pcinfo->pwr[1][3] = 0;
1323 pcinfo->pddac[1][3] = 0;
1324 } else if (pd_gains == 1) {
1325 /*
1326 * Pd gain 0 is the last one so
1327 * read the extra point.
1328 */
1329 pcinfo->pwr[0][3] = (val >> 10) & 0xf;
1330
1331 pcinfo->pddac[0][3] = (val >> 14) & 0x3;
1332 AR5K_EEPROM_READ(offset++, val);
1333 pcinfo->pddac[0][3] |= (val & 0xF) << 2;
1334 }
1335
1336 /*
1337 * Proceed with the other pd_gains
1338 * as above.
1339 */
1340 if (pd_gains > 2) {
1341 pcinfo->pwr_i[2] = (val >> 4) & 0x1f;
1342 pcinfo->pddac_i[2] = (val >> 9) & 0x7f;
1343
1344 AR5K_EEPROM_READ(offset++, val);
1345 pcinfo->pwr[2][0] = (val >> 0) & 0xf;
1346 pcinfo->pddac[2][0] = (val >> 4) & 0x3f;
1347 pcinfo->pwr[2][1] = (val >> 10) & 0xf;
1348
1349 pcinfo->pddac[2][1] = (val >> 14) & 0x3;
1350 AR5K_EEPROM_READ(offset++, val);
1351 pcinfo->pddac[2][1] |= (val & 0xF) << 2;
1352
1353 pcinfo->pwr[2][2] = (val >> 4) & 0xf;
1354 pcinfo->pddac[2][2] = (val >> 8) & 0x3f;
1355
1356 pcinfo->pwr[2][3] = 0;
1357 pcinfo->pddac[2][3] = 0;
1358 } else if (pd_gains == 2) {
1359 pcinfo->pwr[1][3] = (val >> 4) & 0xf;
1360 pcinfo->pddac[1][3] = (val >> 8) & 0x3f;
1361 }
1362
1363 if (pd_gains > 3) {
1364 pcinfo->pwr_i[3] = (val >> 14) & 0x3;
1365 AR5K_EEPROM_READ(offset++, val);
1366 pcinfo->pwr_i[3] |= ((val >> 0) & 0x7) << 2;
1367
1368 pcinfo->pddac_i[3] = (val >> 3) & 0x7f;
1369 pcinfo->pwr[3][0] = (val >> 10) & 0xf;
1370 pcinfo->pddac[3][0] = (val >> 14) & 0x3;
1371
1372 AR5K_EEPROM_READ(offset++, val);
1373 pcinfo->pddac[3][0] |= (val & 0xF) << 2;
1374 pcinfo->pwr[3][1] = (val >> 4) & 0xf;
1375 pcinfo->pddac[3][1] = (val >> 8) & 0x3f;
1376
1377 pcinfo->pwr[3][2] = (val >> 14) & 0x3;
1378 AR5K_EEPROM_READ(offset++, val);
1379 pcinfo->pwr[3][2] |= ((val >> 0) & 0x3) << 2;
1380
1381 pcinfo->pddac[3][2] = (val >> 2) & 0x3f;
1382 pcinfo->pwr[3][3] = (val >> 8) & 0xf;
1383
1384 pcinfo->pddac[3][3] = (val >> 12) & 0xF;
1385 AR5K_EEPROM_READ(offset++, val);
1386 pcinfo->pddac[3][3] |= ((val >> 0) & 0x3) << 4;
1387 } else if (pd_gains == 3) {
1388 pcinfo->pwr[2][3] = (val >> 14) & 0x3;
1389 AR5K_EEPROM_READ(offset++, val);
1390 pcinfo->pwr[2][3] |= ((val >> 0) & 0x3) << 2;
1391
1392 pcinfo->pddac[2][3] = (val >> 2) & 0x3f;
1393 }
1394 }
1395
1396 return ath5k_eeprom_convert_pcal_info_2413(ah, mode, chinfo);
1397}
1398
1399
1400/*
1401 * Read per rate target power (this is the maximum tx power
1402 * supported by the card). This info is used when setting
1403 * tx power, no matter the channel.
1404 *
1405 * This also works for v5 EEPROMs.
1406 */
1407static int
1408ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode)
1409{
1410 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1411 struct ath5k_rate_pcal_info *rate_pcal_info;
1412 u8 *rate_target_pwr_num;
1413 u32 offset;
1414 u16 val;
1415 int ret, i;
1416
1417 offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1);
1418 rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode];
1419 switch (mode) {
1420 case AR5K_EEPROM_MODE_11A:
1421 offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version);
1422 rate_pcal_info = ee->ee_rate_tpwr_a;
1423 ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN;
1424 break;
1425 case AR5K_EEPROM_MODE_11B:
1426 offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version);
1427 rate_pcal_info = ee->ee_rate_tpwr_b;
1428 ee->ee_rate_target_pwr_num[mode] = 2; /* 3rd is g mode's 1st */
1429 break;
1430 case AR5K_EEPROM_MODE_11G:
1431 offset += AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version);
1432 rate_pcal_info = ee->ee_rate_tpwr_g;
1433 ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_2GHZ_CHAN;
1434 break;
1435 default:
1436 return -EINVAL;
1437 }
1438
1439 /* Different freq mask for older eeproms (<= v3.2) */
1440 if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2) {
1441 for (i = 0; i < (*rate_target_pwr_num); i++) {
1442 AR5K_EEPROM_READ(offset++, val);
1443 rate_pcal_info[i].freq =
1444 ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode);
1445
1446 rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f);
1447 rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f;
1448
1449 AR5K_EEPROM_READ(offset++, val);
1450
1451 if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
1452 val == 0) {
1453 (*rate_target_pwr_num) = i;
1454 break;
1455 }
1456
1457 rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7);
1458 rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f);
1459 rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f);
1460 }
1461 } else {
1462 for (i = 0; i < (*rate_target_pwr_num); i++) {
1463 AR5K_EEPROM_READ(offset++, val);
1464 rate_pcal_info[i].freq =
1465 ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
1466
1467 rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f);
1468 rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f;
1469
1470 AR5K_EEPROM_READ(offset++, val);
1471
1472 if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
1473 val == 0) {
1474 (*rate_target_pwr_num) = i;
1475 break;
1476 }
1477
1478 rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf;
1479 rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f);
1480 rate_pcal_info[i].target_power_54 = (val & 0x3f);
1481 }
1482 }
1483
1484 return 0;
1485}
1486
1487/*
1488 * Read per channel calibration info from EEPROM
1489 *
1490 * This info is used to calibrate the baseband power table. Imagine
1491 * that for each channel there is a power curve that's hw specific
1492 * (depends on amplifier etc) and we try to "correct" this curve using
1493 * offests we pass on to phy chip (baseband -> before amplifier) so that
1494 * it can use accurate power values when setting tx power (takes amplifier's
1495 * performance on each channel into account).
1496 *
1497 * EEPROM provides us with the offsets for some pre-calibrated channels
1498 * and we have to interpolate to create the full table for these channels and
1499 * also the table for any channel.
1500 */
1501static int
1502ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
1503{
1504 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1505 int (*read_pcal)(struct ath5k_hw *hw, int mode);
1506 int mode;
1507 int err;
1508
1509 if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) &&
1510 (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 1))
1511 read_pcal = ath5k_eeprom_read_pcal_info_5112;
1512 else if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0) &&
1513 (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 2))
1514 read_pcal = ath5k_eeprom_read_pcal_info_2413;
1515 else
1516 read_pcal = ath5k_eeprom_read_pcal_info_5111;
1517
1518
1519 for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G;
1520 mode++) {
1521 err = read_pcal(ah, mode);
1522 if (err)
1523 return err;
1524
1525 err = ath5k_eeprom_read_target_rate_pwr_info(ah, mode);
1526 if (err < 0)
1527 return err;
1528 }
1529
1530 return 0;
1531}
1532
1533static int
1534ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
1535{
1536 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1537 struct ath5k_chan_pcal_info *chinfo;
1538 u8 pier, pdg;
1539
1540 switch (mode) {
1541 case AR5K_EEPROM_MODE_11A:
1542 if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
1543 return 0;
1544 chinfo = ee->ee_pwr_cal_a;
1545 break;
1546 case AR5K_EEPROM_MODE_11B:
1547 if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
1548 return 0;
1549 chinfo = ee->ee_pwr_cal_b;
1550 break;
1551 case AR5K_EEPROM_MODE_11G:
1552 if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
1553 return 0;
1554 chinfo = ee->ee_pwr_cal_g;
1555 break;
1556 default:
1557 return -EINVAL;
1558 }
1559
1560 for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
1561 if (!chinfo[pier].pd_curves)
1562 continue;
1563
1564 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
1565 struct ath5k_pdgain_info *pd =
1566 &chinfo[pier].pd_curves[pdg];
1567
1568 if (pd != NULL) {
1569 kfree(pd->pd_step);
1570 kfree(pd->pd_pwr);
1571 }
1572 }
1573
1574 kfree(chinfo[pier].pd_curves);
1575 }
1576
1577 return 0;
1578}
1579
1580void
1581ath5k_eeprom_detach(struct ath5k_hw *ah)
1582{
1583 u8 mode;
1584
1585 for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++)
1586 ath5k_eeprom_free_pcal_info(ah, mode);
1587}
1588
1589/* Read conformance test limits used for regulatory control */
1590static int
1591ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
1592{
1593 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1594 struct ath5k_edge_power *rep;
1595 unsigned int fmask, pmask;
1596 unsigned int ctl_mode;
1597 int ret, i, j;
1598 u32 offset;
1599 u16 val;
1600
1601 pmask = AR5K_EEPROM_POWER_M;
1602 fmask = AR5K_EEPROM_FREQ_M(ee->ee_version);
1603 offset = AR5K_EEPROM_CTL(ee->ee_version);
1604 ee->ee_ctls = AR5K_EEPROM_N_CTLS(ee->ee_version);
1605 for (i = 0; i < ee->ee_ctls; i += 2) {
1606 AR5K_EEPROM_READ(offset++, val);
1607 ee->ee_ctl[i] = (val >> 8) & 0xff;
1608 ee->ee_ctl[i + 1] = val & 0xff;
1609 }
1610
1611 offset = AR5K_EEPROM_GROUP8_OFFSET;
1612 if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0)
1613 offset += AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) -
1614 AR5K_EEPROM_GROUP5_OFFSET;
1615 else
1616 offset += AR5K_EEPROM_GROUPS_START(ee->ee_version);
1617
1618 rep = ee->ee_ctl_pwr;
1619 for(i = 0; i < ee->ee_ctls; i++) {
1620 switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) {
1621 case AR5K_CTL_11A:
1622 case AR5K_CTL_TURBO:
1623 ctl_mode = AR5K_EEPROM_MODE_11A;
1624 break;
1625 default:
1626 ctl_mode = AR5K_EEPROM_MODE_11G;
1627 break;
1628 }
1629 if (ee->ee_ctl[i] == 0) {
1630 if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3)
1631 offset += 8;
1632 else
1633 offset += 7;
1634 rep += AR5K_EEPROM_N_EDGES;
1635 continue;
1636 }
1637 if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
1638 for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) {
1639 AR5K_EEPROM_READ(offset++, val);
1640 rep[j].freq = (val >> 8) & fmask;
1641 rep[j + 1].freq = val & fmask;
1642 }
1643 for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) {
1644 AR5K_EEPROM_READ(offset++, val);
1645 rep[j].edge = (val >> 8) & pmask;
1646 rep[j].flag = (val >> 14) & 1;
1647 rep[j + 1].edge = val & pmask;
1648 rep[j + 1].flag = (val >> 6) & 1;
1649 }
1650 } else {
1651 AR5K_EEPROM_READ(offset++, val);
1652 rep[0].freq = (val >> 9) & fmask;
1653 rep[1].freq = (val >> 2) & fmask;
1654 rep[2].freq = (val << 5) & fmask;
1655
1656 AR5K_EEPROM_READ(offset++, val);
1657 rep[2].freq |= (val >> 11) & 0x1f;
1658 rep[3].freq = (val >> 4) & fmask;
1659 rep[4].freq = (val << 3) & fmask;
1660
1661 AR5K_EEPROM_READ(offset++, val);
1662 rep[4].freq |= (val >> 13) & 0x7;
1663 rep[5].freq = (val >> 6) & fmask;
1664 rep[6].freq = (val << 1) & fmask;
1665
1666 AR5K_EEPROM_READ(offset++, val);
1667 rep[6].freq |= (val >> 15) & 0x1;
1668 rep[7].freq = (val >> 8) & fmask;
1669
1670 rep[0].edge = (val >> 2) & pmask;
1671 rep[1].edge = (val << 4) & pmask;
1672
1673 AR5K_EEPROM_READ(offset++, val);
1674 rep[1].edge |= (val >> 12) & 0xf;
1675 rep[2].edge = (val >> 6) & pmask;
1676 rep[3].edge = val & pmask;
1677
1678 AR5K_EEPROM_READ(offset++, val);
1679 rep[4].edge = (val >> 10) & pmask;
1680 rep[5].edge = (val >> 4) & pmask;
1681 rep[6].edge = (val << 2) & pmask;
1682
1683 AR5K_EEPROM_READ(offset++, val);
1684 rep[6].edge |= (val >> 14) & 0x3;
1685 rep[7].edge = (val >> 8) & pmask;
1686 }
1687 for (j = 0; j < AR5K_EEPROM_N_EDGES; j++) {
1688 rep[j].freq = ath5k_eeprom_bin2freq(ee,
1689 rep[j].freq, ctl_mode);
1690 }
1691 rep += AR5K_EEPROM_N_EDGES;
1692 }
1693
1694 return 0;
1695}
1696
1697
1698/*
1699 * Initialize eeprom power tables
1700 */
1701int
1702ath5k_eeprom_init(struct ath5k_hw *ah)
1703{
1704 int err;
1705
1706 err = ath5k_eeprom_init_header(ah);
1707 if (err < 0)
1708 return err;
1709
1710 err = ath5k_eeprom_init_modes(ah);
1711 if (err < 0)
1712 return err;
1713
1714 err = ath5k_eeprom_read_pcal_info(ah);
1715 if (err < 0)
1716 return err;
1717
1718 err = ath5k_eeprom_read_ctl_info(ah);
1719 if (err < 0)
1720 return err;
1721
1722 return 0;
1723}
1724
1725/*
1726 * Read the MAC address from eeprom
1727 */
1728int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
1729{
1730 u8 mac_d[ETH_ALEN] = {};
1731 u32 total, offset;
1732 u16 data;
1733 int octet, ret;
1734
1735 ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
1736 if (ret)
1737 return ret;
1738
1739 for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
1740 ret = ath5k_hw_eeprom_read(ah, offset, &data);
1741 if (ret)
1742 return ret;
1743
1744 total += data;
1745 mac_d[octet + 1] = data & 0xff;
1746 mac_d[octet] = data >> 8;
1747 octet += 2;
1748 }
1749
1750 if (!total || total == 3 * 0xffff)
1751 return -EINVAL;
1752
1753 memcpy(mac, mac_d, ETH_ALEN);
1754
1755 return 0;
1756}
1757
1758bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah)
1759{
1760 u16 data;
1761
1762 ath5k_hw_eeprom_read(ah, AR5K_EEPROM_IS_HB63, &data);
1763
1764 if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && data)
1765 return true;
1766 else
1767 return false;
1768}
1769
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
new file mode 100644
index 000000000000..b0c0606dea0b
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/eeprom.h
@@ -0,0 +1,441 @@
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 */
18
19/*
20 * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE)
21 */
22#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */
23#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */
24#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */
25#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */
26#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */
27
28#define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */
29#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
30#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */
31#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
32#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
33#define AR5K_EEPROM_INFO_CKSUM 0xffff
34#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n))
35
36#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */
37#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */
38#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */
39#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */
40#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
41#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */
42#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
43#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */
44#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */
45#define AR5K_EEPROM_VERSION_4_3 0x4003 /* power calibration changes */
46#define AR5K_EEPROM_VERSION_4_4 0x4004
47#define AR5K_EEPROM_VERSION_4_5 0x4005
48#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */
49#define AR5K_EEPROM_VERSION_4_7 0x3007 /* 4007 ? */
50#define AR5K_EEPROM_VERSION_4_9 0x4009 /* EAR futureproofing */
51#define AR5K_EEPROM_VERSION_5_0 0x5000 /* Has 2413 PDADC calibration etc */
52#define AR5K_EEPROM_VERSION_5_1 0x5001 /* Has capability values */
53#define AR5K_EEPROM_VERSION_5_3 0x5003 /* Has spur mitigation tables */
54
55#define AR5K_EEPROM_MODE_11A 0
56#define AR5K_EEPROM_MODE_11B 1
57#define AR5K_EEPROM_MODE_11G 2
58
59#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */
60#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
61#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
62#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
63#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */
64#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */
65#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7)
66#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
67#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */
68
69#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
70#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
71#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002
72#define AR5K_EEPROM_RFKILL_POLARITY_S 1
73
74/* Newer EEPROMs are using a different offset */
75#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
76 (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
77
78#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
79#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((s8)(((_v) >> 8) & 0xff))
80#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((s8)((_v) & 0xff))
81
82/* Misc values available since EEPROM 4.0 */
83#define AR5K_EEPROM_MISC0 AR5K_EEPROM_INFO(4)
84#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff)
85#define AR5K_EEPROM_HDR_XR2_DIS(_v) (((_v) >> 12) & 0x1)
86#define AR5K_EEPROM_HDR_XR5_DIS(_v) (((_v) >> 13) & 0x1)
87#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3)
88
89#define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5)
90#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
91#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
92#define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1)
93
94#define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6)
95#define AR5K_EEPROM_EEP_FILE_VERSION(_v) (((_v) >> 8) & 0xff)
96#define AR5K_EEPROM_EAR_FILE_VERSION(_v) ((_v) & 0xff)
97
98#define AR5K_EEPROM_MISC3 AR5K_EEPROM_INFO(7)
99#define AR5K_EEPROM_ART_BUILD_NUM(_v) (((_v) >> 10) & 0x3f)
100#define AR5K_EEPROM_EAR_FILE_ID(_v) ((_v) & 0xff)
101
102#define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8)
103#define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff)
104#define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3)
105#define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3)
106
107#define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9)
108#define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1)
109#define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1)
110#define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1)
111#define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1)
112#define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf)
113#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1)
114#define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf)
115
116#define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10)
117#define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x8)
118#define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x8)
119#define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1)
120#define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1)
121#define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1)
122#define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 9) & 0x1)
123#define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 10) & 0x1)
124
125/* calibration settings */
126#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
127#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
128#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
129#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */
130#define AR5K_EEPROM_GROUPS_START(_v) AR5K_EEPROM_OFF(_v, 0x0100, 0x0150) /* Start of Groups */
131#define AR5K_EEPROM_GROUP1_OFFSET 0x0
132#define AR5K_EEPROM_GROUP2_OFFSET 0x5
133#define AR5K_EEPROM_GROUP3_OFFSET 0x37
134#define AR5K_EEPROM_GROUP4_OFFSET 0x46
135#define AR5K_EEPROM_GROUP5_OFFSET 0x55
136#define AR5K_EEPROM_GROUP6_OFFSET 0x65
137#define AR5K_EEPROM_GROUP7_OFFSET 0x69
138#define AR5K_EEPROM_GROUP8_OFFSET 0x6f
139
140#define AR5K_EEPROM_TARGET_PWR_OFF_11A(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
141 AR5K_EEPROM_GROUP5_OFFSET, 0x0000)
142#define AR5K_EEPROM_TARGET_PWR_OFF_11B(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
143 AR5K_EEPROM_GROUP6_OFFSET, 0x0010)
144#define AR5K_EEPROM_TARGET_PWR_OFF_11G(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
145 AR5K_EEPROM_GROUP7_OFFSET, 0x0014)
146
147/* [3.1 - 3.3] */
148#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec
149#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed
150
151#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */
152#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */
153#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */
154#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */
155#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008
156#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */
157#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020
158#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */
159#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080
160#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */
161#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200
162#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */
163#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800
164#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */
165#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000
166#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */
167#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000
168
169/* Some EEPROM defines */
170#define AR5K_EEPROM_EEP_SCALE 100
171#define AR5K_EEPROM_EEP_DELTA 10
172#define AR5K_EEPROM_N_MODES 3
173#define AR5K_EEPROM_N_5GHZ_CHAN 10
174#define AR5K_EEPROM_N_2GHZ_CHAN 3
175#define AR5K_EEPROM_N_2GHZ_CHAN_2413 4
176#define AR5K_EEPROM_N_2GHZ_CHAN_MAX 4
177#define AR5K_EEPROM_MAX_CHAN 10
178#define AR5K_EEPROM_N_PWR_POINTS_5111 11
179#define AR5K_EEPROM_N_PCDAC 11
180#define AR5K_EEPROM_N_PHASE_CAL 5
181#define AR5K_EEPROM_N_TEST_FREQ 8
182#define AR5K_EEPROM_N_EDGES 8
183#define AR5K_EEPROM_N_INTERCEPTS 11
184#define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff)
185#define AR5K_EEPROM_PCDAC_M 0x3f
186#define AR5K_EEPROM_PCDAC_START 1
187#define AR5K_EEPROM_PCDAC_STOP 63
188#define AR5K_EEPROM_PCDAC_STEP 1
189#define AR5K_EEPROM_NON_EDGE_M 0x40
190#define AR5K_EEPROM_CHANNEL_POWER 8
191#define AR5K_EEPROM_N_OBDB 4
192#define AR5K_EEPROM_OBDB_DIS 0xffff
193#define AR5K_EEPROM_CHANNEL_DIS 0xff
194#define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10)
195#define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32)
196#define AR5K_EEPROM_MAX_CTLS 32
197#define AR5K_EEPROM_N_PD_CURVES 4
198#define AR5K_EEPROM_N_XPD0_POINTS 4
199#define AR5K_EEPROM_N_XPD3_POINTS 3
200#define AR5K_EEPROM_N_PD_GAINS 4
201#define AR5K_EEPROM_N_PD_POINTS 5
202#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35
203#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55
204#define AR5K_EEPROM_POWER_M 0x3f
205#define AR5K_EEPROM_POWER_MIN 0
206#define AR5K_EEPROM_POWER_MAX 3150
207#define AR5K_EEPROM_POWER_STEP 50
208#define AR5K_EEPROM_POWER_TABLE_SIZE 64
209#define AR5K_EEPROM_N_POWER_LOC_11B 4
210#define AR5K_EEPROM_N_POWER_LOC_11G 6
211#define AR5K_EEPROM_I_GAIN 10
212#define AR5K_EEPROM_CCK_OFDM_DELTA 15
213#define AR5K_EEPROM_N_IQ_CAL 2
214
215#define AR5K_EEPROM_READ(_o, _v) do { \
216 ret = ath5k_hw_eeprom_read(ah, (_o), &(_v)); \
217 if (ret) \
218 return ret; \
219} while (0)
220
221#define AR5K_EEPROM_READ_HDR(_o, _v) \
222 AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \
223
224enum ath5k_ant_setting {
225 AR5K_ANT_VARIABLE = 0, /* variable by programming */
226 AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */
227 AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */
228 AR5K_ANT_MAX = 3,
229};
230
231enum ath5k_ctl_mode {
232 AR5K_CTL_11A = 0,
233 AR5K_CTL_11B = 1,
234 AR5K_CTL_11G = 2,
235 AR5K_CTL_TURBO = 3,
236 AR5K_CTL_TURBOG = 4,
237 AR5K_CTL_2GHT20 = 5,
238 AR5K_CTL_5GHT20 = 6,
239 AR5K_CTL_2GHT40 = 7,
240 AR5K_CTL_5GHT40 = 8,
241 AR5K_CTL_MODE_M = 15,
242};
243
244/* Default CTL ids for the 3 main reg domains.
245 * Atheros only uses these by default but vendors
246 * can have up to 32 different CTLs for different
247 * scenarios. Note that theese values are ORed with
248 * the mode id (above) so we can have up to 24 CTL
249 * datasets out of these 3 main regdomains. That leaves
250 * 8 ids that can be used by vendors and since 0x20 is
251 * missing from HAL sources i guess this is the set of
252 * custom CTLs vendors can use. */
253#define AR5K_CTL_FCC 0x10
254#define AR5K_CTL_CUSTOM 0x20
255#define AR5K_CTL_ETSI 0x30
256#define AR5K_CTL_MKK 0x40
257
258/* Indicates a CTL with only mode set and
259 * no reg domain mapping, such CTLs are used
260 * for world roaming domains or simply when
261 * a reg domain is not set */
262#define AR5K_CTL_NO_REGDOMAIN 0xf0
263
264/* Indicates an empty (invalid) CTL */
265#define AR5K_CTL_NO_CTL 0xff
266
267/* Per channel calibration data, used for power table setup */
268struct ath5k_chan_pcal_info_rf5111 {
269 /* Power levels in half dbm units
270 * for one power curve. */
271 u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111];
272 /* PCDAC table steps
273 * for the above values */
274 u8 pcdac[AR5K_EEPROM_N_PWR_POINTS_5111];
275 /* Starting PCDAC step */
276 u8 pcdac_min;
277 /* Final PCDAC step */
278 u8 pcdac_max;
279};
280
281struct ath5k_chan_pcal_info_rf5112 {
282 /* Power levels in quarter dBm units
283 * for lower (0) and higher (3)
284 * level curves in 0.25dB units */
285 s8 pwr_x0[AR5K_EEPROM_N_XPD0_POINTS];
286 s8 pwr_x3[AR5K_EEPROM_N_XPD3_POINTS];
287 /* PCDAC table steps
288 * for the above values */
289 u8 pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS];
290 u8 pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS];
291};
292
293struct ath5k_chan_pcal_info_rf2413 {
294 /* Starting pwr/pddac values */
295 s8 pwr_i[AR5K_EEPROM_N_PD_GAINS];
296 u8 pddac_i[AR5K_EEPROM_N_PD_GAINS];
297 /* (pwr,pddac) points
298 * power levels in 0.5dB units */
299 s8 pwr[AR5K_EEPROM_N_PD_GAINS]
300 [AR5K_EEPROM_N_PD_POINTS];
301 u8 pddac[AR5K_EEPROM_N_PD_GAINS]
302 [AR5K_EEPROM_N_PD_POINTS];
303};
304
305enum ath5k_powertable_type {
306 AR5K_PWRTABLE_PWR_TO_PCDAC = 0,
307 AR5K_PWRTABLE_LINEAR_PCDAC = 1,
308 AR5K_PWRTABLE_PWR_TO_PDADC = 2,
309};
310
311struct ath5k_pdgain_info {
312 u8 pd_points;
313 u8 *pd_step;
314 /* Power values are in
315 * 0.25dB units */
316 s16 *pd_pwr;
317};
318
319struct ath5k_chan_pcal_info {
320 /* Frequency */
321 u16 freq;
322 /* Tx power boundaries */
323 s16 max_pwr;
324 s16 min_pwr;
325 union {
326 struct ath5k_chan_pcal_info_rf5111 rf5111_info;
327 struct ath5k_chan_pcal_info_rf5112 rf5112_info;
328 struct ath5k_chan_pcal_info_rf2413 rf2413_info;
329 };
330 /* Raw values used by phy code
331 * Curves are stored in order from lower
332 * gain to higher gain (max txpower -> min txpower) */
333 struct ath5k_pdgain_info *pd_curves;
334};
335
336/* Per rate calibration data for each mode,
337 * used for rate power table setup.
338 * Note: Values in 0.5dB units */
339struct ath5k_rate_pcal_info {
340 u16 freq; /* Frequency */
341 /* Power level for 6-24Mbit/s rates or
342 * 1Mb rate */
343 u16 target_power_6to24;
344 /* Power level for 36Mbit rate or
345 * 2Mb rate */
346 u16 target_power_36;
347 /* Power level for 48Mbit rate or
348 * 5.5Mbit rate */
349 u16 target_power_48;
350 /* Power level for 54Mbit rate or
351 * 11Mbit rate */
352 u16 target_power_54;
353};
354
355/* Power edges for conformance test limits */
356struct ath5k_edge_power {
357 u16 freq;
358 u16 edge; /* in half dBm */
359 bool flag;
360};
361
362/* EEPROM calibration data */
363struct ath5k_eeprom_info {
364
365 /* Header information */
366 u16 ee_magic;
367 u16 ee_protect;
368 u16 ee_regdomain;
369 u16 ee_version;
370 u16 ee_header;
371 u16 ee_ant_gain;
372 u16 ee_misc0;
373 u16 ee_misc1;
374 u16 ee_misc2;
375 u16 ee_misc3;
376 u16 ee_misc4;
377 u16 ee_misc5;
378 u16 ee_misc6;
379 u16 ee_cck_ofdm_gain_delta;
380 u16 ee_cck_ofdm_power_delta;
381 u16 ee_scaled_cck_delta;
382
383 /* RF Calibration settings (reset, rfregs) */
384 u16 ee_i_cal[AR5K_EEPROM_N_MODES];
385 u16 ee_q_cal[AR5K_EEPROM_N_MODES];
386 u16 ee_fixed_bias[AR5K_EEPROM_N_MODES];
387 u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES];
388 u16 ee_xr_power[AR5K_EEPROM_N_MODES];
389 u16 ee_switch_settling[AR5K_EEPROM_N_MODES];
390 u16 ee_atn_tx_rx[AR5K_EEPROM_N_MODES];
391 u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
392 u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
393 u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
394 u16 ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES];
395 u16 ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES];
396 u16 ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES];
397 u16 ee_thr_62[AR5K_EEPROM_N_MODES];
398 u16 ee_xlna_gain[AR5K_EEPROM_N_MODES];
399 u16 ee_xpd[AR5K_EEPROM_N_MODES];
400 u16 ee_x_gain[AR5K_EEPROM_N_MODES];
401 u16 ee_i_gain[AR5K_EEPROM_N_MODES];
402 u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
403 u16 ee_switch_settling_turbo[AR5K_EEPROM_N_MODES];
404 u16 ee_margin_tx_rx_turbo[AR5K_EEPROM_N_MODES];
405 u16 ee_atn_tx_rx_turbo[AR5K_EEPROM_N_MODES];
406
407 /* Power calibration data */
408 u16 ee_false_detect[AR5K_EEPROM_N_MODES];
409
410 /* Number of pd gain curves per mode */
411 u8 ee_pd_gains[AR5K_EEPROM_N_MODES];
412 /* Back mapping pdcurve number -> pdcurve index in pd->pd_curves */
413 u8 ee_pdc_to_idx[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PD_GAINS];
414
415 u8 ee_n_piers[AR5K_EEPROM_N_MODES];
416 struct ath5k_chan_pcal_info ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN];
417 struct ath5k_chan_pcal_info ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
418 struct ath5k_chan_pcal_info ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
419
420 /* Per rate target power levels */
421 u8 ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES];
422 struct ath5k_rate_pcal_info ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN];
423 struct ath5k_rate_pcal_info ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
424 struct ath5k_rate_pcal_info ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
425
426 /* Conformance test limits (Unused) */
427 u8 ee_ctls;
428 u8 ee_ctl[AR5K_EEPROM_MAX_CTLS];
429 struct ath5k_edge_power ee_ctl_pwr[AR5K_EEPROM_N_EDGES * AR5K_EEPROM_MAX_CTLS];
430
431 /* Noise Floor Calibration settings */
432 s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
433 s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES];
434 s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES];
435 s8 ee_adc_desired_size_turbo[AR5K_EEPROM_N_MODES];
436 s8 ee_pga_desired_size_turbo[AR5K_EEPROM_N_MODES];
437 s8 ee_pd_gain_overlap;
438
439 u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
440};
441
diff --git a/drivers/net/wireless/ath/ath5k/gpio.c b/drivers/net/wireless/ath/ath5k/gpio.c
new file mode 100644
index 000000000000..64a27e73d02e
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/gpio.c
@@ -0,0 +1,176 @@
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 */
18
19/****************\
20 GPIO Functions
21\****************/
22
23#include "ath5k.h"
24#include "reg.h"
25#include "debug.h"
26#include "base.h"
27
28/*
29 * Set led state
30 */
31void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
32{
33 u32 led;
34 /*5210 has different led mode handling*/
35 u32 led_5210;
36
37 ATH5K_TRACE(ah->ah_sc);
38
39 /*Reset led status*/
40 if (ah->ah_version != AR5K_AR5210)
41 AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
42 AR5K_PCICFG_LEDMODE | AR5K_PCICFG_LED);
43 else
44 AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED);
45
46 /*
47 * Some blinking values, define at your wish
48 */
49 switch (state) {
50 case AR5K_LED_SCAN:
51 case AR5K_LED_AUTH:
52 led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND;
53 led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL;
54 break;
55
56 case AR5K_LED_INIT:
57 led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE;
58 led_5210 = AR5K_PCICFG_LED_PEND;
59 break;
60
61 case AR5K_LED_ASSOC:
62 case AR5K_LED_RUN:
63 led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC;
64 led_5210 = AR5K_PCICFG_LED_ASSOC;
65 break;
66
67 default:
68 led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE;
69 led_5210 = AR5K_PCICFG_LED_PEND;
70 break;
71 }
72
73 /*Write new status to the register*/
74 if (ah->ah_version != AR5K_AR5210)
75 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led);
76 else
77 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210);
78}
79
80/*
81 * Set GPIO inputs
82 */
83int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
84{
85 ATH5K_TRACE(ah->ah_sc);
86 if (gpio >= AR5K_NUM_GPIO)
87 return -EINVAL;
88
89 ath5k_hw_reg_write(ah,
90 (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
91 | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR);
92
93 return 0;
94}
95
96/*
97 * Set GPIO outputs
98 */
99int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
100{
101 ATH5K_TRACE(ah->ah_sc);
102 if (gpio >= AR5K_NUM_GPIO)
103 return -EINVAL;
104
105 ath5k_hw_reg_write(ah,
106 (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
107 | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR);
108
109 return 0;
110}
111
112/*
113 * Get GPIO state
114 */
115u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
116{
117 ATH5K_TRACE(ah->ah_sc);
118 if (gpio >= AR5K_NUM_GPIO)
119 return 0xffffffff;
120
121 /* GPIO input magic */
122 return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) &
123 0x1;
124}
125
126/*
127 * Set GPIO state
128 */
129int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
130{
131 u32 data;
132 ATH5K_TRACE(ah->ah_sc);
133
134 if (gpio >= AR5K_NUM_GPIO)
135 return -EINVAL;
136
137 /* GPIO output magic */
138 data = ath5k_hw_reg_read(ah, AR5K_GPIODO);
139
140 data &= ~(1 << gpio);
141 data |= (val & 1) << gpio;
142
143 ath5k_hw_reg_write(ah, data, AR5K_GPIODO);
144
145 return 0;
146}
147
148/*
149 * Initialize the GPIO interrupt (RFKill switch)
150 */
151void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
152 u32 interrupt_level)
153{
154 u32 data;
155
156 ATH5K_TRACE(ah->ah_sc);
157 if (gpio >= AR5K_NUM_GPIO)
158 return;
159
160 /*
161 * Set the GPIO interrupt
162 */
163 data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &
164 ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH |
165 AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) |
166 (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA);
167
168 ath5k_hw_reg_write(ah, interrupt_level ? data :
169 (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR);
170
171 ah->ah_imr |= AR5K_IMR_GPIO;
172
173 /* Enable GPIO interrupts */
174 AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO);
175}
176
diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c
new file mode 100644
index 000000000000..61fb621ed20d
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/initvals.c
@@ -0,0 +1,1557 @@
1/*
2 * Initial register settings functions
3 *
4 * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
5 * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
6 * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *
20 */
21
22#include "ath5k.h"
23#include "reg.h"
24#include "debug.h"
25#include "base.h"
26
27/*
28 * Mode-independent initial register writes
29 */
30
31struct ath5k_ini {
32 u16 ini_register;
33 u32 ini_value;
34
35 enum {
36 AR5K_INI_WRITE = 0, /* Default */
37 AR5K_INI_READ = 1, /* Cleared on read */
38 } ini_mode;
39};
40
41/*
42 * Mode specific initial register values
43 */
44
45struct ath5k_ini_mode {
46 u16 mode_register;
47 u32 mode_value[5];
48};
49
50/* Initial register settings for AR5210 */
51static const struct ath5k_ini ar5210_ini[] = {
52 /* PCU and MAC registers */
53 { AR5K_NOQCU_TXDP0, 0 },
54 { AR5K_NOQCU_TXDP1, 0 },
55 { AR5K_RXDP, 0 },
56 { AR5K_CR, 0 },
57 { AR5K_ISR, 0, AR5K_INI_READ },
58 { AR5K_IMR, 0 },
59 { AR5K_IER, AR5K_IER_DISABLE },
60 { AR5K_BSR, 0, AR5K_INI_READ },
61 { AR5K_TXCFG, AR5K_DMASIZE_128B },
62 { AR5K_RXCFG, AR5K_DMASIZE_128B },
63 { AR5K_CFG, AR5K_INIT_CFG },
64 { AR5K_TOPS, 8 },
65 { AR5K_RXNOFRM, 8 },
66 { AR5K_RPGTO, 0 },
67 { AR5K_TXNOFRM, 0 },
68 { AR5K_SFR, 0 },
69 { AR5K_MIBC, 0 },
70 { AR5K_MISC, 0 },
71 { AR5K_RX_FILTER_5210, 0 },
72 { AR5K_MCAST_FILTER0_5210, 0 },
73 { AR5K_MCAST_FILTER1_5210, 0 },
74 { AR5K_TX_MASK0, 0 },
75 { AR5K_TX_MASK1, 0 },
76 { AR5K_CLR_TMASK, 0 },
77 { AR5K_TRIG_LVL, AR5K_TUNE_MIN_TX_FIFO_THRES },
78 { AR5K_DIAG_SW_5210, 0 },
79 { AR5K_RSSI_THR, AR5K_TUNE_RSSI_THRES },
80 { AR5K_TSF_L32_5210, 0 },
81 { AR5K_TIMER0_5210, 0 },
82 { AR5K_TIMER1_5210, 0xffffffff },
83 { AR5K_TIMER2_5210, 0xffffffff },
84 { AR5K_TIMER3_5210, 1 },
85 { AR5K_CFP_DUR_5210, 0 },
86 { AR5K_CFP_PERIOD_5210, 0 },
87 /* PHY registers */
88 { AR5K_PHY(0), 0x00000047 },
89 { AR5K_PHY_AGC, 0x00000000 },
90 { AR5K_PHY(3), 0x09848ea6 },
91 { AR5K_PHY(4), 0x3d32e000 },
92 { AR5K_PHY(5), 0x0000076b },
93 { AR5K_PHY_ACT, AR5K_PHY_ACT_DISABLE },
94 { AR5K_PHY(8), 0x02020200 },
95 { AR5K_PHY(9), 0x00000e0e },
96 { AR5K_PHY(10), 0x0a020201 },
97 { AR5K_PHY(11), 0x00036ffc },
98 { AR5K_PHY(12), 0x00000000 },
99 { AR5K_PHY(13), 0x00000e0e },
100 { AR5K_PHY(14), 0x00000007 },
101 { AR5K_PHY(15), 0x00020100 },
102 { AR5K_PHY(16), 0x89630000 },
103 { AR5K_PHY(17), 0x1372169c },
104 { AR5K_PHY(18), 0x0018b633 },
105 { AR5K_PHY(19), 0x1284613c },
106 { AR5K_PHY(20), 0x0de8b8e0 },
107 { AR5K_PHY(21), 0x00074859 },
108 { AR5K_PHY(22), 0x7e80beba },
109 { AR5K_PHY(23), 0x313a665e },
110 { AR5K_PHY_AGCCTL, 0x00001d08 },
111 { AR5K_PHY(25), 0x0001ce00 },
112 { AR5K_PHY(26), 0x409a4190 },
113 { AR5K_PHY(28), 0x0000000f },
114 { AR5K_PHY(29), 0x00000080 },
115 { AR5K_PHY(30), 0x00000004 },
116 { AR5K_PHY(31), 0x00000018 }, /* 0x987c */
117 { AR5K_PHY(64), 0x00000000 }, /* 0x9900 */
118 { AR5K_PHY(65), 0x00000000 },
119 { AR5K_PHY(66), 0x00000000 },
120 { AR5K_PHY(67), 0x00800000 },
121 { AR5K_PHY(68), 0x00000003 },
122 /* BB gain table (64bytes) */
123 { AR5K_BB_GAIN(0), 0x00000000 },
124 { AR5K_BB_GAIN(1), 0x00000020 },
125 { AR5K_BB_GAIN(2), 0x00000010 },
126 { AR5K_BB_GAIN(3), 0x00000030 },
127 { AR5K_BB_GAIN(4), 0x00000008 },
128 { AR5K_BB_GAIN(5), 0x00000028 },
129 { AR5K_BB_GAIN(6), 0x00000028 },
130 { AR5K_BB_GAIN(7), 0x00000004 },
131 { AR5K_BB_GAIN(8), 0x00000024 },
132 { AR5K_BB_GAIN(9), 0x00000014 },
133 { AR5K_BB_GAIN(10), 0x00000034 },
134 { AR5K_BB_GAIN(11), 0x0000000c },
135 { AR5K_BB_GAIN(12), 0x0000002c },
136 { AR5K_BB_GAIN(13), 0x00000002 },
137 { AR5K_BB_GAIN(14), 0x00000022 },
138 { AR5K_BB_GAIN(15), 0x00000012 },
139 { AR5K_BB_GAIN(16), 0x00000032 },
140 { AR5K_BB_GAIN(17), 0x0000000a },
141 { AR5K_BB_GAIN(18), 0x0000002a },
142 { AR5K_BB_GAIN(19), 0x00000001 },
143 { AR5K_BB_GAIN(20), 0x00000021 },
144 { AR5K_BB_GAIN(21), 0x00000011 },
145 { AR5K_BB_GAIN(22), 0x00000031 },
146 { AR5K_BB_GAIN(23), 0x00000009 },
147 { AR5K_BB_GAIN(24), 0x00000029 },
148 { AR5K_BB_GAIN(25), 0x00000005 },
149 { AR5K_BB_GAIN(26), 0x00000025 },
150 { AR5K_BB_GAIN(27), 0x00000015 },
151 { AR5K_BB_GAIN(28), 0x00000035 },
152 { AR5K_BB_GAIN(29), 0x0000000d },
153 { AR5K_BB_GAIN(30), 0x0000002d },
154 { AR5K_BB_GAIN(31), 0x00000003 },
155 { AR5K_BB_GAIN(32), 0x00000023 },
156 { AR5K_BB_GAIN(33), 0x00000013 },
157 { AR5K_BB_GAIN(34), 0x00000033 },
158 { AR5K_BB_GAIN(35), 0x0000000b },
159 { AR5K_BB_GAIN(36), 0x0000002b },
160 { AR5K_BB_GAIN(37), 0x00000007 },
161 { AR5K_BB_GAIN(38), 0x00000027 },
162 { AR5K_BB_GAIN(39), 0x00000017 },
163 { AR5K_BB_GAIN(40), 0x00000037 },
164 { AR5K_BB_GAIN(41), 0x0000000f },
165 { AR5K_BB_GAIN(42), 0x0000002f },
166 { AR5K_BB_GAIN(43), 0x0000002f },
167 { AR5K_BB_GAIN(44), 0x0000002f },
168 { AR5K_BB_GAIN(45), 0x0000002f },
169 { AR5K_BB_GAIN(46), 0x0000002f },
170 { AR5K_BB_GAIN(47), 0x0000002f },
171 { AR5K_BB_GAIN(48), 0x0000002f },
172 { AR5K_BB_GAIN(49), 0x0000002f },
173 { AR5K_BB_GAIN(50), 0x0000002f },
174 { AR5K_BB_GAIN(51), 0x0000002f },
175 { AR5K_BB_GAIN(52), 0x0000002f },
176 { AR5K_BB_GAIN(53), 0x0000002f },
177 { AR5K_BB_GAIN(54), 0x0000002f },
178 { AR5K_BB_GAIN(55), 0x0000002f },
179 { AR5K_BB_GAIN(56), 0x0000002f },
180 { AR5K_BB_GAIN(57), 0x0000002f },
181 { AR5K_BB_GAIN(58), 0x0000002f },
182 { AR5K_BB_GAIN(59), 0x0000002f },
183 { AR5K_BB_GAIN(60), 0x0000002f },
184 { AR5K_BB_GAIN(61), 0x0000002f },
185 { AR5K_BB_GAIN(62), 0x0000002f },
186 { AR5K_BB_GAIN(63), 0x0000002f },
187 /* 5110 RF gain table (64btes) */
188 { AR5K_RF_GAIN(0), 0x0000001d },
189 { AR5K_RF_GAIN(1), 0x0000005d },
190 { AR5K_RF_GAIN(2), 0x0000009d },
191 { AR5K_RF_GAIN(3), 0x000000dd },
192 { AR5K_RF_GAIN(4), 0x0000011d },
193 { AR5K_RF_GAIN(5), 0x00000021 },
194 { AR5K_RF_GAIN(6), 0x00000061 },
195 { AR5K_RF_GAIN(7), 0x000000a1 },
196 { AR5K_RF_GAIN(8), 0x000000e1 },
197 { AR5K_RF_GAIN(9), 0x00000031 },
198 { AR5K_RF_GAIN(10), 0x00000071 },
199 { AR5K_RF_GAIN(11), 0x000000b1 },
200 { AR5K_RF_GAIN(12), 0x0000001c },
201 { AR5K_RF_GAIN(13), 0x0000005c },
202 { AR5K_RF_GAIN(14), 0x00000029 },
203 { AR5K_RF_GAIN(15), 0x00000069 },
204 { AR5K_RF_GAIN(16), 0x000000a9 },
205 { AR5K_RF_GAIN(17), 0x00000020 },
206 { AR5K_RF_GAIN(18), 0x00000019 },
207 { AR5K_RF_GAIN(19), 0x00000059 },
208 { AR5K_RF_GAIN(20), 0x00000099 },
209 { AR5K_RF_GAIN(21), 0x00000030 },
210 { AR5K_RF_GAIN(22), 0x00000005 },
211 { AR5K_RF_GAIN(23), 0x00000025 },
212 { AR5K_RF_GAIN(24), 0x00000065 },
213 { AR5K_RF_GAIN(25), 0x000000a5 },
214 { AR5K_RF_GAIN(26), 0x00000028 },
215 { AR5K_RF_GAIN(27), 0x00000068 },
216 { AR5K_RF_GAIN(28), 0x0000001f },
217 { AR5K_RF_GAIN(29), 0x0000001e },
218 { AR5K_RF_GAIN(30), 0x00000018 },
219 { AR5K_RF_GAIN(31), 0x00000058 },
220 { AR5K_RF_GAIN(32), 0x00000098 },
221 { AR5K_RF_GAIN(33), 0x00000003 },
222 { AR5K_RF_GAIN(34), 0x00000004 },
223 { AR5K_RF_GAIN(35), 0x00000044 },
224 { AR5K_RF_GAIN(36), 0x00000084 },
225 { AR5K_RF_GAIN(37), 0x00000013 },
226 { AR5K_RF_GAIN(38), 0x00000012 },
227 { AR5K_RF_GAIN(39), 0x00000052 },
228 { AR5K_RF_GAIN(40), 0x00000092 },
229 { AR5K_RF_GAIN(41), 0x000000d2 },
230 { AR5K_RF_GAIN(42), 0x0000002b },
231 { AR5K_RF_GAIN(43), 0x0000002a },
232 { AR5K_RF_GAIN(44), 0x0000006a },
233 { AR5K_RF_GAIN(45), 0x000000aa },
234 { AR5K_RF_GAIN(46), 0x0000001b },
235 { AR5K_RF_GAIN(47), 0x0000001a },
236 { AR5K_RF_GAIN(48), 0x0000005a },
237 { AR5K_RF_GAIN(49), 0x0000009a },
238 { AR5K_RF_GAIN(50), 0x000000da },
239 { AR5K_RF_GAIN(51), 0x00000006 },
240 { AR5K_RF_GAIN(52), 0x00000006 },
241 { AR5K_RF_GAIN(53), 0x00000006 },
242 { AR5K_RF_GAIN(54), 0x00000006 },
243 { AR5K_RF_GAIN(55), 0x00000006 },
244 { AR5K_RF_GAIN(56), 0x00000006 },
245 { AR5K_RF_GAIN(57), 0x00000006 },
246 { AR5K_RF_GAIN(58), 0x00000006 },
247 { AR5K_RF_GAIN(59), 0x00000006 },
248 { AR5K_RF_GAIN(60), 0x00000006 },
249 { AR5K_RF_GAIN(61), 0x00000006 },
250 { AR5K_RF_GAIN(62), 0x00000006 },
251 { AR5K_RF_GAIN(63), 0x00000006 },
252 /* PHY activation */
253 { AR5K_PHY(53), 0x00000020 },
254 { AR5K_PHY(51), 0x00000004 },
255 { AR5K_PHY(50), 0x00060106 },
256 { AR5K_PHY(39), 0x0000006d },
257 { AR5K_PHY(48), 0x00000000 },
258 { AR5K_PHY(52), 0x00000014 },
259 { AR5K_PHY_ACT, AR5K_PHY_ACT_ENABLE },
260};
261
262/* Initial register settings for AR5211 */
263static const struct ath5k_ini ar5211_ini[] = {
264 { AR5K_RXDP, 0x00000000 },
265 { AR5K_RTSD0, 0x84849c9c },
266 { AR5K_RTSD1, 0x7c7c7c7c },
267 { AR5K_RXCFG, 0x00000005 },
268 { AR5K_MIBC, 0x00000000 },
269 { AR5K_TOPS, 0x00000008 },
270 { AR5K_RXNOFRM, 0x00000008 },
271 { AR5K_TXNOFRM, 0x00000010 },
272 { AR5K_RPGTO, 0x00000000 },
273 { AR5K_RFCNT, 0x0000001f },
274 { AR5K_QUEUE_TXDP(0), 0x00000000 },
275 { AR5K_QUEUE_TXDP(1), 0x00000000 },
276 { AR5K_QUEUE_TXDP(2), 0x00000000 },
277 { AR5K_QUEUE_TXDP(3), 0x00000000 },
278 { AR5K_QUEUE_TXDP(4), 0x00000000 },
279 { AR5K_QUEUE_TXDP(5), 0x00000000 },
280 { AR5K_QUEUE_TXDP(6), 0x00000000 },
281 { AR5K_QUEUE_TXDP(7), 0x00000000 },
282 { AR5K_QUEUE_TXDP(8), 0x00000000 },
283 { AR5K_QUEUE_TXDP(9), 0x00000000 },
284 { AR5K_DCU_FP, 0x00000000 },
285 { AR5K_STA_ID1, 0x00000000 },
286 { AR5K_BSS_ID0, 0x00000000 },
287 { AR5K_BSS_ID1, 0x00000000 },
288 { AR5K_RSSI_THR, 0x00000000 },
289 { AR5K_CFP_PERIOD_5211, 0x00000000 },
290 { AR5K_TIMER0_5211, 0x00000030 },
291 { AR5K_TIMER1_5211, 0x0007ffff },
292 { AR5K_TIMER2_5211, 0x01ffffff },
293 { AR5K_TIMER3_5211, 0x00000031 },
294 { AR5K_CFP_DUR_5211, 0x00000000 },
295 { AR5K_RX_FILTER_5211, 0x00000000 },
296 { AR5K_MCAST_FILTER0_5211, 0x00000000 },
297 { AR5K_MCAST_FILTER1_5211, 0x00000002 },
298 { AR5K_DIAG_SW_5211, 0x00000000 },
299 { AR5K_ADDAC_TEST, 0x00000000 },
300 { AR5K_DEFAULT_ANTENNA, 0x00000000 },
301 /* PHY registers */
302 { AR5K_PHY_AGC, 0x00000000 },
303 { AR5K_PHY(3), 0x2d849093 },
304 { AR5K_PHY(4), 0x7d32e000 },
305 { AR5K_PHY(5), 0x00000f6b },
306 { AR5K_PHY_ACT, 0x00000000 },
307 { AR5K_PHY(11), 0x00026ffe },
308 { AR5K_PHY(12), 0x00000000 },
309 { AR5K_PHY(15), 0x00020100 },
310 { AR5K_PHY(16), 0x206a017a },
311 { AR5K_PHY(19), 0x1284613c },
312 { AR5K_PHY(21), 0x00000859 },
313 { AR5K_PHY(26), 0x409a4190 }, /* 0x9868 */
314 { AR5K_PHY(27), 0x050cb081 },
315 { AR5K_PHY(28), 0x0000000f },
316 { AR5K_PHY(29), 0x00000080 },
317 { AR5K_PHY(30), 0x0000000c },
318 { AR5K_PHY(64), 0x00000000 },
319 { AR5K_PHY(65), 0x00000000 },
320 { AR5K_PHY(66), 0x00000000 },
321 { AR5K_PHY(67), 0x00800000 },
322 { AR5K_PHY(68), 0x00000001 },
323 { AR5K_PHY(71), 0x0000092a },
324 { AR5K_PHY_IQ, 0x00000000 },
325 { AR5K_PHY(73), 0x00058a05 },
326 { AR5K_PHY(74), 0x00000001 },
327 { AR5K_PHY(75), 0x00000000 },
328 { AR5K_PHY_PAPD_PROBE, 0x00000000 },
329 { AR5K_PHY(77), 0x00000000 }, /* 0x9934 */
330 { AR5K_PHY(78), 0x00000000 }, /* 0x9938 */
331 { AR5K_PHY(79), 0x0000003f }, /* 0x993c */
332 { AR5K_PHY(80), 0x00000004 },
333 { AR5K_PHY(82), 0x00000000 },
334 { AR5K_PHY(83), 0x00000000 },
335 { AR5K_PHY(84), 0x00000000 },
336 { AR5K_PHY_RADAR, 0x5d50f14c },
337 { AR5K_PHY(86), 0x00000018 },
338 { AR5K_PHY(87), 0x004b6a8e },
339 /* Initial Power table (32bytes)
340 * common on all cards/modes.
341 * Note: Table is rewritten during
342 * txpower setup later using calibration
343 * data etc. so next write is non-common */
344 { AR5K_PHY_PCDAC_TXPOWER(1), 0x06ff05ff },
345 { AR5K_PHY_PCDAC_TXPOWER(2), 0x07ff07ff },
346 { AR5K_PHY_PCDAC_TXPOWER(3), 0x08ff08ff },
347 { AR5K_PHY_PCDAC_TXPOWER(4), 0x09ff09ff },
348 { AR5K_PHY_PCDAC_TXPOWER(5), 0x0aff0aff },
349 { AR5K_PHY_PCDAC_TXPOWER(6), 0x0bff0bff },
350 { AR5K_PHY_PCDAC_TXPOWER(7), 0x0cff0cff },
351 { AR5K_PHY_PCDAC_TXPOWER(8), 0x0dff0dff },
352 { AR5K_PHY_PCDAC_TXPOWER(9), 0x0fff0eff },
353 { AR5K_PHY_PCDAC_TXPOWER(10), 0x12ff12ff },
354 { AR5K_PHY_PCDAC_TXPOWER(11), 0x14ff13ff },
355 { AR5K_PHY_PCDAC_TXPOWER(12), 0x16ff15ff },
356 { AR5K_PHY_PCDAC_TXPOWER(13), 0x19ff17ff },
357 { AR5K_PHY_PCDAC_TXPOWER(14), 0x1bff1aff },
358 { AR5K_PHY_PCDAC_TXPOWER(15), 0x1eff1dff },
359 { AR5K_PHY_PCDAC_TXPOWER(16), 0x23ff20ff },
360 { AR5K_PHY_PCDAC_TXPOWER(17), 0x27ff25ff },
361 { AR5K_PHY_PCDAC_TXPOWER(18), 0x2cff29ff },
362 { AR5K_PHY_PCDAC_TXPOWER(19), 0x31ff2fff },
363 { AR5K_PHY_PCDAC_TXPOWER(20), 0x37ff34ff },
364 { AR5K_PHY_PCDAC_TXPOWER(21), 0x3aff3aff },
365 { AR5K_PHY_PCDAC_TXPOWER(22), 0x3aff3aff },
366 { AR5K_PHY_PCDAC_TXPOWER(23), 0x3aff3aff },
367 { AR5K_PHY_PCDAC_TXPOWER(24), 0x3aff3aff },
368 { AR5K_PHY_PCDAC_TXPOWER(25), 0x3aff3aff },
369 { AR5K_PHY_PCDAC_TXPOWER(26), 0x3aff3aff },
370 { AR5K_PHY_PCDAC_TXPOWER(27), 0x3aff3aff },
371 { AR5K_PHY_PCDAC_TXPOWER(28), 0x3aff3aff },
372 { AR5K_PHY_PCDAC_TXPOWER(29), 0x3aff3aff },
373 { AR5K_PHY_PCDAC_TXPOWER(30), 0x3aff3aff },
374 { AR5K_PHY_PCDAC_TXPOWER(31), 0x3aff3aff },
375 { AR5K_PHY_CCKTXCTL, 0x00000000 },
376 { AR5K_PHY(642), 0x503e4646 },
377 { AR5K_PHY_GAIN_2GHZ, 0x6480416c },
378 { AR5K_PHY(644), 0x0199a003 },
379 { AR5K_PHY(645), 0x044cd610 },
380 { AR5K_PHY(646), 0x13800040 },
381 { AR5K_PHY(647), 0x1be00060 },
382 { AR5K_PHY(648), 0x0c53800a },
383 { AR5K_PHY(649), 0x0014df3b },
384 { AR5K_PHY(650), 0x000001b5 },
385 { AR5K_PHY(651), 0x00000020 },
386};
387
388/* Initial mode-specific settings for AR5211
389 * 5211 supports OFDM-only g (draft g) but we
390 * need to test it !
391 */
392static const struct ath5k_ini_mode ar5211_ini_mode[] = {
393 { AR5K_TXCFG,
394 /* a aTurbo b g (OFDM) */
395 { 0x00000015, 0x00000015, 0x0000001d, 0x00000015 } },
396 { AR5K_QUEUE_DFS_LOCAL_IFS(0),
397 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
398 { AR5K_QUEUE_DFS_LOCAL_IFS(1),
399 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
400 { AR5K_QUEUE_DFS_LOCAL_IFS(2),
401 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
402 { AR5K_QUEUE_DFS_LOCAL_IFS(3),
403 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
404 { AR5K_QUEUE_DFS_LOCAL_IFS(4),
405 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
406 { AR5K_QUEUE_DFS_LOCAL_IFS(5),
407 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
408 { AR5K_QUEUE_DFS_LOCAL_IFS(6),
409 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
410 { AR5K_QUEUE_DFS_LOCAL_IFS(7),
411 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
412 { AR5K_QUEUE_DFS_LOCAL_IFS(8),
413 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
414 { AR5K_QUEUE_DFS_LOCAL_IFS(9),
415 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
416 { AR5K_DCU_GBL_IFS_SLOT,
417 { 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 } },
418 { AR5K_DCU_GBL_IFS_SIFS,
419 { 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 } },
420 { AR5K_DCU_GBL_IFS_EIFS,
421 { 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 } },
422 { AR5K_DCU_GBL_IFS_MISC,
423 { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 } },
424 { AR5K_TIME_OUT,
425 { 0x04000400, 0x08000800, 0x20003000, 0x04000400 } },
426 { AR5K_USEC_5211,
427 { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 } },
428 { AR5K_PHY_TURBO,
429 { 0x00000000, 0x00000003, 0x00000000, 0x00000000 } },
430 { AR5K_PHY(8),
431 { 0x02020200, 0x02020200, 0x02010200, 0x02020200 } },
432 { AR5K_PHY(9),
433 { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e } },
434 { AR5K_PHY(10),
435 { 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 } },
436 { AR5K_PHY(13),
437 { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
438 { AR5K_PHY(14),
439 { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b } },
440 { AR5K_PHY(17),
441 { 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c } },
442 { AR5K_PHY(18),
443 { 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 } },
444 { AR5K_PHY(20),
445 { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } },
446 { AR5K_PHY_SIG,
447 { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } },
448 { AR5K_PHY_AGCCOARSE,
449 { 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e } },
450 { AR5K_PHY_AGCCTL,
451 { 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 } },
452 { AR5K_PHY_NF,
453 { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
454 { AR5K_PHY_RX_DELAY,
455 { 0x00002710, 0x00002710, 0x0000157c, 0x00002710 } },
456 { AR5K_PHY(70),
457 { 0x00000190, 0x00000190, 0x00000084, 0x00000190 } },
458 { AR5K_PHY_FRAME_CTL_5211,
459 { 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 } },
460 { AR5K_PHY_PCDAC_TXPOWER_BASE,
461 { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } },
462 { AR5K_RF_BUFFER_CONTROL_4,
463 { 0x00000010, 0x00000014, 0x00000010, 0x00000010 } },
464};
465
466/* Initial register settings for AR5212 */
467static const struct ath5k_ini ar5212_ini_common_start[] = {
468 { AR5K_RXDP, 0x00000000 },
469 { AR5K_RXCFG, 0x00000005 },
470 { AR5K_MIBC, 0x00000000 },
471 { AR5K_TOPS, 0x00000008 },
472 { AR5K_RXNOFRM, 0x00000008 },
473 { AR5K_TXNOFRM, 0x00000010 },
474 { AR5K_RPGTO, 0x00000000 },
475 { AR5K_RFCNT, 0x0000001f },
476 { AR5K_QUEUE_TXDP(0), 0x00000000 },
477 { AR5K_QUEUE_TXDP(1), 0x00000000 },
478 { AR5K_QUEUE_TXDP(2), 0x00000000 },
479 { AR5K_QUEUE_TXDP(3), 0x00000000 },
480 { AR5K_QUEUE_TXDP(4), 0x00000000 },
481 { AR5K_QUEUE_TXDP(5), 0x00000000 },
482 { AR5K_QUEUE_TXDP(6), 0x00000000 },
483 { AR5K_QUEUE_TXDP(7), 0x00000000 },
484 { AR5K_QUEUE_TXDP(8), 0x00000000 },
485 { AR5K_QUEUE_TXDP(9), 0x00000000 },
486 { AR5K_DCU_FP, 0x00000000 },
487 { AR5K_DCU_TXP, 0x00000000 },
488 /* Tx filter table 0 (32 entries) */
489 { AR5K_DCU_TX_FILTER_0(0), 0x00000000 }, /* DCU 0 */
490 { AR5K_DCU_TX_FILTER_0(1), 0x00000000 },
491 { AR5K_DCU_TX_FILTER_0(2), 0x00000000 },
492 { AR5K_DCU_TX_FILTER_0(3), 0x00000000 },
493 { AR5K_DCU_TX_FILTER_0(4), 0x00000000 }, /* DCU 1 */
494 { AR5K_DCU_TX_FILTER_0(5), 0x00000000 },
495 { AR5K_DCU_TX_FILTER_0(6), 0x00000000 },
496 { AR5K_DCU_TX_FILTER_0(7), 0x00000000 },
497 { AR5K_DCU_TX_FILTER_0(8), 0x00000000 }, /* DCU 2 */
498 { AR5K_DCU_TX_FILTER_0(9), 0x00000000 },
499 { AR5K_DCU_TX_FILTER_0(10), 0x00000000 },
500 { AR5K_DCU_TX_FILTER_0(11), 0x00000000 },
501 { AR5K_DCU_TX_FILTER_0(12), 0x00000000 }, /* DCU 3 */
502 { AR5K_DCU_TX_FILTER_0(13), 0x00000000 },
503 { AR5K_DCU_TX_FILTER_0(14), 0x00000000 },
504 { AR5K_DCU_TX_FILTER_0(15), 0x00000000 },
505 { AR5K_DCU_TX_FILTER_0(16), 0x00000000 }, /* DCU 4 */
506 { AR5K_DCU_TX_FILTER_0(17), 0x00000000 },
507 { AR5K_DCU_TX_FILTER_0(18), 0x00000000 },
508 { AR5K_DCU_TX_FILTER_0(19), 0x00000000 },
509 { AR5K_DCU_TX_FILTER_0(20), 0x00000000 }, /* DCU 5 */
510 { AR5K_DCU_TX_FILTER_0(21), 0x00000000 },
511 { AR5K_DCU_TX_FILTER_0(22), 0x00000000 },
512 { AR5K_DCU_TX_FILTER_0(23), 0x00000000 },
513 { AR5K_DCU_TX_FILTER_0(24), 0x00000000 }, /* DCU 6 */
514 { AR5K_DCU_TX_FILTER_0(25), 0x00000000 },
515 { AR5K_DCU_TX_FILTER_0(26), 0x00000000 },
516 { AR5K_DCU_TX_FILTER_0(27), 0x00000000 },
517 { AR5K_DCU_TX_FILTER_0(28), 0x00000000 }, /* DCU 7 */
518 { AR5K_DCU_TX_FILTER_0(29), 0x00000000 },
519 { AR5K_DCU_TX_FILTER_0(30), 0x00000000 },
520 { AR5K_DCU_TX_FILTER_0(31), 0x00000000 },
521 /* Tx filter table 1 (16 entries) */
522 { AR5K_DCU_TX_FILTER_1(0), 0x00000000 },
523 { AR5K_DCU_TX_FILTER_1(1), 0x00000000 },
524 { AR5K_DCU_TX_FILTER_1(2), 0x00000000 },
525 { AR5K_DCU_TX_FILTER_1(3), 0x00000000 },
526 { AR5K_DCU_TX_FILTER_1(4), 0x00000000 },
527 { AR5K_DCU_TX_FILTER_1(5), 0x00000000 },
528 { AR5K_DCU_TX_FILTER_1(6), 0x00000000 },
529 { AR5K_DCU_TX_FILTER_1(7), 0x00000000 },
530 { AR5K_DCU_TX_FILTER_1(8), 0x00000000 },
531 { AR5K_DCU_TX_FILTER_1(9), 0x00000000 },
532 { AR5K_DCU_TX_FILTER_1(10), 0x00000000 },
533 { AR5K_DCU_TX_FILTER_1(11), 0x00000000 },
534 { AR5K_DCU_TX_FILTER_1(12), 0x00000000 },
535 { AR5K_DCU_TX_FILTER_1(13), 0x00000000 },
536 { AR5K_DCU_TX_FILTER_1(14), 0x00000000 },
537 { AR5K_DCU_TX_FILTER_1(15), 0x00000000 },
538 { AR5K_DCU_TX_FILTER_CLR, 0x00000000 },
539 { AR5K_DCU_TX_FILTER_SET, 0x00000000 },
540 { AR5K_DCU_TX_FILTER_CLR, 0x00000000 },
541 { AR5K_DCU_TX_FILTER_SET, 0x00000000 },
542 { AR5K_STA_ID1, 0x00000000 },
543 { AR5K_BSS_ID0, 0x00000000 },
544 { AR5K_BSS_ID1, 0x00000000 },
545 { AR5K_BEACON_5211, 0x00000000 },
546 { AR5K_CFP_PERIOD_5211, 0x00000000 },
547 { AR5K_TIMER0_5211, 0x00000030 },
548 { AR5K_TIMER1_5211, 0x0007ffff },
549 { AR5K_TIMER2_5211, 0x01ffffff },
550 { AR5K_TIMER3_5211, 0x00000031 },
551 { AR5K_CFP_DUR_5211, 0x00000000 },
552 { AR5K_RX_FILTER_5211, 0x00000000 },
553 { AR5K_DIAG_SW_5211, 0x00000000 },
554 { AR5K_ADDAC_TEST, 0x00000000 },
555 { AR5K_DEFAULT_ANTENNA, 0x00000000 },
556 { AR5K_FRAME_CTL_QOSM, 0x000fc78f },
557 { AR5K_XRMODE, 0x2a82301a },
558 { AR5K_XRDELAY, 0x05dc01e0 },
559 { AR5K_XRTIMEOUT, 0x1f402710 },
560 { AR5K_XRCHIRP, 0x01f40000 },
561 { AR5K_XRSTOMP, 0x00001e1c },
562 { AR5K_SLEEP0, 0x0002aaaa },
563 { AR5K_SLEEP1, 0x02005555 },
564 { AR5K_SLEEP2, 0x00000000 },
565 { AR5K_BSS_IDM0, 0xffffffff },
566 { AR5K_BSS_IDM1, 0x0000ffff },
567 { AR5K_TXPC, 0x00000000 },
568 { AR5K_PROFCNT_TX, 0x00000000 },
569 { AR5K_PROFCNT_RX, 0x00000000 },
570 { AR5K_PROFCNT_RXCLR, 0x00000000 },
571 { AR5K_PROFCNT_CYCLE, 0x00000000 },
572 { AR5K_QUIET_CTL1, 0x00000088 },
573 /* Initial rate duration table (32 entries )*/
574 { AR5K_RATE_DUR(0), 0x00000000 },
575 { AR5K_RATE_DUR(1), 0x0000008c },
576 { AR5K_RATE_DUR(2), 0x000000e4 },
577 { AR5K_RATE_DUR(3), 0x000002d5 },
578 { AR5K_RATE_DUR(4), 0x00000000 },
579 { AR5K_RATE_DUR(5), 0x00000000 },
580 { AR5K_RATE_DUR(6), 0x000000a0 },
581 { AR5K_RATE_DUR(7), 0x000001c9 },
582 { AR5K_RATE_DUR(8), 0x0000002c },
583 { AR5K_RATE_DUR(9), 0x0000002c },
584 { AR5K_RATE_DUR(10), 0x00000030 },
585 { AR5K_RATE_DUR(11), 0x0000003c },
586 { AR5K_RATE_DUR(12), 0x0000002c },
587 { AR5K_RATE_DUR(13), 0x0000002c },
588 { AR5K_RATE_DUR(14), 0x00000030 },
589 { AR5K_RATE_DUR(15), 0x0000003c },
590 { AR5K_RATE_DUR(16), 0x00000000 },
591 { AR5K_RATE_DUR(17), 0x00000000 },
592 { AR5K_RATE_DUR(18), 0x00000000 },
593 { AR5K_RATE_DUR(19), 0x00000000 },
594 { AR5K_RATE_DUR(20), 0x00000000 },
595 { AR5K_RATE_DUR(21), 0x00000000 },
596 { AR5K_RATE_DUR(22), 0x00000000 },
597 { AR5K_RATE_DUR(23), 0x00000000 },
598 { AR5K_RATE_DUR(24), 0x000000d5 },
599 { AR5K_RATE_DUR(25), 0x000000df },
600 { AR5K_RATE_DUR(26), 0x00000102 },
601 { AR5K_RATE_DUR(27), 0x0000013a },
602 { AR5K_RATE_DUR(28), 0x00000075 },
603 { AR5K_RATE_DUR(29), 0x0000007f },
604 { AR5K_RATE_DUR(30), 0x000000a2 },
605 { AR5K_RATE_DUR(31), 0x00000000 },
606 { AR5K_QUIET_CTL2, 0x00010002 },
607 { AR5K_TSF_PARM, 0x00000001 },
608 { AR5K_QOS_NOACK, 0x000000c0 },
609 { AR5K_PHY_ERR_FIL, 0x00000000 },
610 { AR5K_XRLAT_TX, 0x00000168 },
611 { AR5K_ACKSIFS, 0x00000000 },
612 /* Rate -> db table
613 * notice ...03<-02<-01<-00 ! */
614 { AR5K_RATE2DB(0), 0x03020100 },
615 { AR5K_RATE2DB(1), 0x07060504 },
616 { AR5K_RATE2DB(2), 0x0b0a0908 },
617 { AR5K_RATE2DB(3), 0x0f0e0d0c },
618 { AR5K_RATE2DB(4), 0x13121110 },
619 { AR5K_RATE2DB(5), 0x17161514 },
620 { AR5K_RATE2DB(6), 0x1b1a1918 },
621 { AR5K_RATE2DB(7), 0x1f1e1d1c },
622 /* Db -> Rate table */
623 { AR5K_DB2RATE(0), 0x03020100 },
624 { AR5K_DB2RATE(1), 0x07060504 },
625 { AR5K_DB2RATE(2), 0x0b0a0908 },
626 { AR5K_DB2RATE(3), 0x0f0e0d0c },
627 { AR5K_DB2RATE(4), 0x13121110 },
628 { AR5K_DB2RATE(5), 0x17161514 },
629 { AR5K_DB2RATE(6), 0x1b1a1918 },
630 { AR5K_DB2RATE(7), 0x1f1e1d1c },
631 /* PHY registers (Common settings
632 * for all chips/modes) */
633 { AR5K_PHY(3), 0xad848e19 },
634 { AR5K_PHY(4), 0x7d28e000 },
635 { AR5K_PHY_TIMING_3, 0x9c0a9f6b },
636 { AR5K_PHY_ACT, 0x00000000 },
637 { AR5K_PHY(16), 0x206a017a },
638 { AR5K_PHY(21), 0x00000859 },
639 { AR5K_PHY_BIN_MASK_1, 0x00000000 },
640 { AR5K_PHY_BIN_MASK_2, 0x00000000 },
641 { AR5K_PHY_BIN_MASK_3, 0x00000000 },
642 { AR5K_PHY_BIN_MASK_CTL, 0x00800000 },
643 { AR5K_PHY_ANT_CTL, 0x00000001 },
644 /*{ AR5K_PHY(71), 0x0000092a },*/ /* Old value */
645 { AR5K_PHY_MAX_RX_LEN, 0x00000c80 },
646 { AR5K_PHY_IQ, 0x05100000 },
647 { AR5K_PHY_WARM_RESET, 0x00000001 },
648 { AR5K_PHY_CTL, 0x00000004 },
649 { AR5K_PHY_TXPOWER_RATE1, 0x1e1f2022 },
650 { AR5K_PHY_TXPOWER_RATE2, 0x0a0b0c0d },
651 { AR5K_PHY_TXPOWER_RATE_MAX, 0x0000003f },
652 { AR5K_PHY(82), 0x9280b212 },
653 { AR5K_PHY_RADAR, 0x5d50e188 },
654 /*{ AR5K_PHY(86), 0x000000ff },*/
655 { AR5K_PHY(87), 0x004b6a8e },
656 { AR5K_PHY_NFTHRES, 0x000003ce },
657 { AR5K_PHY_RESTART, 0x192fb515 },
658 { AR5K_PHY(94), 0x00000001 },
659 { AR5K_PHY_RFBUS_REQ, 0x00000000 },
660 /*{ AR5K_PHY(644), 0x0080a333 },*/ /* Old value */
661 /*{ AR5K_PHY(645), 0x00206c10 },*/ /* Old value */
662 { AR5K_PHY(644), 0x00806333 },
663 { AR5K_PHY(645), 0x00106c10 },
664 { AR5K_PHY(646), 0x009c4060 },
665 /* { AR5K_PHY(647), 0x1483800a }, */
666 /* { AR5K_PHY(648), 0x01831061 }, */ /* Old value */
667 { AR5K_PHY(648), 0x018830c6 },
668 { AR5K_PHY(649), 0x00000400 },
669 /*{ AR5K_PHY(650), 0x000001b5 },*/
670 { AR5K_PHY(651), 0x00000000 },
671 { AR5K_PHY_TXPOWER_RATE3, 0x20202020 },
672 { AR5K_PHY_TXPOWER_RATE2, 0x20202020 },
673 /*{ AR5K_PHY(655), 0x13c889af },*/
674 { AR5K_PHY(656), 0x38490a20 },
675 { AR5K_PHY(657), 0x00007bb6 },
676 { AR5K_PHY(658), 0x0fff3ffc },
677};
678
679/* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */
680static const struct ath5k_ini_mode ar5212_ini_mode_start[] = {
681 { AR5K_QUEUE_DFS_LOCAL_IFS(0),
682 /* a/XR aTurbo b g (DYN) gTurbo */
683 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
684 { AR5K_QUEUE_DFS_LOCAL_IFS(1),
685 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
686 { AR5K_QUEUE_DFS_LOCAL_IFS(2),
687 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
688 { AR5K_QUEUE_DFS_LOCAL_IFS(3),
689 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
690 { AR5K_QUEUE_DFS_LOCAL_IFS(4),
691 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
692 { AR5K_QUEUE_DFS_LOCAL_IFS(5),
693 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
694 { AR5K_QUEUE_DFS_LOCAL_IFS(6),
695 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
696 { AR5K_QUEUE_DFS_LOCAL_IFS(7),
697 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
698 { AR5K_QUEUE_DFS_LOCAL_IFS(8),
699 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
700 { AR5K_QUEUE_DFS_LOCAL_IFS(9),
701 { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
702 { AR5K_DCU_GBL_IFS_SIFS,
703 { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } },
704 { AR5K_DCU_GBL_IFS_SLOT,
705 { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } },
706 { AR5K_DCU_GBL_IFS_EIFS,
707 { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } },
708 { AR5K_DCU_GBL_IFS_MISC,
709 { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } },
710 { AR5K_TIME_OUT,
711 { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } },
712 { AR5K_PHY_TURBO,
713 { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } },
714 { AR5K_PHY(8),
715 { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } },
716 { AR5K_PHY_RF_CTL2,
717 { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } },
718 { AR5K_PHY_SETTLING,
719 { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } },
720 { AR5K_PHY_AGCCTL,
721 { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d18 } },
722 { AR5K_PHY_NF,
723 { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
724 { AR5K_PHY_WEAK_OFDM_HIGH_THR,
725 { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } },
726 { AR5K_PHY(70),
727 { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } },
728 { AR5K_PHY_OFDM_SELFCORR,
729 { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } },
730 { 0xa230,
731 { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } },
732};
733
734/* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */
735static const struct ath5k_ini_mode rf5111_ini_mode_end[] = {
736 { AR5K_TXCFG,
737 /* a/XR aTurbo b g (DYN) gTurbo */
738 { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
739 { AR5K_USEC_5211,
740 { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } },
741 { AR5K_PHY_RF_CTL3,
742 { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } },
743 { AR5K_PHY_RF_CTL4,
744 { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
745 { AR5K_PHY_PA_CTL,
746 { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
747 { AR5K_PHY_GAIN,
748 { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } },
749 { AR5K_PHY_DESIRED_SIZE,
750 { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
751 { AR5K_PHY_SIG,
752 { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } },
753 { AR5K_PHY_AGCCOARSE,
754 { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } },
755 { AR5K_PHY_WEAK_OFDM_LOW_THR,
756 { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } },
757 { AR5K_PHY_RX_DELAY,
758 { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } },
759 { AR5K_PHY_FRAME_CTL_5211,
760 { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } },
761 { AR5K_PHY_GAIN_2GHZ,
762 { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } },
763 { AR5K_PHY_CCK_RX_CTL_4,
764 { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
765};
766
767static const struct ath5k_ini rf5111_ini_common_end[] = {
768 { AR5K_DCU_FP, 0x00000000 },
769 { AR5K_PHY_AGC, 0x00000000 },
770 { AR5K_PHY_ADC_CTL, 0x00022ffe },
771 { 0x983c, 0x00020100 },
772 { AR5K_PHY_GAIN_OFFSET, 0x1284613c },
773 { AR5K_PHY_PAPD_PROBE, 0x00004883 },
774 { 0x9940, 0x00000004 },
775 { 0x9958, 0x000000ff },
776 { 0x9974, 0x00000000 },
777 { AR5K_PHY_SPENDING, 0x00000018 },
778 { AR5K_PHY_CCKTXCTL, 0x00000000 },
779 { AR5K_PHY_CCK_CROSSCORR, 0xd03e6788 },
780 { AR5K_PHY_DAG_CCK_CTL, 0x000001b5 },
781 { 0xa23c, 0x13c889af },
782};
783
784/* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */
785static const struct ath5k_ini_mode rf5112_ini_mode_end[] = {
786 { AR5K_TXCFG,
787 /* a/XR aTurbo b g (DYN) gTurbo */
788 { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
789 { AR5K_USEC_5211,
790 { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
791 { AR5K_PHY_RF_CTL3,
792 { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
793 { AR5K_PHY_RF_CTL4,
794 { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
795 { AR5K_PHY_PA_CTL,
796 { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
797 { AR5K_PHY_GAIN,
798 { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } },
799 { AR5K_PHY_DESIRED_SIZE,
800 { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
801 { AR5K_PHY_SIG,
802 { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7ee80d2e } },
803 { AR5K_PHY_AGCCOARSE,
804 { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } },
805 { AR5K_PHY_WEAK_OFDM_LOW_THR,
806 { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
807 { AR5K_PHY_RX_DELAY,
808 { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
809 { AR5K_PHY_FRAME_CTL_5211,
810 { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } },
811 { AR5K_PHY_CCKTXCTL,
812 { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } },
813 { AR5K_PHY_CCK_CROSSCORR,
814 { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
815 { AR5K_PHY_GAIN_2GHZ,
816 { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } },
817 { AR5K_PHY_CCK_RX_CTL_4,
818 { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
819};
820
821static const struct ath5k_ini rf5112_ini_common_end[] = {
822 { AR5K_DCU_FP, 0x00000000 },
823 { AR5K_PHY_AGC, 0x00000000 },
824 { AR5K_PHY_ADC_CTL, 0x00022ffe },
825 { 0x983c, 0x00020100 },
826 { AR5K_PHY_GAIN_OFFSET, 0x1284613c },
827 { AR5K_PHY_PAPD_PROBE, 0x00004882 },
828 { 0x9940, 0x00000004 },
829 { 0x9958, 0x000000ff },
830 { 0x9974, 0x00000000 },
831 { AR5K_PHY_DAG_CCK_CTL, 0x000001b5 },
832 { 0xa23c, 0x13c889af },
833};
834
835/* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */
836static const struct ath5k_ini_mode rf5413_ini_mode_end[] = {
837 { AR5K_TXCFG,
838 /* a/XR aTurbo b g (DYN) gTurbo */
839 { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
840 { AR5K_USEC_5211,
841 { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
842 { AR5K_PHY_RF_CTL3,
843 { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
844 { AR5K_PHY_RF_CTL4,
845 { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
846 { AR5K_PHY_PA_CTL,
847 { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
848 { AR5K_PHY_GAIN,
849 { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } },
850 { AR5K_PHY_DESIRED_SIZE,
851 { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
852 { AR5K_PHY_SIG,
853 { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
854 { AR5K_PHY_AGCCOARSE,
855 { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
856 { AR5K_PHY_WEAK_OFDM_LOW_THR,
857 { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
858 { AR5K_PHY_RX_DELAY,
859 { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
860 { AR5K_PHY_FRAME_CTL_5211,
861 { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
862 { AR5K_PHY_CCKTXCTL,
863 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
864 { AR5K_PHY_CCK_CROSSCORR,
865 { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
866 { AR5K_PHY_GAIN_2GHZ,
867 { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } },
868 { AR5K_PHY_CCK_RX_CTL_4,
869 { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
870 { 0xa300,
871 { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } },
872 { 0xa304,
873 { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } },
874 { 0xa308,
875 { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } },
876 { 0xa30c,
877 { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
878 { 0xa310,
879 { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } },
880 { 0xa314,
881 { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
882 { 0xa318,
883 { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
884 { 0xa31c,
885 { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } },
886 { 0xa320,
887 { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } },
888 { 0xa324,
889 { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } },
890 { 0xa328,
891 { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } },
892 { 0xa32c,
893 { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } },
894 { 0xa330,
895 { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } },
896 { 0xa334,
897 { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } },
898};
899
900static const struct ath5k_ini rf5413_ini_common_end[] = {
901 { AR5K_DCU_FP, 0x000003e0 },
902 { AR5K_5414_CBCFG, 0x00000010 },
903 { AR5K_SEQ_MASK, 0x0000000f },
904 { 0x809c, 0x00000000 },
905 { 0x80a0, 0x00000000 },
906 { AR5K_MIC_QOS_CTL, 0x00000000 },
907 { AR5K_MIC_QOS_SEL, 0x00000000 },
908 { AR5K_MISC_MODE, 0x00000000 },
909 { AR5K_OFDM_FIL_CNT, 0x00000000 },
910 { AR5K_CCK_FIL_CNT, 0x00000000 },
911 { AR5K_PHYERR_CNT1, 0x00000000 },
912 { AR5K_PHYERR_CNT1_MASK, 0x00000000 },
913 { AR5K_PHYERR_CNT2, 0x00000000 },
914 { AR5K_PHYERR_CNT2_MASK, 0x00000000 },
915 { AR5K_TSF_THRES, 0x00000000 },
916 { 0x8140, 0x800003f9 },
917 { 0x8144, 0x00000000 },
918 { AR5K_PHY_AGC, 0x00000000 },
919 { AR5K_PHY_ADC_CTL, 0x0000a000 },
920 { 0x983c, 0x00200400 },
921 { AR5K_PHY_GAIN_OFFSET, 0x1284233c },
922 { AR5K_PHY_SCR, 0x0000001f },
923 { AR5K_PHY_SLMT, 0x00000080 },
924 { AR5K_PHY_SCAL, 0x0000000e },
925 { 0x9958, 0x00081fff },
926 { AR5K_PHY_TIMING_7, 0x00000000 },
927 { AR5K_PHY_TIMING_8, 0x02800000 },
928 { AR5K_PHY_TIMING_11, 0x00000000 },
929 { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 },
930 { 0x99e4, 0xaaaaaaaa },
931 { 0x99e8, 0x3c466478 },
932 { 0x99ec, 0x000000aa },
933 { AR5K_PHY_SCLOCK, 0x0000000c },
934 { AR5K_PHY_SDELAY, 0x000000ff },
935 { AR5K_PHY_SPENDING, 0x00000014 },
936 { AR5K_PHY_DAG_CCK_CTL, 0x000009b5 },
937 { 0xa23c, 0x93c889af },
938 { AR5K_PHY_FAST_ADC, 0x00000001 },
939 { 0xa250, 0x0000a000 },
940 { AR5K_PHY_BLUETOOTH, 0x00000000 },
941 { AR5K_PHY_TPC_RG1, 0x0cc75380 },
942 { 0xa25c, 0x0f0f0f01 },
943 { 0xa260, 0x5f690f01 },
944 { 0xa264, 0x00418a11 },
945 { 0xa268, 0x00000000 },
946 { AR5K_PHY_TPC_RG5, 0x0c30c16a },
947 { 0xa270, 0x00820820 },
948 { 0xa274, 0x081b7caa },
949 { 0xa278, 0x1ce739ce },
950 { 0xa27c, 0x051701ce },
951 { 0xa338, 0x00000000 },
952 { 0xa33c, 0x00000000 },
953 { 0xa340, 0x00000000 },
954 { 0xa344, 0x00000000 },
955 { 0xa348, 0x3fffffff },
956 { 0xa34c, 0x3fffffff },
957 { 0xa350, 0x3fffffff },
958 { 0xa354, 0x0003ffff },
959 { 0xa358, 0x79a8aa1f },
960 { 0xa35c, 0x066c420f },
961 { 0xa360, 0x0f282207 },
962 { 0xa364, 0x17601685 },
963 { 0xa368, 0x1f801104 },
964 { 0xa36c, 0x37a00c03 },
965 { 0xa370, 0x3fc40883 },
966 { 0xa374, 0x57c00803 },
967 { 0xa378, 0x5fd80682 },
968 { 0xa37c, 0x7fe00482 },
969 { 0xa380, 0x7f3c7bba },
970 { 0xa384, 0xf3307ff0 },
971};
972
973/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */
974/* XXX: a mode ? */
975static const struct ath5k_ini_mode rf2413_ini_mode_end[] = {
976 { AR5K_TXCFG,
977 /* a/XR aTurbo b g (DYN) gTurbo */
978 { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
979 { AR5K_USEC_5211,
980 { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
981 { AR5K_PHY_RF_CTL3,
982 { 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 } },
983 { AR5K_PHY_RF_CTL4,
984 { 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 } },
985 { AR5K_PHY_PA_CTL,
986 { 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a } },
987 { AR5K_PHY_GAIN,
988 { 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 } },
989 { AR5K_PHY_DESIRED_SIZE,
990 { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da } },
991 { AR5K_PHY_SIG,
992 { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e } },
993 { AR5K_PHY_AGCCOARSE,
994 { 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e } },
995 { AR5K_PHY_WEAK_OFDM_LOW_THR,
996 { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
997 { AR5K_PHY_RX_DELAY,
998 { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
999 { AR5K_PHY_FRAME_CTL_5211,
1000 { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
1001 { AR5K_PHY_CCKTXCTL,
1002 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1003 { AR5K_PHY_CCK_CROSSCORR,
1004 { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
1005 { AR5K_PHY_GAIN_2GHZ,
1006 { 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 } },
1007 { AR5K_PHY_CCK_RX_CTL_4,
1008 { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
1009};
1010
1011static const struct ath5k_ini rf2413_ini_common_end[] = {
1012 { AR5K_DCU_FP, 0x000003e0 },
1013 { AR5K_SEQ_MASK, 0x0000000f },
1014 { AR5K_MIC_QOS_CTL, 0x00000000 },
1015 { AR5K_MIC_QOS_SEL, 0x00000000 },
1016 { AR5K_MISC_MODE, 0x00000000 },
1017 { AR5K_OFDM_FIL_CNT, 0x00000000 },
1018 { AR5K_CCK_FIL_CNT, 0x00000000 },
1019 { AR5K_PHYERR_CNT1, 0x00000000 },
1020 { AR5K_PHYERR_CNT1_MASK, 0x00000000 },
1021 { AR5K_PHYERR_CNT2, 0x00000000 },
1022 { AR5K_PHYERR_CNT2_MASK, 0x00000000 },
1023 { AR5K_TSF_THRES, 0x00000000 },
1024 { 0x8140, 0x800000a8 },
1025 { 0x8144, 0x00000000 },
1026 { AR5K_PHY_AGC, 0x00000000 },
1027 { AR5K_PHY_ADC_CTL, 0x0000a000 },
1028 { 0x983c, 0x00200400 },
1029 { AR5K_PHY_GAIN_OFFSET, 0x1284233c },
1030 { AR5K_PHY_SCR, 0x0000001f },
1031 { AR5K_PHY_SLMT, 0x00000080 },
1032 { AR5K_PHY_SCAL, 0x0000000e },
1033 { 0x9958, 0x000000ff },
1034 { AR5K_PHY_TIMING_7, 0x00000000 },
1035 { AR5K_PHY_TIMING_8, 0x02800000 },
1036 { AR5K_PHY_TIMING_11, 0x00000000 },
1037 { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 },
1038 { 0x99e4, 0xaaaaaaaa },
1039 { 0x99e8, 0x3c466478 },
1040 { 0x99ec, 0x000000aa },
1041 { AR5K_PHY_SCLOCK, 0x0000000c },
1042 { AR5K_PHY_SDELAY, 0x000000ff },
1043 { AR5K_PHY_SPENDING, 0x00000014 },
1044 { AR5K_PHY_DAG_CCK_CTL, 0x000009b5 },
1045 { 0xa23c, 0x93c889af },
1046 { AR5K_PHY_FAST_ADC, 0x00000001 },
1047 { 0xa250, 0x0000a000 },
1048 { AR5K_PHY_BLUETOOTH, 0x00000000 },
1049 { AR5K_PHY_TPC_RG1, 0x0cc75380 },
1050 { 0xa25c, 0x0f0f0f01 },
1051 { 0xa260, 0x5f690f01 },
1052 { 0xa264, 0x00418a11 },
1053 { 0xa268, 0x00000000 },
1054 { AR5K_PHY_TPC_RG5, 0x0c30c16a },
1055 { 0xa270, 0x00820820 },
1056 { 0xa274, 0x001b7caa },
1057 { 0xa278, 0x1ce739ce },
1058 { 0xa27c, 0x051701ce },
1059 { 0xa300, 0x18010000 },
1060 { 0xa304, 0x30032602 },
1061 { 0xa308, 0x48073e06 },
1062 { 0xa30c, 0x560b4c0a },
1063 { 0xa310, 0x641a600f },
1064 { 0xa314, 0x784f6e1b },
1065 { 0xa318, 0x868f7c5a },
1066 { 0xa31c, 0x8ecf865b },
1067 { 0xa320, 0x9d4f970f },
1068 { 0xa324, 0xa5cfa18f },
1069 { 0xa328, 0xb55faf1f },
1070 { 0xa32c, 0xbddfb99f },
1071 { 0xa330, 0xcd7fc73f },
1072 { 0xa334, 0xd5ffd1bf },
1073 { 0xa338, 0x00000000 },
1074 { 0xa33c, 0x00000000 },
1075 { 0xa340, 0x00000000 },
1076 { 0xa344, 0x00000000 },
1077 { 0xa348, 0x3fffffff },
1078 { 0xa34c, 0x3fffffff },
1079 { 0xa350, 0x3fffffff },
1080 { 0xa354, 0x0003ffff },
1081 { 0xa358, 0x79a8aa1f },
1082 { 0xa35c, 0x066c420f },
1083 { 0xa360, 0x0f282207 },
1084 { 0xa364, 0x17601685 },
1085 { 0xa368, 0x1f801104 },
1086 { 0xa36c, 0x37a00c03 },
1087 { 0xa370, 0x3fc40883 },
1088 { 0xa374, 0x57c00803 },
1089 { 0xa378, 0x5fd80682 },
1090 { 0xa37c, 0x7fe00482 },
1091 { 0xa380, 0x7f3c7bba },
1092 { 0xa384, 0xf3307ff0 },
1093};
1094
1095/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */
1096/* XXX: a mode ? */
1097static const struct ath5k_ini_mode rf2425_ini_mode_end[] = {
1098 { AR5K_TXCFG,
1099 /* a/XR aTurbo b g (DYN) gTurbo */
1100 { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
1101 { AR5K_USEC_5211,
1102 { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
1103 { AR5K_PHY_TURBO,
1104 { 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 } },
1105 { AR5K_PHY_RF_CTL3,
1106 { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
1107 { AR5K_PHY_RF_CTL4,
1108 { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
1109 { AR5K_PHY_PA_CTL,
1110 { 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b } },
1111 { AR5K_PHY_SETTLING,
1112 { 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 } },
1113 { AR5K_PHY_GAIN,
1114 { 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 } },
1115 { AR5K_PHY_DESIRED_SIZE,
1116 { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
1117 { AR5K_PHY_SIG,
1118 { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
1119 { AR5K_PHY_AGCCOARSE,
1120 { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
1121 { AR5K_PHY_WEAK_OFDM_LOW_THR,
1122 { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
1123 { AR5K_PHY_RX_DELAY,
1124 { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
1125 { AR5K_PHY_FRAME_CTL_5211,
1126 { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
1127 { AR5K_PHY_CCKTXCTL,
1128 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1129 { AR5K_PHY_CCK_CROSSCORR,
1130 { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
1131 { AR5K_PHY_GAIN_2GHZ,
1132 { 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 } },
1133 { AR5K_PHY_CCK_RX_CTL_4,
1134 { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
1135 { 0xa324,
1136 { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
1137 { 0xa328,
1138 { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
1139 { 0xa32c,
1140 { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
1141 { 0xa330,
1142 { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
1143 { 0xa334,
1144 { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
1145};
1146
1147static const struct ath5k_ini rf2425_ini_common_end[] = {
1148 { AR5K_DCU_FP, 0x000003e0 },
1149 { AR5K_SEQ_MASK, 0x0000000f },
1150 { 0x809c, 0x00000000 },
1151 { 0x80a0, 0x00000000 },
1152 { AR5K_MIC_QOS_CTL, 0x00000000 },
1153 { AR5K_MIC_QOS_SEL, 0x00000000 },
1154 { AR5K_MISC_MODE, 0x00000000 },
1155 { AR5K_OFDM_FIL_CNT, 0x00000000 },
1156 { AR5K_CCK_FIL_CNT, 0x00000000 },
1157 { AR5K_PHYERR_CNT1, 0x00000000 },
1158 { AR5K_PHYERR_CNT1_MASK, 0x00000000 },
1159 { AR5K_PHYERR_CNT2, 0x00000000 },
1160 { AR5K_PHYERR_CNT2_MASK, 0x00000000 },
1161 { AR5K_TSF_THRES, 0x00000000 },
1162 { 0x8140, 0x800003f9 },
1163 { 0x8144, 0x00000000 },
1164 { AR5K_PHY_AGC, 0x00000000 },
1165 { AR5K_PHY_ADC_CTL, 0x0000a000 },
1166 { 0x983c, 0x00200400 },
1167 { AR5K_PHY_GAIN_OFFSET, 0x1284233c },
1168 { AR5K_PHY_SCR, 0x0000001f },
1169 { AR5K_PHY_SLMT, 0x00000080 },
1170 { AR5K_PHY_SCAL, 0x0000000e },
1171 { 0x9958, 0x00081fff },
1172 { AR5K_PHY_TIMING_7, 0x00000000 },
1173 { AR5K_PHY_TIMING_8, 0x02800000 },
1174 { AR5K_PHY_TIMING_11, 0x00000000 },
1175 { 0x99dc, 0xfebadbe8 },
1176 { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 },
1177 { 0x99e4, 0xaaaaaaaa },
1178 { 0x99e8, 0x3c466478 },
1179 { 0x99ec, 0x000000aa },
1180 { AR5K_PHY_SCLOCK, 0x0000000c },
1181 { AR5K_PHY_SDELAY, 0x000000ff },
1182 { AR5K_PHY_SPENDING, 0x00000014 },
1183 { AR5K_PHY_DAG_CCK_CTL, 0x000009b5 },
1184 { AR5K_PHY_TXPOWER_RATE3, 0x20202020 },
1185 { AR5K_PHY_TXPOWER_RATE4, 0x20202020 },
1186 { 0xa23c, 0x93c889af },
1187 { AR5K_PHY_FAST_ADC, 0x00000001 },
1188 { 0xa250, 0x0000a000 },
1189 { AR5K_PHY_BLUETOOTH, 0x00000000 },
1190 { AR5K_PHY_TPC_RG1, 0x0cc75380 },
1191 { 0xa25c, 0x0f0f0f01 },
1192 { 0xa260, 0x5f690f01 },
1193 { 0xa264, 0x00418a11 },
1194 { 0xa268, 0x00000000 },
1195 { AR5K_PHY_TPC_RG5, 0x0c30c166 },
1196 { 0xa270, 0x00820820 },
1197 { 0xa274, 0x081a3caa },
1198 { 0xa278, 0x1ce739ce },
1199 { 0xa27c, 0x051701ce },
1200 { 0xa300, 0x16010000 },
1201 { 0xa304, 0x2c032402 },
1202 { 0xa308, 0x48433e42 },
1203 { 0xa30c, 0x5a0f500b },
1204 { 0xa310, 0x6c4b624a },
1205 { 0xa314, 0x7e8b748a },
1206 { 0xa318, 0x96cf8ccb },
1207 { 0xa31c, 0xa34f9d0f },
1208 { 0xa320, 0xa7cfa58f },
1209 { 0xa348, 0x3fffffff },
1210 { 0xa34c, 0x3fffffff },
1211 { 0xa350, 0x3fffffff },
1212 { 0xa354, 0x0003ffff },
1213 { 0xa358, 0x79a8aa1f },
1214 { 0xa35c, 0x066c420f },
1215 { 0xa360, 0x0f282207 },
1216 { 0xa364, 0x17601685 },
1217 { 0xa368, 0x1f801104 },
1218 { 0xa36c, 0x37a00c03 },
1219 { 0xa370, 0x3fc40883 },
1220 { 0xa374, 0x57c00803 },
1221 { 0xa378, 0x5fd80682 },
1222 { 0xa37c, 0x7fe00482 },
1223 { 0xa380, 0x7f3c7bba },
1224 { 0xa384, 0xf3307ff0 },
1225};
1226
1227/*
1228 * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with
1229 * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI)
1230 */
1231
1232/* RF5111 Initial BaseBand Gain settings */
1233static const struct ath5k_ini rf5111_ini_bbgain[] = {
1234 { AR5K_BB_GAIN(0), 0x00000000 },
1235 { AR5K_BB_GAIN(1), 0x00000020 },
1236 { AR5K_BB_GAIN(2), 0x00000010 },
1237 { AR5K_BB_GAIN(3), 0x00000030 },
1238 { AR5K_BB_GAIN(4), 0x00000008 },
1239 { AR5K_BB_GAIN(5), 0x00000028 },
1240 { AR5K_BB_GAIN(6), 0x00000004 },
1241 { AR5K_BB_GAIN(7), 0x00000024 },
1242 { AR5K_BB_GAIN(8), 0x00000014 },
1243 { AR5K_BB_GAIN(9), 0x00000034 },
1244 { AR5K_BB_GAIN(10), 0x0000000c },
1245 { AR5K_BB_GAIN(11), 0x0000002c },
1246 { AR5K_BB_GAIN(12), 0x00000002 },
1247 { AR5K_BB_GAIN(13), 0x00000022 },
1248 { AR5K_BB_GAIN(14), 0x00000012 },
1249 { AR5K_BB_GAIN(15), 0x00000032 },
1250 { AR5K_BB_GAIN(16), 0x0000000a },
1251 { AR5K_BB_GAIN(17), 0x0000002a },
1252 { AR5K_BB_GAIN(18), 0x00000006 },
1253 { AR5K_BB_GAIN(19), 0x00000026 },
1254 { AR5K_BB_GAIN(20), 0x00000016 },
1255 { AR5K_BB_GAIN(21), 0x00000036 },
1256 { AR5K_BB_GAIN(22), 0x0000000e },
1257 { AR5K_BB_GAIN(23), 0x0000002e },
1258 { AR5K_BB_GAIN(24), 0x00000001 },
1259 { AR5K_BB_GAIN(25), 0x00000021 },
1260 { AR5K_BB_GAIN(26), 0x00000011 },
1261 { AR5K_BB_GAIN(27), 0x00000031 },
1262 { AR5K_BB_GAIN(28), 0x00000009 },
1263 { AR5K_BB_GAIN(29), 0x00000029 },
1264 { AR5K_BB_GAIN(30), 0x00000005 },
1265 { AR5K_BB_GAIN(31), 0x00000025 },
1266 { AR5K_BB_GAIN(32), 0x00000015 },
1267 { AR5K_BB_GAIN(33), 0x00000035 },
1268 { AR5K_BB_GAIN(34), 0x0000000d },
1269 { AR5K_BB_GAIN(35), 0x0000002d },
1270 { AR5K_BB_GAIN(36), 0x00000003 },
1271 { AR5K_BB_GAIN(37), 0x00000023 },
1272 { AR5K_BB_GAIN(38), 0x00000013 },
1273 { AR5K_BB_GAIN(39), 0x00000033 },
1274 { AR5K_BB_GAIN(40), 0x0000000b },
1275 { AR5K_BB_GAIN(41), 0x0000002b },
1276 { AR5K_BB_GAIN(42), 0x0000002b },
1277 { AR5K_BB_GAIN(43), 0x0000002b },
1278 { AR5K_BB_GAIN(44), 0x0000002b },
1279 { AR5K_BB_GAIN(45), 0x0000002b },
1280 { AR5K_BB_GAIN(46), 0x0000002b },
1281 { AR5K_BB_GAIN(47), 0x0000002b },
1282 { AR5K_BB_GAIN(48), 0x0000002b },
1283 { AR5K_BB_GAIN(49), 0x0000002b },
1284 { AR5K_BB_GAIN(50), 0x0000002b },
1285 { AR5K_BB_GAIN(51), 0x0000002b },
1286 { AR5K_BB_GAIN(52), 0x0000002b },
1287 { AR5K_BB_GAIN(53), 0x0000002b },
1288 { AR5K_BB_GAIN(54), 0x0000002b },
1289 { AR5K_BB_GAIN(55), 0x0000002b },
1290 { AR5K_BB_GAIN(56), 0x0000002b },
1291 { AR5K_BB_GAIN(57), 0x0000002b },
1292 { AR5K_BB_GAIN(58), 0x0000002b },
1293 { AR5K_BB_GAIN(59), 0x0000002b },
1294 { AR5K_BB_GAIN(60), 0x0000002b },
1295 { AR5K_BB_GAIN(61), 0x0000002b },
1296 { AR5K_BB_GAIN(62), 0x00000002 },
1297 { AR5K_BB_GAIN(63), 0x00000016 },
1298};
1299
1300/* RF5112 Initial BaseBand Gain settings (Same for RF5413/5414+) */
1301static const struct ath5k_ini rf5112_ini_bbgain[] = {
1302 { AR5K_BB_GAIN(0), 0x00000000 },
1303 { AR5K_BB_GAIN(1), 0x00000001 },
1304 { AR5K_BB_GAIN(2), 0x00000002 },
1305 { AR5K_BB_GAIN(3), 0x00000003 },
1306 { AR5K_BB_GAIN(4), 0x00000004 },
1307 { AR5K_BB_GAIN(5), 0x00000005 },
1308 { AR5K_BB_GAIN(6), 0x00000008 },
1309 { AR5K_BB_GAIN(7), 0x00000009 },
1310 { AR5K_BB_GAIN(8), 0x0000000a },
1311 { AR5K_BB_GAIN(9), 0x0000000b },
1312 { AR5K_BB_GAIN(10), 0x0000000c },
1313 { AR5K_BB_GAIN(11), 0x0000000d },
1314 { AR5K_BB_GAIN(12), 0x00000010 },
1315 { AR5K_BB_GAIN(13), 0x00000011 },
1316 { AR5K_BB_GAIN(14), 0x00000012 },
1317 { AR5K_BB_GAIN(15), 0x00000013 },
1318 { AR5K_BB_GAIN(16), 0x00000014 },
1319 { AR5K_BB_GAIN(17), 0x00000015 },
1320 { AR5K_BB_GAIN(18), 0x00000018 },
1321 { AR5K_BB_GAIN(19), 0x00000019 },
1322 { AR5K_BB_GAIN(20), 0x0000001a },
1323 { AR5K_BB_GAIN(21), 0x0000001b },
1324 { AR5K_BB_GAIN(22), 0x0000001c },
1325 { AR5K_BB_GAIN(23), 0x0000001d },
1326 { AR5K_BB_GAIN(24), 0x00000020 },
1327 { AR5K_BB_GAIN(25), 0x00000021 },
1328 { AR5K_BB_GAIN(26), 0x00000022 },
1329 { AR5K_BB_GAIN(27), 0x00000023 },
1330 { AR5K_BB_GAIN(28), 0x00000024 },
1331 { AR5K_BB_GAIN(29), 0x00000025 },
1332 { AR5K_BB_GAIN(30), 0x00000028 },
1333 { AR5K_BB_GAIN(31), 0x00000029 },
1334 { AR5K_BB_GAIN(32), 0x0000002a },
1335 { AR5K_BB_GAIN(33), 0x0000002b },
1336 { AR5K_BB_GAIN(34), 0x0000002c },
1337 { AR5K_BB_GAIN(35), 0x0000002d },
1338 { AR5K_BB_GAIN(36), 0x00000030 },
1339 { AR5K_BB_GAIN(37), 0x00000031 },
1340 { AR5K_BB_GAIN(38), 0x00000032 },
1341 { AR5K_BB_GAIN(39), 0x00000033 },
1342 { AR5K_BB_GAIN(40), 0x00000034 },
1343 { AR5K_BB_GAIN(41), 0x00000035 },
1344 { AR5K_BB_GAIN(42), 0x00000035 },
1345 { AR5K_BB_GAIN(43), 0x00000035 },
1346 { AR5K_BB_GAIN(44), 0x00000035 },
1347 { AR5K_BB_GAIN(45), 0x00000035 },
1348 { AR5K_BB_GAIN(46), 0x00000035 },
1349 { AR5K_BB_GAIN(47), 0x00000035 },
1350 { AR5K_BB_GAIN(48), 0x00000035 },
1351 { AR5K_BB_GAIN(49), 0x00000035 },
1352 { AR5K_BB_GAIN(50), 0x00000035 },
1353 { AR5K_BB_GAIN(51), 0x00000035 },
1354 { AR5K_BB_GAIN(52), 0x00000035 },
1355 { AR5K_BB_GAIN(53), 0x00000035 },
1356 { AR5K_BB_GAIN(54), 0x00000035 },
1357 { AR5K_BB_GAIN(55), 0x00000035 },
1358 { AR5K_BB_GAIN(56), 0x00000035 },
1359 { AR5K_BB_GAIN(57), 0x00000035 },
1360 { AR5K_BB_GAIN(58), 0x00000035 },
1361 { AR5K_BB_GAIN(59), 0x00000035 },
1362 { AR5K_BB_GAIN(60), 0x00000035 },
1363 { AR5K_BB_GAIN(61), 0x00000035 },
1364 { AR5K_BB_GAIN(62), 0x00000010 },
1365 { AR5K_BB_GAIN(63), 0x0000001a },
1366};
1367
1368
1369/*
1370 * Write initial register dump
1371 */
1372static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size,
1373 const struct ath5k_ini *ini_regs, bool change_channel)
1374{
1375 unsigned int i;
1376
1377 /* Write initial registers */
1378 for (i = 0; i < size; i++) {
1379 /* On channel change there is
1380 * no need to mess with PCU */
1381 if (change_channel &&
1382 ini_regs[i].ini_register >= AR5K_PCU_MIN &&
1383 ini_regs[i].ini_register <= AR5K_PCU_MAX)
1384 continue;
1385
1386 switch (ini_regs[i].ini_mode) {
1387 case AR5K_INI_READ:
1388 /* Cleared on read */
1389 ath5k_hw_reg_read(ah, ini_regs[i].ini_register);
1390 break;
1391 case AR5K_INI_WRITE:
1392 default:
1393 AR5K_REG_WAIT(i);
1394 ath5k_hw_reg_write(ah, ini_regs[i].ini_value,
1395 ini_regs[i].ini_register);
1396 }
1397 }
1398}
1399
1400static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah,
1401 unsigned int size, const struct ath5k_ini_mode *ini_mode,
1402 u8 mode)
1403{
1404 unsigned int i;
1405
1406 for (i = 0; i < size; i++) {
1407 AR5K_REG_WAIT(i);
1408 ath5k_hw_reg_write(ah, ini_mode[i].mode_value[mode],
1409 (u32)ini_mode[i].mode_register);
1410 }
1411
1412}
1413
1414int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
1415{
1416 /*
1417 * Write initial register settings
1418 */
1419
1420 /* For AR5212 and combatible */
1421 if (ah->ah_version == AR5K_AR5212) {
1422
1423 /* First set of mode-specific settings */
1424 ath5k_hw_ini_mode_registers(ah,
1425 ARRAY_SIZE(ar5212_ini_mode_start),
1426 ar5212_ini_mode_start, mode);
1427
1428 /*
1429 * Write initial settings common for all modes
1430 */
1431 ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini_common_start),
1432 ar5212_ini_common_start, change_channel);
1433
1434 /* Second set of mode-specific settings */
1435 switch (ah->ah_radio) {
1436 case AR5K_RF5111:
1437
1438 ath5k_hw_ini_mode_registers(ah,
1439 ARRAY_SIZE(rf5111_ini_mode_end),
1440 rf5111_ini_mode_end, mode);
1441
1442 ath5k_hw_ini_registers(ah,
1443 ARRAY_SIZE(rf5111_ini_common_end),
1444 rf5111_ini_common_end, change_channel);
1445
1446 /* Baseband gain table */
1447 ath5k_hw_ini_registers(ah,
1448 ARRAY_SIZE(rf5111_ini_bbgain),
1449 rf5111_ini_bbgain, change_channel);
1450
1451 break;
1452 case AR5K_RF5112:
1453
1454 ath5k_hw_ini_mode_registers(ah,
1455 ARRAY_SIZE(rf5112_ini_mode_end),
1456 rf5112_ini_mode_end, mode);
1457
1458 ath5k_hw_ini_registers(ah,
1459 ARRAY_SIZE(rf5112_ini_common_end),
1460 rf5112_ini_common_end, change_channel);
1461
1462 ath5k_hw_ini_registers(ah,
1463 ARRAY_SIZE(rf5112_ini_bbgain),
1464 rf5112_ini_bbgain, change_channel);
1465
1466 break;
1467 case AR5K_RF5413:
1468
1469 ath5k_hw_ini_mode_registers(ah,
1470 ARRAY_SIZE(rf5413_ini_mode_end),
1471 rf5413_ini_mode_end, mode);
1472
1473 ath5k_hw_ini_registers(ah,
1474 ARRAY_SIZE(rf5413_ini_common_end),
1475 rf5413_ini_common_end, change_channel);
1476
1477 ath5k_hw_ini_registers(ah,
1478 ARRAY_SIZE(rf5112_ini_bbgain),
1479 rf5112_ini_bbgain, change_channel);
1480
1481 break;
1482 case AR5K_RF2316:
1483 case AR5K_RF2413:
1484
1485 ath5k_hw_ini_mode_registers(ah,
1486 ARRAY_SIZE(rf2413_ini_mode_end),
1487 rf2413_ini_mode_end, mode);
1488
1489 ath5k_hw_ini_registers(ah,
1490 ARRAY_SIZE(rf2413_ini_common_end),
1491 rf2413_ini_common_end, change_channel);
1492
1493 /* Override settings from rf2413_ini_common_end */
1494 if (ah->ah_radio == AR5K_RF2316) {
1495 ath5k_hw_reg_write(ah, 0x00004000,
1496 AR5K_PHY_AGC);
1497 ath5k_hw_reg_write(ah, 0x081b7caa,
1498 0xa274);
1499 }
1500
1501 ath5k_hw_ini_registers(ah,
1502 ARRAY_SIZE(rf5112_ini_bbgain),
1503 rf5112_ini_bbgain, change_channel);
1504 break;
1505 case AR5K_RF2317:
1506 case AR5K_RF2425:
1507
1508 ath5k_hw_ini_mode_registers(ah,
1509 ARRAY_SIZE(rf2425_ini_mode_end),
1510 rf2425_ini_mode_end, mode);
1511
1512 ath5k_hw_ini_registers(ah,
1513 ARRAY_SIZE(rf2425_ini_common_end),
1514 rf2425_ini_common_end, change_channel);
1515
1516 ath5k_hw_ini_registers(ah,
1517 ARRAY_SIZE(rf5112_ini_bbgain),
1518 rf5112_ini_bbgain, change_channel);
1519 break;
1520 default:
1521 return -EINVAL;
1522
1523 }
1524
1525 /* For AR5211 */
1526 } else if (ah->ah_version == AR5K_AR5211) {
1527
1528 /* AR5K_MODE_11B */
1529 if (mode > 2) {
1530 ATH5K_ERR(ah->ah_sc,
1531 "unsupported channel mode: %d\n", mode);
1532 return -EINVAL;
1533 }
1534
1535 /* Mode-specific settings */
1536 ath5k_hw_ini_mode_registers(ah, ARRAY_SIZE(ar5211_ini_mode),
1537 ar5211_ini_mode, mode);
1538
1539 /*
1540 * Write initial settings common for all modes
1541 */
1542 ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini),
1543 ar5211_ini, change_channel);
1544
1545 /* AR5211 only comes with 5111 */
1546
1547 /* Baseband gain table */
1548 ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain),
1549 rf5111_ini_bbgain, change_channel);
1550 /* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */
1551 } else if (ah->ah_version == AR5K_AR5210) {
1552 ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini),
1553 ar5210_ini, change_channel);
1554 }
1555
1556 return 0;
1557}
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
new file mode 100644
index 000000000000..19555fb79c9b
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -0,0 +1,176 @@
1/*
2 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
3 * Copyright (c) 2004-2005 Atheros Communications, Inc.
4 * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
5 * Copyright (c) 2009 Bob Copeland <me@bobcopeland.com>
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer,
14 * without modification.
15 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
16 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
17 * redistribution must be conditioned upon including a substantially
18 * similar Disclaimer requirement for further binary redistribution.
19 * 3. Neither the names of the above-listed copyright holders nor the names
20 * of any contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * Alternatively, this software may be distributed under the terms of the
24 * GNU General Public License ("GPL") version 2 as published by the Free
25 * Software Foundation.
26 *
27 * NO WARRANTY
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
31 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
33 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
36 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
38 * THE POSSIBILITY OF SUCH DAMAGES.
39 *
40 */
41
42#include <linux/pci.h>
43#include "ath5k.h"
44#include "base.h"
45
46#define ATH_SDEVICE(subv,subd) \
47 .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
48 .subvendor = (subv), .subdevice = (subd)
49
50#define ATH_LED(pin,polarity) .driver_data = (((pin) << 8) | (polarity))
51#define ATH_PIN(data) ((data) >> 8)
52#define ATH_POLARITY(data) ((data) & 0xff)
53
54/* Devices we match on for LED config info (typically laptops) */
55static const struct pci_device_id ath5k_led_devices[] = {
56 /* IBM-specific AR5212 */
57 { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) },
58 /* AR5211 */
59 { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) },
60 /* HP Compaq nc6xx, nc4000, nx6000 */
61 { ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) },
62 /* Acer Aspire One A150 (maximlevitsky@gmail.com) */
63 { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) },
64 /* Acer Ferrari 5000 (russ.dill@gmail.com) */
65 { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) },
66 /* E-machines E510 (tuliom@gmail.com) */
67 { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) },
68 /* Acer Extensa 5620z (nekoreeve@gmail.com) */
69 { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) },
70 { }
71};
72
73void ath5k_led_enable(struct ath5k_softc *sc)
74{
75 if (test_bit(ATH_STAT_LEDSOFT, sc->status)) {
76 ath5k_hw_set_gpio_output(sc->ah, sc->led_pin);
77 ath5k_led_off(sc);
78 }
79}
80
81void ath5k_led_on(struct ath5k_softc *sc)
82{
83 if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
84 return;
85 ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on);
86}
87
88void ath5k_led_off(struct ath5k_softc *sc)
89{
90 if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
91 return;
92 ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on);
93}
94
95static void
96ath5k_led_brightness_set(struct led_classdev *led_dev,
97 enum led_brightness brightness)
98{
99 struct ath5k_led *led = container_of(led_dev, struct ath5k_led,
100 led_dev);
101
102 if (brightness == LED_OFF)
103 ath5k_led_off(led->sc);
104 else
105 ath5k_led_on(led->sc);
106}
107
108static int
109ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led,
110 const char *name, char *trigger)
111{
112 int err;
113
114 led->sc = sc;
115 strncpy(led->name, name, sizeof(led->name));
116 led->led_dev.name = led->name;
117 led->led_dev.default_trigger = trigger;
118 led->led_dev.brightness_set = ath5k_led_brightness_set;
119
120 err = led_classdev_register(&sc->pdev->dev, &led->led_dev);
121 if (err) {
122 ATH5K_WARN(sc, "could not register LED %s\n", name);
123 led->sc = NULL;
124 }
125 return err;
126}
127
128static void
129ath5k_unregister_led(struct ath5k_led *led)
130{
131 if (!led->sc)
132 return;
133 led_classdev_unregister(&led->led_dev);
134 ath5k_led_off(led->sc);
135 led->sc = NULL;
136}
137
138void ath5k_unregister_leds(struct ath5k_softc *sc)
139{
140 ath5k_unregister_led(&sc->rx_led);
141 ath5k_unregister_led(&sc->tx_led);
142}
143
144int ath5k_init_leds(struct ath5k_softc *sc)
145{
146 int ret = 0;
147 struct ieee80211_hw *hw = sc->hw;
148 struct pci_dev *pdev = sc->pdev;
149 char name[ATH5K_LED_MAX_NAME_LEN + 1];
150 const struct pci_device_id *match;
151
152 match = pci_match_id(&ath5k_led_devices[0], pdev);
153 if (match) {
154 __set_bit(ATH_STAT_LEDSOFT, sc->status);
155 sc->led_pin = ATH_PIN(match->driver_data);
156 sc->led_on = ATH_POLARITY(match->driver_data);
157 }
158
159 if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
160 goto out;
161
162 ath5k_led_enable(sc);
163
164 snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy));
165 ret = ath5k_register_led(sc, &sc->rx_led, name,
166 ieee80211_get_rx_led_name(hw));
167 if (ret)
168 goto out;
169
170 snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy));
171 ret = ath5k_register_led(sc, &sc->tx_led, name,
172 ieee80211_get_tx_led_name(hw));
173out:
174 return ret;
175}
176
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
new file mode 100644
index 000000000000..55122f1e1986
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -0,0 +1,1174 @@
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4 * Copyright (c) 2007-2008 Matthew W. S. Bell <mentor@madwifi.org>
5 * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
6 * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
7 * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *
21 */
22
23/*********************************\
24* Protocol Control Unit Functions *
25\*********************************/
26
27#include "ath5k.h"
28#include "reg.h"
29#include "debug.h"
30#include "base.h"
31
32/*******************\
33* Generic functions *
34\*******************/
35
36/**
37 * ath5k_hw_set_opmode - Set PCU operating mode
38 *
39 * @ah: The &struct ath5k_hw
40 *
41 * Initialize PCU for the various operating modes (AP/STA etc)
42 *
43 * NOTE: ah->ah_op_mode must be set before calling this.
44 */
45int ath5k_hw_set_opmode(struct ath5k_hw *ah)
46{
47 u32 pcu_reg, beacon_reg, low_id, high_id;
48
49
50 /* Preserve rest settings */
51 pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
52 pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
53 | AR5K_STA_ID1_KEYSRCH_MODE
54 | (ah->ah_version == AR5K_AR5210 ?
55 (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
56
57 beacon_reg = 0;
58
59 ATH5K_TRACE(ah->ah_sc);
60
61 switch (ah->ah_op_mode) {
62 case NL80211_IFTYPE_ADHOC:
63 pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
64 beacon_reg |= AR5K_BCR_ADHOC;
65 if (ah->ah_version == AR5K_AR5210)
66 pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
67 else
68 AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
69 break;
70
71 case NL80211_IFTYPE_AP:
72 case NL80211_IFTYPE_MESH_POINT:
73 pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE;
74 beacon_reg |= AR5K_BCR_AP;
75 if (ah->ah_version == AR5K_AR5210)
76 pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
77 else
78 AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
79 break;
80
81 case NL80211_IFTYPE_STATION:
82 pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
83 | (ah->ah_version == AR5K_AR5210 ?
84 AR5K_STA_ID1_PWR_SV : 0);
85 case NL80211_IFTYPE_MONITOR:
86 pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
87 | (ah->ah_version == AR5K_AR5210 ?
88 AR5K_STA_ID1_NO_PSPOLL : 0);
89 break;
90
91 default:
92 return -EINVAL;
93 }
94
95 /*
96 * Set PCU registers
97 */
98 low_id = AR5K_LOW_ID(ah->ah_sta_id);
99 high_id = AR5K_HIGH_ID(ah->ah_sta_id);
100 ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
101 ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
102
103 /*
104 * Set Beacon Control Register on 5210
105 */
106 if (ah->ah_version == AR5K_AR5210)
107 ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
108
109 return 0;
110}
111
112/**
113 * ath5k_hw_update - Update mib counters (mac layer statistics)
114 *
115 * @ah: The &struct ath5k_hw
116 * @stats: The &struct ieee80211_low_level_stats we use to track
117 * statistics on the driver
118 *
119 * Reads MIB counters from PCU and updates sw statistics. Must be
120 * called after a MIB interrupt.
121 */
122void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
123 struct ieee80211_low_level_stats *stats)
124{
125 ATH5K_TRACE(ah->ah_sc);
126
127 /* Read-And-Clear */
128 stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
129 stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
130 stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
131 stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
132
133 /* XXX: Should we use this to track beacon count ?
134 * -we read it anyway to clear the register */
135 ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
136
137 /* Reset profile count registers on 5212*/
138 if (ah->ah_version == AR5K_AR5212) {
139 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
140 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
141 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
142 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
143 }
144
145 /* TODO: Handle ANI stats */
146}
147
148/**
149 * ath5k_hw_set_ack_bitrate - set bitrate for ACKs
150 *
151 * @ah: The &struct ath5k_hw
152 * @high: Flag to determine if we want to use high transmition rate
153 * for ACKs or not
154 *
155 * If high flag is set, we tell hw to use a set of control rates based on
156 * the current transmition rate (check out control_rates array inside reset.c).
157 * If not hw just uses the lowest rate available for the current modulation
158 * scheme being used (1Mbit for CCK and 6Mbits for OFDM).
159 */
160void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
161{
162 if (ah->ah_version != AR5K_AR5212)
163 return;
164 else {
165 u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
166 if (high)
167 AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
168 else
169 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
170 }
171}
172
173
174/******************\
175* ACK/CTS Timeouts *
176\******************/
177
178/**
179 * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec
180 *
181 * @ah: The &struct ath5k_hw
182 */
183unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
184{
185 ATH5K_TRACE(ah->ah_sc);
186
187 return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
188 AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
189}
190
191/**
192 * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
193 *
194 * @ah: The &struct ath5k_hw
195 * @timeout: Timeout in usec
196 */
197int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
198{
199 ATH5K_TRACE(ah->ah_sc);
200 if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
201 ah->ah_turbo) <= timeout)
202 return -EINVAL;
203
204 AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
205 ath5k_hw_htoclock(timeout, ah->ah_turbo));
206
207 return 0;
208}
209
210/**
211 * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec
212 *
213 * @ah: The &struct ath5k_hw
214 */
215unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
216{
217 ATH5K_TRACE(ah->ah_sc);
218 return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
219 AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
220}
221
222/**
223 * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU
224 *
225 * @ah: The &struct ath5k_hw
226 * @timeout: Timeout in usec
227 */
228int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
229{
230 ATH5K_TRACE(ah->ah_sc);
231 if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
232 ah->ah_turbo) <= timeout)
233 return -EINVAL;
234
235 AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
236 ath5k_hw_htoclock(timeout, ah->ah_turbo));
237
238 return 0;
239}
240
241
242/****************\
243* BSSID handling *
244\****************/
245
246/**
247 * ath5k_hw_get_lladdr - Get station id
248 *
249 * @ah: The &struct ath5k_hw
250 * @mac: The card's mac address
251 *
252 * Initialize ah->ah_sta_id using the mac address provided
253 * (just a memcpy).
254 *
255 * TODO: Remove it once we merge ath5k_softc and ath5k_hw
256 */
257void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
258{
259 ATH5K_TRACE(ah->ah_sc);
260 memcpy(mac, ah->ah_sta_id, ETH_ALEN);
261}
262
263/**
264 * ath5k_hw_set_lladdr - Set station id
265 *
266 * @ah: The &struct ath5k_hw
267 * @mac: The card's mac address
268 *
269 * Set station id on hw using the provided mac address
270 */
271int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
272{
273 u32 low_id, high_id;
274 u32 pcu_reg;
275
276 ATH5K_TRACE(ah->ah_sc);
277 /* Set new station ID */
278 memcpy(ah->ah_sta_id, mac, ETH_ALEN);
279
280 pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
281
282 low_id = AR5K_LOW_ID(mac);
283 high_id = AR5K_HIGH_ID(mac);
284
285 ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
286 ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
287
288 return 0;
289}
290
291/**
292 * ath5k_hw_set_associd - Set BSSID for association
293 *
294 * @ah: The &struct ath5k_hw
295 * @bssid: BSSID
296 * @assoc_id: Assoc id
297 *
298 * Sets the BSSID which trigers the "SME Join" operation
299 */
300void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
301{
302 u32 low_id, high_id;
303 u16 tim_offset = 0;
304
305 /*
306 * Set simple BSSID mask on 5212
307 */
308 if (ah->ah_version == AR5K_AR5212) {
309 ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask),
310 AR5K_BSS_IDM0);
311 ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask),
312 AR5K_BSS_IDM1);
313 }
314
315 /*
316 * Set BSSID which triggers the "SME Join" operation
317 */
318 low_id = AR5K_LOW_ID(bssid);
319 high_id = AR5K_HIGH_ID(bssid);
320 ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
321 ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
322 AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
323
324 if (assoc_id == 0) {
325 ath5k_hw_disable_pspoll(ah);
326 return;
327 }
328
329 AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM,
330 tim_offset ? tim_offset + 4 : 0);
331
332 ath5k_hw_enable_pspoll(ah, NULL, 0);
333}
334
335/**
336 * ath5k_hw_set_bssid_mask - filter out bssids we listen
337 *
338 * @ah: the &struct ath5k_hw
339 * @mask: the bssid_mask, a u8 array of size ETH_ALEN
340 *
341 * BSSID masking is a method used by AR5212 and newer hardware to inform PCU
342 * which bits of the interface's MAC address should be looked at when trying
343 * to decide which packets to ACK. In station mode and AP mode with a single
344 * BSS every bit matters since we lock to only one BSS. In AP mode with
345 * multiple BSSes (virtual interfaces) not every bit matters because hw must
346 * accept frames for all BSSes and so we tweak some bits of our mac address
347 * in order to have multiple BSSes.
348 *
349 * NOTE: This is a simple filter and does *not* filter out all
350 * relevant frames. Some frames that are not for us might get ACKed from us
351 * by PCU because they just match the mask.
352 *
353 * When handling multiple BSSes you can get the BSSID mask by computing the
354 * set of ~ ( MAC XOR BSSID ) for all bssids we handle.
355 *
356 * When you do this you are essentially computing the common bits of all your
357 * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with
358 * the MAC address to obtain the relevant bits and compare the result with
359 * (frame's BSSID & mask) to see if they match.
360 */
361/*
362 * Simple example: on your card you have have two BSSes you have created with
363 * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
364 * There is another BSSID-03 but you are not part of it. For simplicity's sake,
365 * assuming only 4 bits for a mac address and for BSSIDs you can then have:
366 *
367 * \
368 * MAC: 0001 |
369 * BSSID-01: 0100 | --> Belongs to us
370 * BSSID-02: 1001 |
371 * /
372 * -------------------
373 * BSSID-03: 0110 | --> External
374 * -------------------
375 *
376 * Our bssid_mask would then be:
377 *
378 * On loop iteration for BSSID-01:
379 * ~(0001 ^ 0100) -> ~(0101)
380 * -> 1010
381 * bssid_mask = 1010
382 *
383 * On loop iteration for BSSID-02:
384 * bssid_mask &= ~(0001 ^ 1001)
385 * bssid_mask = (1010) & ~(0001 ^ 1001)
386 * bssid_mask = (1010) & ~(1001)
387 * bssid_mask = (1010) & (0110)
388 * bssid_mask = 0010
389 *
390 * A bssid_mask of 0010 means "only pay attention to the second least
391 * significant bit". This is because its the only bit common
392 * amongst the MAC and all BSSIDs we support. To findout what the real
393 * common bit is we can simply "&" the bssid_mask now with any BSSID we have
394 * or our MAC address (we assume the hardware uses the MAC address).
395 *
396 * Now, suppose there's an incoming frame for BSSID-03:
397 *
398 * IFRAME-01: 0110
399 *
400 * An easy eye-inspeciton of this already should tell you that this frame
401 * will not pass our check. This is beacuse the bssid_mask tells the
402 * hardware to only look at the second least significant bit and the
403 * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
404 * as 1, which does not match 0.
405 *
406 * So with IFRAME-01 we *assume* the hardware will do:
407 *
408 * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
409 * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
410 * --> allow = (0010) == 0000 ? 1 : 0;
411 * --> allow = 0
412 *
413 * Lets now test a frame that should work:
414 *
415 * IFRAME-02: 0001 (we should allow)
416 *
417 * allow = (0001 & 1010) == 1010
418 *
419 * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
420 * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0;
421 * --> allow = (0010) == (0010)
422 * --> allow = 1
423 *
424 * Other examples:
425 *
426 * IFRAME-03: 0100 --> allowed
427 * IFRAME-04: 1001 --> allowed
428 * IFRAME-05: 1101 --> allowed but its not for us!!!
429 *
430 */
431int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
432{
433 u32 low_id, high_id;
434 ATH5K_TRACE(ah->ah_sc);
435
436 /* Cache bssid mask so that we can restore it
437 * on reset */
438 memcpy(ah->ah_bssid_mask, mask, ETH_ALEN);
439 if (ah->ah_version == AR5K_AR5212) {
440 low_id = AR5K_LOW_ID(mask);
441 high_id = AR5K_HIGH_ID(mask);
442
443 ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
444 ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
445
446 return 0;
447 }
448
449 return -EIO;
450}
451
452
453/************\
454* RX Control *
455\************/
456
457/**
458 * ath5k_hw_start_rx_pcu - Start RX engine
459 *
460 * @ah: The &struct ath5k_hw
461 *
462 * Starts RX engine on PCU so that hw can process RXed frames
463 * (ACK etc).
464 *
465 * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
466 * TODO: Init ANI here
467 */
468void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
469{
470 ATH5K_TRACE(ah->ah_sc);
471 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
472}
473
474/**
475 * at5k_hw_stop_rx_pcu - Stop RX engine
476 *
477 * @ah: The &struct ath5k_hw
478 *
479 * Stops RX engine on PCU
480 *
481 * TODO: Detach ANI here
482 */
483void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
484{
485 ATH5K_TRACE(ah->ah_sc);
486 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
487}
488
489/*
490 * Set multicast filter
491 */
492void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
493{
494 ATH5K_TRACE(ah->ah_sc);
495 /* Set the multicat filter */
496 ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
497 ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
498}
499
500/*
501 * Set multicast filter by index
502 */
503int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
504{
505
506 ATH5K_TRACE(ah->ah_sc);
507 if (index >= 64)
508 return -EINVAL;
509 else if (index >= 32)
510 AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1,
511 (1 << (index - 32)));
512 else
513 AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
514
515 return 0;
516}
517
518/*
519 * Clear Multicast filter by index
520 */
521int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
522{
523
524 ATH5K_TRACE(ah->ah_sc);
525 if (index >= 64)
526 return -EINVAL;
527 else if (index >= 32)
528 AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1,
529 (1 << (index - 32)));
530 else
531 AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
532
533 return 0;
534}
535
536/**
537 * ath5k_hw_get_rx_filter - Get current rx filter
538 *
539 * @ah: The &struct ath5k_hw
540 *
541 * Returns the RX filter by reading rx filter and
542 * phy error filter registers. RX filter is used
543 * to set the allowed frame types that PCU will accept
544 * and pass to the driver. For a list of frame types
545 * check out reg.h.
546 */
547u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
548{
549 u32 data, filter = 0;
550
551 ATH5K_TRACE(ah->ah_sc);
552 filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
553
554 /*Radar detection for 5212*/
555 if (ah->ah_version == AR5K_AR5212) {
556 data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL);
557
558 if (data & AR5K_PHY_ERR_FIL_RADAR)
559 filter |= AR5K_RX_FILTER_RADARERR;
560 if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK))
561 filter |= AR5K_RX_FILTER_PHYERR;
562 }
563
564 return filter;
565}
566
567/**
568 * ath5k_hw_set_rx_filter - Set rx filter
569 *
570 * @ah: The &struct ath5k_hw
571 * @filter: RX filter mask (see reg.h)
572 *
573 * Sets RX filter register and also handles PHY error filter
574 * register on 5212 and newer chips so that we have proper PHY
575 * error reporting.
576 */
577void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
578{
579 u32 data = 0;
580
581 ATH5K_TRACE(ah->ah_sc);
582
583 /* Set PHY error filter register on 5212*/
584 if (ah->ah_version == AR5K_AR5212) {
585 if (filter & AR5K_RX_FILTER_RADARERR)
586 data |= AR5K_PHY_ERR_FIL_RADAR;
587 if (filter & AR5K_RX_FILTER_PHYERR)
588 data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK;
589 }
590
591 /*
592 * The AR5210 uses promiscous mode to detect radar activity
593 */
594 if (ah->ah_version == AR5K_AR5210 &&
595 (filter & AR5K_RX_FILTER_RADARERR)) {
596 filter &= ~AR5K_RX_FILTER_RADARERR;
597 filter |= AR5K_RX_FILTER_PROM;
598 }
599
600 /*Zero length DMA (phy error reporting) */
601 if (data)
602 AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
603 else
604 AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
605
606 /*Write RX Filter register*/
607 ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER);
608
609 /*Write PHY error filter register on 5212*/
610 if (ah->ah_version == AR5K_AR5212)
611 ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL);
612
613}
614
615
616/****************\
617* Beacon control *
618\****************/
619
620/**
621 * ath5k_hw_get_tsf32 - Get a 32bit TSF
622 *
623 * @ah: The &struct ath5k_hw
624 *
625 * Returns lower 32 bits of current TSF
626 */
627u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah)
628{
629 ATH5K_TRACE(ah->ah_sc);
630 return ath5k_hw_reg_read(ah, AR5K_TSF_L32);
631}
632
633/**
634 * ath5k_hw_get_tsf64 - Get the full 64bit TSF
635 *
636 * @ah: The &struct ath5k_hw
637 *
638 * Returns the current TSF
639 */
640u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
641{
642 u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
643 ATH5K_TRACE(ah->ah_sc);
644
645 return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32);
646}
647
648/**
649 * ath5k_hw_set_tsf64 - Set a new 64bit TSF
650 *
651 * @ah: The &struct ath5k_hw
652 * @tsf64: The new 64bit TSF
653 *
654 * Sets the new TSF
655 */
656void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64)
657{
658 ATH5K_TRACE(ah->ah_sc);
659
660 ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32);
661 ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32);
662}
663
664/**
665 * ath5k_hw_reset_tsf - Force a TSF reset
666 *
667 * @ah: The &struct ath5k_hw
668 *
669 * Forces a TSF reset on PCU
670 */
671void ath5k_hw_reset_tsf(struct ath5k_hw *ah)
672{
673 u32 val;
674
675 ATH5K_TRACE(ah->ah_sc);
676
677 val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF;
678
679 /*
680 * Each write to the RESET_TSF bit toggles a hardware internal
681 * signal to reset TSF, but if left high it will cause a TSF reset
682 * on the next chip reset as well. Thus we always write the value
683 * twice to clear the signal.
684 */
685 ath5k_hw_reg_write(ah, val, AR5K_BEACON);
686 ath5k_hw_reg_write(ah, val, AR5K_BEACON);
687}
688
689/*
690 * Initialize beacon timers
691 */
692void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
693{
694 u32 timer1, timer2, timer3;
695
696 ATH5K_TRACE(ah->ah_sc);
697 /*
698 * Set the additional timers by mode
699 */
700 switch (ah->ah_op_mode) {
701 case NL80211_IFTYPE_MONITOR:
702 case NL80211_IFTYPE_STATION:
703 /* In STA mode timer1 is used as next wakeup
704 * timer and timer2 as next CFP duration start
705 * timer. Both in 1/8TUs. */
706 /* TODO: PCF handling */
707 if (ah->ah_version == AR5K_AR5210) {
708 timer1 = 0xffffffff;
709 timer2 = 0xffffffff;
710 } else {
711 timer1 = 0x0000ffff;
712 timer2 = 0x0007ffff;
713 }
714 /* Mark associated AP as PCF incapable for now */
715 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PCF);
716 break;
717 case NL80211_IFTYPE_ADHOC:
718 AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM);
719 default:
720 /* On non-STA modes timer1 is used as next DMA
721 * beacon alert (DBA) timer and timer2 as next
722 * software beacon alert. Both in 1/8TUs. */
723 timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3;
724 timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3;
725 break;
726 }
727
728 /* Timer3 marks the end of our ATIM window
729 * a zero length window is not allowed because
730 * we 'll get no beacons */
731 timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1);
732
733 /*
734 * Set the beacon register and enable all timers.
735 */
736 /* When in AP mode zero timer0 to start TSF */
737 if (ah->ah_op_mode == NL80211_IFTYPE_AP)
738 ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
739 else
740 ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
741 ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1);
742 ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2);
743 ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3);
744
745 /* Force a TSF reset if requested and enable beacons */
746 if (interval & AR5K_BEACON_RESET_TSF)
747 ath5k_hw_reset_tsf(ah);
748
749 ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD |
750 AR5K_BEACON_ENABLE),
751 AR5K_BEACON);
752
753 /* Flush any pending BMISS interrupts on ISR by
754 * performing a clear-on-write operation on PISR
755 * register for the BMISS bit (writing a bit on
756 * ISR togles a reset for that bit and leaves
757 * the rest bits intact) */
758 if (ah->ah_version == AR5K_AR5210)
759 ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR);
760 else
761 ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR);
762
763 /* TODO: Set enchanced sleep registers on AR5212
764 * based on vif->bss_conf params, until then
765 * disable power save reporting.*/
766 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV);
767
768}
769
770#if 0
771/*
772 * Set beacon timers
773 */
774int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah,
775 const struct ath5k_beacon_state *state)
776{
777 u32 cfp_period, next_cfp, dtim, interval, next_beacon;
778
779 /*
780 * TODO: should be changed through *state
781 * review struct ath5k_beacon_state struct
782 *
783 * XXX: These are used for cfp period bellow, are they
784 * ok ? Is it O.K. for tsf here to be 0 or should we use
785 * get_tsf ?
786 */
787 u32 dtim_count = 0; /* XXX */
788 u32 cfp_count = 0; /* XXX */
789 u32 tsf = 0; /* XXX */
790
791 ATH5K_TRACE(ah->ah_sc);
792 /* Return on an invalid beacon state */
793 if (state->bs_interval < 1)
794 return -EINVAL;
795
796 interval = state->bs_interval;
797 dtim = state->bs_dtim_period;
798
799 /*
800 * PCF support?
801 */
802 if (state->bs_cfp_period > 0) {
803 /*
804 * Enable PCF mode and set the CFP
805 * (Contention Free Period) and timer registers
806 */
807 cfp_period = state->bs_cfp_period * state->bs_dtim_period *
808 state->bs_interval;
809 next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) *
810 state->bs_interval;
811
812 AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
813 AR5K_STA_ID1_DEFAULT_ANTENNA |
814 AR5K_STA_ID1_PCF);
815 ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD);
816 ath5k_hw_reg_write(ah, state->bs_cfp_max_duration,
817 AR5K_CFP_DUR);
818 ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period :
819 next_cfp)) << 3, AR5K_TIMER2);
820 } else {
821 /* Disable PCF mode */
822 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
823 AR5K_STA_ID1_DEFAULT_ANTENNA |
824 AR5K_STA_ID1_PCF);
825 }
826
827 /*
828 * Enable the beacon timer register
829 */
830 ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0);
831
832 /*
833 * Start the beacon timers
834 */
835 ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) &
836 ~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) |
837 AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0,
838 AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval,
839 AR5K_BEACON_PERIOD), AR5K_BEACON);
840
841 /*
842 * Write new beacon miss threshold, if it appears to be valid
843 * XXX: Figure out right values for min <= bs_bmiss_threshold <= max
844 * and return if its not in range. We can test this by reading value and
845 * setting value to a largest value and seeing which values register.
846 */
847
848 AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS,
849 state->bs_bmiss_threshold);
850
851 /*
852 * Set sleep control register
853 * XXX: Didn't find this in 5210 code but since this register
854 * exists also in ar5k's 5210 headers i leave it as common code.
855 */
856 AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR,
857 (state->bs_sleep_duration - 3) << 3);
858
859 /*
860 * Set enhanced sleep registers on 5212
861 */
862 if (ah->ah_version == AR5K_AR5212) {
863 if (state->bs_sleep_duration > state->bs_interval &&
864 roundup(state->bs_sleep_duration, interval) ==
865 state->bs_sleep_duration)
866 interval = state->bs_sleep_duration;
867
868 if (state->bs_sleep_duration > dtim && (dtim == 0 ||
869 roundup(state->bs_sleep_duration, dtim) ==
870 state->bs_sleep_duration))
871 dtim = state->bs_sleep_duration;
872
873 if (interval > dtim)
874 return -EINVAL;
875
876 next_beacon = interval == dtim ? state->bs_next_dtim :
877 state->bs_next_beacon;
878
879 ath5k_hw_reg_write(ah,
880 AR5K_REG_SM((state->bs_next_dtim - 3) << 3,
881 AR5K_SLEEP0_NEXT_DTIM) |
882 AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) |
883 AR5K_SLEEP0_ENH_SLEEP_EN |
884 AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0);
885
886 ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3,
887 AR5K_SLEEP1_NEXT_TIM) |
888 AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1);
889
890 ath5k_hw_reg_write(ah,
891 AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) |
892 AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2);
893 }
894
895 return 0;
896}
897
898/*
899 * Reset beacon timers
900 */
901void ath5k_hw_reset_beacon(struct ath5k_hw *ah)
902{
903 ATH5K_TRACE(ah->ah_sc);
904 /*
905 * Disable beacon timer
906 */
907 ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
908
909 /*
910 * Disable some beacon register values
911 */
912 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
913 AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF);
914 ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON);
915}
916
917/*
918 * Wait for beacon queue to finish
919 */
920int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr)
921{
922 unsigned int i;
923 int ret;
924
925 ATH5K_TRACE(ah->ah_sc);
926
927 /* 5210 doesn't have QCU*/
928 if (ah->ah_version == AR5K_AR5210) {
929 /*
930 * Wait for beaconn queue to finish by checking
931 * Control Register and Beacon Status Register.
932 */
933 for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) {
934 if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F)
935 ||
936 !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F))
937 break;
938 udelay(10);
939 }
940
941 /* Timeout... */
942 if (i <= 0) {
943 /*
944 * Re-schedule the beacon queue
945 */
946 ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1);
947 ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
948 AR5K_BCR);
949
950 return -EIO;
951 }
952 ret = 0;
953 } else {
954 /*5211/5212*/
955 ret = ath5k_hw_register_timeout(ah,
956 AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON),
957 AR5K_QCU_STS_FRMPENDCNT, 0, false);
958
959 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON))
960 return -EIO;
961 }
962
963 return ret;
964}
965#endif
966
967
968/*********************\
969* Key table functions *
970\*********************/
971
972/*
973 * Reset a key entry on the table
974 */
975int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
976{
977 unsigned int i, type;
978 u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
979
980 ATH5K_TRACE(ah->ah_sc);
981 AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
982
983 type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry));
984
985 for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
986 ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
987
988 /* Reset associated MIC entry if TKIP
989 * is enabled located at offset (entry + 64) */
990 if (type == AR5K_KEYTABLE_TYPE_TKIP) {
991 AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE);
992 for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++)
993 ath5k_hw_reg_write(ah, 0,
994 AR5K_KEYTABLE_OFF(micentry, i));
995 }
996
997 /*
998 * Set NULL encryption on AR5212+
999 *
1000 * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
1001 * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
1002 *
1003 * Note2: Windows driver (ndiswrapper) sets this to
1004 * 0x00000714 instead of 0x00000007
1005 */
1006 if (ah->ah_version > AR5K_AR5211) {
1007 ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
1008 AR5K_KEYTABLE_TYPE(entry));
1009
1010 if (type == AR5K_KEYTABLE_TYPE_TKIP) {
1011 ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
1012 AR5K_KEYTABLE_TYPE(micentry));
1013 }
1014 }
1015
1016 return 0;
1017}
1018
1019/*
1020 * Check if a table entry is valid
1021 */
1022int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry)
1023{
1024 ATH5K_TRACE(ah->ah_sc);
1025 AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
1026
1027 /* Check the validation flag at the end of the entry */
1028 return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) &
1029 AR5K_KEYTABLE_VALID;
1030}
1031
1032static
1033int ath5k_keycache_type(const struct ieee80211_key_conf *key)
1034{
1035 switch (key->alg) {
1036 case ALG_TKIP:
1037 return AR5K_KEYTABLE_TYPE_TKIP;
1038 case ALG_CCMP:
1039 return AR5K_KEYTABLE_TYPE_CCM;
1040 case ALG_WEP:
1041 if (key->keylen == LEN_WEP40)
1042 return AR5K_KEYTABLE_TYPE_40;
1043 else if (key->keylen == LEN_WEP104)
1044 return AR5K_KEYTABLE_TYPE_104;
1045 return -EINVAL;
1046 default:
1047 return -EINVAL;
1048 }
1049 return -EINVAL;
1050}
1051
1052/*
1053 * Set a key entry on the table
1054 */
1055int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
1056 const struct ieee80211_key_conf *key, const u8 *mac)
1057{
1058 unsigned int i;
1059 int keylen;
1060 __le32 key_v[5] = {};
1061 __le32 key0 = 0, key1 = 0;
1062 __le32 *rxmic, *txmic;
1063 int keytype;
1064 u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
1065 bool is_tkip;
1066 const u8 *key_ptr;
1067
1068 ATH5K_TRACE(ah->ah_sc);
1069
1070 is_tkip = (key->alg == ALG_TKIP);
1071
1072 /*
1073 * key->keylen comes in from mac80211 in bytes.
1074 * TKIP is 128 bit + 128 bit mic
1075 */
1076 keylen = (is_tkip) ? (128 / 8) : key->keylen;
1077
1078 if (entry > AR5K_KEYTABLE_SIZE ||
1079 (is_tkip && micentry > AR5K_KEYTABLE_SIZE))
1080 return -EOPNOTSUPP;
1081
1082 if (unlikely(keylen > 16))
1083 return -EOPNOTSUPP;
1084
1085 keytype = ath5k_keycache_type(key);
1086 if (keytype < 0)
1087 return keytype;
1088
1089 /*
1090 * each key block is 6 bytes wide, written as pairs of
1091 * alternating 32 and 16 bit le values.
1092 */
1093 key_ptr = key->key;
1094 for (i = 0; keylen >= 6; keylen -= 6) {
1095 memcpy(&key_v[i], key_ptr, 6);
1096 i += 2;
1097 key_ptr += 6;
1098 }
1099 if (keylen)
1100 memcpy(&key_v[i], key_ptr, keylen);
1101
1102 /* intentionally corrupt key until mic is installed */
1103 if (is_tkip) {
1104 key0 = key_v[0] = ~key_v[0];
1105 key1 = key_v[1] = ~key_v[1];
1106 }
1107
1108 for (i = 0; i < ARRAY_SIZE(key_v); i++)
1109 ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
1110 AR5K_KEYTABLE_OFF(entry, i));
1111
1112 ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry));
1113
1114 if (is_tkip) {
1115 /* Install rx/tx MIC */
1116 rxmic = (__le32 *) &key->key[16];
1117 txmic = (__le32 *) &key->key[24];
1118
1119 if (ah->ah_combined_mic) {
1120 key_v[0] = rxmic[0];
1121 key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16);
1122 key_v[2] = rxmic[1];
1123 key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff);
1124 key_v[4] = txmic[1];
1125 } else {
1126 key_v[0] = rxmic[0];
1127 key_v[1] = 0;
1128 key_v[2] = rxmic[1];
1129 key_v[3] = 0;
1130 key_v[4] = 0;
1131 }
1132 for (i = 0; i < ARRAY_SIZE(key_v); i++)
1133 ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
1134 AR5K_KEYTABLE_OFF(micentry, i));
1135
1136 ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
1137 AR5K_KEYTABLE_TYPE(micentry));
1138 ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry));
1139 ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry));
1140
1141 /* restore first 2 words of key */
1142 ath5k_hw_reg_write(ah, le32_to_cpu(~key0),
1143 AR5K_KEYTABLE_OFF(entry, 0));
1144 ath5k_hw_reg_write(ah, le32_to_cpu(~key1),
1145 AR5K_KEYTABLE_OFF(entry, 1));
1146 }
1147
1148 return ath5k_hw_set_key_lladdr(ah, entry, mac);
1149}
1150
1151int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
1152{
1153 u32 low_id, high_id;
1154
1155 ATH5K_TRACE(ah->ah_sc);
1156 /* Invalid entry (key table overflow) */
1157 AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
1158
1159 /* MAC may be NULL if it's a broadcast key. In this case no need to
1160 * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */
1161 if (!mac) {
1162 low_id = 0xffffffff;
1163 high_id = 0xffff | AR5K_KEYTABLE_VALID;
1164 } else {
1165 low_id = AR5K_LOW_ID(mac);
1166 high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID;
1167 }
1168
1169 ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry));
1170 ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry));
1171
1172 return 0;
1173}
1174
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
new file mode 100644
index 000000000000..9e2faae5ae94
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -0,0 +1,2599 @@
1/*
2 * PHY functions
3 *
4 * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
5 * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
6 * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
7 * Copyright (c) 2008-2009 Felix Fietkau <nbd@openwrt.org>
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *
21 */
22
23#define _ATH5K_PHY
24
25#include <linux/delay.h>
26
27#include "ath5k.h"
28#include "reg.h"
29#include "base.h"
30#include "rfbuffer.h"
31#include "rfgain.h"
32
33/*
34 * Used to modify RF Banks before writing them to AR5K_RF_BUFFER
35 */
36static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah,
37 const struct ath5k_rf_reg *rf_regs,
38 u32 val, u8 reg_id, bool set)
39{
40 const struct ath5k_rf_reg *rfreg = NULL;
41 u8 offset, bank, num_bits, col, position;
42 u16 entry;
43 u32 mask, data, last_bit, bits_shifted, first_bit;
44 u32 *rfb;
45 s32 bits_left;
46 int i;
47
48 data = 0;
49 rfb = ah->ah_rf_banks;
50
51 for (i = 0; i < ah->ah_rf_regs_count; i++) {
52 if (rf_regs[i].index == reg_id) {
53 rfreg = &rf_regs[i];
54 break;
55 }
56 }
57
58 if (rfb == NULL || rfreg == NULL) {
59 ATH5K_PRINTF("Rf register not found!\n");
60 /* should not happen */
61 return 0;
62 }
63
64 bank = rfreg->bank;
65 num_bits = rfreg->field.len;
66 first_bit = rfreg->field.pos;
67 col = rfreg->field.col;
68
69 /* first_bit is an offset from bank's
70 * start. Since we have all banks on
71 * the same array, we use this offset
72 * to mark each bank's start */
73 offset = ah->ah_offset[bank];
74
75 /* Boundary check */
76 if (!(col <= 3 && num_bits <= 32 && first_bit + num_bits <= 319)) {
77 ATH5K_PRINTF("invalid values at offset %u\n", offset);
78 return 0;
79 }
80
81 entry = ((first_bit - 1) / 8) + offset;
82 position = (first_bit - 1) % 8;
83
84 if (set)
85 data = ath5k_hw_bitswap(val, num_bits);
86
87 for (bits_shifted = 0, bits_left = num_bits; bits_left > 0;
88 position = 0, entry++) {
89
90 last_bit = (position + bits_left > 8) ? 8 :
91 position + bits_left;
92
93 mask = (((1 << last_bit) - 1) ^ ((1 << position) - 1)) <<
94 (col * 8);
95
96 if (set) {
97 rfb[entry] &= ~mask;
98 rfb[entry] |= ((data << position) << (col * 8)) & mask;
99 data >>= (8 - position);
100 } else {
101 data |= (((rfb[entry] & mask) >> (col * 8)) >> position)
102 << bits_shifted;
103 bits_shifted += last_bit - position;
104 }
105
106 bits_left -= 8 - position;
107 }
108
109 data = set ? 1 : ath5k_hw_bitswap(data, num_bits);
110
111 return data;
112}
113
114/**********************\
115* RF Gain optimization *
116\**********************/
117
118/*
119 * This code is used to optimize rf gain on different environments
120 * (temprature mostly) based on feedback from a power detector.
121 *
122 * It's only used on RF5111 and RF5112, later RF chips seem to have
123 * auto adjustment on hw -notice they have a much smaller BANK 7 and
124 * no gain optimization ladder-.
125 *
126 * For more infos check out this patent doc
127 * http://www.freepatentsonline.com/7400691.html
128 *
129 * This paper describes power drops as seen on the receiver due to
130 * probe packets
131 * http://www.cnri.dit.ie/publications/ICT08%20-%20Practical%20Issues
132 * %20of%20Power%20Control.pdf
133 *
134 * And this is the MadWiFi bug entry related to the above
135 * http://madwifi-project.org/ticket/1659
136 * with various measurements and diagrams
137 *
138 * TODO: Deal with power drops due to probes by setting an apropriate
139 * tx power on the probe packets ! Make this part of the calibration process.
140 */
141
142/* Initialize ah_gain durring attach */
143int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah)
144{
145 /* Initialize the gain optimization values */
146 switch (ah->ah_radio) {
147 case AR5K_RF5111:
148 ah->ah_gain.g_step_idx = rfgain_opt_5111.go_default;
149 ah->ah_gain.g_low = 20;
150 ah->ah_gain.g_high = 35;
151 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
152 break;
153 case AR5K_RF5112:
154 ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default;
155 ah->ah_gain.g_low = 20;
156 ah->ah_gain.g_high = 85;
157 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
158 break;
159 default:
160 return -EINVAL;
161 }
162
163 return 0;
164}
165
166/* Schedule a gain probe check on the next transmited packet.
167 * That means our next packet is going to be sent with lower
168 * tx power and a Peak to Average Power Detector (PAPD) will try
169 * to measure the gain.
170 *
171 * TODO: Use propper tx power setting for the probe packet so
172 * that we don't observe a serious power drop on the receiver
173 *
174 * XXX: How about forcing a tx packet (bypassing PCU arbitrator etc)
175 * just after we enable the probe so that we don't mess with
176 * standard traffic ? Maybe it's time to use sw interrupts and
177 * a probe tasklet !!!
178 */
179static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah)
180{
181
182 /* Skip if gain calibration is inactive or
183 * we already handle a probe request */
184 if (ah->ah_gain.g_state != AR5K_RFGAIN_ACTIVE)
185 return;
186
187 /* Send the packet with 2dB below max power as
188 * patent doc suggest */
189 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max_pwr - 4,
190 AR5K_PHY_PAPD_PROBE_TXPOWER) |
191 AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE);
192
193 ah->ah_gain.g_state = AR5K_RFGAIN_READ_REQUESTED;
194
195}
196
197/* Calculate gain_F measurement correction
198 * based on the current step for RF5112 rev. 2 */
199static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah)
200{
201 u32 mix, step;
202 u32 *rf;
203 const struct ath5k_gain_opt *go;
204 const struct ath5k_gain_opt_step *g_step;
205 const struct ath5k_rf_reg *rf_regs;
206
207 /* Only RF5112 Rev. 2 supports it */
208 if ((ah->ah_radio != AR5K_RF5112) ||
209 (ah->ah_radio_5ghz_revision <= AR5K_SREV_RAD_5112A))
210 return 0;
211
212 go = &rfgain_opt_5112;
213 rf_regs = rf_regs_5112a;
214 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a);
215
216 g_step = &go->go_step[ah->ah_gain.g_step_idx];
217
218 if (ah->ah_rf_banks == NULL)
219 return 0;
220
221 rf = ah->ah_rf_banks;
222 ah->ah_gain.g_f_corr = 0;
223
224 /* No VGA (Variable Gain Amplifier) override, skip */
225 if (ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, false) != 1)
226 return 0;
227
228 /* Mix gain stepping */
229 step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXGAIN_STEP, false);
230
231 /* Mix gain override */
232 mix = g_step->gos_param[0];
233
234 switch (mix) {
235 case 3:
236 ah->ah_gain.g_f_corr = step * 2;
237 break;
238 case 2:
239 ah->ah_gain.g_f_corr = (step - 5) * 2;
240 break;
241 case 1:
242 ah->ah_gain.g_f_corr = step;
243 break;
244 default:
245 ah->ah_gain.g_f_corr = 0;
246 break;
247 }
248
249 return ah->ah_gain.g_f_corr;
250}
251
252/* Check if current gain_F measurement is in the range of our
253 * power detector windows. If we get a measurement outside range
254 * we know it's not accurate (detectors can't measure anything outside
255 * their detection window) so we must ignore it */
256static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah)
257{
258 const struct ath5k_rf_reg *rf_regs;
259 u32 step, mix_ovr, level[4];
260 u32 *rf;
261
262 if (ah->ah_rf_banks == NULL)
263 return false;
264
265 rf = ah->ah_rf_banks;
266
267 if (ah->ah_radio == AR5K_RF5111) {
268
269 rf_regs = rf_regs_5111;
270 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111);
271
272 step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_RFGAIN_STEP,
273 false);
274
275 level[0] = 0;
276 level[1] = (step == 63) ? 50 : step + 4;
277 level[2] = (step != 63) ? 64 : level[0];
278 level[3] = level[2] + 50 ;
279
280 ah->ah_gain.g_high = level[3] -
281 (step == 63 ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
282 ah->ah_gain.g_low = level[0] +
283 (step == 63 ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0);
284 } else {
285
286 rf_regs = rf_regs_5112;
287 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112);
288
289 mix_ovr = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR,
290 false);
291
292 level[0] = level[2] = 0;
293
294 if (mix_ovr == 1) {
295 level[1] = level[3] = 83;
296 } else {
297 level[1] = level[3] = 107;
298 ah->ah_gain.g_high = 55;
299 }
300 }
301
302 return (ah->ah_gain.g_current >= level[0] &&
303 ah->ah_gain.g_current <= level[1]) ||
304 (ah->ah_gain.g_current >= level[2] &&
305 ah->ah_gain.g_current <= level[3]);
306}
307
308/* Perform gain_F adjustment by choosing the right set
309 * of parameters from rf gain optimization ladder */
310static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
311{
312 const struct ath5k_gain_opt *go;
313 const struct ath5k_gain_opt_step *g_step;
314 int ret = 0;
315
316 switch (ah->ah_radio) {
317 case AR5K_RF5111:
318 go = &rfgain_opt_5111;
319 break;
320 case AR5K_RF5112:
321 go = &rfgain_opt_5112;
322 break;
323 default:
324 return 0;
325 }
326
327 g_step = &go->go_step[ah->ah_gain.g_step_idx];
328
329 if (ah->ah_gain.g_current >= ah->ah_gain.g_high) {
330
331 /* Reached maximum */
332 if (ah->ah_gain.g_step_idx == 0)
333 return -1;
334
335 for (ah->ah_gain.g_target = ah->ah_gain.g_current;
336 ah->ah_gain.g_target >= ah->ah_gain.g_high &&
337 ah->ah_gain.g_step_idx > 0;
338 g_step = &go->go_step[ah->ah_gain.g_step_idx])
339 ah->ah_gain.g_target -= 2 *
340 (go->go_step[--(ah->ah_gain.g_step_idx)].gos_gain -
341 g_step->gos_gain);
342
343 ret = 1;
344 goto done;
345 }
346
347 if (ah->ah_gain.g_current <= ah->ah_gain.g_low) {
348
349 /* Reached minimum */
350 if (ah->ah_gain.g_step_idx == (go->go_steps_count - 1))
351 return -2;
352
353 for (ah->ah_gain.g_target = ah->ah_gain.g_current;
354 ah->ah_gain.g_target <= ah->ah_gain.g_low &&
355 ah->ah_gain.g_step_idx < go->go_steps_count-1;
356 g_step = &go->go_step[ah->ah_gain.g_step_idx])
357 ah->ah_gain.g_target -= 2 *
358 (go->go_step[++ah->ah_gain.g_step_idx].gos_gain -
359 g_step->gos_gain);
360
361 ret = 2;
362 goto done;
363 }
364
365done:
366 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
367 "ret %d, gain step %u, current gain %u, target gain %u\n",
368 ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current,
369 ah->ah_gain.g_target);
370
371 return ret;
372}
373
374/* Main callback for thermal rf gain calibration engine
375 * Check for a new gain reading and schedule an adjustment
376 * if needed.
377 *
378 * TODO: Use sw interrupt to schedule reset if gain_F needs
379 * adjustment */
380enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah)
381{
382 u32 data, type;
383 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
384
385 ATH5K_TRACE(ah->ah_sc);
386
387 if (ah->ah_rf_banks == NULL ||
388 ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE)
389 return AR5K_RFGAIN_INACTIVE;
390
391 /* No check requested, either engine is inactive
392 * or an adjustment is already requested */
393 if (ah->ah_gain.g_state != AR5K_RFGAIN_READ_REQUESTED)
394 goto done;
395
396 /* Read the PAPD (Peak to Average Power Detector)
397 * register */
398 data = ath5k_hw_reg_read(ah, AR5K_PHY_PAPD_PROBE);
399
400 /* No probe is scheduled, read gain_F measurement */
401 if (!(data & AR5K_PHY_PAPD_PROBE_TX_NEXT)) {
402 ah->ah_gain.g_current = data >> AR5K_PHY_PAPD_PROBE_GAINF_S;
403 type = AR5K_REG_MS(data, AR5K_PHY_PAPD_PROBE_TYPE);
404
405 /* If tx packet is CCK correct the gain_F measurement
406 * by cck ofdm gain delta */
407 if (type == AR5K_PHY_PAPD_PROBE_TYPE_CCK) {
408 if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A)
409 ah->ah_gain.g_current +=
410 ee->ee_cck_ofdm_gain_delta;
411 else
412 ah->ah_gain.g_current +=
413 AR5K_GAIN_CCK_PROBE_CORR;
414 }
415
416 /* Further correct gain_F measurement for
417 * RF5112A radios */
418 if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
419 ath5k_hw_rf_gainf_corr(ah);
420 ah->ah_gain.g_current =
421 ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ?
422 (ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
423 0;
424 }
425
426 /* Check if measurement is ok and if we need
427 * to adjust gain, schedule a gain adjustment,
428 * else switch back to the acive state */
429 if (ath5k_hw_rf_check_gainf_readback(ah) &&
430 AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) &&
431 ath5k_hw_rf_gainf_adjust(ah)) {
432 ah->ah_gain.g_state = AR5K_RFGAIN_NEED_CHANGE;
433 } else {
434 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
435 }
436 }
437
438done:
439 return ah->ah_gain.g_state;
440}
441
442/* Write initial rf gain table to set the RF sensitivity
443 * this one works on all RF chips and has nothing to do
444 * with gain_F calibration */
445int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
446{
447 const struct ath5k_ini_rfgain *ath5k_rfg;
448 unsigned int i, size;
449
450 switch (ah->ah_radio) {
451 case AR5K_RF5111:
452 ath5k_rfg = rfgain_5111;
453 size = ARRAY_SIZE(rfgain_5111);
454 break;
455 case AR5K_RF5112:
456 ath5k_rfg = rfgain_5112;
457 size = ARRAY_SIZE(rfgain_5112);
458 break;
459 case AR5K_RF2413:
460 ath5k_rfg = rfgain_2413;
461 size = ARRAY_SIZE(rfgain_2413);
462 break;
463 case AR5K_RF2316:
464 ath5k_rfg = rfgain_2316;
465 size = ARRAY_SIZE(rfgain_2316);
466 break;
467 case AR5K_RF5413:
468 ath5k_rfg = rfgain_5413;
469 size = ARRAY_SIZE(rfgain_5413);
470 break;
471 case AR5K_RF2317:
472 case AR5K_RF2425:
473 ath5k_rfg = rfgain_2425;
474 size = ARRAY_SIZE(rfgain_2425);
475 break;
476 default:
477 return -EINVAL;
478 }
479
480 switch (freq) {
481 case AR5K_INI_RFGAIN_2GHZ:
482 case AR5K_INI_RFGAIN_5GHZ:
483 break;
484 default:
485 return -EINVAL;
486 }
487
488 for (i = 0; i < size; i++) {
489 AR5K_REG_WAIT(i);
490 ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq],
491 (u32)ath5k_rfg[i].rfg_register);
492 }
493
494 return 0;
495}
496
497
498
499/********************\
500* RF Registers setup *
501\********************/
502
503
504/*
505 * Setup RF registers by writing rf buffer on hw
506 */
507int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
508 unsigned int mode)
509{
510 const struct ath5k_rf_reg *rf_regs;
511 const struct ath5k_ini_rfbuffer *ini_rfb;
512 const struct ath5k_gain_opt *go = NULL;
513 const struct ath5k_gain_opt_step *g_step;
514 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
515 u8 ee_mode = 0;
516 u32 *rfb;
517 int i, obdb = -1, bank = -1;
518
519 switch (ah->ah_radio) {
520 case AR5K_RF5111:
521 rf_regs = rf_regs_5111;
522 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111);
523 ini_rfb = rfb_5111;
524 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5111);
525 go = &rfgain_opt_5111;
526 break;
527 case AR5K_RF5112:
528 if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
529 rf_regs = rf_regs_5112a;
530 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a);
531 ini_rfb = rfb_5112a;
532 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112a);
533 } else {
534 rf_regs = rf_regs_5112;
535 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112);
536 ini_rfb = rfb_5112;
537 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112);
538 }
539 go = &rfgain_opt_5112;
540 break;
541 case AR5K_RF2413:
542 rf_regs = rf_regs_2413;
543 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2413);
544 ini_rfb = rfb_2413;
545 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2413);
546 break;
547 case AR5K_RF2316:
548 rf_regs = rf_regs_2316;
549 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2316);
550 ini_rfb = rfb_2316;
551 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2316);
552 break;
553 case AR5K_RF5413:
554 rf_regs = rf_regs_5413;
555 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5413);
556 ini_rfb = rfb_5413;
557 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5413);
558 break;
559 case AR5K_RF2317:
560 rf_regs = rf_regs_2425;
561 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425);
562 ini_rfb = rfb_2317;
563 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2317);
564 break;
565 case AR5K_RF2425:
566 rf_regs = rf_regs_2425;
567 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425);
568 if (ah->ah_mac_srev < AR5K_SREV_AR2417) {
569 ini_rfb = rfb_2425;
570 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2425);
571 } else {
572 ini_rfb = rfb_2417;
573 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2417);
574 }
575 break;
576 default:
577 return -EINVAL;
578 }
579
580 /* If it's the first time we set rf buffer, allocate
581 * ah->ah_rf_banks based on ah->ah_rf_banks_size
582 * we set above */
583 if (ah->ah_rf_banks == NULL) {
584 ah->ah_rf_banks = kmalloc(sizeof(u32) * ah->ah_rf_banks_size,
585 GFP_KERNEL);
586 if (ah->ah_rf_banks == NULL) {
587 ATH5K_ERR(ah->ah_sc, "out of memory\n");
588 return -ENOMEM;
589 }
590 }
591
592 /* Copy values to modify them */
593 rfb = ah->ah_rf_banks;
594
595 for (i = 0; i < ah->ah_rf_banks_size; i++) {
596 if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) {
597 ATH5K_ERR(ah->ah_sc, "invalid bank\n");
598 return -EINVAL;
599 }
600
601 /* Bank changed, write down the offset */
602 if (bank != ini_rfb[i].rfb_bank) {
603 bank = ini_rfb[i].rfb_bank;
604 ah->ah_offset[bank] = i;
605 }
606
607 rfb[i] = ini_rfb[i].rfb_mode_data[mode];
608 }
609
610 /* Set Output and Driver bias current (OB/DB) */
611 if (channel->hw_value & CHANNEL_2GHZ) {
612
613 if (channel->hw_value & CHANNEL_CCK)
614 ee_mode = AR5K_EEPROM_MODE_11B;
615 else
616 ee_mode = AR5K_EEPROM_MODE_11G;
617
618 /* For RF511X/RF211X combination we
619 * use b_OB and b_DB parameters stored
620 * in eeprom on ee->ee_ob[ee_mode][0]
621 *
622 * For all other chips we use OB/DB for 2Ghz
623 * stored in the b/g modal section just like
624 * 802.11a on ee->ee_ob[ee_mode][1] */
625 if ((ah->ah_radio == AR5K_RF5111) ||
626 (ah->ah_radio == AR5K_RF5112))
627 obdb = 0;
628 else
629 obdb = 1;
630
631 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb],
632 AR5K_RF_OB_2GHZ, true);
633
634 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb],
635 AR5K_RF_DB_2GHZ, true);
636
637 /* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */
638 } else if ((channel->hw_value & CHANNEL_5GHZ) ||
639 (ah->ah_radio == AR5K_RF5111)) {
640
641 /* For 11a, Turbo and XR we need to choose
642 * OB/DB based on frequency range */
643 ee_mode = AR5K_EEPROM_MODE_11A;
644 obdb = channel->center_freq >= 5725 ? 3 :
645 (channel->center_freq >= 5500 ? 2 :
646 (channel->center_freq >= 5260 ? 1 :
647 (channel->center_freq > 4000 ? 0 : -1)));
648
649 if (obdb < 0)
650 return -EINVAL;
651
652 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb],
653 AR5K_RF_OB_5GHZ, true);
654
655 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb],
656 AR5K_RF_DB_5GHZ, true);
657 }
658
659 g_step = &go->go_step[ah->ah_gain.g_step_idx];
660
661 /* Bank Modifications (chip-specific) */
662 if (ah->ah_radio == AR5K_RF5111) {
663
664 /* Set gain_F settings according to current step */
665 if (channel->hw_value & CHANNEL_OFDM) {
666
667 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
668 AR5K_PHY_FRAME_CTL_TX_CLIP,
669 g_step->gos_param[0]);
670
671 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1],
672 AR5K_RF_PWD_90, true);
673
674 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2],
675 AR5K_RF_PWD_84, true);
676
677 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3],
678 AR5K_RF_RFGAIN_SEL, true);
679
680 /* We programmed gain_F parameters, switch back
681 * to active state */
682 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
683
684 }
685
686 /* Bank 6/7 setup */
687
688 ath5k_hw_rfb_op(ah, rf_regs, !ee->ee_xpd[ee_mode],
689 AR5K_RF_PWD_XPD, true);
690
691 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_x_gain[ee_mode],
692 AR5K_RF_XPD_GAIN, true);
693
694 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
695 AR5K_RF_GAIN_I, true);
696
697 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
698 AR5K_RF_PLO_SEL, true);
699
700 /* TODO: Half/quarter channel support */
701 }
702
703 if (ah->ah_radio == AR5K_RF5112) {
704
705 /* Set gain_F settings according to current step */
706 if (channel->hw_value & CHANNEL_OFDM) {
707
708 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0],
709 AR5K_RF_MIXGAIN_OVR, true);
710
711 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1],
712 AR5K_RF_PWD_138, true);
713
714 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2],
715 AR5K_RF_PWD_137, true);
716
717 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3],
718 AR5K_RF_PWD_136, true);
719
720 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[4],
721 AR5K_RF_PWD_132, true);
722
723 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[5],
724 AR5K_RF_PWD_131, true);
725
726 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[6],
727 AR5K_RF_PWD_130, true);
728
729 /* We programmed gain_F parameters, switch back
730 * to active state */
731 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
732 }
733
734 /* Bank 6/7 setup */
735
736 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
737 AR5K_RF_XPD_SEL, true);
738
739 if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
740 /* Rev. 1 supports only one xpd */
741 ath5k_hw_rfb_op(ah, rf_regs,
742 ee->ee_x_gain[ee_mode],
743 AR5K_RF_XPD_GAIN, true);
744
745 } else {
746 /* TODO: Set high and low gain bits */
747 ath5k_hw_rfb_op(ah, rf_regs,
748 ee->ee_x_gain[ee_mode],
749 AR5K_RF_PD_GAIN_LO, true);
750 ath5k_hw_rfb_op(ah, rf_regs,
751 ee->ee_x_gain[ee_mode],
752 AR5K_RF_PD_GAIN_HI, true);
753
754 /* Lower synth voltage on Rev 2 */
755 ath5k_hw_rfb_op(ah, rf_regs, 2,
756 AR5K_RF_HIGH_VC_CP, true);
757
758 ath5k_hw_rfb_op(ah, rf_regs, 2,
759 AR5K_RF_MID_VC_CP, true);
760
761 ath5k_hw_rfb_op(ah, rf_regs, 2,
762 AR5K_RF_LOW_VC_CP, true);
763
764 ath5k_hw_rfb_op(ah, rf_regs, 2,
765 AR5K_RF_PUSH_UP, true);
766
767 /* Decrease power consumption on 5213+ BaseBand */
768 if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
769 ath5k_hw_rfb_op(ah, rf_regs, 1,
770 AR5K_RF_PAD2GND, true);
771
772 ath5k_hw_rfb_op(ah, rf_regs, 1,
773 AR5K_RF_XB2_LVL, true);
774
775 ath5k_hw_rfb_op(ah, rf_regs, 1,
776 AR5K_RF_XB5_LVL, true);
777
778 ath5k_hw_rfb_op(ah, rf_regs, 1,
779 AR5K_RF_PWD_167, true);
780
781 ath5k_hw_rfb_op(ah, rf_regs, 1,
782 AR5K_RF_PWD_166, true);
783 }
784 }
785
786 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
787 AR5K_RF_GAIN_I, true);
788
789 /* TODO: Half/quarter channel support */
790
791 }
792
793 if (ah->ah_radio == AR5K_RF5413 &&
794 channel->hw_value & CHANNEL_2GHZ) {
795
796 ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE,
797 true);
798
799 /* Set optimum value for early revisions (on pci-e chips) */
800 if (ah->ah_mac_srev >= AR5K_SREV_AR5424 &&
801 ah->ah_mac_srev < AR5K_SREV_AR5413)
802 ath5k_hw_rfb_op(ah, rf_regs, ath5k_hw_bitswap(6, 3),
803 AR5K_RF_PWD_ICLOBUF_2G, true);
804
805 }
806
807 /* Write RF banks on hw */
808 for (i = 0; i < ah->ah_rf_banks_size; i++) {
809 AR5K_REG_WAIT(i);
810 ath5k_hw_reg_write(ah, rfb[i], ini_rfb[i].rfb_ctrl_register);
811 }
812
813 return 0;
814}
815
816
817/**************************\
818 PHY/RF channel functions
819\**************************/
820
821/*
822 * Check if a channel is supported
823 */
824bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
825{
826 /* Check if the channel is in our supported range */
827 if (flags & CHANNEL_2GHZ) {
828 if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
829 (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
830 return true;
831 } else if (flags & CHANNEL_5GHZ)
832 if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
833 (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
834 return true;
835
836 return false;
837}
838
839/*
840 * Convertion needed for RF5110
841 */
842static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel)
843{
844 u32 athchan;
845
846 /*
847 * Convert IEEE channel/MHz to an internal channel value used
848 * by the AR5210 chipset. This has not been verified with
849 * newer chipsets like the AR5212A who have a completely
850 * different RF/PHY part.
851 */
852 athchan = (ath5k_hw_bitswap(
853 (ieee80211_frequency_to_channel(
854 channel->center_freq) - 24) / 2, 5)
855 << 1) | (1 << 6) | 0x1;
856 return athchan;
857}
858
859/*
860 * Set channel on RF5110
861 */
862static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah,
863 struct ieee80211_channel *channel)
864{
865 u32 data;
866
867 /*
868 * Set the channel and wait
869 */
870 data = ath5k_hw_rf5110_chan2athchan(channel);
871 ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER);
872 ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0);
873 mdelay(1);
874
875 return 0;
876}
877
878/*
879 * Convertion needed for 5111
880 */
881static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee,
882 struct ath5k_athchan_2ghz *athchan)
883{
884 int channel;
885
886 /* Cast this value to catch negative channel numbers (>= -19) */
887 channel = (int)ieee;
888
889 /*
890 * Map 2GHz IEEE channel to 5GHz Atheros channel
891 */
892 if (channel <= 13) {
893 athchan->a2_athchan = 115 + channel;
894 athchan->a2_flags = 0x46;
895 } else if (channel == 14) {
896 athchan->a2_athchan = 124;
897 athchan->a2_flags = 0x44;
898 } else if (channel >= 15 && channel <= 26) {
899 athchan->a2_athchan = ((channel - 14) * 4) + 132;
900 athchan->a2_flags = 0x46;
901 } else
902 return -EINVAL;
903
904 return 0;
905}
906
907/*
908 * Set channel on 5111
909 */
910static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
911 struct ieee80211_channel *channel)
912{
913 struct ath5k_athchan_2ghz ath5k_channel_2ghz;
914 unsigned int ath5k_channel =
915 ieee80211_frequency_to_channel(channel->center_freq);
916 u32 data0, data1, clock;
917 int ret;
918
919 /*
920 * Set the channel on the RF5111 radio
921 */
922 data0 = data1 = 0;
923
924 if (channel->hw_value & CHANNEL_2GHZ) {
925 /* Map 2GHz channel to 5GHz Atheros channel ID */
926 ret = ath5k_hw_rf5111_chan2athchan(
927 ieee80211_frequency_to_channel(channel->center_freq),
928 &ath5k_channel_2ghz);
929 if (ret)
930 return ret;
931
932 ath5k_channel = ath5k_channel_2ghz.a2_athchan;
933 data0 = ((ath5k_hw_bitswap(ath5k_channel_2ghz.a2_flags, 8) & 0xff)
934 << 5) | (1 << 4);
935 }
936
937 if (ath5k_channel < 145 || !(ath5k_channel & 1)) {
938 clock = 1;
939 data1 = ((ath5k_hw_bitswap(ath5k_channel - 24, 8) & 0xff) << 2) |
940 (clock << 1) | (1 << 10) | 1;
941 } else {
942 clock = 0;
943 data1 = ((ath5k_hw_bitswap((ath5k_channel - 24) / 2, 8) & 0xff)
944 << 2) | (clock << 1) | (1 << 10) | 1;
945 }
946
947 ath5k_hw_reg_write(ah, (data1 & 0xff) | ((data0 & 0xff) << 8),
948 AR5K_RF_BUFFER);
949 ath5k_hw_reg_write(ah, ((data1 >> 8) & 0xff) | (data0 & 0xff00),
950 AR5K_RF_BUFFER_CONTROL_3);
951
952 return 0;
953}
954
955/*
956 * Set channel on 5112 and newer
957 */
958static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
959 struct ieee80211_channel *channel)
960{
961 u32 data, data0, data1, data2;
962 u16 c;
963
964 data = data0 = data1 = data2 = 0;
965 c = channel->center_freq;
966
967 if (c < 4800) {
968 if (!((c - 2224) % 5)) {
969 data0 = ((2 * (c - 704)) - 3040) / 10;
970 data1 = 1;
971 } else if (!((c - 2192) % 5)) {
972 data0 = ((2 * (c - 672)) - 3040) / 10;
973 data1 = 0;
974 } else
975 return -EINVAL;
976
977 data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8);
978 } else if ((c - (c % 5)) != 2 || c > 5435) {
979 if (!(c % 20) && c >= 5120) {
980 data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
981 data2 = ath5k_hw_bitswap(3, 2);
982 } else if (!(c % 10)) {
983 data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
984 data2 = ath5k_hw_bitswap(2, 2);
985 } else if (!(c % 5)) {
986 data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
987 data2 = ath5k_hw_bitswap(1, 2);
988 } else
989 return -EINVAL;
990 } else {
991 data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
992 data2 = ath5k_hw_bitswap(0, 2);
993 }
994
995 data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
996
997 ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
998 ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
999
1000 return 0;
1001}
1002
1003/*
1004 * Set the channel on the RF2425
1005 */
1006static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah,
1007 struct ieee80211_channel *channel)
1008{
1009 u32 data, data0, data2;
1010 u16 c;
1011
1012 data = data0 = data2 = 0;
1013 c = channel->center_freq;
1014
1015 if (c < 4800) {
1016 data0 = ath5k_hw_bitswap((c - 2272), 8);
1017 data2 = 0;
1018 /* ? 5GHz ? */
1019 } else if ((c - (c % 5)) != 2 || c > 5435) {
1020 if (!(c % 20) && c < 5120)
1021 data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
1022 else if (!(c % 10))
1023 data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
1024 else if (!(c % 5))
1025 data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
1026 else
1027 return -EINVAL;
1028 data2 = ath5k_hw_bitswap(1, 2);
1029 } else {
1030 data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
1031 data2 = ath5k_hw_bitswap(0, 2);
1032 }
1033
1034 data = (data0 << 4) | data2 << 2 | 0x1001;
1035
1036 ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
1037 ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
1038
1039 return 0;
1040}
1041
1042/*
1043 * Set a channel on the radio chip
1044 */
1045int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
1046{
1047 int ret;
1048 /*
1049 * Check bounds supported by the PHY (we don't care about regultory
1050 * restrictions at this point). Note: hw_value already has the band
1051 * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()
1052 * of the band by that */
1053 if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
1054 ATH5K_ERR(ah->ah_sc,
1055 "channel frequency (%u MHz) out of supported "
1056 "band range\n",
1057 channel->center_freq);
1058 return -EINVAL;
1059 }
1060
1061 /*
1062 * Set the channel and wait
1063 */
1064 switch (ah->ah_radio) {
1065 case AR5K_RF5110:
1066 ret = ath5k_hw_rf5110_channel(ah, channel);
1067 break;
1068 case AR5K_RF5111:
1069 ret = ath5k_hw_rf5111_channel(ah, channel);
1070 break;
1071 case AR5K_RF2425:
1072 ret = ath5k_hw_rf2425_channel(ah, channel);
1073 break;
1074 default:
1075 ret = ath5k_hw_rf5112_channel(ah, channel);
1076 break;
1077 }
1078
1079 if (ret)
1080 return ret;
1081
1082 /* Set JAPAN setting for channel 14 */
1083 if (channel->center_freq == 2484) {
1084 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
1085 AR5K_PHY_CCKTXCTL_JAPAN);
1086 } else {
1087 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
1088 AR5K_PHY_CCKTXCTL_WORLD);
1089 }
1090
1091 ah->ah_current_channel.center_freq = channel->center_freq;
1092 ah->ah_current_channel.hw_value = channel->hw_value;
1093 ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
1094
1095 return 0;
1096}
1097
1098/*****************\
1099 PHY calibration
1100\*****************/
1101
1102/**
1103 * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
1104 *
1105 * @ah: struct ath5k_hw pointer we are operating on
1106 * @freq: the channel frequency, just used for error logging
1107 *
1108 * This function performs a noise floor calibration of the PHY and waits for
1109 * it to complete. Then the noise floor value is compared to some maximum
1110 * noise floor we consider valid.
1111 *
1112 * Note that this is different from what the madwifi HAL does: it reads the
1113 * noise floor and afterwards initiates the calibration. Since the noise floor
1114 * calibration can take some time to finish, depending on the current channel
1115 * use, that avoids the occasional timeout warnings we are seeing now.
1116 *
1117 * See the following link for an Atheros patent on noise floor calibration:
1118 * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \
1119 * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7
1120 *
1121 * XXX: Since during noise floor calibration antennas are detached according to
1122 * the patent, we should stop tx queues here.
1123 */
1124int
1125ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
1126{
1127 int ret;
1128 unsigned int i;
1129 s32 noise_floor;
1130
1131 /*
1132 * Enable noise floor calibration
1133 */
1134 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
1135 AR5K_PHY_AGCCTL_NF);
1136
1137 ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
1138 AR5K_PHY_AGCCTL_NF, 0, false);
1139 if (ret) {
1140 ATH5K_ERR(ah->ah_sc,
1141 "noise floor calibration timeout (%uMHz)\n", freq);
1142 return -EAGAIN;
1143 }
1144
1145 /* Wait until the noise floor is calibrated and read the value */
1146 for (i = 20; i > 0; i--) {
1147 mdelay(1);
1148 noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
1149 noise_floor = AR5K_PHY_NF_RVAL(noise_floor);
1150 if (noise_floor & AR5K_PHY_NF_ACTIVE) {
1151 noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
1152
1153 if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
1154 break;
1155 }
1156 }
1157
1158 ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
1159 "noise floor %d\n", noise_floor);
1160
1161 if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
1162 ATH5K_ERR(ah->ah_sc,
1163 "noise floor calibration failed (%uMHz)\n", freq);
1164 return -EAGAIN;
1165 }
1166
1167 ah->ah_noise_floor = noise_floor;
1168
1169 return 0;
1170}
1171
1172/*
1173 * Perform a PHY calibration on RF5110
1174 * -Fix BPSK/QAM Constellation (I/Q correction)
1175 * -Calculate Noise Floor
1176 */
1177static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
1178 struct ieee80211_channel *channel)
1179{
1180 u32 phy_sig, phy_agc, phy_sat, beacon;
1181 int ret;
1182
1183 /*
1184 * Disable beacons and RX/TX queues, wait
1185 */
1186 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210,
1187 AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
1188 beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
1189 ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
1190
1191 mdelay(2);
1192
1193 /*
1194 * Set the channel (with AGC turned off)
1195 */
1196 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
1197 udelay(10);
1198 ret = ath5k_hw_channel(ah, channel);
1199
1200 /*
1201 * Activate PHY and wait
1202 */
1203 ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
1204 mdelay(1);
1205
1206 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
1207
1208 if (ret)
1209 return ret;
1210
1211 /*
1212 * Calibrate the radio chip
1213 */
1214
1215 /* Remember normal state */
1216 phy_sig = ath5k_hw_reg_read(ah, AR5K_PHY_SIG);
1217 phy_agc = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCOARSE);
1218 phy_sat = ath5k_hw_reg_read(ah, AR5K_PHY_ADCSAT);
1219
1220 /* Update radio registers */
1221 ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) |
1222 AR5K_REG_SM(-1, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG);
1223
1224 ath5k_hw_reg_write(ah, (phy_agc & ~(AR5K_PHY_AGCCOARSE_HI |
1225 AR5K_PHY_AGCCOARSE_LO)) |
1226 AR5K_REG_SM(-1, AR5K_PHY_AGCCOARSE_HI) |
1227 AR5K_REG_SM(-127, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE);
1228
1229 ath5k_hw_reg_write(ah, (phy_sat & ~(AR5K_PHY_ADCSAT_ICNT |
1230 AR5K_PHY_ADCSAT_THR)) |
1231 AR5K_REG_SM(2, AR5K_PHY_ADCSAT_ICNT) |
1232 AR5K_REG_SM(12, AR5K_PHY_ADCSAT_THR), AR5K_PHY_ADCSAT);
1233
1234 udelay(20);
1235
1236 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
1237 udelay(10);
1238 ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG);
1239 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
1240
1241 mdelay(1);
1242
1243 /*
1244 * Enable calibration and wait until completion
1245 */
1246 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL);
1247
1248 ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
1249 AR5K_PHY_AGCCTL_CAL, 0, false);
1250
1251 /* Reset to normal state */
1252 ath5k_hw_reg_write(ah, phy_sig, AR5K_PHY_SIG);
1253 ath5k_hw_reg_write(ah, phy_agc, AR5K_PHY_AGCCOARSE);
1254 ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT);
1255
1256 if (ret) {
1257 ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
1258 channel->center_freq);
1259 return ret;
1260 }
1261
1262 ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
1263
1264 /*
1265 * Re-enable RX/TX and beacons
1266 */
1267 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210,
1268 AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
1269 ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210);
1270
1271 return 0;
1272}
1273
1274/*
1275 * Perform a PHY calibration on RF5111/5112 and newer chips
1276 */
1277static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
1278 struct ieee80211_channel *channel)
1279{
1280 u32 i_pwr, q_pwr;
1281 s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
1282 int i;
1283 ATH5K_TRACE(ah->ah_sc);
1284
1285 if (!ah->ah_calibration ||
1286 ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
1287 goto done;
1288
1289 /* Calibration has finished, get the results and re-run */
1290 for (i = 0; i <= 10; i++) {
1291 iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
1292 i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I);
1293 q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q);
1294 }
1295
1296 i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7;
1297 q_coffd = q_pwr >> 7;
1298
1299 /* No correction */
1300 if (i_coffd == 0 || q_coffd == 0)
1301 goto done;
1302
1303 i_coff = ((-iq_corr) / i_coffd) & 0x3f;
1304
1305 /* Boundary check */
1306 if (i_coff > 31)
1307 i_coff = 31;
1308 if (i_coff < -32)
1309 i_coff = -32;
1310
1311 q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f;
1312
1313 /* Boundary check */
1314 if (q_coff > 15)
1315 q_coff = 15;
1316 if (q_coff < -16)
1317 q_coff = -16;
1318
1319 /* Commit new I/Q value */
1320 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE |
1321 ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
1322
1323 /* Re-enable calibration -if we don't we'll commit
1324 * the same values again and again */
1325 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
1326 AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
1327 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN);
1328
1329done:
1330
1331 /* TODO: Separate noise floor calibration from I/Q calibration
1332 * since noise floor calibration interrupts rx path while I/Q
1333 * calibration doesn't. We don't need to run noise floor calibration
1334 * as often as I/Q calibration.*/
1335 ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
1336
1337 /* Initiate a gain_F calibration */
1338 ath5k_hw_request_rfgain_probe(ah);
1339
1340 return 0;
1341}
1342
1343/*
1344 * Perform a PHY calibration
1345 */
1346int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
1347 struct ieee80211_channel *channel)
1348{
1349 int ret;
1350
1351 if (ah->ah_radio == AR5K_RF5110)
1352 ret = ath5k_hw_rf5110_calibrate(ah, channel);
1353 else
1354 ret = ath5k_hw_rf511x_calibrate(ah, channel);
1355
1356 return ret;
1357}
1358
1359int ath5k_hw_phy_disable(struct ath5k_hw *ah)
1360{
1361 ATH5K_TRACE(ah->ah_sc);
1362 /*Just a try M.F.*/
1363 ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
1364
1365 return 0;
1366}
1367
1368/********************\
1369 Misc PHY functions
1370\********************/
1371
1372/*
1373 * Get the PHY Chip revision
1374 */
1375u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
1376{
1377 unsigned int i;
1378 u32 srev;
1379 u16 ret;
1380
1381 ATH5K_TRACE(ah->ah_sc);
1382
1383 /*
1384 * Set the radio chip access register
1385 */
1386 switch (chan) {
1387 case CHANNEL_2GHZ:
1388 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
1389 break;
1390 case CHANNEL_5GHZ:
1391 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
1392 break;
1393 default:
1394 return 0;
1395 }
1396
1397 mdelay(2);
1398
1399 /* ...wait until PHY is ready and read the selected radio revision */
1400 ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34));
1401
1402 for (i = 0; i < 8; i++)
1403 ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
1404
1405 if (ah->ah_version == AR5K_AR5210) {
1406 srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
1407 ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
1408 } else {
1409 srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
1410 ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) |
1411 ((srev & 0x0f) << 4), 8);
1412 }
1413
1414 /* Reset to the 5GHz mode */
1415 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
1416
1417 return ret;
1418}
1419
1420void /*TODO:Boundary check*/
1421ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant)
1422{
1423 ATH5K_TRACE(ah->ah_sc);
1424 /*Just a try M.F.*/
1425 if (ah->ah_version != AR5K_AR5210)
1426 ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA);
1427}
1428
1429unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah)
1430{
1431 ATH5K_TRACE(ah->ah_sc);
1432 /*Just a try M.F.*/
1433 if (ah->ah_version != AR5K_AR5210)
1434 return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
1435
1436 return false; /*XXX: What do we return for 5210 ?*/
1437}
1438
1439
1440/****************\
1441* TX power setup *
1442\****************/
1443
1444/*
1445 * Helper functions
1446 */
1447
1448/*
1449 * Do linear interpolation between two given (x, y) points
1450 */
1451static s16
1452ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right,
1453 s16 y_left, s16 y_right)
1454{
1455 s16 ratio, result;
1456
1457 /* Avoid divide by zero and skip interpolation
1458 * if we have the same point */
1459 if ((x_left == x_right) || (y_left == y_right))
1460 return y_left;
1461
1462 /*
1463 * Since we use ints and not fps, we need to scale up in
1464 * order to get a sane ratio value (or else we 'll eg. get
1465 * always 1 instead of 1.25, 1.75 etc). We scale up by 100
1466 * to have some accuracy both for 0.5 and 0.25 steps.
1467 */
1468 ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left));
1469
1470 /* Now scale down to be in range */
1471 result = y_left + (ratio * (target - x_left) / 100);
1472
1473 return result;
1474}
1475
1476/*
1477 * Find vertical boundary (min pwr) for the linear PCDAC curve.
1478 *
1479 * Since we have the top of the curve and we draw the line below
1480 * until we reach 1 (1 pcdac step) we need to know which point
1481 * (x value) that is so that we don't go below y axis and have negative
1482 * pcdac values when creating the curve, or fill the table with zeroes.
1483 */
1484static s16
1485ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR,
1486 const s16 *pwrL, const s16 *pwrR)
1487{
1488 s8 tmp;
1489 s16 min_pwrL, min_pwrR;
1490 s16 pwr_i = pwrL[0];
1491
1492 do {
1493 pwr_i--;
1494 tmp = (s8) ath5k_get_interpolated_value(pwr_i,
1495 pwrL[0], pwrL[1],
1496 stepL[0], stepL[1]);
1497
1498 } while (tmp > 1);
1499
1500 min_pwrL = pwr_i;
1501
1502 pwr_i = pwrR[0];
1503 do {
1504 pwr_i--;
1505 tmp = (s8) ath5k_get_interpolated_value(pwr_i,
1506 pwrR[0], pwrR[1],
1507 stepR[0], stepR[1]);
1508
1509 } while (tmp > 1);
1510
1511 min_pwrR = pwr_i;
1512
1513 /* Keep the right boundary so that it works for both curves */
1514 return max(min_pwrL, min_pwrR);
1515}
1516
1517/*
1518 * Interpolate (pwr,vpd) points to create a Power to PDADC or a
1519 * Power to PCDAC curve.
1520 *
1521 * Each curve has power on x axis (in 0.5dB units) and PCDAC/PDADC
1522 * steps (offsets) on y axis. Power can go up to 31.5dB and max
1523 * PCDAC/PDADC step for each curve is 64 but we can write more than
1524 * one curves on hw so we can go up to 128 (which is the max step we
1525 * can write on the final table).
1526 *
1527 * We write y values (PCDAC/PDADC steps) on hw.
1528 */
1529static void
1530ath5k_create_power_curve(s16 pmin, s16 pmax,
1531 const s16 *pwr, const u8 *vpd,
1532 u8 num_points,
1533 u8 *vpd_table, u8 type)
1534{
1535 u8 idx[2] = { 0, 1 };
1536 s16 pwr_i = 2*pmin;
1537 int i;
1538
1539 if (num_points < 2)
1540 return;
1541
1542 /* We want the whole line, so adjust boundaries
1543 * to cover the entire power range. Note that
1544 * power values are already 0.25dB so no need
1545 * to multiply pwr_i by 2 */
1546 if (type == AR5K_PWRTABLE_LINEAR_PCDAC) {
1547 pwr_i = pmin;
1548 pmin = 0;
1549 pmax = 63;
1550 }
1551
1552 /* Find surrounding turning points (TPs)
1553 * and interpolate between them */
1554 for (i = 0; (i <= (u16) (pmax - pmin)) &&
1555 (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) {
1556
1557 /* We passed the right TP, move to the next set of TPs
1558 * if we pass the last TP, extrapolate above using the last
1559 * two TPs for ratio */
1560 if ((pwr_i > pwr[idx[1]]) && (idx[1] < num_points - 1)) {
1561 idx[0]++;
1562 idx[1]++;
1563 }
1564
1565 vpd_table[i] = (u8) ath5k_get_interpolated_value(pwr_i,
1566 pwr[idx[0]], pwr[idx[1]],
1567 vpd[idx[0]], vpd[idx[1]]);
1568
1569 /* Increase by 0.5dB
1570 * (0.25 dB units) */
1571 pwr_i += 2;
1572 }
1573}
1574
1575/*
1576 * Get the surrounding per-channel power calibration piers
1577 * for a given frequency so that we can interpolate between
1578 * them and come up with an apropriate dataset for our current
1579 * channel.
1580 */
1581static void
1582ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah,
1583 struct ieee80211_channel *channel,
1584 struct ath5k_chan_pcal_info **pcinfo_l,
1585 struct ath5k_chan_pcal_info **pcinfo_r)
1586{
1587 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1588 struct ath5k_chan_pcal_info *pcinfo;
1589 u8 idx_l, idx_r;
1590 u8 mode, max, i;
1591 u32 target = channel->center_freq;
1592
1593 idx_l = 0;
1594 idx_r = 0;
1595
1596 if (!(channel->hw_value & CHANNEL_OFDM)) {
1597 pcinfo = ee->ee_pwr_cal_b;
1598 mode = AR5K_EEPROM_MODE_11B;
1599 } else if (channel->hw_value & CHANNEL_2GHZ) {
1600 pcinfo = ee->ee_pwr_cal_g;
1601 mode = AR5K_EEPROM_MODE_11G;
1602 } else {
1603 pcinfo = ee->ee_pwr_cal_a;
1604 mode = AR5K_EEPROM_MODE_11A;
1605 }
1606 max = ee->ee_n_piers[mode] - 1;
1607
1608 /* Frequency is below our calibrated
1609 * range. Use the lowest power curve
1610 * we have */
1611 if (target < pcinfo[0].freq) {
1612 idx_l = idx_r = 0;
1613 goto done;
1614 }
1615
1616 /* Frequency is above our calibrated
1617 * range. Use the highest power curve
1618 * we have */
1619 if (target > pcinfo[max].freq) {
1620 idx_l = idx_r = max;
1621 goto done;
1622 }
1623
1624 /* Frequency is inside our calibrated
1625 * channel range. Pick the surrounding
1626 * calibration piers so that we can
1627 * interpolate */
1628 for (i = 0; i <= max; i++) {
1629
1630 /* Frequency matches one of our calibration
1631 * piers, no need to interpolate, just use
1632 * that calibration pier */
1633 if (pcinfo[i].freq == target) {
1634 idx_l = idx_r = i;
1635 goto done;
1636 }
1637
1638 /* We found a calibration pier that's above
1639 * frequency, use this pier and the previous
1640 * one to interpolate */
1641 if (target < pcinfo[i].freq) {
1642 idx_r = i;
1643 idx_l = idx_r - 1;
1644 goto done;
1645 }
1646 }
1647
1648done:
1649 *pcinfo_l = &pcinfo[idx_l];
1650 *pcinfo_r = &pcinfo[idx_r];
1651
1652 return;
1653}
1654
1655/*
1656 * Get the surrounding per-rate power calibration data
1657 * for a given frequency and interpolate between power
1658 * values to set max target power supported by hw for
1659 * each rate.
1660 */
1661static void
1662ath5k_get_rate_pcal_data(struct ath5k_hw *ah,
1663 struct ieee80211_channel *channel,
1664 struct ath5k_rate_pcal_info *rates)
1665{
1666 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1667 struct ath5k_rate_pcal_info *rpinfo;
1668 u8 idx_l, idx_r;
1669 u8 mode, max, i;
1670 u32 target = channel->center_freq;
1671
1672 idx_l = 0;
1673 idx_r = 0;
1674
1675 if (!(channel->hw_value & CHANNEL_OFDM)) {
1676 rpinfo = ee->ee_rate_tpwr_b;
1677 mode = AR5K_EEPROM_MODE_11B;
1678 } else if (channel->hw_value & CHANNEL_2GHZ) {
1679 rpinfo = ee->ee_rate_tpwr_g;
1680 mode = AR5K_EEPROM_MODE_11G;
1681 } else {
1682 rpinfo = ee->ee_rate_tpwr_a;
1683 mode = AR5K_EEPROM_MODE_11A;
1684 }
1685 max = ee->ee_rate_target_pwr_num[mode] - 1;
1686
1687 /* Get the surrounding calibration
1688 * piers - same as above */
1689 if (target < rpinfo[0].freq) {
1690 idx_l = idx_r = 0;
1691 goto done;
1692 }
1693
1694 if (target > rpinfo[max].freq) {
1695 idx_l = idx_r = max;
1696 goto done;
1697 }
1698
1699 for (i = 0; i <= max; i++) {
1700
1701 if (rpinfo[i].freq == target) {
1702 idx_l = idx_r = i;
1703 goto done;
1704 }
1705
1706 if (target < rpinfo[i].freq) {
1707 idx_r = i;
1708 idx_l = idx_r - 1;
1709 goto done;
1710 }
1711 }
1712
1713done:
1714 /* Now interpolate power value, based on the frequency */
1715 rates->freq = target;
1716
1717 rates->target_power_6to24 =
1718 ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
1719 rpinfo[idx_r].freq,
1720 rpinfo[idx_l].target_power_6to24,
1721 rpinfo[idx_r].target_power_6to24);
1722
1723 rates->target_power_36 =
1724 ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
1725 rpinfo[idx_r].freq,
1726 rpinfo[idx_l].target_power_36,
1727 rpinfo[idx_r].target_power_36);
1728
1729 rates->target_power_48 =
1730 ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
1731 rpinfo[idx_r].freq,
1732 rpinfo[idx_l].target_power_48,
1733 rpinfo[idx_r].target_power_48);
1734
1735 rates->target_power_54 =
1736 ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
1737 rpinfo[idx_r].freq,
1738 rpinfo[idx_l].target_power_54,
1739 rpinfo[idx_r].target_power_54);
1740}
1741
1742/*
1743 * Get the max edge power for this channel if
1744 * we have such data from EEPROM's Conformance Test
1745 * Limits (CTL), and limit max power if needed.
1746 *
1747 * FIXME: Only works for world regulatory domains
1748 */
1749static void
1750ath5k_get_max_ctl_power(struct ath5k_hw *ah,
1751 struct ieee80211_channel *channel)
1752{
1753 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1754 struct ath5k_edge_power *rep = ee->ee_ctl_pwr;
1755 u8 *ctl_val = ee->ee_ctl;
1756 s16 max_chan_pwr = ah->ah_txpower.txp_max_pwr / 4;
1757 s16 edge_pwr = 0;
1758 u8 rep_idx;
1759 u8 i, ctl_mode;
1760 u8 ctl_idx = 0xFF;
1761 u32 target = channel->center_freq;
1762
1763 /* Find out a CTL for our mode that's not mapped
1764 * on a specific reg domain.
1765 *
1766 * TODO: Map our current reg domain to one of the 3 available
1767 * reg domain ids so that we can support more CTLs. */
1768 switch (channel->hw_value & CHANNEL_MODES) {
1769 case CHANNEL_A:
1770 ctl_mode = AR5K_CTL_11A | AR5K_CTL_NO_REGDOMAIN;
1771 break;
1772 case CHANNEL_G:
1773 ctl_mode = AR5K_CTL_11G | AR5K_CTL_NO_REGDOMAIN;
1774 break;
1775 case CHANNEL_B:
1776 ctl_mode = AR5K_CTL_11B | AR5K_CTL_NO_REGDOMAIN;
1777 break;
1778 case CHANNEL_T:
1779 ctl_mode = AR5K_CTL_TURBO | AR5K_CTL_NO_REGDOMAIN;
1780 break;
1781 case CHANNEL_TG:
1782 ctl_mode = AR5K_CTL_TURBOG | AR5K_CTL_NO_REGDOMAIN;
1783 break;
1784 case CHANNEL_XR:
1785 /* Fall through */
1786 default:
1787 return;
1788 }
1789
1790 for (i = 0; i < ee->ee_ctls; i++) {
1791 if (ctl_val[i] == ctl_mode) {
1792 ctl_idx = i;
1793 break;
1794 }
1795 }
1796
1797 /* If we have a CTL dataset available grab it and find the
1798 * edge power for our frequency */
1799 if (ctl_idx == 0xFF)
1800 return;
1801
1802 /* Edge powers are sorted by frequency from lower
1803 * to higher. Each CTL corresponds to 8 edge power
1804 * measurements. */
1805 rep_idx = ctl_idx * AR5K_EEPROM_N_EDGES;
1806
1807 /* Don't do boundaries check because we
1808 * might have more that one bands defined
1809 * for this mode */
1810
1811 /* Get the edge power that's closer to our
1812 * frequency */
1813 for (i = 0; i < AR5K_EEPROM_N_EDGES; i++) {
1814 rep_idx += i;
1815 if (target <= rep[rep_idx].freq)
1816 edge_pwr = (s16) rep[rep_idx].edge;
1817 }
1818
1819 if (edge_pwr)
1820 ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr);
1821}
1822
1823
1824/*
1825 * Power to PCDAC table functions
1826 */
1827
1828/*
1829 * Fill Power to PCDAC table on RF5111
1830 *
1831 * No further processing is needed for RF5111, the only thing we have to
1832 * do is fill the values below and above calibration range since eeprom data
1833 * may not cover the entire PCDAC table.
1834 */
1835static void
1836ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min,
1837 s16 *table_max)
1838{
1839 u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
1840 u8 *pcdac_tmp = ah->ah_txpower.tmpL[0];
1841 u8 pcdac_0, pcdac_n, pcdac_i, pwr_idx, i;
1842 s16 min_pwr, max_pwr;
1843
1844 /* Get table boundaries */
1845 min_pwr = table_min[0];
1846 pcdac_0 = pcdac_tmp[0];
1847
1848 max_pwr = table_max[0];
1849 pcdac_n = pcdac_tmp[table_max[0] - table_min[0]];
1850
1851 /* Extrapolate below minimum using pcdac_0 */
1852 pcdac_i = 0;
1853 for (i = 0; i < min_pwr; i++)
1854 pcdac_out[pcdac_i++] = pcdac_0;
1855
1856 /* Copy values from pcdac_tmp */
1857 pwr_idx = min_pwr;
1858 for (i = 0 ; pwr_idx <= max_pwr &&
1859 pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) {
1860 pcdac_out[pcdac_i++] = pcdac_tmp[i];
1861 pwr_idx++;
1862 }
1863
1864 /* Extrapolate above maximum */
1865 while (pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE)
1866 pcdac_out[pcdac_i++] = pcdac_n;
1867
1868}
1869
1870/*
1871 * Combine available XPD Curves and fill Linear Power to PCDAC table
1872 * on RF5112
1873 *
1874 * RFX112 can have up to 2 curves (one for low txpower range and one for
1875 * higher txpower range). We need to put them both on pcdac_out and place
1876 * them in the correct location. In case we only have one curve available
1877 * just fit it on pcdac_out (it's supposed to cover the entire range of
1878 * available pwr levels since it's always the higher power curve). Extrapolate
1879 * below and above final table if needed.
1880 */
1881static void
1882ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
1883 s16 *table_max, u8 pdcurves)
1884{
1885 u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
1886 u8 *pcdac_low_pwr;
1887 u8 *pcdac_high_pwr;
1888 u8 *pcdac_tmp;
1889 u8 pwr;
1890 s16 max_pwr_idx;
1891 s16 min_pwr_idx;
1892 s16 mid_pwr_idx = 0;
1893 /* Edge flag turs on the 7nth bit on the PCDAC
1894 * to delcare the higher power curve (force values
1895 * to be greater than 64). If we only have one curve
1896 * we don't need to set this, if we have 2 curves and
1897 * fill the table backwards this can also be used to
1898 * switch from higher power curve to lower power curve */
1899 u8 edge_flag;
1900 int i;
1901
1902 /* When we have only one curve available
1903 * that's the higher power curve. If we have
1904 * two curves the first is the high power curve
1905 * and the next is the low power curve. */
1906 if (pdcurves > 1) {
1907 pcdac_low_pwr = ah->ah_txpower.tmpL[1];
1908 pcdac_high_pwr = ah->ah_txpower.tmpL[0];
1909 mid_pwr_idx = table_max[1] - table_min[1] - 1;
1910 max_pwr_idx = (table_max[0] - table_min[0]) / 2;
1911
1912 /* If table size goes beyond 31.5dB, keep the
1913 * upper 31.5dB range when setting tx power.
1914 * Note: 126 = 31.5 dB in quarter dB steps */
1915 if (table_max[0] - table_min[1] > 126)
1916 min_pwr_idx = table_max[0] - 126;
1917 else
1918 min_pwr_idx = table_min[1];
1919
1920 /* Since we fill table backwards
1921 * start from high power curve */
1922 pcdac_tmp = pcdac_high_pwr;
1923
1924 edge_flag = 0x40;
1925#if 0
1926 /* If both min and max power limits are in lower
1927 * power curve's range, only use the low power curve.
1928 * TODO: min/max levels are related to target
1929 * power values requested from driver/user
1930 * XXX: Is this really needed ? */
1931 if (min_pwr < table_max[1] &&
1932 max_pwr < table_max[1]) {
1933 edge_flag = 0;
1934 pcdac_tmp = pcdac_low_pwr;
1935 max_pwr_idx = (table_max[1] - table_min[1])/2;
1936 }
1937#endif
1938 } else {
1939 pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */
1940 pcdac_high_pwr = ah->ah_txpower.tmpL[0];
1941 min_pwr_idx = table_min[0];
1942 max_pwr_idx = (table_max[0] - table_min[0]) / 2;
1943 pcdac_tmp = pcdac_high_pwr;
1944 edge_flag = 0;
1945 }
1946
1947 /* This is used when setting tx power*/
1948 ah->ah_txpower.txp_min_idx = min_pwr_idx/2;
1949
1950 /* Fill Power to PCDAC table backwards */
1951 pwr = max_pwr_idx;
1952 for (i = 63; i >= 0; i--) {
1953 /* Entering lower power range, reset
1954 * edge flag and set pcdac_tmp to lower
1955 * power curve.*/
1956 if (edge_flag == 0x40 &&
1957 (2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) {
1958 edge_flag = 0x00;
1959 pcdac_tmp = pcdac_low_pwr;
1960 pwr = mid_pwr_idx/2;
1961 }
1962
1963 /* Don't go below 1, extrapolate below if we have
1964 * already swithced to the lower power curve -or
1965 * we only have one curve and edge_flag is zero
1966 * anyway */
1967 if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) {
1968 while (i >= 0) {
1969 pcdac_out[i] = pcdac_out[i + 1];
1970 i--;
1971 }
1972 break;
1973 }
1974
1975 pcdac_out[i] = pcdac_tmp[pwr] | edge_flag;
1976
1977 /* Extrapolate above if pcdac is greater than
1978 * 126 -this can happen because we OR pcdac_out
1979 * value with edge_flag on high power curve */
1980 if (pcdac_out[i] > 126)
1981 pcdac_out[i] = 126;
1982
1983 /* Decrease by a 0.5dB step */
1984 pwr--;
1985 }
1986}
1987
1988/* Write PCDAC values on hw */
1989static void
1990ath5k_setup_pcdac_table(struct ath5k_hw *ah)
1991{
1992 u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
1993 int i;
1994
1995 /*
1996 * Write TX power values
1997 */
1998 for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
1999 ath5k_hw_reg_write(ah,
2000 (((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) |
2001 (((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16),
2002 AR5K_PHY_PCDAC_TXPOWER(i));
2003 }
2004}
2005
2006
2007/*
2008 * Power to PDADC table functions
2009 */
2010
2011/*
2012 * Set the gain boundaries and create final Power to PDADC table
2013 *
2014 * We can have up to 4 pd curves, we need to do a simmilar process
2015 * as we do for RF5112. This time we don't have an edge_flag but we
2016 * set the gain boundaries on a separate register.
2017 */
2018static void
2019ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah,
2020 s16 *pwr_min, s16 *pwr_max, u8 pdcurves)
2021{
2022 u8 gain_boundaries[AR5K_EEPROM_N_PD_GAINS];
2023 u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
2024 u8 *pdadc_tmp;
2025 s16 pdadc_0;
2026 u8 pdadc_i, pdadc_n, pwr_step, pdg, max_idx, table_size;
2027 u8 pd_gain_overlap;
2028
2029 /* Note: Register value is initialized on initvals
2030 * there is no feedback from hw.
2031 * XXX: What about pd_gain_overlap from EEPROM ? */
2032 pd_gain_overlap = (u8) ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG5) &
2033 AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP;
2034
2035 /* Create final PDADC table */
2036 for (pdg = 0, pdadc_i = 0; pdg < pdcurves; pdg++) {
2037 pdadc_tmp = ah->ah_txpower.tmpL[pdg];
2038
2039 if (pdg == pdcurves - 1)
2040 /* 2 dB boundary stretch for last
2041 * (higher power) curve */
2042 gain_boundaries[pdg] = pwr_max[pdg] + 4;
2043 else
2044 /* Set gain boundary in the middle
2045 * between this curve and the next one */
2046 gain_boundaries[pdg] =
2047 (pwr_max[pdg] + pwr_min[pdg + 1]) / 2;
2048
2049 /* Sanity check in case our 2 db stretch got out of
2050 * range. */
2051 if (gain_boundaries[pdg] > AR5K_TUNE_MAX_TXPOWER)
2052 gain_boundaries[pdg] = AR5K_TUNE_MAX_TXPOWER;
2053
2054 /* For the first curve (lower power)
2055 * start from 0 dB */
2056 if (pdg == 0)
2057 pdadc_0 = 0;
2058 else
2059 /* For the other curves use the gain overlap */
2060 pdadc_0 = (gain_boundaries[pdg - 1] - pwr_min[pdg]) -
2061 pd_gain_overlap;
2062
2063 /* Force each power step to be at least 0.5 dB */
2064 if ((pdadc_tmp[1] - pdadc_tmp[0]) > 1)
2065 pwr_step = pdadc_tmp[1] - pdadc_tmp[0];
2066 else
2067 pwr_step = 1;
2068
2069 /* If pdadc_0 is negative, we need to extrapolate
2070 * below this pdgain by a number of pwr_steps */
2071 while ((pdadc_0 < 0) && (pdadc_i < 128)) {
2072 s16 tmp = pdadc_tmp[0] + pdadc_0 * pwr_step;
2073 pdadc_out[pdadc_i++] = (tmp < 0) ? 0 : (u8) tmp;
2074 pdadc_0++;
2075 }
2076
2077 /* Set last pwr level, using gain boundaries */
2078 pdadc_n = gain_boundaries[pdg] + pd_gain_overlap - pwr_min[pdg];
2079 /* Limit it to be inside pwr range */
2080 table_size = pwr_max[pdg] - pwr_min[pdg];
2081 max_idx = (pdadc_n < table_size) ? pdadc_n : table_size;
2082
2083 /* Fill pdadc_out table */
2084 while (pdadc_0 < max_idx)
2085 pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++];
2086
2087 /* Need to extrapolate above this pdgain? */
2088 if (pdadc_n <= max_idx)
2089 continue;
2090
2091 /* Force each power step to be at least 0.5 dB */
2092 if ((pdadc_tmp[table_size - 1] - pdadc_tmp[table_size - 2]) > 1)
2093 pwr_step = pdadc_tmp[table_size - 1] -
2094 pdadc_tmp[table_size - 2];
2095 else
2096 pwr_step = 1;
2097
2098 /* Extrapolate above */
2099 while ((pdadc_0 < (s16) pdadc_n) &&
2100 (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2)) {
2101 s16 tmp = pdadc_tmp[table_size - 1] +
2102 (pdadc_0 - max_idx) * pwr_step;
2103 pdadc_out[pdadc_i++] = (tmp > 127) ? 127 : (u8) tmp;
2104 pdadc_0++;
2105 }
2106 }
2107
2108 while (pdg < AR5K_EEPROM_N_PD_GAINS) {
2109 gain_boundaries[pdg] = gain_boundaries[pdg - 1];
2110 pdg++;
2111 }
2112
2113 while (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2) {
2114 pdadc_out[pdadc_i] = pdadc_out[pdadc_i - 1];
2115 pdadc_i++;
2116 }
2117
2118 /* Set gain boundaries */
2119 ath5k_hw_reg_write(ah,
2120 AR5K_REG_SM(pd_gain_overlap,
2121 AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP) |
2122 AR5K_REG_SM(gain_boundaries[0],
2123 AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1) |
2124 AR5K_REG_SM(gain_boundaries[1],
2125 AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2) |
2126 AR5K_REG_SM(gain_boundaries[2],
2127 AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3) |
2128 AR5K_REG_SM(gain_boundaries[3],
2129 AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4),
2130 AR5K_PHY_TPC_RG5);
2131
2132 /* Used for setting rate power table */
2133 ah->ah_txpower.txp_min_idx = pwr_min[0];
2134
2135}
2136
2137/* Write PDADC values on hw */
2138static void
2139ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah,
2140 u8 pdcurves, u8 *pdg_to_idx)
2141{
2142 u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
2143 u32 reg;
2144 u8 i;
2145
2146 /* Select the right pdgain curves */
2147
2148 /* Clear current settings */
2149 reg = ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG1);
2150 reg &= ~(AR5K_PHY_TPC_RG1_PDGAIN_1 |
2151 AR5K_PHY_TPC_RG1_PDGAIN_2 |
2152 AR5K_PHY_TPC_RG1_PDGAIN_3 |
2153 AR5K_PHY_TPC_RG1_NUM_PD_GAIN);
2154
2155 /*
2156 * Use pd_gains curve from eeprom
2157 *
2158 * This overrides the default setting from initvals
2159 * in case some vendors (e.g. Zcomax) don't use the default
2160 * curves. If we don't honor their settings we 'll get a
2161 * 5dB (1 * gain overlap ?) drop.
2162 */
2163 reg |= AR5K_REG_SM(pdcurves, AR5K_PHY_TPC_RG1_NUM_PD_GAIN);
2164
2165 switch (pdcurves) {
2166 case 3:
2167 reg |= AR5K_REG_SM(pdg_to_idx[2], AR5K_PHY_TPC_RG1_PDGAIN_3);
2168 /* Fall through */
2169 case 2:
2170 reg |= AR5K_REG_SM(pdg_to_idx[1], AR5K_PHY_TPC_RG1_PDGAIN_2);
2171 /* Fall through */
2172 case 1:
2173 reg |= AR5K_REG_SM(pdg_to_idx[0], AR5K_PHY_TPC_RG1_PDGAIN_1);
2174 break;
2175 }
2176 ath5k_hw_reg_write(ah, reg, AR5K_PHY_TPC_RG1);
2177
2178 /*
2179 * Write TX power values
2180 */
2181 for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
2182 ath5k_hw_reg_write(ah,
2183 ((pdadc_out[4*i + 0] & 0xff) << 0) |
2184 ((pdadc_out[4*i + 1] & 0xff) << 8) |
2185 ((pdadc_out[4*i + 2] & 0xff) << 16) |
2186 ((pdadc_out[4*i + 3] & 0xff) << 24),
2187 AR5K_PHY_PDADC_TXPOWER(i));
2188 }
2189}
2190
2191
2192/*
2193 * Common code for PCDAC/PDADC tables
2194 */
2195
2196/*
2197 * This is the main function that uses all of the above
2198 * to set PCDAC/PDADC table on hw for the current channel.
2199 * This table is used for tx power calibration on the basband,
2200 * without it we get weird tx power levels and in some cases
2201 * distorted spectral mask
2202 */
2203static int
2204ath5k_setup_channel_powertable(struct ath5k_hw *ah,
2205 struct ieee80211_channel *channel,
2206 u8 ee_mode, u8 type)
2207{
2208 struct ath5k_pdgain_info *pdg_L, *pdg_R;
2209 struct ath5k_chan_pcal_info *pcinfo_L;
2210 struct ath5k_chan_pcal_info *pcinfo_R;
2211 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
2212 u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode];
2213 s16 table_min[AR5K_EEPROM_N_PD_GAINS];
2214 s16 table_max[AR5K_EEPROM_N_PD_GAINS];
2215 u8 *tmpL;
2216 u8 *tmpR;
2217 u32 target = channel->center_freq;
2218 int pdg, i;
2219
2220 /* Get surounding freq piers for this channel */
2221 ath5k_get_chan_pcal_surrounding_piers(ah, channel,
2222 &pcinfo_L,
2223 &pcinfo_R);
2224
2225 /* Loop over pd gain curves on
2226 * surounding freq piers by index */
2227 for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) {
2228
2229 /* Fill curves in reverse order
2230 * from lower power (max gain)
2231 * to higher power. Use curve -> idx
2232 * backmaping we did on eeprom init */
2233 u8 idx = pdg_curve_to_idx[pdg];
2234
2235 /* Grab the needed curves by index */
2236 pdg_L = &pcinfo_L->pd_curves[idx];
2237 pdg_R = &pcinfo_R->pd_curves[idx];
2238
2239 /* Initialize the temp tables */
2240 tmpL = ah->ah_txpower.tmpL[pdg];
2241 tmpR = ah->ah_txpower.tmpR[pdg];
2242
2243 /* Set curve's x boundaries and create
2244 * curves so that they cover the same
2245 * range (if we don't do that one table
2246 * will have values on some range and the
2247 * other one won't have any so interpolation
2248 * will fail) */
2249 table_min[pdg] = min(pdg_L->pd_pwr[0],
2250 pdg_R->pd_pwr[0]) / 2;
2251
2252 table_max[pdg] = max(pdg_L->pd_pwr[pdg_L->pd_points - 1],
2253 pdg_R->pd_pwr[pdg_R->pd_points - 1]) / 2;
2254
2255 /* Now create the curves on surrounding channels
2256 * and interpolate if needed to get the final
2257 * curve for this gain on this channel */
2258 switch (type) {
2259 case AR5K_PWRTABLE_LINEAR_PCDAC:
2260 /* Override min/max so that we don't loose
2261 * accuracy (don't divide by 2) */
2262 table_min[pdg] = min(pdg_L->pd_pwr[0],
2263 pdg_R->pd_pwr[0]);
2264
2265 table_max[pdg] =
2266 max(pdg_L->pd_pwr[pdg_L->pd_points - 1],
2267 pdg_R->pd_pwr[pdg_R->pd_points - 1]);
2268
2269 /* Override minimum so that we don't get
2270 * out of bounds while extrapolating
2271 * below. Don't do this when we have 2
2272 * curves and we are on the high power curve
2273 * because table_min is ok in this case */
2274 if (!(ee->ee_pd_gains[ee_mode] > 1 && pdg == 0)) {
2275
2276 table_min[pdg] =
2277 ath5k_get_linear_pcdac_min(pdg_L->pd_step,
2278 pdg_R->pd_step,
2279 pdg_L->pd_pwr,
2280 pdg_R->pd_pwr);
2281
2282 /* Don't go too low because we will
2283 * miss the upper part of the curve.
2284 * Note: 126 = 31.5dB (max power supported)
2285 * in 0.25dB units */
2286 if (table_max[pdg] - table_min[pdg] > 126)
2287 table_min[pdg] = table_max[pdg] - 126;
2288 }
2289
2290 /* Fall through */
2291 case AR5K_PWRTABLE_PWR_TO_PCDAC:
2292 case AR5K_PWRTABLE_PWR_TO_PDADC:
2293
2294 ath5k_create_power_curve(table_min[pdg],
2295 table_max[pdg],
2296 pdg_L->pd_pwr,
2297 pdg_L->pd_step,
2298 pdg_L->pd_points, tmpL, type);
2299
2300 /* We are in a calibration
2301 * pier, no need to interpolate
2302 * between freq piers */
2303 if (pcinfo_L == pcinfo_R)
2304 continue;
2305
2306 ath5k_create_power_curve(table_min[pdg],
2307 table_max[pdg],
2308 pdg_R->pd_pwr,
2309 pdg_R->pd_step,
2310 pdg_R->pd_points, tmpR, type);
2311 break;
2312 default:
2313 return -EINVAL;
2314 }
2315
2316 /* Interpolate between curves
2317 * of surounding freq piers to
2318 * get the final curve for this
2319 * pd gain. Re-use tmpL for interpolation
2320 * output */
2321 for (i = 0; (i < (u16) (table_max[pdg] - table_min[pdg])) &&
2322 (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) {
2323 tmpL[i] = (u8) ath5k_get_interpolated_value(target,
2324 (s16) pcinfo_L->freq,
2325 (s16) pcinfo_R->freq,
2326 (s16) tmpL[i],
2327 (s16) tmpR[i]);
2328 }
2329 }
2330
2331 /* Now we have a set of curves for this
2332 * channel on tmpL (x range is table_max - table_min
2333 * and y values are tmpL[pdg][]) sorted in the same
2334 * order as EEPROM (because we've used the backmaping).
2335 * So for RF5112 it's from higher power to lower power
2336 * and for RF2413 it's from lower power to higher power.
2337 * For RF5111 we only have one curve. */
2338
2339 /* Fill min and max power levels for this
2340 * channel by interpolating the values on
2341 * surounding channels to complete the dataset */
2342 ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target,
2343 (s16) pcinfo_L->freq,
2344 (s16) pcinfo_R->freq,
2345 pcinfo_L->min_pwr, pcinfo_R->min_pwr);
2346
2347 ah->ah_txpower.txp_max_pwr = ath5k_get_interpolated_value(target,
2348 (s16) pcinfo_L->freq,
2349 (s16) pcinfo_R->freq,
2350 pcinfo_L->max_pwr, pcinfo_R->max_pwr);
2351
2352 /* We are ready to go, fill PCDAC/PDADC
2353 * table and write settings on hardware */
2354 switch (type) {
2355 case AR5K_PWRTABLE_LINEAR_PCDAC:
2356 /* For RF5112 we can have one or two curves
2357 * and each curve covers a certain power lvl
2358 * range so we need to do some more processing */
2359 ath5k_combine_linear_pcdac_curves(ah, table_min, table_max,
2360 ee->ee_pd_gains[ee_mode]);
2361
2362 /* Set txp.offset so that we can
2363 * match max power value with max
2364 * table index */
2365 ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2);
2366
2367 /* Write settings on hw */
2368 ath5k_setup_pcdac_table(ah);
2369 break;
2370 case AR5K_PWRTABLE_PWR_TO_PCDAC:
2371 /* We are done for RF5111 since it has only
2372 * one curve, just fit the curve on the table */
2373 ath5k_fill_pwr_to_pcdac_table(ah, table_min, table_max);
2374
2375 /* No rate powertable adjustment for RF5111 */
2376 ah->ah_txpower.txp_min_idx = 0;
2377 ah->ah_txpower.txp_offset = 0;
2378
2379 /* Write settings on hw */
2380 ath5k_setup_pcdac_table(ah);
2381 break;
2382 case AR5K_PWRTABLE_PWR_TO_PDADC:
2383 /* Set PDADC boundaries and fill
2384 * final PDADC table */
2385 ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max,
2386 ee->ee_pd_gains[ee_mode]);
2387
2388 /* Write settings on hw */
2389 ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx);
2390
2391 /* Set txp.offset, note that table_min
2392 * can be negative */
2393 ah->ah_txpower.txp_offset = table_min[0];
2394 break;
2395 default:
2396 return -EINVAL;
2397 }
2398
2399 return 0;
2400}
2401
2402
2403/*
2404 * Per-rate tx power setting
2405 *
2406 * This is the code that sets the desired tx power (below
2407 * maximum) on hw for each rate (we also have TPC that sets
2408 * power per packet). We do that by providing an index on the
2409 * PCDAC/PDADC table we set up.
2410 */
2411
2412/*
2413 * Set rate power table
2414 *
2415 * For now we only limit txpower based on maximum tx power
2416 * supported by hw (what's inside rate_info). We need to limit
2417 * this even more, based on regulatory domain etc.
2418 *
2419 * Rate power table contains indices to PCDAC/PDADC table (0.5dB steps)
2420 * and is indexed as follows:
2421 * rates[0] - rates[7] -> OFDM rates
2422 * rates[8] - rates[14] -> CCK rates
2423 * rates[15] -> XR rates (they all have the same power)
2424 */
2425static void
2426ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
2427 struct ath5k_rate_pcal_info *rate_info,
2428 u8 ee_mode)
2429{
2430 unsigned int i;
2431 u16 *rates;
2432
2433 /* max_pwr is power level we got from driver/user in 0.5dB
2434 * units, switch to 0.25dB units so we can compare */
2435 max_pwr *= 2;
2436 max_pwr = min(max_pwr, (u16) ah->ah_txpower.txp_max_pwr) / 2;
2437
2438 /* apply rate limits */
2439 rates = ah->ah_txpower.txp_rates_power_table;
2440
2441 /* OFDM rates 6 to 24Mb/s */
2442 for (i = 0; i < 5; i++)
2443 rates[i] = min(max_pwr, rate_info->target_power_6to24);
2444
2445 /* Rest OFDM rates */
2446 rates[5] = min(rates[0], rate_info->target_power_36);
2447 rates[6] = min(rates[0], rate_info->target_power_48);
2448 rates[7] = min(rates[0], rate_info->target_power_54);
2449
2450 /* CCK rates */
2451 /* 1L */
2452 rates[8] = min(rates[0], rate_info->target_power_6to24);
2453 /* 2L */
2454 rates[9] = min(rates[0], rate_info->target_power_36);
2455 /* 2S */
2456 rates[10] = min(rates[0], rate_info->target_power_36);
2457 /* 5L */
2458 rates[11] = min(rates[0], rate_info->target_power_48);
2459 /* 5S */
2460 rates[12] = min(rates[0], rate_info->target_power_48);
2461 /* 11L */
2462 rates[13] = min(rates[0], rate_info->target_power_54);
2463 /* 11S */
2464 rates[14] = min(rates[0], rate_info->target_power_54);
2465
2466 /* XR rates */
2467 rates[15] = min(rates[0], rate_info->target_power_6to24);
2468
2469 /* CCK rates have different peak to average ratio
2470 * so we have to tweak their power so that gainf
2471 * correction works ok. For this we use OFDM to
2472 * CCK delta from eeprom */
2473 if ((ee_mode == AR5K_EEPROM_MODE_11G) &&
2474 (ah->ah_phy_revision < AR5K_SREV_PHY_5212A))
2475 for (i = 8; i <= 15; i++)
2476 rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta;
2477
2478 ah->ah_txpower.txp_min_pwr = rates[7];
2479 ah->ah_txpower.txp_max_pwr = rates[0];
2480 ah->ah_txpower.txp_ofdm = rates[7];
2481}
2482
2483
2484/*
2485 * Set transmition power
2486 */
2487int
2488ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
2489 u8 ee_mode, u8 txpower)
2490{
2491 struct ath5k_rate_pcal_info rate_info;
2492 u8 type;
2493 int ret;
2494
2495 ATH5K_TRACE(ah->ah_sc);
2496 if (txpower > AR5K_TUNE_MAX_TXPOWER) {
2497 ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
2498 return -EINVAL;
2499 }
2500 if (txpower == 0)
2501 txpower = AR5K_TUNE_DEFAULT_TXPOWER;
2502
2503 /* Reset TX power values */
2504 memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
2505 ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
2506 ah->ah_txpower.txp_min_pwr = 0;
2507 ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER;
2508
2509 /* Initialize TX power table */
2510 switch (ah->ah_radio) {
2511 case AR5K_RF5111:
2512 type = AR5K_PWRTABLE_PWR_TO_PCDAC;
2513 break;
2514 case AR5K_RF5112:
2515 type = AR5K_PWRTABLE_LINEAR_PCDAC;
2516 break;
2517 case AR5K_RF2413:
2518 case AR5K_RF5413:
2519 case AR5K_RF2316:
2520 case AR5K_RF2317:
2521 case AR5K_RF2425:
2522 type = AR5K_PWRTABLE_PWR_TO_PDADC;
2523 break;
2524 default:
2525 return -EINVAL;
2526 }
2527
2528 /* FIXME: Only on channel/mode change */
2529 ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type);
2530 if (ret)
2531 return ret;
2532
2533 /* Limit max power if we have a CTL available */
2534 ath5k_get_max_ctl_power(ah, channel);
2535
2536 /* FIXME: Tx power limit for this regdomain
2537 * XXX: Mac80211/CRDA will do that anyway ? */
2538
2539 /* FIXME: Antenna reduction stuff */
2540
2541 /* FIXME: Limit power on turbo modes */
2542
2543 /* FIXME: TPC scale reduction */
2544
2545 /* Get surounding channels for per-rate power table
2546 * calibration */
2547 ath5k_get_rate_pcal_data(ah, channel, &rate_info);
2548
2549 /* Setup rate power table */
2550 ath5k_setup_rate_powertable(ah, txpower, &rate_info, ee_mode);
2551
2552 /* Write rate power table on hw */
2553 ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(3, 24) |
2554 AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) |
2555 AR5K_TXPOWER_OFDM(0, 0), AR5K_PHY_TXPOWER_RATE1);
2556
2557 ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(7, 24) |
2558 AR5K_TXPOWER_OFDM(6, 16) | AR5K_TXPOWER_OFDM(5, 8) |
2559 AR5K_TXPOWER_OFDM(4, 0), AR5K_PHY_TXPOWER_RATE2);
2560
2561 ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(10, 24) |
2562 AR5K_TXPOWER_CCK(9, 16) | AR5K_TXPOWER_CCK(15, 8) |
2563 AR5K_TXPOWER_CCK(8, 0), AR5K_PHY_TXPOWER_RATE3);
2564
2565 ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(14, 24) |
2566 AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) |
2567 AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4);
2568
2569 /* FIXME: TPC support */
2570 if (ah->ah_txpower.txp_tpc) {
2571 ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE |
2572 AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
2573
2574 ath5k_hw_reg_write(ah,
2575 AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_ACK) |
2576 AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CTS) |
2577 AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CHIRP),
2578 AR5K_TPC);
2579 } else {
2580 ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX |
2581 AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
2582 }
2583
2584 return 0;
2585}
2586
2587int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 mode, u8 txpower)
2588{
2589 /*Just a try M.F.*/
2590 struct ieee80211_channel *channel = &ah->ah_current_channel;
2591
2592 ATH5K_TRACE(ah->ah_sc);
2593 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
2594 "changing txpower to %d\n", txpower);
2595
2596 return ath5k_hw_txpower(ah, channel, mode, txpower);
2597}
2598
2599#undef _ATH5K_PHY
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
new file mode 100644
index 000000000000..5094c394a4b2
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -0,0 +1,546 @@
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 */
18
19/********************************************\
20Queue Control Unit, DFS Control Unit Functions
21\********************************************/
22
23#include "ath5k.h"
24#include "reg.h"
25#include "debug.h"
26#include "base.h"
27
28/*
29 * Get properties for a transmit queue
30 */
31int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
32 struct ath5k_txq_info *queue_info)
33{
34 ATH5K_TRACE(ah->ah_sc);
35 memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
36 return 0;
37}
38
39/*
40 * Set properties for a transmit queue
41 */
42int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
43 const struct ath5k_txq_info *queue_info)
44{
45 ATH5K_TRACE(ah->ah_sc);
46 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
47
48 if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
49 return -EIO;
50
51 memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info));
52
53 /*XXX: Is this supported on 5210 ?*/
54 if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA &&
55 ((queue_info->tqi_subtype == AR5K_WME_AC_VI) ||
56 (queue_info->tqi_subtype == AR5K_WME_AC_VO))) ||
57 queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD)
58 ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
59
60 return 0;
61}
62
63/*
64 * Initialize a transmit queue
65 */
66int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
67 struct ath5k_txq_info *queue_info)
68{
69 unsigned int queue;
70 int ret;
71
72 ATH5K_TRACE(ah->ah_sc);
73
74 /*
75 * Get queue by type
76 */
77 /*5210 only has 2 queues*/
78 if (ah->ah_version == AR5K_AR5210) {
79 switch (queue_type) {
80 case AR5K_TX_QUEUE_DATA:
81 queue = AR5K_TX_QUEUE_ID_NOQCU_DATA;
82 break;
83 case AR5K_TX_QUEUE_BEACON:
84 case AR5K_TX_QUEUE_CAB:
85 queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON;
86 break;
87 default:
88 return -EINVAL;
89 }
90 } else {
91 switch (queue_type) {
92 case AR5K_TX_QUEUE_DATA:
93 for (queue = AR5K_TX_QUEUE_ID_DATA_MIN;
94 ah->ah_txq[queue].tqi_type !=
95 AR5K_TX_QUEUE_INACTIVE; queue++) {
96
97 if (queue > AR5K_TX_QUEUE_ID_DATA_MAX)
98 return -EINVAL;
99 }
100 break;
101 case AR5K_TX_QUEUE_UAPSD:
102 queue = AR5K_TX_QUEUE_ID_UAPSD;
103 break;
104 case AR5K_TX_QUEUE_BEACON:
105 queue = AR5K_TX_QUEUE_ID_BEACON;
106 break;
107 case AR5K_TX_QUEUE_CAB:
108 queue = AR5K_TX_QUEUE_ID_CAB;
109 break;
110 case AR5K_TX_QUEUE_XR_DATA:
111 if (ah->ah_version != AR5K_AR5212)
112 ATH5K_ERR(ah->ah_sc,
113 "XR data queues only supported in"
114 " 5212!\n");
115 queue = AR5K_TX_QUEUE_ID_XR_DATA;
116 break;
117 default:
118 return -EINVAL;
119 }
120 }
121
122 /*
123 * Setup internal queue structure
124 */
125 memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info));
126 ah->ah_txq[queue].tqi_type = queue_type;
127
128 if (queue_info != NULL) {
129 queue_info->tqi_type = queue_type;
130 ret = ath5k_hw_set_tx_queueprops(ah, queue, queue_info);
131 if (ret)
132 return ret;
133 }
134
135 /*
136 * We use ah_txq_status to hold a temp value for
137 * the Secondary interrupt mask registers on 5211+
138 * check out ath5k_hw_reset_tx_queue
139 */
140 AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue);
141
142 return queue;
143}
144
145/*
146 * Get number of pending frames
147 * for a specific queue [5211+]
148 */
149u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
150{
151 u32 pending;
152 ATH5K_TRACE(ah->ah_sc);
153 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
154
155 /* Return if queue is declared inactive */
156 if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
157 return false;
158
159 /* XXX: How about AR5K_CFG_TXCNT ? */
160 if (ah->ah_version == AR5K_AR5210)
161 return false;
162
163 pending = (AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT);
164
165 /* It's possible to have no frames pending even if TXE
166 * is set. To indicate that q has not stopped return
167 * true */
168 if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
169 return true;
170
171 return pending;
172}
173
174/*
175 * Set a transmit queue inactive
176 */
177void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
178{
179 ATH5K_TRACE(ah->ah_sc);
180 if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
181 return;
182
183 /* This queue will be skipped in further operations */
184 ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
185 /*For SIMR setup*/
186 AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
187}
188
189/*
190 * Set DFS properties for a transmit queue on DCU
191 */
192int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
193{
194 u32 cw_min, cw_max, retry_lg, retry_sh;
195 struct ath5k_txq_info *tq = &ah->ah_txq[queue];
196
197 ATH5K_TRACE(ah->ah_sc);
198 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
199
200 tq = &ah->ah_txq[queue];
201
202 if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)
203 return 0;
204
205 if (ah->ah_version == AR5K_AR5210) {
206 /* Only handle data queues, others will be ignored */
207 if (tq->tqi_type != AR5K_TX_QUEUE_DATA)
208 return 0;
209
210 /* Set Slot time */
211 ath5k_hw_reg_write(ah, ah->ah_turbo ?
212 AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
213 AR5K_SLOT_TIME);
214 /* Set ACK_CTS timeout */
215 ath5k_hw_reg_write(ah, ah->ah_turbo ?
216 AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
217 AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
218 /* Set Transmit Latency */
219 ath5k_hw_reg_write(ah, ah->ah_turbo ?
220 AR5K_INIT_TRANSMIT_LATENCY_TURBO :
221 AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
222
223 /* Set IFS0 */
224 if (ah->ah_turbo) {
225 ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
226 (ah->ah_aifs + tq->tqi_aifs) *
227 AR5K_INIT_SLOT_TIME_TURBO) <<
228 AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
229 AR5K_IFS0);
230 } else {
231 ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
232 (ah->ah_aifs + tq->tqi_aifs) *
233 AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) |
234 AR5K_INIT_SIFS, AR5K_IFS0);
235 }
236
237 /* Set IFS1 */
238 ath5k_hw_reg_write(ah, ah->ah_turbo ?
239 AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
240 AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
241 /* Set AR5K_PHY_SETTLING */
242 ath5k_hw_reg_write(ah, ah->ah_turbo ?
243 (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
244 | 0x38 :
245 (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
246 | 0x1C,
247 AR5K_PHY_SETTLING);
248 /* Set Frame Control Register */
249 ath5k_hw_reg_write(ah, ah->ah_turbo ?
250 (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
251 AR5K_PHY_TURBO_SHORT | 0x2020) :
252 (AR5K_PHY_FRAME_CTL_INI | 0x1020),
253 AR5K_PHY_FRAME_CTL_5210);
254 }
255
256 /*
257 * Calculate cwmin/max by channel mode
258 */
259 cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN;
260 cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX;
261 ah->ah_aifs = AR5K_TUNE_AIFS;
262 /*XR is only supported on 5212*/
263 if (IS_CHAN_XR(ah->ah_current_channel) &&
264 ah->ah_version == AR5K_AR5212) {
265 cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR;
266 cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR;
267 ah->ah_aifs = AR5K_TUNE_AIFS_XR;
268 /*B mode is not supported on 5210*/
269 } else if (IS_CHAN_B(ah->ah_current_channel) &&
270 ah->ah_version != AR5K_AR5210) {
271 cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B;
272 cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B;
273 ah->ah_aifs = AR5K_TUNE_AIFS_11B;
274 }
275
276 cw_min = 1;
277 while (cw_min < ah->ah_cw_min)
278 cw_min = (cw_min << 1) | 1;
279
280 cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) :
281 ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
282 cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) :
283 ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
284
285 /*
286 * Calculate and set retry limits
287 */
288 if (ah->ah_software_retry) {
289 /* XXX Need to test this */
290 retry_lg = ah->ah_limit_tx_retries;
291 retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
292 AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg;
293 } else {
294 retry_lg = AR5K_INIT_LG_RETRY;
295 retry_sh = AR5K_INIT_SH_RETRY;
296 }
297
298 /*No QCU/DCU [5210]*/
299 if (ah->ah_version == AR5K_AR5210) {
300 ath5k_hw_reg_write(ah,
301 (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
302 | AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
303 AR5K_NODCU_RETRY_LMT_SLG_RETRY)
304 | AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
305 AR5K_NODCU_RETRY_LMT_SSH_RETRY)
306 | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY)
307 | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY),
308 AR5K_NODCU_RETRY_LMT);
309 } else {
310 /*QCU/DCU [5211+]*/
311 ath5k_hw_reg_write(ah,
312 AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
313 AR5K_DCU_RETRY_LMT_SLG_RETRY) |
314 AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
315 AR5K_DCU_RETRY_LMT_SSH_RETRY) |
316 AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) |
317 AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY),
318 AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
319
320 /*===Rest is also for QCU/DCU only [5211+]===*/
321
322 /*
323 * Set initial content window (cw_min/cw_max)
324 * and arbitrated interframe space (aifs)...
325 */
326 ath5k_hw_reg_write(ah,
327 AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
328 AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
329 AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs,
330 AR5K_DCU_LCL_IFS_AIFS),
331 AR5K_QUEUE_DFS_LOCAL_IFS(queue));
332
333 /*
334 * Set misc registers
335 */
336 /* Enable DCU early termination for this queue */
337 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
338 AR5K_QCU_MISC_DCU_EARLY);
339
340 /* Enable DCU to wait for next fragment from QCU */
341 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
342 AR5K_DCU_MISC_FRAG_WAIT);
343
344 /* On Maui and Spirit use the global seqnum on DCU */
345 if (ah->ah_mac_version < AR5K_SREV_AR5211)
346 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
347 AR5K_DCU_MISC_SEQNUM_CTL);
348
349 if (tq->tqi_cbr_period) {
350 ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
351 AR5K_QCU_CBRCFG_INTVAL) |
352 AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
353 AR5K_QCU_CBRCFG_ORN_THRES),
354 AR5K_QUEUE_CBRCFG(queue));
355 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
356 AR5K_QCU_MISC_FRSHED_CBR);
357 if (tq->tqi_cbr_overflow_limit)
358 AR5K_REG_ENABLE_BITS(ah,
359 AR5K_QUEUE_MISC(queue),
360 AR5K_QCU_MISC_CBR_THRES_ENABLE);
361 }
362
363 if (tq->tqi_ready_time &&
364 (tq->tqi_type != AR5K_TX_QUEUE_ID_CAB))
365 ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
366 AR5K_QCU_RDYTIMECFG_INTVAL) |
367 AR5K_QCU_RDYTIMECFG_ENABLE,
368 AR5K_QUEUE_RDYTIMECFG(queue));
369
370 if (tq->tqi_burst_time) {
371 ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
372 AR5K_DCU_CHAN_TIME_DUR) |
373 AR5K_DCU_CHAN_TIME_ENABLE,
374 AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
375
376 if (tq->tqi_flags
377 & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
378 AR5K_REG_ENABLE_BITS(ah,
379 AR5K_QUEUE_MISC(queue),
380 AR5K_QCU_MISC_RDY_VEOL_POLICY);
381 }
382
383 if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
384 ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
385 AR5K_QUEUE_DFS_MISC(queue));
386
387 if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
388 ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
389 AR5K_QUEUE_DFS_MISC(queue));
390
391 /*
392 * Set registers by queue type
393 */
394 switch (tq->tqi_type) {
395 case AR5K_TX_QUEUE_BEACON:
396 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
397 AR5K_QCU_MISC_FRSHED_DBA_GT |
398 AR5K_QCU_MISC_CBREXP_BCN_DIS |
399 AR5K_QCU_MISC_BCN_ENABLE);
400
401 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
402 (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
403 AR5K_DCU_MISC_ARBLOCK_CTL_S) |
404 AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
405 AR5K_DCU_MISC_BCN_ENABLE);
406 break;
407
408 case AR5K_TX_QUEUE_CAB:
409 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
410 AR5K_QCU_MISC_FRSHED_DBA_GT |
411 AR5K_QCU_MISC_CBREXP_DIS |
412 AR5K_QCU_MISC_CBREXP_BCN_DIS);
413
414 ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
415 (AR5K_TUNE_SW_BEACON_RESP -
416 AR5K_TUNE_DMA_BEACON_RESP) -
417 AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
418 AR5K_QCU_RDYTIMECFG_ENABLE,
419 AR5K_QUEUE_RDYTIMECFG(queue));
420
421 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
422 (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
423 AR5K_DCU_MISC_ARBLOCK_CTL_S));
424 break;
425
426 case AR5K_TX_QUEUE_UAPSD:
427 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
428 AR5K_QCU_MISC_CBREXP_DIS);
429 break;
430
431 case AR5K_TX_QUEUE_DATA:
432 default:
433 break;
434 }
435
436 /* TODO: Handle frame compression */
437
438 /*
439 * Enable interrupts for this tx queue
440 * in the secondary interrupt mask registers
441 */
442 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
443 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
444
445 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
446 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
447
448 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
449 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
450
451 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
452 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
453
454 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
455 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
456
457 if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
458 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
459
460 if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
461 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
462
463 if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
464 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
465
466 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
467 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
468
469 /* Update secondary interrupt mask registers */
470
471 /* Filter out inactive queues */
472 ah->ah_txq_imr_txok &= ah->ah_txq_status;
473 ah->ah_txq_imr_txerr &= ah->ah_txq_status;
474 ah->ah_txq_imr_txurn &= ah->ah_txq_status;
475 ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
476 ah->ah_txq_imr_txeol &= ah->ah_txq_status;
477 ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
478 ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
479 ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
480 ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
481
482 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
483 AR5K_SIMR0_QCU_TXOK) |
484 AR5K_REG_SM(ah->ah_txq_imr_txdesc,
485 AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0);
486 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
487 AR5K_SIMR1_QCU_TXERR) |
488 AR5K_REG_SM(ah->ah_txq_imr_txeol,
489 AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
490 /* Update simr2 but don't overwrite rest simr2 settings */
491 AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
492 AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
493 AR5K_REG_SM(ah->ah_txq_imr_txurn,
494 AR5K_SIMR2_QCU_TXURN));
495 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
496 AR5K_SIMR3_QCBRORN) |
497 AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
498 AR5K_SIMR3_QCBRURN), AR5K_SIMR3);
499 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
500 AR5K_SIMR4_QTRIG), AR5K_SIMR4);
501 /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
502 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
503 AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
504 /* No queue has TXNOFRM enabled, disable the interrupt
505 * by setting AR5K_TXNOFRM to zero */
506 if (ah->ah_txq_imr_nofrm == 0)
507 ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
508
509 /* Set QCU mask for this DCU to save power */
510 AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
511 }
512
513 return 0;
514}
515
516/*
517 * Get slot time from DCU
518 */
519unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah)
520{
521 ATH5K_TRACE(ah->ah_sc);
522 if (ah->ah_version == AR5K_AR5210)
523 return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah,
524 AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo);
525 else
526 return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff;
527}
528
529/*
530 * Set slot time on DCU
531 */
532int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
533{
534 ATH5K_TRACE(ah->ah_sc);
535 if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX)
536 return -EINVAL;
537
538 if (ah->ah_version == AR5K_AR5210)
539 ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time,
540 ah->ah_turbo), AR5K_SLOT_TIME);
541 else
542 ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT);
543
544 return 0;
545}
546
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h
new file mode 100644
index 000000000000..7070d1543cdc
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/reg.h
@@ -0,0 +1,2589 @@
1/*
2 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
3 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
4 * Copyright (c) 2007-2008 Michael Taylor <mike.taylor@apprion.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20/*
21 * Register values for Atheros 5210/5211/5212 cards from OpenBSD's ar5k
22 * maintained by Reyk Floeter
23 *
24 * I tried to document those registers by looking at ar5k code, some
25 * 802.11 (802.11e mostly) papers and by reading various public available
26 * Atheros presentations and papers like these:
27 *
28 * 5210 - http://nova.stanford.edu/~bbaas/ps/isscc2002_slides.pdf
29 * http://www.it.iitb.ac.in/~janak/wifire/01222734.pdf
30 *
31 * 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf
32 *
33 * This file also contains register values found on a memory dump of
34 * Atheros's ART program (Atheros Radio Test), on ath9k, on legacy-hal
35 * released by Atheros and on various debug messages found on the net.
36 */
37
38
39
40/*====MAC DMA REGISTERS====*/
41
42/*
43 * AR5210-Specific TXDP registers
44 * 5210 has only 2 transmit queues so no DCU/QCU, just
45 * 2 transmit descriptor pointers...
46 */
47#define AR5K_NOQCU_TXDP0 0x0000 /* Queue 0 - data */
48#define AR5K_NOQCU_TXDP1 0x0004 /* Queue 1 - beacons */
49
50/*
51 * Mac Control Register
52 */
53#define AR5K_CR 0x0008 /* Register Address */
54#define AR5K_CR_TXE0 0x00000001 /* TX Enable for queue 0 on 5210 */
55#define AR5K_CR_TXE1 0x00000002 /* TX Enable for queue 1 on 5210 */
56#define AR5K_CR_RXE 0x00000004 /* RX Enable */
57#define AR5K_CR_TXD0 0x00000008 /* TX Disable for queue 0 on 5210 */
58#define AR5K_CR_TXD1 0x00000010 /* TX Disable for queue 1 on 5210 */
59#define AR5K_CR_RXD 0x00000020 /* RX Disable */
60#define AR5K_CR_SWI 0x00000040 /* Software Interrupt */
61
62/*
63 * RX Descriptor Pointer register
64 */
65#define AR5K_RXDP 0x000c
66
67/*
68 * Configuration and status register
69 */
70#define AR5K_CFG 0x0014 /* Register Address */
71#define AR5K_CFG_SWTD 0x00000001 /* Byte-swap TX descriptor (for big endian archs) */
72#define AR5K_CFG_SWTB 0x00000002 /* Byte-swap TX buffer */
73#define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */
74#define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer */
75#define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register access */
76#define AR5K_CFG_IBSS 0x00000020 /* 0-BSS, 1-IBSS [5211+] */
77#define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */
78#define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */
79#define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (Disable dynamic clock) */
80#define AR5K_CFG_TXCNT 0x00007800 /* Tx frame count (?) [5210] */
81#define AR5K_CFG_TXCNT_S 11
82#define AR5K_CFG_TXFSTAT 0x00008000 /* Tx frame status (?) [5210] */
83#define AR5K_CFG_TXFSTRT 0x00010000 /* [5210] */
84#define AR5K_CFG_PCI_THRES 0x00060000 /* PCI Master req q threshold [5211+] */
85#define AR5K_CFG_PCI_THRES_S 17
86
87/*
88 * Interrupt enable register
89 */
90#define AR5K_IER 0x0024 /* Register Address */
91#define AR5K_IER_DISABLE 0x00000000 /* Disable card interrupts */
92#define AR5K_IER_ENABLE 0x00000001 /* Enable card interrupts */
93
94
95/*
96 * 0x0028 is Beacon Control Register on 5210
97 * and first RTS duration register on 5211
98 */
99
100/*
101 * Beacon control register [5210]
102 */
103#define AR5K_BCR 0x0028 /* Register Address */
104#define AR5K_BCR_AP 0x00000000 /* AP mode */
105#define AR5K_BCR_ADHOC 0x00000001 /* Ad-Hoc mode */
106#define AR5K_BCR_BDMAE 0x00000002 /* DMA enable */
107#define AR5K_BCR_TQ1FV 0x00000004 /* Use Queue1 for CAB traffic */
108#define AR5K_BCR_TQ1V 0x00000008 /* Use Queue1 for Beacon traffic */
109#define AR5K_BCR_BCGET 0x00000010
110
111/*
112 * First RTS duration register [5211]
113 */
114#define AR5K_RTSD0 0x0028 /* Register Address */
115#define AR5K_RTSD0_6 0x000000ff /* 6Mb RTS duration mask (?) */
116#define AR5K_RTSD0_6_S 0 /* 6Mb RTS duration shift (?) */
117#define AR5K_RTSD0_9 0x0000ff00 /* 9Mb*/
118#define AR5K_RTSD0_9_S 8
119#define AR5K_RTSD0_12 0x00ff0000 /* 12Mb*/
120#define AR5K_RTSD0_12_S 16
121#define AR5K_RTSD0_18 0xff000000 /* 16Mb*/
122#define AR5K_RTSD0_18_S 24
123
124
125/*
126 * 0x002c is Beacon Status Register on 5210
127 * and second RTS duration register on 5211
128 */
129
130/*
131 * Beacon status register [5210]
132 *
133 * As i can see in ar5k_ar5210_tx_start Reyk uses some of the values of BCR
134 * for this register, so i guess TQ1V,TQ1FV and BDMAE have the same meaning
135 * here and SNP/SNAP means "snapshot" (so this register gets synced with BCR).
136 * So SNAPPEDBCRVALID sould also stand for "snapped BCR -values- valid", so i
137 * renamed it to SNAPSHOTSVALID to make more sense. I realy have no idea what
138 * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR.
139 */
140#define AR5K_BSR 0x002c /* Register Address */
141#define AR5K_BSR_BDLYSW 0x00000001 /* SW Beacon delay (?) */
142#define AR5K_BSR_BDLYDMA 0x00000002 /* DMA Beacon delay (?) */
143#define AR5K_BSR_TXQ1F 0x00000004 /* Beacon queue (1) finished */
144#define AR5K_BSR_ATIMDLY 0x00000008 /* ATIM delay (?) */
145#define AR5K_BSR_SNPADHOC 0x00000100 /* Ad-hoc mode set (?) */
146#define AR5K_BSR_SNPBDMAE 0x00000200 /* Beacon DMA enabled (?) */
147#define AR5K_BSR_SNPTQ1FV 0x00000400 /* Queue1 is used for CAB traffic (?) */
148#define AR5K_BSR_SNPTQ1V 0x00000800 /* Queue1 is used for Beacon traffic (?) */
149#define AR5K_BSR_SNAPSHOTSVALID 0x00001000 /* BCR snapshots are valid (?) */
150#define AR5K_BSR_SWBA_CNT 0x00ff0000
151
152/*
153 * Second RTS duration register [5211]
154 */
155#define AR5K_RTSD1 0x002c /* Register Address */
156#define AR5K_RTSD1_24 0x000000ff /* 24Mb */
157#define AR5K_RTSD1_24_S 0
158#define AR5K_RTSD1_36 0x0000ff00 /* 36Mb */
159#define AR5K_RTSD1_36_S 8
160#define AR5K_RTSD1_48 0x00ff0000 /* 48Mb */
161#define AR5K_RTSD1_48_S 16
162#define AR5K_RTSD1_54 0xff000000 /* 54Mb */
163#define AR5K_RTSD1_54_S 24
164
165
166/*
167 * Transmit configuration register
168 */
169#define AR5K_TXCFG 0x0030 /* Register Address */
170#define AR5K_TXCFG_SDMAMR 0x00000007 /* DMA size (read) */
171#define AR5K_TXCFG_SDMAMR_S 0
172#define AR5K_TXCFG_B_MODE 0x00000008 /* Set b mode for 5111 (enable 2111) */
173#define AR5K_TXCFG_TXFSTP 0x00000008 /* TX DMA full Stop [5210] */
174#define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Triger level mask */
175#define AR5K_TXCFG_TXFULL_S 4
176#define AR5K_TXCFG_TXFULL_0B 0x00000000
177#define AR5K_TXCFG_TXFULL_64B 0x00000010
178#define AR5K_TXCFG_TXFULL_128B 0x00000020
179#define AR5K_TXCFG_TXFULL_192B 0x00000030
180#define AR5K_TXCFG_TXFULL_256B 0x00000040
181#define AR5K_TXCFG_TXCONT_EN 0x00000080
182#define AR5K_TXCFG_DMASIZE 0x00000100 /* Flag for passing DMA size [5210] */
183#define AR5K_TXCFG_JUMBO_DESC_EN 0x00000400 /* Enable jumbo tx descriptors [5211+] */
184#define AR5K_TXCFG_ADHOC_BCN_ATIM 0x00000800 /* Adhoc Beacon ATIM Policy */
185#define AR5K_TXCFG_ATIM_WINDOW_DEF_DIS 0x00001000 /* Disable ATIM window defer [5211+] */
186#define AR5K_TXCFG_RTSRND 0x00001000 /* [5211+] */
187#define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */
188#define AR5K_TXCFG_RDY_CBR_DIS 0x00004000 /* Ready time CBR disable [5211+] */
189#define AR5K_TXCFG_JUMBO_FRM_MODE 0x00008000 /* Jumbo frame mode [5211+] */
190#define AR5K_TXCFG_DCU_DBL_BUF_DIS 0x00008000 /* Disable double buffering on DCU */
191#define AR5K_TXCFG_DCU_CACHING_DIS 0x00010000 /* Disable DCU caching */
192
193/*
194 * Receive configuration register
195 */
196#define AR5K_RXCFG 0x0034 /* Register Address */
197#define AR5K_RXCFG_SDMAMW 0x00000007 /* DMA size (write) */
198#define AR5K_RXCFG_SDMAMW_S 0
199#define AR5K_RXCFG_ZLFDMA 0x00000008 /* Enable Zero-length frame DMA */
200#define AR5K_RXCFG_DEF_ANTENNA 0x00000010 /* Default antenna (?) */
201#define AR5K_RXCFG_JUMBO_RXE 0x00000020 /* Enable jumbo rx descriptors [5211+] */
202#define AR5K_RXCFG_JUMBO_WRAP 0x00000040 /* Wrap jumbo frames [5211+] */
203#define AR5K_RXCFG_SLE_ENTRY 0x00000080 /* Sleep entry policy */
204
205/*
206 * Receive jumbo descriptor last address register
207 * Only found in 5211 (?)
208 */
209#define AR5K_RXJLA 0x0038
210
211/*
212 * MIB control register
213 */
214#define AR5K_MIBC 0x0040 /* Register Address */
215#define AR5K_MIBC_COW 0x00000001 /* Warn test indicator */
216#define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */
217#define AR5K_MIBC_CMC 0x00000004 /* Clean MIB Counters */
218#define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe */
219
220/*
221 * Timeout prescale register
222 */
223#define AR5K_TOPS 0x0044
224#define AR5K_TOPS_M 0x0000ffff
225
226/*
227 * Receive timeout register (no frame received)
228 */
229#define AR5K_RXNOFRM 0x0048
230#define AR5K_RXNOFRM_M 0x000003ff
231
232/*
233 * Transmit timeout register (no frame sent)
234 */
235#define AR5K_TXNOFRM 0x004c
236#define AR5K_TXNOFRM_M 0x000003ff
237#define AR5K_TXNOFRM_QCU 0x000ffc00
238#define AR5K_TXNOFRM_QCU_S 10
239
240/*
241 * Receive frame gap timeout register
242 */
243#define AR5K_RPGTO 0x0050
244#define AR5K_RPGTO_M 0x000003ff
245
246/*
247 * Receive frame count limit register
248 */
249#define AR5K_RFCNT 0x0054
250#define AR5K_RFCNT_M 0x0000001f /* [5211+] (?) */
251#define AR5K_RFCNT_RFCL 0x0000000f /* [5210] */
252
253/*
254 * Misc settings register
255 * (reserved0-3)
256 */
257#define AR5K_MISC 0x0058 /* Register Address */
258#define AR5K_MISC_DMA_OBS_M 0x000001e0
259#define AR5K_MISC_DMA_OBS_S 5
260#define AR5K_MISC_MISC_OBS_M 0x00000e00
261#define AR5K_MISC_MISC_OBS_S 9
262#define AR5K_MISC_MAC_OBS_LSB_M 0x00007000
263#define AR5K_MISC_MAC_OBS_LSB_S 12
264#define AR5K_MISC_MAC_OBS_MSB_M 0x00038000
265#define AR5K_MISC_MAC_OBS_MSB_S 15
266#define AR5K_MISC_LED_DECAY 0x001c0000 /* [5210] */
267#define AR5K_MISC_LED_BLINK 0x00e00000 /* [5210] */
268
269/*
270 * QCU/DCU clock gating register (5311)
271 * (reserved4-5)
272 */
273#define AR5K_QCUDCU_CLKGT 0x005c /* Register Address (?) */
274#define AR5K_QCUDCU_CLKGT_QCU 0x0000ffff /* Mask for QCU clock */
275#define AR5K_QCUDCU_CLKGT_DCU 0x07ff0000 /* Mask for DCU clock */
276
277/*
278 * Interrupt Status Registers
279 *
280 * For 5210 there is only one status register but for
281 * 5211/5212 we have one primary and 4 secondary registers.
282 * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212.
283 * Most of these bits are common for all chipsets.
284 */
285#define AR5K_ISR 0x001c /* Register Address [5210] */
286#define AR5K_PISR 0x0080 /* Register Address [5211+] */
287#define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly recieved */
288#define AR5K_ISR_RXDESC 0x00000002 /* RX descriptor request */
289#define AR5K_ISR_RXERR 0x00000004 /* Receive error */
290#define AR5K_ISR_RXNOFRM 0x00000008 /* No frame received (receive timeout) */
291#define AR5K_ISR_RXEOL 0x00000010 /* Empty RX descriptor */
292#define AR5K_ISR_RXORN 0x00000020 /* Receive FIFO overrun */
293#define AR5K_ISR_TXOK 0x00000040 /* Frame successfuly transmited */
294#define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */
295#define AR5K_ISR_TXERR 0x00000100 /* Transmit error */
296#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout) */
297#define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */
298#define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */
299#define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */
300#define AR5K_ISR_SWI 0x00002000 /* Software interrupt */
301#define AR5K_ISR_RXPHY 0x00004000 /* PHY error */
302#define AR5K_ISR_RXKCM 0x00008000 /* RX Key cache miss */
303#define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */
304#define AR5K_ISR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */
305#define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */
306#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
307#define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */
308#define AR5K_ISR_MCABT 0x00100000 /* Master Cycle Abort [5210] */
309#define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */
310#define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */
311#define AR5K_ISR_DPERR 0x00400000 /* Det par Error (?) [5210] */
312#define AR5K_ISR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */
313#define AR5K_ISR_TIM 0x00800000 /* [5211+] */
314#define AR5K_ISR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT,
315 CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */
316#define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill) */
317#define AR5K_ISR_QCBRORN 0x02000000 /* QCU CBR overrun [5211+] */
318#define AR5K_ISR_QCBRURN 0x04000000 /* QCU CBR underrun [5211+] */
319#define AR5K_ISR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */
320
321/*
322 * Secondary status registers [5211+] (0 - 4)
323 *
324 * These give the status for each QCU, only QCUs 0-9 are
325 * represented.
326 */
327#define AR5K_SISR0 0x0084 /* Register Address [5211+] */
328#define AR5K_SISR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */
329#define AR5K_SISR0_QCU_TXOK_S 0
330#define AR5K_SISR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */
331#define AR5K_SISR0_QCU_TXDESC_S 16
332
333#define AR5K_SISR1 0x0088 /* Register Address [5211+] */
334#define AR5K_SISR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */
335#define AR5K_SISR1_QCU_TXERR_S 0
336#define AR5K_SISR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */
337#define AR5K_SISR1_QCU_TXEOL_S 16
338
339#define AR5K_SISR2 0x008c /* Register Address [5211+] */
340#define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */
341#define AR5K_SISR2_QCU_TXURN_S 0
342#define AR5K_SISR2_MCABT 0x00100000 /* Master Cycle Abort */
343#define AR5K_SISR2_SSERR 0x00200000 /* Signaled System Error */
344#define AR5K_SISR2_DPERR 0x00400000 /* Bus parity error */
345#define AR5K_SISR2_TIM 0x01000000 /* [5212+] */
346#define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */
347#define AR5K_SISR2_DTIM_SYNC 0x04000000 /* DTIM sync lost [5212+] */
348#define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */
349#define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */
350#define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */
351#define AR5K_SISR2_TSFOOR 0x80000000 /* TSF OOR (?) */
352
353#define AR5K_SISR3 0x0090 /* Register Address [5211+] */
354#define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
355#define AR5K_SISR3_QCBRORN_S 0
356#define AR5K_SISR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */
357#define AR5K_SISR3_QCBRURN_S 16
358
359#define AR5K_SISR4 0x0094 /* Register Address [5211+] */
360#define AR5K_SISR4_QTRIG 0x000003ff /* Mask for QTRIG */
361#define AR5K_SISR4_QTRIG_S 0
362
363/*
364 * Shadow read-and-clear interrupt status registers [5211+]
365 */
366#define AR5K_RAC_PISR 0x00c0 /* Read and clear PISR */
367#define AR5K_RAC_SISR0 0x00c4 /* Read and clear SISR0 */
368#define AR5K_RAC_SISR1 0x00c8 /* Read and clear SISR1 */
369#define AR5K_RAC_SISR2 0x00cc /* Read and clear SISR2 */
370#define AR5K_RAC_SISR3 0x00d0 /* Read and clear SISR3 */
371#define AR5K_RAC_SISR4 0x00d4 /* Read and clear SISR4 */
372
373/*
374 * Interrupt Mask Registers
375 *
376 * As whith ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary
377 * (AR5K_PIMR) and 4 secondary IMRs (AR5K_SIMRx). Note that ISR/IMR flags match.
378 */
379#define AR5K_IMR 0x0020 /* Register Address [5210] */
380#define AR5K_PIMR 0x00a0 /* Register Address [5211+] */
381#define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly recieved*/
382#define AR5K_IMR_RXDESC 0x00000002 /* RX descriptor request*/
383#define AR5K_IMR_RXERR 0x00000004 /* Receive error*/
384#define AR5K_IMR_RXNOFRM 0x00000008 /* No frame received (receive timeout)*/
385#define AR5K_IMR_RXEOL 0x00000010 /* Empty RX descriptor*/
386#define AR5K_IMR_RXORN 0x00000020 /* Receive FIFO overrun*/
387#define AR5K_IMR_TXOK 0x00000040 /* Frame successfuly transmited*/
388#define AR5K_IMR_TXDESC 0x00000080 /* TX descriptor request*/
389#define AR5K_IMR_TXERR 0x00000100 /* Transmit error*/
390#define AR5K_IMR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout)*/
391#define AR5K_IMR_TXEOL 0x00000400 /* Empty TX descriptor*/
392#define AR5K_IMR_TXURN 0x00000800 /* Transmit FIFO underrun*/
393#define AR5K_IMR_MIB 0x00001000 /* Update MIB counters*/
394#define AR5K_IMR_SWI 0x00002000 /* Software interrupt */
395#define AR5K_IMR_RXPHY 0x00004000 /* PHY error*/
396#define AR5K_IMR_RXKCM 0x00008000 /* RX Key cache miss */
397#define AR5K_IMR_SWBA 0x00010000 /* Software beacon alert*/
398#define AR5K_IMR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */
399#define AR5K_IMR_BMISS 0x00040000 /* Beacon missed*/
400#define AR5K_IMR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
401#define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */
402#define AR5K_IMR_MCABT 0x00100000 /* Master Cycle Abort [5210] */
403#define AR5K_IMR_RXCHIRP 0x00200000 /* CHIRP Received [5212+]*/
404#define AR5K_IMR_SSERR 0x00200000 /* Signaled System Error [5210] */
405#define AR5K_IMR_DPERR 0x00400000 /* Det par Error (?) [5210] */
406#define AR5K_IMR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */
407#define AR5K_IMR_TIM 0x00800000 /* [5211+] */
408#define AR5K_IMR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT,
409 CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */
410#define AR5K_IMR_GPIO 0x01000000 /* GPIO (rf kill)*/
411#define AR5K_IMR_QCBRORN 0x02000000 /* QCU CBR overrun (?) [5211+] */
412#define AR5K_IMR_QCBRURN 0x04000000 /* QCU CBR underrun (?) [5211+] */
413#define AR5K_IMR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */
414
415/*
416 * Secondary interrupt mask registers [5211+] (0 - 4)
417 */
418#define AR5K_SIMR0 0x00a4 /* Register Address [5211+] */
419#define AR5K_SIMR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */
420#define AR5K_SIMR0_QCU_TXOK_S 0
421#define AR5K_SIMR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */
422#define AR5K_SIMR0_QCU_TXDESC_S 16
423
424#define AR5K_SIMR1 0x00a8 /* Register Address [5211+] */
425#define AR5K_SIMR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */
426#define AR5K_SIMR1_QCU_TXERR_S 0
427#define AR5K_SIMR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */
428#define AR5K_SIMR1_QCU_TXEOL_S 16
429
430#define AR5K_SIMR2 0x00ac /* Register Address [5211+] */
431#define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */
432#define AR5K_SIMR2_QCU_TXURN_S 0
433#define AR5K_SIMR2_MCABT 0x00100000 /* Master Cycle Abort */
434#define AR5K_SIMR2_SSERR 0x00200000 /* Signaled System Error */
435#define AR5K_SIMR2_DPERR 0x00400000 /* Bus parity error */
436#define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */
437#define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */
438#define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* DTIM Sync lost [5212+] */
439#define AR5K_SIMR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */
440#define AR5K_SIMR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */
441#define AR5K_SIMR2_DTIM 0x20000000 /* [5212+] */
442#define AR5K_SIMR2_TSFOOR 0x80000000 /* TSF OOR (?) */
443
444#define AR5K_SIMR3 0x00b0 /* Register Address [5211+] */
445#define AR5K_SIMR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
446#define AR5K_SIMR3_QCBRORN_S 0
447#define AR5K_SIMR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */
448#define AR5K_SIMR3_QCBRURN_S 16
449
450#define AR5K_SIMR4 0x00b4 /* Register Address [5211+] */
451#define AR5K_SIMR4_QTRIG 0x000003ff /* Mask for QTRIG */
452#define AR5K_SIMR4_QTRIG_S 0
453
454/*
455 * DMA Debug registers 0-7
456 * 0xe0 - 0xfc
457 */
458
459/*
460 * Decompression mask registers [5212+]
461 */
462#define AR5K_DCM_ADDR 0x0400 /*Decompression mask address (index) */
463#define AR5K_DCM_DATA 0x0404 /*Decompression mask data */
464
465/*
466 * Wake On Wireless pattern control register [5212+]
467 */
468#define AR5K_WOW_PCFG 0x0410 /* Register Address */
469#define AR5K_WOW_PCFG_PAT_MATCH_EN 0x00000001 /* Pattern match enable */
470#define AR5K_WOW_PCFG_LONG_FRAME_POL 0x00000002 /* Long frame policy */
471#define AR5K_WOW_PCFG_WOBMISS 0x00000004 /* Wake on bea(con) miss (?) */
472#define AR5K_WOW_PCFG_PAT_0_EN 0x00000100 /* Enable pattern 0 */
473#define AR5K_WOW_PCFG_PAT_1_EN 0x00000200 /* Enable pattern 1 */
474#define AR5K_WOW_PCFG_PAT_2_EN 0x00000400 /* Enable pattern 2 */
475#define AR5K_WOW_PCFG_PAT_3_EN 0x00000800 /* Enable pattern 3 */
476#define AR5K_WOW_PCFG_PAT_4_EN 0x00001000 /* Enable pattern 4 */
477#define AR5K_WOW_PCFG_PAT_5_EN 0x00002000 /* Enable pattern 5 */
478
479/*
480 * Wake On Wireless pattern index register (?) [5212+]
481 */
482#define AR5K_WOW_PAT_IDX 0x0414
483
484/*
485 * Wake On Wireless pattern data register [5212+]
486 */
487#define AR5K_WOW_PAT_DATA 0x0418 /* Register Address */
488#define AR5K_WOW_PAT_DATA_0_3_V 0x00000001 /* Pattern 0, 3 value */
489#define AR5K_WOW_PAT_DATA_1_4_V 0x00000100 /* Pattern 1, 4 value */
490#define AR5K_WOW_PAT_DATA_2_5_V 0x00010000 /* Pattern 2, 5 value */
491#define AR5K_WOW_PAT_DATA_0_3_M 0x01000000 /* Pattern 0, 3 mask */
492#define AR5K_WOW_PAT_DATA_1_4_M 0x04000000 /* Pattern 1, 4 mask */
493#define AR5K_WOW_PAT_DATA_2_5_M 0x10000000 /* Pattern 2, 5 mask */
494
495/*
496 * Decompression configuration registers [5212+]
497 */
498#define AR5K_DCCFG 0x0420 /* Register Address */
499#define AR5K_DCCFG_GLOBAL_EN 0x00000001 /* Enable decompression on all queues */
500#define AR5K_DCCFG_BYPASS_EN 0x00000002 /* Bypass decompression */
501#define AR5K_DCCFG_BCAST_EN 0x00000004 /* Enable decompression for bcast frames */
502#define AR5K_DCCFG_MCAST_EN 0x00000008 /* Enable decompression for mcast frames */
503
504/*
505 * Compression configuration registers [5212+]
506 */
507#define AR5K_CCFG 0x0600 /* Register Address */
508#define AR5K_CCFG_WINDOW_SIZE 0x00000007 /* Compression window size */
509#define AR5K_CCFG_CPC_EN 0x00000008 /* Enable performance counters */
510
511#define AR5K_CCFG_CCU 0x0604 /* Register Address */
512#define AR5K_CCFG_CCU_CUP_EN 0x00000001 /* CCU Catchup enable */
513#define AR5K_CCFG_CCU_CREDIT 0x00000002 /* CCU Credit (field) */
514#define AR5K_CCFG_CCU_CD_THRES 0x00000080 /* CCU Cyc(lic?) debt threshold (field) */
515#define AR5K_CCFG_CCU_CUP_LCNT 0x00010000 /* CCU Catchup lit(?) count */
516#define AR5K_CCFG_CCU_INIT 0x00100200 /* Initial value during reset */
517
518/*
519 * Compression performance counter registers [5212+]
520 */
521#define AR5K_CPC0 0x0610 /* Compression performance counter 0 */
522#define AR5K_CPC1 0x0614 /* Compression performance counter 1*/
523#define AR5K_CPC2 0x0618 /* Compression performance counter 2 */
524#define AR5K_CPC3 0x061c /* Compression performance counter 3 */
525#define AR5K_CPCOVF 0x0620 /* Compression performance overflow */
526
527
528/*
529 * Queue control unit (QCU) registers [5211+]
530 *
531 * Card has 12 TX Queues but i see that only 0-9 are used (?)
532 * both in binary HAL (see ah.h) and ar5k. Each queue has it's own
533 * TXDP at addresses 0x0800 - 0x082c, a CBR (Constant Bit Rate)
534 * configuration register (0x08c0 - 0x08ec), a ready time configuration
535 * register (0x0900 - 0x092c), a misc configuration register (0x09c0 -
536 * 0x09ec) and a status register (0x0a00 - 0x0a2c). We also have some
537 * global registers, QCU transmit enable/disable and "one shot arm (?)"
538 * set/clear, which contain status for all queues (we shift by 1 for each
539 * queue). To access these registers easily we define some macros here
540 * that are used inside HAL. For more infos check out *_tx_queue functs.
541 */
542
543/*
544 * Generic QCU Register access macros
545 */
546#define AR5K_QUEUE_REG(_r, _q) (((_q) << 2) + _r)
547#define AR5K_QCU_GLOBAL_READ(_r, _q) (AR5K_REG_READ(_r) & (1 << _q))
548#define AR5K_QCU_GLOBAL_WRITE(_r, _q) AR5K_REG_WRITE(_r, (1 << _q))
549
550/*
551 * QCU Transmit descriptor pointer registers
552 */
553#define AR5K_QCU_TXDP_BASE 0x0800 /* Register Address - Queue0 TXDP */
554#define AR5K_QUEUE_TXDP(_q) AR5K_QUEUE_REG(AR5K_QCU_TXDP_BASE, _q)
555
556/*
557 * QCU Transmit enable register
558 */
559#define AR5K_QCU_TXE 0x0840
560#define AR5K_ENABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXE, _q)
561#define AR5K_QUEUE_ENABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXE, _q)
562
563/*
564 * QCU Transmit disable register
565 */
566#define AR5K_QCU_TXD 0x0880
567#define AR5K_DISABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXD, _q)
568#define AR5K_QUEUE_DISABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXD, _q)
569
570/*
571 * QCU Constant Bit Rate configuration registers
572 */
573#define AR5K_QCU_CBRCFG_BASE 0x08c0 /* Register Address - Queue0 CBRCFG */
574#define AR5K_QCU_CBRCFG_INTVAL 0x00ffffff /* CBR Interval mask */
575#define AR5K_QCU_CBRCFG_INTVAL_S 0
576#define AR5K_QCU_CBRCFG_ORN_THRES 0xff000000 /* CBR overrun threshold mask */
577#define AR5K_QCU_CBRCFG_ORN_THRES_S 24
578#define AR5K_QUEUE_CBRCFG(_q) AR5K_QUEUE_REG(AR5K_QCU_CBRCFG_BASE, _q)
579
580/*
581 * QCU Ready time configuration registers
582 */
583#define AR5K_QCU_RDYTIMECFG_BASE 0x0900 /* Register Address - Queue0 RDYTIMECFG */
584#define AR5K_QCU_RDYTIMECFG_INTVAL 0x00ffffff /* Ready time interval mask */
585#define AR5K_QCU_RDYTIMECFG_INTVAL_S 0
586#define AR5K_QCU_RDYTIMECFG_ENABLE 0x01000000 /* Ready time enable mask */
587#define AR5K_QUEUE_RDYTIMECFG(_q) AR5K_QUEUE_REG(AR5K_QCU_RDYTIMECFG_BASE, _q)
588
589/*
590 * QCU one shot arm set registers
591 */
592#define AR5K_QCU_ONESHOTARM_SET 0x0940 /* Register Address -QCU "one shot arm set (?)" */
593#define AR5K_QCU_ONESHOTARM_SET_M 0x0000ffff
594
595/*
596 * QCU one shot arm clear registers
597 */
598#define AR5K_QCU_ONESHOTARM_CLEAR 0x0980 /* Register Address -QCU "one shot arm clear (?)" */
599#define AR5K_QCU_ONESHOTARM_CLEAR_M 0x0000ffff
600
601/*
602 * QCU misc registers
603 */
604#define AR5K_QCU_MISC_BASE 0x09c0 /* Register Address -Queue0 MISC */
605#define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame sheduling mask */
606#define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */
607#define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */
608#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated */
609#define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* TIMT gated */
610#define AR5K_QCU_MISC_FRSHED_BCN_SENT_GT 4 /* Beacon sent gated */
611#define AR5K_QCU_MISC_ONESHOT_ENABLE 0x00000010 /* Oneshot enable */
612#define AR5K_QCU_MISC_CBREXP_DIS 0x00000020 /* Disable CBR expired counter (normal queue) */
613#define AR5K_QCU_MISC_CBREXP_BCN_DIS 0x00000040 /* Disable CBR expired counter (beacon queue) */
614#define AR5K_QCU_MISC_BCN_ENABLE 0x00000080 /* Enable Beacon use */
615#define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR expired threshold enabled */
616#define AR5K_QCU_MISC_RDY_VEOL_POLICY 0x00000200 /* TXE reset when RDYTIME expired or VEOL */
617#define AR5K_QCU_MISC_CBR_RESET_CNT 0x00000400 /* CBR threshold (counter) reset */
618#define AR5K_QCU_MISC_DCU_EARLY 0x00000800 /* DCU early termination */
619#define AR5K_QCU_MISC_DCU_CMP_EN 0x00001000 /* Enable frame compression */
620#define AR5K_QUEUE_MISC(_q) AR5K_QUEUE_REG(AR5K_QCU_MISC_BASE, _q)
621
622
623/*
624 * QCU status registers
625 */
626#define AR5K_QCU_STS_BASE 0x0a00 /* Register Address - Queue0 STS */
627#define AR5K_QCU_STS_FRMPENDCNT 0x00000003 /* Frames pending counter */
628#define AR5K_QCU_STS_CBREXPCNT 0x0000ff00 /* CBR expired counter */
629#define AR5K_QUEUE_STATUS(_q) AR5K_QUEUE_REG(AR5K_QCU_STS_BASE, _q)
630
631/*
632 * QCU ready time shutdown register
633 */
634#define AR5K_QCU_RDYTIMESHDN 0x0a40
635#define AR5K_QCU_RDYTIMESHDN_M 0x000003ff
636
637/*
638 * QCU compression buffer base registers [5212+]
639 */
640#define AR5K_QCU_CBB_SELECT 0x0b00
641#define AR5K_QCU_CBB_ADDR 0x0b04
642#define AR5K_QCU_CBB_ADDR_S 9
643
644/*
645 * QCU compression buffer configuration register [5212+]
646 * (buffer size)
647 */
648#define AR5K_QCU_CBCFG 0x0b08
649
650
651
652/*
653 * Distributed Coordination Function (DCF) control unit (DCU)
654 * registers [5211+]
655 *
656 * These registers control the various characteristics of each queue
657 * for 802.11e (WME) combatibility so they go together with
658 * QCU registers in pairs. For each queue we have a QCU mask register,
659 * (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c),
660 * a retry limit register (0x1080 - 0x10ac), a channel time register
661 * (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and
662 * a sequence number register (0x1140 - 0x116c). It seems that "global"
663 * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k).
664 * We use the same macros here for easier register access.
665 *
666 */
667
668/*
669 * DCU QCU mask registers
670 */
671#define AR5K_DCU_QCUMASK_BASE 0x1000 /* Register Address -Queue0 DCU_QCUMASK */
672#define AR5K_DCU_QCUMASK_M 0x000003ff
673#define AR5K_QUEUE_QCUMASK(_q) AR5K_QUEUE_REG(AR5K_DCU_QCUMASK_BASE, _q)
674
675/*
676 * DCU local Inter Frame Space settings register
677 */
678#define AR5K_DCU_LCL_IFS_BASE 0x1040 /* Register Address -Queue0 DCU_LCL_IFS */
679#define AR5K_DCU_LCL_IFS_CW_MIN 0x000003ff /* Minimum Contention Window */
680#define AR5K_DCU_LCL_IFS_CW_MIN_S 0
681#define AR5K_DCU_LCL_IFS_CW_MAX 0x000ffc00 /* Maximum Contention Window */
682#define AR5K_DCU_LCL_IFS_CW_MAX_S 10
683#define AR5K_DCU_LCL_IFS_AIFS 0x0ff00000 /* Arbitrated Interframe Space */
684#define AR5K_DCU_LCL_IFS_AIFS_S 20
685#define AR5K_DCU_LCL_IFS_AIFS_MAX 0xfc /* Anything above that can cause DCU to hang */
686#define AR5K_QUEUE_DFS_LOCAL_IFS(_q) AR5K_QUEUE_REG(AR5K_DCU_LCL_IFS_BASE, _q)
687
688/*
689 * DCU retry limit registers
690 */
691#define AR5K_DCU_RETRY_LMT_BASE 0x1080 /* Register Address -Queue0 DCU_RETRY_LMT */
692#define AR5K_DCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */
693#define AR5K_DCU_RETRY_LMT_SH_RETRY_S 0
694#define AR5K_DCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry limit mask */
695#define AR5K_DCU_RETRY_LMT_LG_RETRY_S 4
696#define AR5K_DCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask (?) */
697#define AR5K_DCU_RETRY_LMT_SSH_RETRY_S 8
698#define AR5K_DCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask (?) */
699#define AR5K_DCU_RETRY_LMT_SLG_RETRY_S 14
700#define AR5K_QUEUE_DFS_RETRY_LIMIT(_q) AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q)
701
702/*
703 * DCU channel time registers
704 */
705#define AR5K_DCU_CHAN_TIME_BASE 0x10c0 /* Register Address -Queue0 DCU_CHAN_TIME */
706#define AR5K_DCU_CHAN_TIME_DUR 0x000fffff /* Channel time duration */
707#define AR5K_DCU_CHAN_TIME_DUR_S 0
708#define AR5K_DCU_CHAN_TIME_ENABLE 0x00100000 /* Enable channel time */
709#define AR5K_QUEUE_DFS_CHANNEL_TIME(_q) AR5K_QUEUE_REG(AR5K_DCU_CHAN_TIME_BASE, _q)
710
711/*
712 * DCU misc registers [5211+]
713 *
714 * Note: Arbiter lockout control controls the
715 * behaviour on low priority queues when we have multiple queues
716 * with pending frames. Intra-frame lockout means we wait until
717 * the queue's current frame transmits (with post frame backoff and bursting)
718 * before we transmit anything else and global lockout means we
719 * wait for the whole queue to finish before higher priority queues
720 * can transmit (this is used on beacon and CAB queues).
721 * No lockout means there is no special handling.
722 */
723#define AR5K_DCU_MISC_BASE 0x1100 /* Register Address -Queue0 DCU_MISC */
724#define AR5K_DCU_MISC_BACKOFF 0x0000003f /* Mask for backoff threshold */
725#define AR5K_DCU_MISC_ETS_RTS_POL 0x00000040 /* End of transmission series
726 station RTS/data failure count
727 reset policy (?) */
728#define AR5K_DCU_MISC_ETS_CW_POL 0x00000080 /* End of transmission series
729 CW reset policy */
730#define AR5K_DCU_MISC_FRAG_WAIT 0x00000100 /* Wait for next fragment */
731#define AR5K_DCU_MISC_BACKOFF_FRAG 0x00000200 /* Enable backoff while bursting */
732#define AR5K_DCU_MISC_HCFPOLL_ENABLE 0x00000800 /* CF - Poll enable */
733#define AR5K_DCU_MISC_BACKOFF_PERSIST 0x00001000 /* Persistent backoff */
734#define AR5K_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 /* Enable frame pre-fetch */
735#define AR5K_DCU_MISC_VIRTCOL 0x0000c000 /* Mask for Virtual Collision (?) */
736#define AR5K_DCU_MISC_VIRTCOL_NORMAL 0
737#define AR5K_DCU_MISC_VIRTCOL_IGNORE 1
738#define AR5K_DCU_MISC_BCN_ENABLE 0x00010000 /* Enable Beacon use */
739#define AR5K_DCU_MISC_ARBLOCK_CTL 0x00060000 /* Arbiter lockout control mask */
740#define AR5K_DCU_MISC_ARBLOCK_CTL_S 17
741#define AR5K_DCU_MISC_ARBLOCK_CTL_NONE 0 /* No arbiter lockout */
742#define AR5K_DCU_MISC_ARBLOCK_CTL_INTFRM 1 /* Intra-frame lockout */
743#define AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL 2 /* Global lockout */
744#define AR5K_DCU_MISC_ARBLOCK_IGNORE 0x00080000 /* Ignore Arbiter lockout */
745#define AR5K_DCU_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Disable sequence number increment */
746#define AR5K_DCU_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Disable post-frame backoff */
747#define AR5K_DCU_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual Collision cw policy */
748#define AR5K_DCU_MISC_BLOWN_IFS_POLICY 0x00800000 /* Blown IFS policy (?) */
749#define AR5K_DCU_MISC_SEQNUM_CTL 0x01000000 /* Sequence number control (?) */
750#define AR5K_QUEUE_DFS_MISC(_q) AR5K_QUEUE_REG(AR5K_DCU_MISC_BASE, _q)
751
752/*
753 * DCU frame sequence number registers
754 */
755#define AR5K_DCU_SEQNUM_BASE 0x1140
756#define AR5K_DCU_SEQNUM_M 0x00000fff
757#define AR5K_QUEUE_DCU_SEQNUM(_q) AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q)
758
759/*
760 * DCU global IFS SIFS register
761 */
762#define AR5K_DCU_GBL_IFS_SIFS 0x1030
763#define AR5K_DCU_GBL_IFS_SIFS_M 0x0000ffff
764
765/*
766 * DCU global IFS slot interval register
767 */
768#define AR5K_DCU_GBL_IFS_SLOT 0x1070
769#define AR5K_DCU_GBL_IFS_SLOT_M 0x0000ffff
770
771/*
772 * DCU global IFS EIFS register
773 */
774#define AR5K_DCU_GBL_IFS_EIFS 0x10b0
775#define AR5K_DCU_GBL_IFS_EIFS_M 0x0000ffff
776
777/*
778 * DCU global IFS misc register
779 *
780 * LFSR stands for Linear Feedback Shift Register
781 * and it's used for generating pseudo-random
782 * number sequences.
783 *
784 * (If i understand corectly, random numbers are
785 * used for idle sensing -multiplied with cwmin/max etc-)
786 */
787#define AR5K_DCU_GBL_IFS_MISC 0x10f0 /* Register Address */
788#define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 /* LFSR Slice Select */
789#define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */
790#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */
791#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */
792#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S 10
793#define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */
794#define AR5K_DCU_GBL_IFS_MISC_SIFS_CNT_RST 0x00400000 /* SIFS cnt reset policy (?) */
795#define AR5K_DCU_GBL_IFS_MISC_AIFS_CNT_RST 0x00800000 /* AIFS cnt reset policy (?) */
796#define AR5K_DCU_GBL_IFS_MISC_RND_LFSR_SL_DIS 0x01000000 /* Disable random LFSR slice */
797
798/*
799 * DCU frame prefetch control register
800 */
801#define AR5K_DCU_FP 0x1230 /* Register Address */
802#define AR5K_DCU_FP_NOBURST_DCU_EN 0x00000001 /* Enable non-burst prefetch on DCU (?) */
803#define AR5K_DCU_FP_NOBURST_EN 0x00000010 /* Enable non-burst prefetch (?) */
804#define AR5K_DCU_FP_BURST_DCU_EN 0x00000020 /* Enable burst prefetch on DCU (?) */
805
806/*
807 * DCU transmit pause control/status register
808 */
809#define AR5K_DCU_TXP 0x1270 /* Register Address */
810#define AR5K_DCU_TXP_M 0x000003ff /* Tx pause mask */
811#define AR5K_DCU_TXP_STATUS 0x00010000 /* Tx pause status */
812
813/*
814 * DCU transmit filter table 0 (32 entries)
815 * each entry contains a 32bit slice of the
816 * 128bit tx filter for each DCU (4 slices per DCU)
817 */
818#define AR5K_DCU_TX_FILTER_0_BASE 0x1038
819#define AR5K_DCU_TX_FILTER_0(_n) (AR5K_DCU_TX_FILTER_0_BASE + (_n * 64))
820
821/*
822 * DCU transmit filter table 1 (16 entries)
823 */
824#define AR5K_DCU_TX_FILTER_1_BASE 0x103c
825#define AR5K_DCU_TX_FILTER_1(_n) (AR5K_DCU_TX_FILTER_1_BASE + (_n * 64))
826
827/*
828 * DCU clear transmit filter register
829 */
830#define AR5K_DCU_TX_FILTER_CLR 0x143c
831
832/*
833 * DCU set transmit filter register
834 */
835#define AR5K_DCU_TX_FILTER_SET 0x147c
836
837/*
838 * Reset control register
839 */
840#define AR5K_RESET_CTL 0x4000 /* Register Address */
841#define AR5K_RESET_CTL_PCU 0x00000001 /* Protocol Control Unit reset */
842#define AR5K_RESET_CTL_DMA 0x00000002 /* DMA (Rx/Tx) reset [5210] */
843#define AR5K_RESET_CTL_BASEBAND 0x00000002 /* Baseband reset [5211+] */
844#define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband ?) [5210] */
845#define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset [5210] */
846#define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */
847
848/*
849 * Sleep control register
850 */
851#define AR5K_SLEEP_CTL 0x4004 /* Register Address */
852#define AR5K_SLEEP_CTL_SLDUR 0x0000ffff /* Sleep duration mask */
853#define AR5K_SLEEP_CTL_SLDUR_S 0
854#define AR5K_SLEEP_CTL_SLE 0x00030000 /* Sleep enable mask */
855#define AR5K_SLEEP_CTL_SLE_S 16
856#define AR5K_SLEEP_CTL_SLE_WAKE 0x00000000 /* Force chip awake */
857#define AR5K_SLEEP_CTL_SLE_SLP 0x00010000 /* Force chip sleep */
858#define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000 /* Normal sleep policy */
859#define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* [5211+] */
860#define AR5K_SLEEP_CTL_DUR_TIM_POL 0x00040000 /* Sleep duration timing policy */
861#define AR5K_SLEEP_CTL_DUR_WRITE_POL 0x00080000 /* Sleep duration write policy */
862#define AR5K_SLEEP_CTL_SLE_POL 0x00100000 /* Sleep policy mode */
863
864/*
865 * Interrupt pending register
866 */
867#define AR5K_INTPEND 0x4008
868#define AR5K_INTPEND_M 0x00000001
869
870/*
871 * Sleep force register
872 */
873#define AR5K_SFR 0x400c
874#define AR5K_SFR_EN 0x00000001
875
876/*
877 * PCI configuration register
878 * TODO: Fix LED stuff
879 */
880#define AR5K_PCICFG 0x4010 /* Register Address */
881#define AR5K_PCICFG_EEAE 0x00000001 /* Eeprom access enable [5210] */
882#define AR5K_PCICFG_SLEEP_CLOCK_EN 0x00000002 /* Enable sleep clock */
883#define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */
884#define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */
885#define AR5K_PCICFG_EESIZE_S 3
886#define AR5K_PCICFG_EESIZE_4K 0 /* 4K */
887#define AR5K_PCICFG_EESIZE_8K 1 /* 8K */
888#define AR5K_PCICFG_EESIZE_16K 2 /* 16K */
889#define AR5K_PCICFG_EESIZE_FAIL 3 /* Failed to get size [5211+] */
890#define AR5K_PCICFG_LED 0x00000060 /* Led status [5211+] */
891#define AR5K_PCICFG_LED_NONE 0x00000000 /* Default [5211+] */
892#define AR5K_PCICFG_LED_PEND 0x00000020 /* Scan / Auth pending */
893#define AR5K_PCICFG_LED_ASSOC 0x00000040 /* Associated */
894#define AR5K_PCICFG_BUS_SEL 0x00000380 /* Mask for "bus select" [5211+] (?) */
895#define AR5K_PCICFG_CBEFIX_DIS 0x00000400 /* Disable CBE fix */
896#define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep */
897#define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */
898#define AR5K_PCICFG_RETRY_FIX 0x00001000 /* Enable pci core retry fix */
899#define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even whith pending interrupts*/
900#define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */
901#define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */
902#define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */
903#define AR5K_PCICFG_LEDMODE_PROM 0x00020000 /* Default mode (blink on any traffic) [5211+] */
904#define AR5K_PCICFG_LEDMODE_PWR 0x00040000 /* Some other blinking mode (?) [5211+] */
905#define AR5K_PCICFG_LEDMODE_RAND 0x00060000 /* Random blinking (?) [5211+] */
906#define AR5K_PCICFG_LEDBLINK 0x00700000 /* Led blink rate */
907#define AR5K_PCICFG_LEDBLINK_S 20
908#define AR5K_PCICFG_LEDSLOW 0x00800000 /* Slowest led blink rate [5211+] */
909#define AR5K_PCICFG_LEDSTATE \
910 (AR5K_PCICFG_LED | AR5K_PCICFG_LEDMODE | \
911 AR5K_PCICFG_LEDBLINK | AR5K_PCICFG_LEDSLOW)
912#define AR5K_PCICFG_SLEEP_CLOCK_RATE 0x03000000 /* Sleep clock rate */
913#define AR5K_PCICFG_SLEEP_CLOCK_RATE_S 24
914
915/*
916 * "General Purpose Input/Output" (GPIO) control register
917 *
918 * I'm not sure about this but after looking at the code
919 * for all chipsets here is what i got.
920 *
921 * We have 6 GPIOs (pins), each GPIO has 4 modes (2 bits)
922 * Mode 0 -> always input
923 * Mode 1 -> output when GPIODO for this GPIO is set to 0
924 * Mode 2 -> output when GPIODO for this GPIO is set to 1
925 * Mode 3 -> always output
926 *
927 * For more infos check out get_gpio/set_gpio and
928 * set_gpio_input/set_gpio_output functs.
929 * For more infos on gpio interrupt check out set_gpio_intr.
930 */
931#define AR5K_NUM_GPIO 6
932
933#define AR5K_GPIOCR 0x4014 /* Register Address */
934#define AR5K_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO interrupt */
935#define AR5K_GPIOCR_INT_SELL 0x00000000 /* Generate interrupt when pin is low */
936#define AR5K_GPIOCR_INT_SELH 0x00010000 /* Generate interrupt when pin is high */
937#define AR5K_GPIOCR_IN(n) (0 << ((n) * 2)) /* Mode 0 for pin n */
938#define AR5K_GPIOCR_OUT0(n) (1 << ((n) * 2)) /* Mode 1 for pin n */
939#define AR5K_GPIOCR_OUT1(n) (2 << ((n) * 2)) /* Mode 2 for pin n */
940#define AR5K_GPIOCR_OUT(n) (3 << ((n) * 2)) /* Mode 3 for pin n */
941#define AR5K_GPIOCR_INT_SEL(n) ((n) << 12) /* Interrupt for GPIO pin n */
942
943/*
944 * "General Purpose Input/Output" (GPIO) data output register
945 */
946#define AR5K_GPIODO 0x4018
947
948/*
949 * "General Purpose Input/Output" (GPIO) data input register
950 */
951#define AR5K_GPIODI 0x401c
952#define AR5K_GPIODI_M 0x0000002f
953
954/*
955 * Silicon revision register
956 */
957#define AR5K_SREV 0x4020 /* Register Address */
958#define AR5K_SREV_REV 0x0000000f /* Mask for revision */
959#define AR5K_SREV_REV_S 0
960#define AR5K_SREV_VER 0x000000ff /* Mask for version */
961#define AR5K_SREV_VER_S 4
962
963/*
964 * TXE write posting register
965 */
966#define AR5K_TXEPOST 0x4028
967
968/*
969 * QCU sleep mask
970 */
971#define AR5K_QCU_SLEEP_MASK 0x402c
972
973/* 0x4068 is compression buffer configuration
974 * register on 5414 and pm configuration register
975 * on 5424 and newer pci-e chips. */
976
977/*
978 * Compression buffer configuration
979 * register (enable/disable) [5414]
980 */
981#define AR5K_5414_CBCFG 0x4068
982#define AR5K_5414_CBCFG_BUF_DIS 0x10 /* Disable buffer */
983
984/*
985 * PCI-E Power managment configuration
986 * and status register [5424+]
987 */
988#define AR5K_PCIE_PM_CTL 0x4068 /* Register address */
989/* Only 5424 */
990#define AR5K_PCIE_PM_CTL_L1_WHEN_D2 0x00000001 /* enable PCIe core enter L1
991 when d2_sleep_en is asserted */
992#define AR5K_PCIE_PM_CTL_L0_L0S_CLEAR 0x00000002 /* Clear L0 and L0S counters */
993#define AR5K_PCIE_PM_CTL_L0_L0S_EN 0x00000004 /* Start L0 nd L0S counters */
994#define AR5K_PCIE_PM_CTL_LDRESET_EN 0x00000008 /* Enable reset when link goes
995 down */
996/* Wake On Wireless */
997#define AR5K_PCIE_PM_CTL_PME_EN 0x00000010 /* PME Enable */
998#define AR5K_PCIE_PM_CTL_AUX_PWR_DET 0x00000020 /* Aux power detect */
999#define AR5K_PCIE_PM_CTL_PME_CLEAR 0x00000040 /* Clear PME */
1000#define AR5K_PCIE_PM_CTL_PSM_D0 0x00000080
1001#define AR5K_PCIE_PM_CTL_PSM_D1 0x00000100
1002#define AR5K_PCIE_PM_CTL_PSM_D2 0x00000200
1003#define AR5K_PCIE_PM_CTL_PSM_D3 0x00000400
1004
1005/*
1006 * PCI-E Workaround enable register
1007 */
1008#define AR5K_PCIE_WAEN 0x407c
1009
1010/*
1011 * PCI-E Serializer/Desirializer
1012 * registers
1013 */
1014#define AR5K_PCIE_SERDES 0x4080
1015#define AR5K_PCIE_SERDES_RESET 0x4084
1016
1017/*====EEPROM REGISTERS====*/
1018
1019/*
1020 * EEPROM access registers
1021 *
1022 * Here we got a difference between 5210/5211-12
1023 * read data register for 5210 is at 0x6800 and
1024 * status register is at 0x6c00. There is also
1025 * no eeprom command register on 5210 and the
1026 * offsets are different.
1027 *
1028 * To read eeprom data for a specific offset:
1029 * 5210 - enable eeprom access (AR5K_PCICFG_EEAE)
1030 * read AR5K_EEPROM_BASE +(4 * offset)
1031 * check the eeprom status register
1032 * and read eeprom data register.
1033 *
1034 * 5211 - write offset to AR5K_EEPROM_BASE
1035 * 5212 write AR5K_EEPROM_CMD_READ on AR5K_EEPROM_CMD
1036 * check the eeprom status register
1037 * and read eeprom data register.
1038 *
1039 * To write eeprom data for a specific offset:
1040 * 5210 - enable eeprom access (AR5K_PCICFG_EEAE)
1041 * write data to AR5K_EEPROM_BASE +(4 * offset)
1042 * check the eeprom status register
1043 * 5211 - write AR5K_EEPROM_CMD_RESET on AR5K_EEPROM_CMD
1044 * 5212 write offset to AR5K_EEPROM_BASE
1045 * write data to data register
1046 * write AR5K_EEPROM_CMD_WRITE on AR5K_EEPROM_CMD
1047 * check the eeprom status register
1048 *
1049 * For more infos check eeprom_* functs and the ar5k.c
1050 * file posted in madwifi-devel mailing list.
1051 * http://sourceforge.net/mailarchive/message.php?msg_id=8966525
1052 *
1053 */
1054#define AR5K_EEPROM_BASE 0x6000
1055
1056/*
1057 * EEPROM data register
1058 */
1059#define AR5K_EEPROM_DATA_5211 0x6004
1060#define AR5K_EEPROM_DATA_5210 0x6800
1061#define AR5K_EEPROM_DATA (ah->ah_version == AR5K_AR5210 ? \
1062 AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211)
1063
1064/*
1065 * EEPROM command register
1066 */
1067#define AR5K_EEPROM_CMD 0x6008 /* Register Addres */
1068#define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */
1069#define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */
1070#define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */
1071
1072/*
1073 * EEPROM status register
1074 */
1075#define AR5K_EEPROM_STAT_5210 0x6c00 /* Register Address [5210] */
1076#define AR5K_EEPROM_STAT_5211 0x600c /* Register Address [5211+] */
1077#define AR5K_EEPROM_STATUS (ah->ah_version == AR5K_AR5210 ? \
1078 AR5K_EEPROM_STAT_5210 : AR5K_EEPROM_STAT_5211)
1079#define AR5K_EEPROM_STAT_RDERR 0x00000001 /* EEPROM read failed */
1080#define AR5K_EEPROM_STAT_RDDONE 0x00000002 /* EEPROM read successful */
1081#define AR5K_EEPROM_STAT_WRERR 0x00000004 /* EEPROM write failed */
1082#define AR5K_EEPROM_STAT_WRDONE 0x00000008 /* EEPROM write successful */
1083
1084/*
1085 * EEPROM config register
1086 */
1087#define AR5K_EEPROM_CFG 0x6010 /* Register Addres */
1088#define AR5K_EEPROM_CFG_SIZE 0x00000003 /* Size determination override */
1089#define AR5K_EEPROM_CFG_SIZE_AUTO 0
1090#define AR5K_EEPROM_CFG_SIZE_4KBIT 1
1091#define AR5K_EEPROM_CFG_SIZE_8KBIT 2
1092#define AR5K_EEPROM_CFG_SIZE_16KBIT 3
1093#define AR5K_EEPROM_CFG_WR_WAIT_DIS 0x00000004 /* Disable write wait */
1094#define AR5K_EEPROM_CFG_CLK_RATE 0x00000018 /* Clock rate */
1095#define AR5K_EEPROM_CFG_CLK_RATE_S 3
1096#define AR5K_EEPROM_CFG_CLK_RATE_156KHZ 0
1097#define AR5K_EEPROM_CFG_CLK_RATE_312KHZ 1
1098#define AR5K_EEPROM_CFG_CLK_RATE_625KHZ 2
1099#define AR5K_EEPROM_CFG_PROT_KEY 0x00ffff00 /* Protection key */
1100#define AR5K_EEPROM_CFG_PROT_KEY_S 8
1101#define AR5K_EEPROM_CFG_LIND_EN 0x01000000 /* Enable length indicator (?) */
1102
1103
1104/*
1105 * TODO: Wake On Wireless registers
1106 * Range 0x7000 - 0x7ce0
1107 */
1108
1109/*
1110 * Protocol Control Unit (PCU) registers
1111 */
1112/*
1113 * Used for checking initial register writes
1114 * during channel reset (see reset func)
1115 */
1116#define AR5K_PCU_MIN 0x8000
1117#define AR5K_PCU_MAX 0x8fff
1118
1119/*
1120 * First station id register (Lower 32 bits of MAC address)
1121 */
1122#define AR5K_STA_ID0 0x8000
1123#define AR5K_STA_ID0_ARRD_L32 0xffffffff
1124
1125/*
1126 * Second station id register (Upper 16 bits of MAC address + PCU settings)
1127 */
1128#define AR5K_STA_ID1 0x8004 /* Register Address */
1129#define AR5K_STA_ID1_ADDR_U16 0x0000ffff /* Upper 16 bits of MAC addres */
1130#define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */
1131#define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */
1132#define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */
1133#define AR5K_STA_ID1_NO_KEYSRCH 0x00080000 /* No key search */
1134#define AR5K_STA_ID1_NO_PSPOLL 0x00100000 /* No power save polling [5210] */
1135#define AR5K_STA_ID1_PCF_5211 0x00100000 /* Enable PCF on [5211+] */
1136#define AR5K_STA_ID1_PCF_5210 0x00200000 /* Enable PCF on [5210]*/
1137#define AR5K_STA_ID1_PCF (ah->ah_version == AR5K_AR5210 ? \
1138 AR5K_STA_ID1_PCF_5210 : AR5K_STA_ID1_PCF_5211)
1139#define AR5K_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */
1140#define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */
1141#define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS */
1142#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS */
1143#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate for ACK/CTS [5211+] */
1144#define AR5K_STA_ID1_SELFGEN_DEF_ANT 0x04000000 /* Use def. antenna for self generated frames */
1145#define AR5K_STA_ID1_CRYPT_MIC_EN 0x08000000 /* Enable MIC */
1146#define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Look up key when key id != 0 */
1147#define AR5K_STA_ID1_PRESERVE_SEQ_NUM 0x20000000 /* Preserve sequence number */
1148#define AR5K_STA_ID1_CBCIV_ENDIAN 0x40000000 /* ??? */
1149#define AR5K_STA_ID1_KEYSRCH_MCAST 0x80000000 /* Do key cache search for mcast frames */
1150
1151/*
1152 * First BSSID register (MAC address, lower 32bits)
1153 */
1154#define AR5K_BSS_ID0 0x8008
1155
1156/*
1157 * Second BSSID register (MAC address in upper 16 bits)
1158 *
1159 * AID: Association ID
1160 */
1161#define AR5K_BSS_ID1 0x800c
1162#define AR5K_BSS_ID1_AID 0xffff0000
1163#define AR5K_BSS_ID1_AID_S 16
1164
1165/*
1166 * Backoff slot time register
1167 */
1168#define AR5K_SLOT_TIME 0x8010
1169
1170/*
1171 * ACK/CTS timeout register
1172 */
1173#define AR5K_TIME_OUT 0x8014 /* Register Address */
1174#define AR5K_TIME_OUT_ACK 0x00001fff /* ACK timeout mask */
1175#define AR5K_TIME_OUT_ACK_S 0
1176#define AR5K_TIME_OUT_CTS 0x1fff0000 /* CTS timeout mask */
1177#define AR5K_TIME_OUT_CTS_S 16
1178
1179/*
1180 * RSSI threshold register
1181 */
1182#define AR5K_RSSI_THR 0x8018 /* Register Address */
1183#define AR5K_RSSI_THR_M 0x000000ff /* Mask for RSSI threshold [5211+] */
1184#define AR5K_RSSI_THR_BMISS_5210 0x00000700 /* Mask for Beacon Missed threshold [5210] */
1185#define AR5K_RSSI_THR_BMISS_5210_S 8
1186#define AR5K_RSSI_THR_BMISS_5211 0x0000ff00 /* Mask for Beacon Missed threshold [5211+] */
1187#define AR5K_RSSI_THR_BMISS_5211_S 8
1188#define AR5K_RSSI_THR_BMISS (ah->ah_version == AR5K_AR5210 ? \
1189 AR5K_RSSI_THR_BMISS_5210 : AR5K_RSSI_THR_BMISS_5211)
1190#define AR5K_RSSI_THR_BMISS_S 8
1191
1192/*
1193 * 5210 has more PCU registers because there is no QCU/DCU
1194 * so queue parameters are set here, this way a lot common
1195 * registers have different address for 5210. To make things
1196 * easier we define a macro based on ah->ah_version for common
1197 * registers with different addresses and common flags.
1198 */
1199
1200/*
1201 * Retry limit register
1202 *
1203 * Retry limit register for 5210 (no QCU/DCU so it's done in PCU)
1204 */
1205#define AR5K_NODCU_RETRY_LMT 0x801c /* Register Address */
1206#define AR5K_NODCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */
1207#define AR5K_NODCU_RETRY_LMT_SH_RETRY_S 0
1208#define AR5K_NODCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry mask */
1209#define AR5K_NODCU_RETRY_LMT_LG_RETRY_S 4
1210#define AR5K_NODCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask */
1211#define AR5K_NODCU_RETRY_LMT_SSH_RETRY_S 8
1212#define AR5K_NODCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask */
1213#define AR5K_NODCU_RETRY_LMT_SLG_RETRY_S 14
1214#define AR5K_NODCU_RETRY_LMT_CW_MIN 0x3ff00000 /* Minimum contention window mask */
1215#define AR5K_NODCU_RETRY_LMT_CW_MIN_S 20
1216
1217/*
1218 * Transmit latency register
1219 */
1220#define AR5K_USEC_5210 0x8020 /* Register Address [5210] */
1221#define AR5K_USEC_5211 0x801c /* Register Address [5211+] */
1222#define AR5K_USEC (ah->ah_version == AR5K_AR5210 ? \
1223 AR5K_USEC_5210 : AR5K_USEC_5211)
1224#define AR5K_USEC_1 0x0000007f /* clock cycles for 1us */
1225#define AR5K_USEC_1_S 0
1226#define AR5K_USEC_32 0x00003f80 /* clock cycles for 1us while on 32Mhz clock */
1227#define AR5K_USEC_32_S 7
1228#define AR5K_USEC_TX_LATENCY_5211 0x007fc000
1229#define AR5K_USEC_TX_LATENCY_5211_S 14
1230#define AR5K_USEC_RX_LATENCY_5211 0x1f800000
1231#define AR5K_USEC_RX_LATENCY_5211_S 23
1232#define AR5K_USEC_TX_LATENCY_5210 0x000fc000 /* also for 5311 */
1233#define AR5K_USEC_TX_LATENCY_5210_S 14
1234#define AR5K_USEC_RX_LATENCY_5210 0x03f00000 /* also for 5311 */
1235#define AR5K_USEC_RX_LATENCY_5210_S 20
1236
1237/*
1238 * PCU beacon control register
1239 */
1240#define AR5K_BEACON_5210 0x8024 /*Register Address [5210] */
1241#define AR5K_BEACON_5211 0x8020 /*Register Address [5211+] */
1242#define AR5K_BEACON (ah->ah_version == AR5K_AR5210 ? \
1243 AR5K_BEACON_5210 : AR5K_BEACON_5211)
1244#define AR5K_BEACON_PERIOD 0x0000ffff /* Mask for beacon period */
1245#define AR5K_BEACON_PERIOD_S 0
1246#define AR5K_BEACON_TIM 0x007f0000 /* Mask for TIM offset */
1247#define AR5K_BEACON_TIM_S 16
1248#define AR5K_BEACON_ENABLE 0x00800000 /* Enable beacons */
1249#define AR5K_BEACON_RESET_TSF 0x01000000 /* Force TSF reset */
1250
1251/*
1252 * CFP period register
1253 */
1254#define AR5K_CFP_PERIOD_5210 0x8028
1255#define AR5K_CFP_PERIOD_5211 0x8024
1256#define AR5K_CFP_PERIOD (ah->ah_version == AR5K_AR5210 ? \
1257 AR5K_CFP_PERIOD_5210 : AR5K_CFP_PERIOD_5211)
1258
1259/*
1260 * Next beacon time register
1261 */
1262#define AR5K_TIMER0_5210 0x802c
1263#define AR5K_TIMER0_5211 0x8028
1264#define AR5K_TIMER0 (ah->ah_version == AR5K_AR5210 ? \
1265 AR5K_TIMER0_5210 : AR5K_TIMER0_5211)
1266
1267/*
1268 * Next DMA beacon alert register
1269 */
1270#define AR5K_TIMER1_5210 0x8030
1271#define AR5K_TIMER1_5211 0x802c
1272#define AR5K_TIMER1 (ah->ah_version == AR5K_AR5210 ? \
1273 AR5K_TIMER1_5210 : AR5K_TIMER1_5211)
1274
1275/*
1276 * Next software beacon alert register
1277 */
1278#define AR5K_TIMER2_5210 0x8034
1279#define AR5K_TIMER2_5211 0x8030
1280#define AR5K_TIMER2 (ah->ah_version == AR5K_AR5210 ? \
1281 AR5K_TIMER2_5210 : AR5K_TIMER2_5211)
1282
1283/*
1284 * Next ATIM window time register
1285 */
1286#define AR5K_TIMER3_5210 0x8038
1287#define AR5K_TIMER3_5211 0x8034
1288#define AR5K_TIMER3 (ah->ah_version == AR5K_AR5210 ? \
1289 AR5K_TIMER3_5210 : AR5K_TIMER3_5211)
1290
1291
1292/*
1293 * 5210 First inter frame spacing register (IFS)
1294 */
1295#define AR5K_IFS0 0x8040
1296#define AR5K_IFS0_SIFS 0x000007ff
1297#define AR5K_IFS0_SIFS_S 0
1298#define AR5K_IFS0_DIFS 0x007ff800
1299#define AR5K_IFS0_DIFS_S 11
1300
1301/*
1302 * 5210 Second inter frame spacing register (IFS)
1303 */
1304#define AR5K_IFS1 0x8044
1305#define AR5K_IFS1_PIFS 0x00000fff
1306#define AR5K_IFS1_PIFS_S 0
1307#define AR5K_IFS1_EIFS 0x03fff000
1308#define AR5K_IFS1_EIFS_S 12
1309#define AR5K_IFS1_CS_EN 0x04000000
1310
1311
1312/*
1313 * CFP duration register
1314 */
1315#define AR5K_CFP_DUR_5210 0x8048
1316#define AR5K_CFP_DUR_5211 0x8038
1317#define AR5K_CFP_DUR (ah->ah_version == AR5K_AR5210 ? \
1318 AR5K_CFP_DUR_5210 : AR5K_CFP_DUR_5211)
1319
1320/*
1321 * Receive filter register
1322 */
1323#define AR5K_RX_FILTER_5210 0x804c /* Register Address [5210] */
1324#define AR5K_RX_FILTER_5211 0x803c /* Register Address [5211+] */
1325#define AR5K_RX_FILTER (ah->ah_version == AR5K_AR5210 ? \
1326 AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211)
1327#define AR5K_RX_FILTER_UCAST 0x00000001 /* Don't filter unicast frames */
1328#define AR5K_RX_FILTER_MCAST 0x00000002 /* Don't filter multicast frames */
1329#define AR5K_RX_FILTER_BCAST 0x00000004 /* Don't filter broadcast frames */
1330#define AR5K_RX_FILTER_CONTROL 0x00000008 /* Don't filter control frames */
1331#define AR5K_RX_FILTER_BEACON 0x00000010 /* Don't filter beacon frames */
1332#define AR5K_RX_FILTER_PROM 0x00000020 /* Set promiscuous mode */
1333#define AR5K_RX_FILTER_XRPOLL 0x00000040 /* Don't filter XR poll frame [5212+] */
1334#define AR5K_RX_FILTER_PROBEREQ 0x00000080 /* Don't filter probe requests [5212+] */
1335#define AR5K_RX_FILTER_PHYERR_5212 0x00000100 /* Don't filter phy errors [5212+] */
1336#define AR5K_RX_FILTER_RADARERR_5212 0x00000200 /* Don't filter phy radar errors [5212+] */
1337#define AR5K_RX_FILTER_PHYERR_5211 0x00000040 /* [5211] */
1338#define AR5K_RX_FILTER_RADARERR_5211 0x00000080 /* [5211] */
1339#define AR5K_RX_FILTER_PHYERR \
1340 ((ah->ah_version == AR5K_AR5211 ? \
1341 AR5K_RX_FILTER_PHYERR_5211 : AR5K_RX_FILTER_PHYERR_5212))
1342#define AR5K_RX_FILTER_RADARERR \
1343 ((ah->ah_version == AR5K_AR5211 ? \
1344 AR5K_RX_FILTER_RADARERR_5211 : AR5K_RX_FILTER_RADARERR_5212))
1345
1346/*
1347 * Multicast filter register (lower 32 bits)
1348 */
1349#define AR5K_MCAST_FILTER0_5210 0x8050
1350#define AR5K_MCAST_FILTER0_5211 0x8040
1351#define AR5K_MCAST_FILTER0 (ah->ah_version == AR5K_AR5210 ? \
1352 AR5K_MCAST_FILTER0_5210 : AR5K_MCAST_FILTER0_5211)
1353
1354/*
1355 * Multicast filter register (higher 16 bits)
1356 */
1357#define AR5K_MCAST_FILTER1_5210 0x8054
1358#define AR5K_MCAST_FILTER1_5211 0x8044
1359#define AR5K_MCAST_FILTER1 (ah->ah_version == AR5K_AR5210 ? \
1360 AR5K_MCAST_FILTER1_5210 : AR5K_MCAST_FILTER1_5211)
1361
1362
1363/*
1364 * Transmit mask register (lower 32 bits) [5210]
1365 */
1366#define AR5K_TX_MASK0 0x8058
1367
1368/*
1369 * Transmit mask register (higher 16 bits) [5210]
1370 */
1371#define AR5K_TX_MASK1 0x805c
1372
1373/*
1374 * Clear transmit mask [5210]
1375 */
1376#define AR5K_CLR_TMASK 0x8060
1377
1378/*
1379 * Trigger level register (before transmission) [5210]
1380 */
1381#define AR5K_TRIG_LVL 0x8064
1382
1383
1384/*
1385 * PCU control register
1386 *
1387 * Only DIS_RX is used in the code, the rest i guess are
1388 * for tweaking/diagnostics.
1389 */
1390#define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */
1391#define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */
1392#define AR5K_DIAG_SW (ah->ah_version == AR5K_AR5210 ? \
1393 AR5K_DIAG_SW_5210 : AR5K_DIAG_SW_5211)
1394#define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001 /* Disable ACKs if WEP key is invalid */
1395#define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs */
1396#define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs */
1397#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption */
1398#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption */
1399#define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */
1400#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */
1401#define AR5K_DIAG_SW_DIS_RX_5211 0x00000020
1402#define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \
1403 AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211)
1404#define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* Loopback (i guess it goes with DIS_TX) [5210] */
1405#define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040
1406#define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \
1407 AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211)
1408#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Corrupted FCS */
1409#define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080
1410#define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \
1411 AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211)
1412#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Dump channel info */
1413#define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100
1414#define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \
1415 AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211)
1416#define AR5K_DIAG_SW_EN_SCRAM_SEED_5210 0x00000400 /* Enable fixed scrambler seed */
1417#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200
1418#define AR5K_DIAG_SW_EN_SCRAM_SEED (ah->ah_version == AR5K_AR5210 ? \
1419 AR5K_DIAG_SW_EN_SCRAM_SEED_5210 : AR5K_DIAG_SW_EN_SCRAM_SEED_5211)
1420#define AR5K_DIAG_SW_ECO_ENABLE 0x00000400 /* [5211+] */
1421#define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */
1422#define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask */
1423#define AR5K_DIAG_SW_SCRAM_SEED_S 10
1424#define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */
1425#define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000
1426#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 /* Accept frames of non-zero protocol number */
1427#define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \
1428 AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211)
1429#define AR5K_DIAG_SW_OBSPT_M 0x000c0000 /* Observation point select (?) */
1430#define AR5K_DIAG_SW_OBSPT_S 18
1431#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */
1432#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */
1433#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high */
1434#define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */
1435
1436/*
1437 * TSF (clock) register (lower 32 bits)
1438 */
1439#define AR5K_TSF_L32_5210 0x806c
1440#define AR5K_TSF_L32_5211 0x804c
1441#define AR5K_TSF_L32 (ah->ah_version == AR5K_AR5210 ? \
1442 AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211)
1443
1444/*
1445 * TSF (clock) register (higher 32 bits)
1446 */
1447#define AR5K_TSF_U32_5210 0x8070
1448#define AR5K_TSF_U32_5211 0x8050
1449#define AR5K_TSF_U32 (ah->ah_version == AR5K_AR5210 ? \
1450 AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211)
1451
1452/*
1453 * Last beacon timestamp register (Read Only)
1454 */
1455#define AR5K_LAST_TSTP 0x8080
1456
1457/*
1458 * ADDAC test register [5211+]
1459 */
1460#define AR5K_ADDAC_TEST 0x8054 /* Register Address */
1461#define AR5K_ADDAC_TEST_TXCONT 0x00000001 /* Test continuous tx */
1462#define AR5K_ADDAC_TEST_TST_MODE 0x00000002 /* Test mode */
1463#define AR5K_ADDAC_TEST_LOOP_EN 0x00000004 /* Enable loop */
1464#define AR5K_ADDAC_TEST_LOOP_LEN 0x00000008 /* Loop length (field) */
1465#define AR5K_ADDAC_TEST_USE_U8 0x00004000 /* Use upper 8 bits */
1466#define AR5K_ADDAC_TEST_MSB 0x00008000 /* State of MSB */
1467#define AR5K_ADDAC_TEST_TRIG_SEL 0x00010000 /* Trigger select */
1468#define AR5K_ADDAC_TEST_TRIG_PTY 0x00020000 /* Trigger polarity */
1469#define AR5K_ADDAC_TEST_RXCONT 0x00040000 /* Continuous capture */
1470#define AR5K_ADDAC_TEST_CAPTURE 0x00080000 /* Begin capture */
1471#define AR5K_ADDAC_TEST_TST_ARM 0x00100000 /* ARM rx buffer for capture */
1472
1473/*
1474 * Default antenna register [5211+]
1475 */
1476#define AR5K_DEFAULT_ANTENNA 0x8058
1477
1478/*
1479 * Frame control QoS mask register (?) [5211+]
1480 * (FC_QOS_MASK)
1481 */
1482#define AR5K_FRAME_CTL_QOSM 0x805c
1483
1484/*
1485 * Seq mask register (?) [5211+]
1486 */
1487#define AR5K_SEQ_MASK 0x8060
1488
1489/*
1490 * Retry count register [5210]
1491 */
1492#define AR5K_RETRY_CNT 0x8084 /* Register Address [5210] */
1493#define AR5K_RETRY_CNT_SSH 0x0000003f /* Station short retry count (?) */
1494#define AR5K_RETRY_CNT_SLG 0x00000fc0 /* Station long retry count (?) */
1495
1496/*
1497 * Back-off status register [5210]
1498 */
1499#define AR5K_BACKOFF 0x8088 /* Register Address [5210] */
1500#define AR5K_BACKOFF_CW 0x000003ff /* Backoff Contention Window (?) */
1501#define AR5K_BACKOFF_CNT 0x03ff0000 /* Backoff count (?) */
1502
1503
1504
1505/*
1506 * NAV register (current)
1507 */
1508#define AR5K_NAV_5210 0x808c
1509#define AR5K_NAV_5211 0x8084
1510#define AR5K_NAV (ah->ah_version == AR5K_AR5210 ? \
1511 AR5K_NAV_5210 : AR5K_NAV_5211)
1512
1513/*
1514 * RTS success register
1515 */
1516#define AR5K_RTS_OK_5210 0x8090
1517#define AR5K_RTS_OK_5211 0x8088
1518#define AR5K_RTS_OK (ah->ah_version == AR5K_AR5210 ? \
1519 AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211)
1520
1521/*
1522 * RTS failure register
1523 */
1524#define AR5K_RTS_FAIL_5210 0x8094
1525#define AR5K_RTS_FAIL_5211 0x808c
1526#define AR5K_RTS_FAIL (ah->ah_version == AR5K_AR5210 ? \
1527 AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211)
1528
1529/*
1530 * ACK failure register
1531 */
1532#define AR5K_ACK_FAIL_5210 0x8098
1533#define AR5K_ACK_FAIL_5211 0x8090
1534#define AR5K_ACK_FAIL (ah->ah_version == AR5K_AR5210 ? \
1535 AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211)
1536
1537/*
1538 * FCS failure register
1539 */
1540#define AR5K_FCS_FAIL_5210 0x809c
1541#define AR5K_FCS_FAIL_5211 0x8094
1542#define AR5K_FCS_FAIL (ah->ah_version == AR5K_AR5210 ? \
1543 AR5K_FCS_FAIL_5210 : AR5K_FCS_FAIL_5211)
1544
1545/*
1546 * Beacon count register
1547 */
1548#define AR5K_BEACON_CNT_5210 0x80a0
1549#define AR5K_BEACON_CNT_5211 0x8098
1550#define AR5K_BEACON_CNT (ah->ah_version == AR5K_AR5210 ? \
1551 AR5K_BEACON_CNT_5210 : AR5K_BEACON_CNT_5211)
1552
1553
1554/*===5212 Specific PCU registers===*/
1555
1556/*
1557 * Transmit power control register
1558 */
1559#define AR5K_TPC 0x80e8
1560#define AR5K_TPC_ACK 0x0000003f /* ack frames */
1561#define AR5K_TPC_ACK_S 0
1562#define AR5K_TPC_CTS 0x00003f00 /* cts frames */
1563#define AR5K_TPC_CTS_S 8
1564#define AR5K_TPC_CHIRP 0x003f0000 /* chirp frames */
1565#define AR5K_TPC_CHIRP_S 16
1566#define AR5K_TPC_DOPPLER 0x0f000000 /* doppler chirp span */
1567#define AR5K_TPC_DOPPLER_S 24
1568
1569/*
1570 * XR (eXtended Range) mode register
1571 */
1572#define AR5K_XRMODE 0x80c0 /* Register Address */
1573#define AR5K_XRMODE_POLL_TYPE_M 0x0000003f /* Mask for Poll type (?) */
1574#define AR5K_XRMODE_POLL_TYPE_S 0
1575#define AR5K_XRMODE_POLL_SUBTYPE_M 0x0000003c /* Mask for Poll subtype (?) */
1576#define AR5K_XRMODE_POLL_SUBTYPE_S 2
1577#define AR5K_XRMODE_POLL_WAIT_ALL 0x00000080 /* Wait for poll */
1578#define AR5K_XRMODE_SIFS_DELAY 0x000fff00 /* Mask for SIFS delay */
1579#define AR5K_XRMODE_FRAME_HOLD_M 0xfff00000 /* Mask for frame hold (?) */
1580#define AR5K_XRMODE_FRAME_HOLD_S 20
1581
1582/*
1583 * XR delay register
1584 */
1585#define AR5K_XRDELAY 0x80c4 /* Register Address */
1586#define AR5K_XRDELAY_SLOT_DELAY_M 0x0000ffff /* Mask for slot delay */
1587#define AR5K_XRDELAY_SLOT_DELAY_S 0
1588#define AR5K_XRDELAY_CHIRP_DELAY_M 0xffff0000 /* Mask for CHIRP data delay */
1589#define AR5K_XRDELAY_CHIRP_DELAY_S 16
1590
1591/*
1592 * XR timeout register
1593 */
1594#define AR5K_XRTIMEOUT 0x80c8 /* Register Address */
1595#define AR5K_XRTIMEOUT_CHIRP_M 0x0000ffff /* Mask for CHIRP timeout */
1596#define AR5K_XRTIMEOUT_CHIRP_S 0
1597#define AR5K_XRTIMEOUT_POLL_M 0xffff0000 /* Mask for Poll timeout */
1598#define AR5K_XRTIMEOUT_POLL_S 16
1599
1600/*
1601 * XR chirp register
1602 */
1603#define AR5K_XRCHIRP 0x80cc /* Register Address */
1604#define AR5K_XRCHIRP_SEND 0x00000001 /* Send CHIRP */
1605#define AR5K_XRCHIRP_GAP 0xffff0000 /* Mask for CHIRP gap (?) */
1606
1607/*
1608 * XR stomp register
1609 */
1610#define AR5K_XRSTOMP 0x80d0 /* Register Address */
1611#define AR5K_XRSTOMP_TX 0x00000001 /* Stomp Tx (?) */
1612#define AR5K_XRSTOMP_RX 0x00000002 /* Stomp Rx (?) */
1613#define AR5K_XRSTOMP_TX_RSSI 0x00000004 /* Stomp Tx RSSI (?) */
1614#define AR5K_XRSTOMP_TX_BSSID 0x00000008 /* Stomp Tx BSSID (?) */
1615#define AR5K_XRSTOMP_DATA 0x00000010 /* Stomp data (?)*/
1616#define AR5K_XRSTOMP_RSSI_THRES 0x0000ff00 /* Mask for XR RSSI threshold */
1617
1618/*
1619 * First enhanced sleep register
1620 */
1621#define AR5K_SLEEP0 0x80d4 /* Register Address */
1622#define AR5K_SLEEP0_NEXT_DTIM 0x0007ffff /* Mask for next DTIM (?) */
1623#define AR5K_SLEEP0_NEXT_DTIM_S 0
1624#define AR5K_SLEEP0_ASSUME_DTIM 0x00080000 /* Assume DTIM */
1625#define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000 /* Enable enchanced sleep control */
1626#define AR5K_SLEEP0_CABTO 0xff000000 /* Mask for CAB Time Out */
1627#define AR5K_SLEEP0_CABTO_S 24
1628
1629/*
1630 * Second enhanced sleep register
1631 */
1632#define AR5K_SLEEP1 0x80d8 /* Register Address */
1633#define AR5K_SLEEP1_NEXT_TIM 0x0007ffff /* Mask for next TIM (?) */
1634#define AR5K_SLEEP1_NEXT_TIM_S 0
1635#define AR5K_SLEEP1_BEACON_TO 0xff000000 /* Mask for Beacon Time Out */
1636#define AR5K_SLEEP1_BEACON_TO_S 24
1637
1638/*
1639 * Third enhanced sleep register
1640 */
1641#define AR5K_SLEEP2 0x80dc /* Register Address */
1642#define AR5K_SLEEP2_TIM_PER 0x0000ffff /* Mask for TIM period (?) */
1643#define AR5K_SLEEP2_TIM_PER_S 0
1644#define AR5K_SLEEP2_DTIM_PER 0xffff0000 /* Mask for DTIM period (?) */
1645#define AR5K_SLEEP2_DTIM_PER_S 16
1646
1647/*
1648 * BSSID mask registers
1649 */
1650#define AR5K_BSS_IDM0 0x80e0 /* Upper bits */
1651#define AR5K_BSS_IDM1 0x80e4 /* Lower bits */
1652
1653/*
1654 * TX power control (TPC) register
1655 *
1656 * XXX: PCDAC steps (0.5dbm) or DBM ?
1657 *
1658 */
1659#define AR5K_TXPC 0x80e8 /* Register Address */
1660#define AR5K_TXPC_ACK_M 0x0000003f /* ACK tx power */
1661#define AR5K_TXPC_ACK_S 0
1662#define AR5K_TXPC_CTS_M 0x00003f00 /* CTS tx power */
1663#define AR5K_TXPC_CTS_S 8
1664#define AR5K_TXPC_CHIRP_M 0x003f0000 /* CHIRP tx power */
1665#define AR5K_TXPC_CHIRP_S 16
1666#define AR5K_TXPC_DOPPLER 0x0f000000 /* Doppler chirp span (?) */
1667#define AR5K_TXPC_DOPPLER_S 24
1668
1669/*
1670 * Profile count registers
1671 */
1672#define AR5K_PROFCNT_TX 0x80ec /* Tx count */
1673#define AR5K_PROFCNT_RX 0x80f0 /* Rx count */
1674#define AR5K_PROFCNT_RXCLR 0x80f4 /* Clear Rx count */
1675#define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle count (?) */
1676
1677/*
1678 * Quiet period control registers
1679 */
1680#define AR5K_QUIET_CTL1 0x80fc /* Register Address */
1681#define AR5K_QUIET_CTL1_NEXT_QT_TSF 0x0000ffff /* Next quiet period TSF (TU) */
1682#define AR5K_QUIET_CTL1_NEXT_QT_TSF_S 0
1683#define AR5K_QUIET_CTL1_QT_EN 0x00010000 /* Enable quiet period */
1684#define AR5K_QUIET_CTL1_ACK_CTS_EN 0x00020000 /* Send ACK/CTS during quiet period */
1685
1686#define AR5K_QUIET_CTL2 0x8100 /* Register Address */
1687#define AR5K_QUIET_CTL2_QT_PER 0x0000ffff /* Mask for quiet period periodicity */
1688#define AR5K_QUIET_CTL2_QT_PER_S 0
1689#define AR5K_QUIET_CTL2_QT_DUR 0xffff0000 /* Mask for quiet period duration */
1690#define AR5K_QUIET_CTL2_QT_DUR_S 16
1691
1692/*
1693 * TSF parameter register
1694 */
1695#define AR5K_TSF_PARM 0x8104 /* Register Address */
1696#define AR5K_TSF_PARM_INC 0x000000ff /* Mask for TSF increment */
1697#define AR5K_TSF_PARM_INC_S 0
1698
1699/*
1700 * QoS NOACK policy
1701 */
1702#define AR5K_QOS_NOACK 0x8108 /* Register Address */
1703#define AR5K_QOS_NOACK_2BIT_VALUES 0x0000000f /* ??? */
1704#define AR5K_QOS_NOACK_2BIT_VALUES_S 0
1705#define AR5K_QOS_NOACK_BIT_OFFSET 0x00000070 /* ??? */
1706#define AR5K_QOS_NOACK_BIT_OFFSET_S 4
1707#define AR5K_QOS_NOACK_BYTE_OFFSET 0x00000180 /* ??? */
1708#define AR5K_QOS_NOACK_BYTE_OFFSET_S 7
1709
1710/*
1711 * PHY error filter register
1712 */
1713#define AR5K_PHY_ERR_FIL 0x810c
1714#define AR5K_PHY_ERR_FIL_RADAR 0x00000020 /* Radar signal */
1715#define AR5K_PHY_ERR_FIL_OFDM 0x00020000 /* OFDM false detect (ANI) */
1716#define AR5K_PHY_ERR_FIL_CCK 0x02000000 /* CCK false detect (ANI) */
1717
1718/*
1719 * XR latency register
1720 */
1721#define AR5K_XRLAT_TX 0x8110
1722
1723/*
1724 * ACK SIFS register
1725 */
1726#define AR5K_ACKSIFS 0x8114 /* Register Address */
1727#define AR5K_ACKSIFS_INC 0x00000000 /* ACK SIFS Increment (field) */
1728
1729/*
1730 * MIC QoS control register (?)
1731 */
1732#define AR5K_MIC_QOS_CTL 0x8118 /* Register Address */
1733#define AR5K_MIC_QOS_CTL_OFF(_n) (1 << (_n * 2))
1734#define AR5K_MIC_QOS_CTL_MQ_EN 0x00010000 /* Enable MIC QoS */
1735
1736/*
1737 * MIC QoS select register (?)
1738 */
1739#define AR5K_MIC_QOS_SEL 0x811c
1740#define AR5K_MIC_QOS_SEL_OFF(_n) (1 << (_n * 4))
1741
1742/*
1743 * Misc mode control register (?)
1744 */
1745#define AR5K_MISC_MODE 0x8120 /* Register Address */
1746#define AR5K_MISC_MODE_FBSSID_MATCH 0x00000001 /* Force BSSID match */
1747#define AR5K_MISC_MODE_ACKSIFS_MEM 0x00000002 /* ACK SIFS memory (?) */
1748#define AR5K_MISC_MODE_COMBINED_MIC 0x00000004 /* use rx/tx MIC key */
1749/* more bits */
1750
1751/*
1752 * OFDM Filter counter
1753 */
1754#define AR5K_OFDM_FIL_CNT 0x8124
1755
1756/*
1757 * CCK Filter counter
1758 */
1759#define AR5K_CCK_FIL_CNT 0x8128
1760
1761/*
1762 * PHY Error Counters (?)
1763 */
1764#define AR5K_PHYERR_CNT1 0x812c
1765#define AR5K_PHYERR_CNT1_MASK 0x8130
1766
1767#define AR5K_PHYERR_CNT2 0x8134
1768#define AR5K_PHYERR_CNT2_MASK 0x8138
1769
1770/*
1771 * TSF Threshold register (?)
1772 */
1773#define AR5K_TSF_THRES 0x813c
1774
1775/*
1776 * TODO: Wake On Wireless registers
1777 * Range: 0x8147 - 0x818c
1778 */
1779
1780/*
1781 * Rate -> ACK SIFS mapping table (32 entries)
1782 */
1783#define AR5K_RATE_ACKSIFS_BASE 0x8680 /* Register Address */
1784#define AR5K_RATE_ACKSIFS(_n) (AR5K_RATE_ACKSIFS_BSE + ((_n) << 2))
1785#define AR5K_RATE_ACKSIFS_NORMAL 0x00000001 /* Normal SIFS (field) */
1786#define AR5K_RATE_ACKSIFS_TURBO 0x00000400 /* Turbo SIFS (field) */
1787
1788/*
1789 * Rate -> duration mapping table (32 entries)
1790 */
1791#define AR5K_RATE_DUR_BASE 0x8700
1792#define AR5K_RATE_DUR(_n) (AR5K_RATE_DUR_BASE + ((_n) << 2))
1793
1794/*
1795 * Rate -> db mapping table
1796 * (8 entries, each one has 4 8bit fields)
1797 */
1798#define AR5K_RATE2DB_BASE 0x87c0
1799#define AR5K_RATE2DB(_n) (AR5K_RATE2DB_BASE + ((_n) << 2))
1800
1801/*
1802 * db -> Rate mapping table
1803 * (8 entries, each one has 4 8bit fields)
1804 */
1805#define AR5K_DB2RATE_BASE 0x87e0
1806#define AR5K_DB2RATE(_n) (AR5K_DB2RATE_BASE + ((_n) << 2))
1807
1808/*===5212 end===*/
1809
1810/*
1811 * Key table (WEP) register
1812 */
1813#define AR5K_KEYTABLE_0_5210 0x9000
1814#define AR5K_KEYTABLE_0_5211 0x8800
1815#define AR5K_KEYTABLE_5210(_n) (AR5K_KEYTABLE_0_5210 + ((_n) << 5))
1816#define AR5K_KEYTABLE_5211(_n) (AR5K_KEYTABLE_0_5211 + ((_n) << 5))
1817#define AR5K_KEYTABLE(_n) (ah->ah_version == AR5K_AR5210 ? \
1818 AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n))
1819#define AR5K_KEYTABLE_OFF(_n, x) (AR5K_KEYTABLE(_n) + (x << 2))
1820#define AR5K_KEYTABLE_TYPE(_n) AR5K_KEYTABLE_OFF(_n, 5)
1821#define AR5K_KEYTABLE_TYPE_40 0x00000000
1822#define AR5K_KEYTABLE_TYPE_104 0x00000001
1823#define AR5K_KEYTABLE_TYPE_128 0x00000003
1824#define AR5K_KEYTABLE_TYPE_TKIP 0x00000004 /* [5212+] */
1825#define AR5K_KEYTABLE_TYPE_AES 0x00000005 /* [5211+] */
1826#define AR5K_KEYTABLE_TYPE_CCM 0x00000006 /* [5212+] */
1827#define AR5K_KEYTABLE_TYPE_NULL 0x00000007 /* [5211+] */
1828#define AR5K_KEYTABLE_ANTENNA 0x00000008 /* [5212+] */
1829#define AR5K_KEYTABLE_MAC0(_n) AR5K_KEYTABLE_OFF(_n, 6)
1830#define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7)
1831#define AR5K_KEYTABLE_VALID 0x00008000
1832
1833/* If key type is TKIP and MIC is enabled
1834 * MIC key goes in offset entry + 64 */
1835#define AR5K_KEYTABLE_MIC_OFFSET 64
1836
1837/* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit
1838 * WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit
1839 * WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit
1840 *
1841 * Some vendors have introduced bigger WEP keys to address
1842 * security vulnerabilities in WEP. This includes:
1843 *
1844 * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit
1845 *
1846 * We can expand this if we find ar5k Atheros cards with a larger
1847 * key table size.
1848 */
1849#define AR5K_KEYTABLE_SIZE_5210 64
1850#define AR5K_KEYTABLE_SIZE_5211 128
1851#define AR5K_KEYTABLE_SIZE (ah->ah_version == AR5K_AR5210 ? \
1852 AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211)
1853
1854
1855/*===PHY REGISTERS===*/
1856
1857/*
1858 * PHY registers start
1859 */
1860#define AR5K_PHY_BASE 0x9800
1861#define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2))
1862
1863/*
1864 * TST_2 (Misc config parameters)
1865 */
1866#define AR5K_PHY_TST2 0x9800 /* Register Address */
1867#define AR5K_PHY_TST2_TRIG_SEL 0x00000007 /* Trigger select (?)*/
1868#define AR5K_PHY_TST2_TRIG 0x00000010 /* Trigger (?) */
1869#define AR5K_PHY_TST2_CBUS_MODE 0x00000060 /* Cardbus mode (?) */
1870#define AR5K_PHY_TST2_CLK32 0x00000400 /* CLK_OUT is CLK32 (32Khz external) */
1871#define AR5K_PHY_TST2_CHANCOR_DUMP_EN 0x00000800 /* Enable Chancor dump (?) */
1872#define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP 0x00001000 /* Even Chancor dump (?) */
1873#define AR5K_PHY_TST2_RFSILENT_EN 0x00002000 /* Enable RFSILENT */
1874#define AR5K_PHY_TST2_ALT_RFDATA 0x00004000 /* Alternate RFDATA (5-2GHz switch ?) */
1875#define AR5K_PHY_TST2_MINI_OBS_EN 0x00008000 /* Enable mini OBS (?) */
1876#define AR5K_PHY_TST2_RX2_IS_RX5_INV 0x00010000 /* 2GHz rx path is the 5GHz path inverted (?) */
1877#define AR5K_PHY_TST2_SLOW_CLK160 0x00020000 /* Slow CLK160 (?) */
1878#define AR5K_PHY_TST2_AGC_OBS_SEL_3 0x00040000 /* AGC OBS Select 3 (?) */
1879#define AR5K_PHY_TST2_BBB_OBS_SEL 0x00080000 /* BB OBS Select (field ?) */
1880#define AR5K_PHY_TST2_ADC_OBS_SEL 0x00800000 /* ADC OBS Select (field ?) */
1881#define AR5K_PHY_TST2_RX_CLR_SEL 0x08000000 /* RX Clear Select (?) */
1882#define AR5K_PHY_TST2_FORCE_AGC_CLR 0x10000000 /* Force AGC clear (?) */
1883#define AR5K_PHY_SHIFT_2GHZ 0x00004007 /* Used to access 2GHz radios */
1884#define AR5K_PHY_SHIFT_5GHZ 0x00000007 /* Used to access 5GHz radios (default) */
1885
1886/*
1887 * PHY frame control register [5110] /turbo mode register [5111+]
1888 *
1889 * There is another frame control register for [5111+]
1890 * at address 0x9944 (see below) but the 2 first flags
1891 * are common here between 5110 frame control register
1892 * and [5111+] turbo mode register, so this also works as
1893 * a "turbo mode register" for 5110. We treat this one as
1894 * a frame control register for 5110 below.
1895 */
1896#define AR5K_PHY_TURBO 0x9804 /* Register Address */
1897#define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */
1898#define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */
1899#define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo mimo */
1900
1901/*
1902 * PHY agility command register
1903 * (aka TST_1)
1904 */
1905#define AR5K_PHY_AGC 0x9808 /* Register Address */
1906#define AR5K_PHY_TST1 0x9808
1907#define AR5K_PHY_AGC_DISABLE 0x08000000 /* Disable AGC to A2 (?)*/
1908#define AR5K_PHY_TST1_TXHOLD 0x00003800 /* Set tx hold (?) */
1909#define AR5K_PHY_TST1_TXSRC_SRC 0x00000002 /* Used with bit 7 (?) */
1910#define AR5K_PHY_TST1_TXSRC_SRC_S 1
1911#define AR5K_PHY_TST1_TXSRC_ALT 0x00000080 /* Set input to tsdac (?) */
1912#define AR5K_PHY_TST1_TXSRC_ALT_S 7
1913
1914
1915/*
1916 * PHY timing register 3 [5112+]
1917 */
1918#define AR5K_PHY_TIMING_3 0x9814
1919#define AR5K_PHY_TIMING_3_DSC_MAN 0xfffe0000
1920#define AR5K_PHY_TIMING_3_DSC_MAN_S 17
1921#define AR5K_PHY_TIMING_3_DSC_EXP 0x0001e000
1922#define AR5K_PHY_TIMING_3_DSC_EXP_S 13
1923
1924/*
1925 * PHY chip revision register
1926 */
1927#define AR5K_PHY_CHIP_ID 0x9818
1928
1929/*
1930 * PHY activation register
1931 */
1932#define AR5K_PHY_ACT 0x981c /* Register Address */
1933#define AR5K_PHY_ACT_ENABLE 0x00000001 /* Activate PHY */
1934#define AR5K_PHY_ACT_DISABLE 0x00000002 /* Deactivate PHY */
1935
1936/*
1937 * PHY RF control registers
1938 */
1939#define AR5K_PHY_RF_CTL2 0x9824 /* Register Address */
1940#define AR5K_PHY_RF_CTL2_TXF2TXD_START 0x0000000f /* TX frame to TX data start */
1941#define AR5K_PHY_RF_CTL2_TXF2TXD_START_S 0
1942
1943#define AR5K_PHY_RF_CTL3 0x9828 /* Register Address */
1944#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000ff00 /* TX end to XLNA on */
1945#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S 8
1946
1947#define AR5K_PHY_ADC_CTL 0x982c
1948#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF 0x00000003
1949#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF_S 0
1950#define AR5K_PHY_ADC_CTL_PWD_DAC_OFF 0x00002000
1951#define AR5K_PHY_ADC_CTL_PWD_BAND_GAP_OFF 0x00004000
1952#define AR5K_PHY_ADC_CTL_PWD_ADC_OFF 0x00008000
1953#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON 0x00030000
1954#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON_S 16
1955
1956#define AR5K_PHY_RF_CTL4 0x9834 /* Register Address */
1957#define AR5K_PHY_RF_CTL4_TXF2XPA_A_ON 0x00000001 /* TX frame to XPA A on (field) */
1958#define AR5K_PHY_RF_CTL4_TXF2XPA_B_ON 0x00000100 /* TX frame to XPA B on (field) */
1959#define AR5K_PHY_RF_CTL4_TXE2XPA_A_OFF 0x00010000 /* TX end to XPA A off (field) */
1960#define AR5K_PHY_RF_CTL4_TXE2XPA_B_OFF 0x01000000 /* TX end to XPA B off (field) */
1961
1962/*
1963 * Pre-Amplifier control register
1964 * (XPA -> external pre-amplifier)
1965 */
1966#define AR5K_PHY_PA_CTL 0x9838 /* Register Address */
1967#define AR5K_PHY_PA_CTL_XPA_A_HI 0x00000001 /* XPA A high (?) */
1968#define AR5K_PHY_PA_CTL_XPA_B_HI 0x00000002 /* XPA B high (?) */
1969#define AR5K_PHY_PA_CTL_XPA_A_EN 0x00000004 /* Enable XPA A */
1970#define AR5K_PHY_PA_CTL_XPA_B_EN 0x00000008 /* Enable XPA B */
1971
1972/*
1973 * PHY settling register
1974 */
1975#define AR5K_PHY_SETTLING 0x9844 /* Register Address */
1976#define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */
1977#define AR5K_PHY_SETTLING_AGC_S 0
1978#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */
1979#define AR5K_PHY_SETTLING_SWITCH_S 7
1980
1981/*
1982 * PHY Gain registers
1983 */
1984#define AR5K_PHY_GAIN 0x9848 /* Register Address */
1985#define AR5K_PHY_GAIN_TXRX_ATTEN 0x0003f000 /* TX-RX Attenuation */
1986#define AR5K_PHY_GAIN_TXRX_ATTEN_S 12
1987#define AR5K_PHY_GAIN_TXRX_RF_MAX 0x007c0000
1988#define AR5K_PHY_GAIN_TXRX_RF_MAX_S 18
1989
1990#define AR5K_PHY_GAIN_OFFSET 0x984c /* Register Address */
1991#define AR5K_PHY_GAIN_OFFSET_RXTX_FLAG 0x00020000 /* RX-TX flag (?) */
1992
1993/*
1994 * Desired ADC/PGA size register
1995 * (for more infos read ANI patent)
1996 */
1997#define AR5K_PHY_DESIRED_SIZE 0x9850 /* Register Address */
1998#define AR5K_PHY_DESIRED_SIZE_ADC 0x000000ff /* ADC desired size */
1999#define AR5K_PHY_DESIRED_SIZE_ADC_S 0
2000#define AR5K_PHY_DESIRED_SIZE_PGA 0x0000ff00 /* PGA desired size */
2001#define AR5K_PHY_DESIRED_SIZE_PGA_S 8
2002#define AR5K_PHY_DESIRED_SIZE_TOT 0x0ff00000 /* Total desired size */
2003#define AR5K_PHY_DESIRED_SIZE_TOT_S 20
2004
2005/*
2006 * PHY signal register
2007 * (for more infos read ANI patent)
2008 */
2009#define AR5K_PHY_SIG 0x9858 /* Register Address */
2010#define AR5K_PHY_SIG_FIRSTEP 0x0003f000 /* FIRSTEP */
2011#define AR5K_PHY_SIG_FIRSTEP_S 12
2012#define AR5K_PHY_SIG_FIRPWR 0x03fc0000 /* FIPWR */
2013#define AR5K_PHY_SIG_FIRPWR_S 18
2014
2015/*
2016 * PHY coarse agility control register
2017 * (for more infos read ANI patent)
2018 */
2019#define AR5K_PHY_AGCCOARSE 0x985c /* Register Address */
2020#define AR5K_PHY_AGCCOARSE_LO 0x00007f80 /* AGC Coarse low */
2021#define AR5K_PHY_AGCCOARSE_LO_S 7
2022#define AR5K_PHY_AGCCOARSE_HI 0x003f8000 /* AGC Coarse high */
2023#define AR5K_PHY_AGCCOARSE_HI_S 15
2024
2025/*
2026 * PHY agility control register
2027 */
2028#define AR5K_PHY_AGCCTL 0x9860 /* Register address */
2029#define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */
2030#define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */
2031#define AR5K_PHY_AGCCTL_NF_EN 0x00008000 /* Enable nf calibration to happen (?) */
2032#define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */
2033
2034/*
2035 * PHY noise floor status register
2036 */
2037#define AR5K_PHY_NF 0x9864 /* Register address */
2038#define AR5K_PHY_NF_M 0x000001ff /* Noise floor mask */
2039#define AR5K_PHY_NF_ACTIVE 0x00000100 /* Noise floor calibration still active */
2040#define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M)
2041#define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1)
2042#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9))
2043#define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */
2044#define AR5K_PHY_NF_THRESH62_S 12
2045#define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* ??? */
2046#define AR5K_PHY_NF_MINCCA_PWR_S 19
2047
2048/*
2049 * PHY ADC saturation register [5110]
2050 */
2051#define AR5K_PHY_ADCSAT 0x9868
2052#define AR5K_PHY_ADCSAT_ICNT 0x0001f800
2053#define AR5K_PHY_ADCSAT_ICNT_S 11
2054#define AR5K_PHY_ADCSAT_THR 0x000007e0
2055#define AR5K_PHY_ADCSAT_THR_S 5
2056
2057/*
2058 * PHY Weak ofdm signal detection threshold registers (ANI) [5212+]
2059 */
2060
2061/* High thresholds */
2062#define AR5K_PHY_WEAK_OFDM_HIGH_THR 0x9868
2063#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT 0x0000001f
2064#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT_S 0
2065#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1 0x00fe0000
2066#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1_S 17
2067#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2 0x7f000000
2068#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_S 24
2069
2070/* Low thresholds */
2071#define AR5K_PHY_WEAK_OFDM_LOW_THR 0x986c
2072#define AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN 0x00000001
2073#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT 0x00003f00
2074#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT_S 8
2075#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1 0x001fc000
2076#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1_S 14
2077#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2 0x0fe00000
2078#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_S 21
2079
2080
2081/*
2082 * PHY sleep registers [5112+]
2083 */
2084#define AR5K_PHY_SCR 0x9870
2085
2086#define AR5K_PHY_SLMT 0x9874
2087#define AR5K_PHY_SLMT_32MHZ 0x0000007f
2088
2089#define AR5K_PHY_SCAL 0x9878
2090#define AR5K_PHY_SCAL_32MHZ 0x0000000e
2091#define AR5K_PHY_SCAL_32MHZ_2417 0x0000000a
2092#define AR5K_PHY_SCAL_32MHZ_HB63 0x00000032
2093
2094/*
2095 * PHY PLL (Phase Locked Loop) control register
2096 */
2097#define AR5K_PHY_PLL 0x987c
2098#define AR5K_PHY_PLL_20MHZ 0x00000013 /* For half rate (?) */
2099/* 40MHz -> 5GHz band */
2100#define AR5K_PHY_PLL_40MHZ_5211 0x00000018
2101#define AR5K_PHY_PLL_40MHZ_5212 0x000000aa
2102#define AR5K_PHY_PLL_40MHZ_5413 0x00000004
2103#define AR5K_PHY_PLL_40MHZ (ah->ah_version == AR5K_AR5211 ? \
2104 AR5K_PHY_PLL_40MHZ_5211 : AR5K_PHY_PLL_40MHZ_5212)
2105/* 44MHz -> 2.4GHz band */
2106#define AR5K_PHY_PLL_44MHZ_5211 0x00000019
2107#define AR5K_PHY_PLL_44MHZ_5212 0x000000ab
2108#define AR5K_PHY_PLL_44MHZ (ah->ah_version == AR5K_AR5211 ? \
2109 AR5K_PHY_PLL_44MHZ_5211 : AR5K_PHY_PLL_44MHZ_5212)
2110
2111#define AR5K_PHY_PLL_RF5111 0x00000000
2112#define AR5K_PHY_PLL_RF5112 0x00000040
2113#define AR5K_PHY_PLL_HALF_RATE 0x00000100
2114#define AR5K_PHY_PLL_QUARTER_RATE 0x00000200
2115
2116/*
2117 * RF Buffer register
2118 *
2119 * It's obvious from the code that 0x989c is the buffer register but
2120 * for the other special registers that we write to after sending each
2121 * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers
2122 * for now. It's interesting that they are also used for some other operations.
2123 */
2124
2125#define AR5K_RF_BUFFER 0x989c
2126#define AR5K_RF_BUFFER_CONTROL_0 0x98c0 /* Channel on 5110 */
2127#define AR5K_RF_BUFFER_CONTROL_1 0x98c4 /* Bank 7 on 5112 */
2128#define AR5K_RF_BUFFER_CONTROL_2 0x98cc /* Bank 7 on 5111 */
2129
2130#define AR5K_RF_BUFFER_CONTROL_3 0x98d0 /* Bank 2 on 5112 */
2131 /* Channel set on 5111 */
2132 /* Used to read radio revision*/
2133
2134#define AR5K_RF_BUFFER_CONTROL_4 0x98d4 /* RF Stage register on 5110 */
2135 /* Bank 0,1,2,6 on 5111 */
2136 /* Bank 1 on 5112 */
2137 /* Used during activation on 5111 */
2138
2139#define AR5K_RF_BUFFER_CONTROL_5 0x98d8 /* Bank 3 on 5111 */
2140 /* Used during activation on 5111 */
2141 /* Channel on 5112 */
2142 /* Bank 6 on 5112 */
2143
2144#define AR5K_RF_BUFFER_CONTROL_6 0x98dc /* Bank 3 on 5112 */
2145
2146/*
2147 * PHY RF stage register [5210]
2148 */
2149#define AR5K_PHY_RFSTG 0x98d4
2150#define AR5K_PHY_RFSTG_DISABLE 0x00000021
2151
2152/*
2153 * BIN masks (?)
2154 */
2155#define AR5K_PHY_BIN_MASK_1 0x9900
2156#define AR5K_PHY_BIN_MASK_2 0x9904
2157#define AR5K_PHY_BIN_MASK_3 0x9908
2158
2159#define AR5K_PHY_BIN_MASK_CTL 0x990c
2160#define AR5K_PHY_BIN_MASK_CTL_MASK_4 0x00003fff
2161#define AR5K_PHY_BIN_MASK_CTL_MASK_4_S 0
2162#define AR5K_PHY_BIN_MASK_CTL_RATE 0xff000000
2163#define AR5K_PHY_BIN_MASK_CTL_RATE_S 24
2164
2165/*
2166 * PHY Antenna control register
2167 */
2168#define AR5K_PHY_ANT_CTL 0x9910 /* Register Address */
2169#define AR5K_PHY_ANT_CTL_TXRX_EN 0x00000001 /* Enable TX/RX (?) */
2170#define AR5K_PHY_ANT_CTL_SECTORED_ANT 0x00000004 /* Sectored Antenna */
2171#define AR5K_PHY_ANT_CTL_HITUNE5 0x00000008 /* Hitune5 (?) */
2172#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x000003f0 /* Switch table idle (?) */
2173#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE_S 4
2174
2175/*
2176 * PHY receiver delay register [5111+]
2177 */
2178#define AR5K_PHY_RX_DELAY 0x9914 /* Register Address */
2179#define AR5K_PHY_RX_DELAY_M 0x00003fff /* Mask for RX activate to receive delay (/100ns) */
2180
2181/*
2182 * PHY max rx length register (?) [5111]
2183 */
2184#define AR5K_PHY_MAX_RX_LEN 0x991c
2185
2186/*
2187 * PHY timing register 4
2188 * I(nphase)/Q(adrature) calibration register [5111+]
2189 */
2190#define AR5K_PHY_IQ 0x9920 /* Register Address */
2191#define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */
2192#define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */
2193#define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5
2194#define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */
2195#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX 0x0000f000 /* Mask for max number of samples in log scale */
2196#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX_S 12
2197#define AR5K_PHY_IQ_RUN 0x00010000 /* Run i/q calibration */
2198#define AR5K_PHY_IQ_USE_PT_DF 0x00020000 /* Use pilot track df (?) */
2199#define AR5K_PHY_IQ_EARLY_TRIG_THR 0x00200000 /* Early trigger threshold (?) (field) */
2200#define AR5K_PHY_IQ_PILOT_MASK_EN 0x10000000 /* Enable pilot mask (?) */
2201#define AR5K_PHY_IQ_CHAN_MASK_EN 0x20000000 /* Enable channel mask (?) */
2202#define AR5K_PHY_IQ_SPUR_FILT_EN 0x40000000 /* Enable spur filter */
2203#define AR5K_PHY_IQ_SPUR_RSSI_EN 0x80000000 /* Enable spur rssi */
2204
2205/*
2206 * PHY timing register 5
2207 * OFDM Self-correlator Cyclic RSSI threshold params
2208 * (Check out bb_cycpwr_thr1 on ANI patent)
2209 */
2210#define AR5K_PHY_OFDM_SELFCORR 0x9924 /* Register Address */
2211#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_EN 0x00000001 /* Enable cyclic RSSI thr 1 */
2212#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1 0x000000fe /* Mask for Cyclic RSSI threshold 1 */
2213#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 1
2214#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR3 0x00000100 /* Cyclic RSSI threshold 3 (field) (?) */
2215#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR_EN 0x00008000 /* Enable 1A RSSI threshold (?) */
2216#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR 0x00010000 /* 1A RSSI threshold (field) (?) */
2217#define AR5K_PHY_OFDM_SELFCORR_LSCTHR_HIRSSI 0x00800000 /* Long sc threshold hi rssi (?) */
2218
2219/*
2220 * PHY-only warm reset register
2221 */
2222#define AR5K_PHY_WARM_RESET 0x9928
2223
2224/*
2225 * PHY-only control register
2226 */
2227#define AR5K_PHY_CTL 0x992c /* Register Address */
2228#define AR5K_PHY_CTL_RX_DRAIN_RATE 0x00000001 /* RX drain rate (?) */
2229#define AR5K_PHY_CTL_LATE_TX_SIG_SYM 0x00000002 /* Late tx signal symbol (?) */
2230#define AR5K_PHY_CTL_GEN_SCRAMBLER 0x00000004 /* Generate scrambler */
2231#define AR5K_PHY_CTL_TX_ANT_SEL 0x00000008 /* TX antenna select */
2232#define AR5K_PHY_CTL_TX_ANT_STATIC 0x00000010 /* Static TX antenna */
2233#define AR5K_PHY_CTL_RX_ANT_SEL 0x00000020 /* RX antenna select */
2234#define AR5K_PHY_CTL_RX_ANT_STATIC 0x00000040 /* Static RX antenna */
2235#define AR5K_PHY_CTL_LOW_FREQ_SLE_EN 0x00000080 /* Enable low freq sleep */
2236
2237/*
2238 * PHY PAPD probe register [5111+]
2239 */
2240#define AR5K_PHY_PAPD_PROBE 0x9930
2241#define AR5K_PHY_PAPD_PROBE_SH_HI_PAR 0x00000001
2242#define AR5K_PHY_PAPD_PROBE_PCDAC_BIAS 0x00000002
2243#define AR5K_PHY_PAPD_PROBE_COMP_GAIN 0x00000040
2244#define AR5K_PHY_PAPD_PROBE_TXPOWER 0x00007e00
2245#define AR5K_PHY_PAPD_PROBE_TXPOWER_S 9
2246#define AR5K_PHY_PAPD_PROBE_TX_NEXT 0x00008000
2247#define AR5K_PHY_PAPD_PROBE_PREDIST_EN 0x00010000
2248#define AR5K_PHY_PAPD_PROBE_TYPE 0x01800000 /* [5112+] */
2249#define AR5K_PHY_PAPD_PROBE_TYPE_S 23
2250#define AR5K_PHY_PAPD_PROBE_TYPE_OFDM 0
2251#define AR5K_PHY_PAPD_PROBE_TYPE_XR 1
2252#define AR5K_PHY_PAPD_PROBE_TYPE_CCK 2
2253#define AR5K_PHY_PAPD_PROBE_GAINF 0xfe000000
2254#define AR5K_PHY_PAPD_PROBE_GAINF_S 25
2255#define AR5K_PHY_PAPD_PROBE_INI_5111 0x00004883 /* [5212+] */
2256#define AR5K_PHY_PAPD_PROBE_INI_5112 0x00004882 /* [5212+] */
2257
2258/*
2259 * PHY TX rate power registers [5112+]
2260 */
2261#define AR5K_PHY_TXPOWER_RATE1 0x9934
2262#define AR5K_PHY_TXPOWER_RATE2 0x9938
2263#define AR5K_PHY_TXPOWER_RATE_MAX 0x993c
2264#define AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE 0x00000040
2265#define AR5K_PHY_TXPOWER_RATE3 0xa234
2266#define AR5K_PHY_TXPOWER_RATE4 0xa238
2267
2268/*
2269 * PHY frame control register [5111+]
2270 */
2271#define AR5K_PHY_FRAME_CTL_5210 0x9804
2272#define AR5K_PHY_FRAME_CTL_5211 0x9944
2273#define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \
2274 AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211)
2275/*---[5111+]---*/
2276#define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 /* Mask for tx clip (?) */
2277#define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3
2278#define AR5K_PHY_FRAME_CTL_PREP_CHINFO 0x00010000 /* Prepend chan info */
2279#define AR5K_PHY_FRAME_CTL_EMU 0x80000000
2280#define AR5K_PHY_FRAME_CTL_EMU_S 31
2281/*---[5110/5111]---*/
2282#define AR5K_PHY_FRAME_CTL_TIMING_ERR 0x01000000 /* PHY timing error */
2283#define AR5K_PHY_FRAME_CTL_PARITY_ERR 0x02000000 /* Parity error */
2284#define AR5K_PHY_FRAME_CTL_ILLRATE_ERR 0x04000000 /* Illegal rate */
2285#define AR5K_PHY_FRAME_CTL_ILLLEN_ERR 0x08000000 /* Illegal length */
2286#define AR5K_PHY_FRAME_CTL_SERVICE_ERR 0x20000000
2287#define AR5K_PHY_FRAME_CTL_TXURN_ERR 0x40000000 /* TX underrun */
2288#define AR5K_PHY_FRAME_CTL_INI AR5K_PHY_FRAME_CTL_SERVICE_ERR | \
2289 AR5K_PHY_FRAME_CTL_TXURN_ERR | \
2290 AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \
2291 AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \
2292 AR5K_PHY_FRAME_CTL_PARITY_ERR | \
2293 AR5K_PHY_FRAME_CTL_TIMING_ERR
2294
2295/*
2296 * PHY Tx Power adjustment register [5212A+]
2297 */
2298#define AR5K_PHY_TX_PWR_ADJ 0x994c
2299#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA 0x00000fc0
2300#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA_S 6
2301#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX 0x00fc0000
2302#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX_S 18
2303
2304/*
2305 * PHY radar detection register [5111+]
2306 */
2307#define AR5K_PHY_RADAR 0x9954
2308#define AR5K_PHY_RADAR_ENABLE 0x00000001
2309#define AR5K_PHY_RADAR_DISABLE 0x00000000
2310#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e /* Inband threshold
2311 5-bits, units unknown {0..31}
2312 (? MHz ?) */
2313#define AR5K_PHY_RADAR_INBANDTHR_S 1
2314
2315#define AR5K_PHY_RADAR_PRSSI_THR 0x00000fc0 /* Pulse RSSI/SNR threshold
2316 6-bits, dBm range {0..63}
2317 in dBm units. */
2318#define AR5K_PHY_RADAR_PRSSI_THR_S 6
2319
2320#define AR5K_PHY_RADAR_PHEIGHT_THR 0x0003f000 /* Pulse height threshold
2321 6-bits, dBm range {0..63}
2322 in dBm units. */
2323#define AR5K_PHY_RADAR_PHEIGHT_THR_S 12
2324
2325#define AR5K_PHY_RADAR_RSSI_THR 0x00fc0000 /* Radar RSSI/SNR threshold.
2326 6-bits, dBm range {0..63}
2327 in dBm units. */
2328#define AR5K_PHY_RADAR_RSSI_THR_S 18
2329
2330#define AR5K_PHY_RADAR_FIRPWR_THR 0x7f000000 /* Finite Impulse Response
2331 filter power out threshold.
2332 7-bits, standard power range
2333 {0..127} in 1/2 dBm units. */
2334#define AR5K_PHY_RADAR_FIRPWR_THRS 24
2335
2336/*
2337 * PHY antenna switch table registers
2338 */
2339#define AR5K_PHY_ANT_SWITCH_TABLE_0 0x9960
2340#define AR5K_PHY_ANT_SWITCH_TABLE_1 0x9964
2341
2342/*
2343 * PHY Noise floor threshold
2344 */
2345#define AR5K_PHY_NFTHRES 0x9968
2346
2347/*
2348 * Sigma Delta register (?) [5213]
2349 */
2350#define AR5K_PHY_SIGMA_DELTA 0x996C
2351#define AR5K_PHY_SIGMA_DELTA_ADC_SEL 0x00000003
2352#define AR5K_PHY_SIGMA_DELTA_ADC_SEL_S 0
2353#define AR5K_PHY_SIGMA_DELTA_FILT2 0x000000f8
2354#define AR5K_PHY_SIGMA_DELTA_FILT2_S 3
2355#define AR5K_PHY_SIGMA_DELTA_FILT1 0x00001f00
2356#define AR5K_PHY_SIGMA_DELTA_FILT1_S 8
2357#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ffe000
2358#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP_S 13
2359
2360/*
2361 * RF restart register [5112+] (?)
2362 */
2363#define AR5K_PHY_RESTART 0x9970 /* restart */
2364#define AR5K_PHY_RESTART_DIV_GC 0x001c0000 /* Fast diversity gc_limit (?) */
2365#define AR5K_PHY_RESTART_DIV_GC_S 18
2366
2367/*
2368 * RF Bus access request register (for synth-oly channel switching)
2369 */
2370#define AR5K_PHY_RFBUS_REQ 0x997C
2371#define AR5K_PHY_RFBUS_REQ_REQUEST 0x00000001
2372
2373/*
2374 * Spur mitigation masks (?)
2375 */
2376#define AR5K_PHY_TIMING_7 0x9980
2377#define AR5K_PHY_TIMING_8 0x9984
2378#define AR5K_PHY_TIMING_8_PILOT_MASK_2 0x000fffff
2379#define AR5K_PHY_TIMING_8_PILOT_MASK_2_S 0
2380
2381#define AR5K_PHY_BIN_MASK2_1 0x9988
2382#define AR5K_PHY_BIN_MASK2_2 0x998c
2383#define AR5K_PHY_BIN_MASK2_3 0x9990
2384
2385#define AR5K_PHY_BIN_MASK2_4 0x9994
2386#define AR5K_PHY_BIN_MASK2_4_MASK_4 0x00003fff
2387#define AR5K_PHY_BIN_MASK2_4_MASK_4_S 0
2388
2389#define AR5K_PHY_TIMING_9 0x9998
2390#define AR5K_PHY_TIMING_10 0x999c
2391#define AR5K_PHY_TIMING_10_PILOT_MASK_2 0x000fffff
2392#define AR5K_PHY_TIMING_10_PILOT_MASK_2_S 0
2393
2394/*
2395 * Spur mitigation control
2396 */
2397#define AR5K_PHY_TIMING_11 0x99a0 /* Register address */
2398#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE 0x000fffff /* Spur delta phase */
2399#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE_S 0
2400#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD 0x3ff00000 /* Freq sigma delta */
2401#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD_S 20
2402#define AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC 0x40000000 /* Spur filter in AGC detector */
2403#define AR5K_PHY_TIMING_11_USE_SPUR_IN_SELFCOR 0x80000000 /* Spur filter in OFDM self correlator */
2404
2405/*
2406 * Gain tables
2407 */
2408#define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */
2409#define AR5K_BB_GAIN(_n) (AR5K_BB_GAIN_BASE + ((_n) << 2))
2410#define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplrifier Gain table base address */
2411#define AR5K_RF_GAIN(_n) (AR5K_RF_GAIN_BASE + ((_n) << 2))
2412
2413/*
2414 * PHY timing IQ calibration result register [5111+]
2415 */
2416#define AR5K_PHY_IQRES_CAL_PWR_I 0x9c10 /* I (Inphase) power value */
2417#define AR5K_PHY_IQRES_CAL_PWR_Q 0x9c14 /* Q (Quadrature) power value */
2418#define AR5K_PHY_IQRES_CAL_CORR 0x9c18 /* I/Q Correlation */
2419
2420/*
2421 * PHY current RSSI register [5111+]
2422 */
2423#define AR5K_PHY_CURRENT_RSSI 0x9c1c
2424
2425/*
2426 * PHY RF Bus grant register
2427 */
2428#define AR5K_PHY_RFBUS_GRANT 0x9c20
2429#define AR5K_PHY_RFBUS_GRANT_OK 0x00000001
2430
2431/*
2432 * PHY ADC test register
2433 */
2434#define AR5K_PHY_ADC_TEST 0x9c24
2435#define AR5K_PHY_ADC_TEST_I 0x00000001
2436#define AR5K_PHY_ADC_TEST_Q 0x00000200
2437
2438/*
2439 * PHY DAC test register
2440 */
2441#define AR5K_PHY_DAC_TEST 0x9c28
2442#define AR5K_PHY_DAC_TEST_I 0x00000001
2443#define AR5K_PHY_DAC_TEST_Q 0x00000200
2444
2445/*
2446 * PHY PTAT register (?)
2447 */
2448#define AR5K_PHY_PTAT 0x9c2c
2449
2450/*
2451 * PHY Illegal TX rate register [5112+]
2452 */
2453#define AR5K_PHY_BAD_TX_RATE 0x9c30
2454
2455/*
2456 * PHY SPUR Power register [5112+]
2457 */
2458#define AR5K_PHY_SPUR_PWR 0x9c34 /* Register Address */
2459#define AR5K_PHY_SPUR_PWR_I 0x00000001 /* SPUR Power estimate for I (field) */
2460#define AR5K_PHY_SPUR_PWR_Q 0x00000100 /* SPUR Power estimate for Q (field) */
2461#define AR5K_PHY_SPUR_PWR_FILT 0x00010000 /* Power with SPUR removed (field) */
2462
2463/*
2464 * PHY Channel status register [5112+] (?)
2465 */
2466#define AR5K_PHY_CHAN_STATUS 0x9c38
2467#define AR5K_PHY_CHAN_STATUS_BT_ACT 0x00000001
2468#define AR5K_PHY_CHAN_STATUS_RX_CLR_RAW 0x00000002
2469#define AR5K_PHY_CHAN_STATUS_RX_CLR_MAC 0x00000004
2470#define AR5K_PHY_CHAN_STATUS_RX_CLR_PAP 0x00000008
2471
2472/*
2473 * Heavy clip enable register
2474 */
2475#define AR5K_PHY_HEAVY_CLIP_ENABLE 0x99e0
2476
2477/*
2478 * PHY clock sleep registers [5112+]
2479 */
2480#define AR5K_PHY_SCLOCK 0x99f0
2481#define AR5K_PHY_SCLOCK_32MHZ 0x0000000c
2482#define AR5K_PHY_SDELAY 0x99f4
2483#define AR5K_PHY_SDELAY_32MHZ 0x000000ff
2484#define AR5K_PHY_SPENDING 0x99f8
2485
2486
2487/*
2488 * PHY PAPD I (power?) table (?)
2489 * (92! entries)
2490 */
2491#define AR5K_PHY_PAPD_I_BASE 0xa000
2492#define AR5K_PHY_PAPD_I(_n) (AR5K_PHY_PAPD_I_BASE + ((_n) << 2))
2493
2494/*
2495 * PHY PCDAC TX power table
2496 */
2497#define AR5K_PHY_PCDAC_TXPOWER_BASE 0xa180
2498#define AR5K_PHY_PCDAC_TXPOWER(_n) (AR5K_PHY_PCDAC_TXPOWER_BASE + ((_n) << 2))
2499
2500/*
2501 * PHY mode register [5111+]
2502 */
2503#define AR5K_PHY_MODE 0x0a200 /* Register Address */
2504#define AR5K_PHY_MODE_MOD 0x00000001 /* PHY Modulation bit */
2505#define AR5K_PHY_MODE_MOD_OFDM 0
2506#define AR5K_PHY_MODE_MOD_CCK 1
2507#define AR5K_PHY_MODE_FREQ 0x00000002 /* Freq mode bit */
2508#define AR5K_PHY_MODE_FREQ_5GHZ 0
2509#define AR5K_PHY_MODE_FREQ_2GHZ 2
2510#define AR5K_PHY_MODE_MOD_DYN 0x00000004 /* Enable Dynamic OFDM/CCK mode [5112+] */
2511#define AR5K_PHY_MODE_RAD 0x00000008 /* [5212+] */
2512#define AR5K_PHY_MODE_RAD_RF5111 0
2513#define AR5K_PHY_MODE_RAD_RF5112 8
2514#define AR5K_PHY_MODE_XR 0x00000010 /* Enable XR mode [5112+] */
2515#define AR5K_PHY_MODE_HALF_RATE 0x00000020 /* Enable Half rate (test) */
2516#define AR5K_PHY_MODE_QUARTER_RATE 0x00000040 /* Enable Quarter rat (test) */
2517
2518/*
2519 * PHY CCK transmit control register [5111+ (?)]
2520 */
2521#define AR5K_PHY_CCKTXCTL 0xa204
2522#define AR5K_PHY_CCKTXCTL_WORLD 0x00000000
2523#define AR5K_PHY_CCKTXCTL_JAPAN 0x00000010
2524#define AR5K_PHY_CCKTXCTL_SCRAMBLER_DIS 0x00000001
2525#define AR5K_PHY_CCKTXCTK_DAC_SCALE 0x00000004
2526
2527/*
2528 * PHY CCK Cross-correlator Barker RSSI threshold register [5212+]
2529 */
2530#define AR5K_PHY_CCK_CROSSCORR 0xa208
2531#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000000f
2532#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S 0
2533
2534/* Same address is used for antenna diversity activation */
2535#define AR5K_PHY_FAST_ANT_DIV 0xa208
2536#define AR5K_PHY_FAST_ANT_DIV_EN 0x00002000
2537
2538/*
2539 * PHY 2GHz gain register [5111+]
2540 */
2541#define AR5K_PHY_GAIN_2GHZ 0xa20c
2542#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX 0x00fc0000
2543#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX_S 18
2544#define AR5K_PHY_GAIN_2GHZ_INI_5111 0x6480416c
2545
2546#define AR5K_PHY_CCK_RX_CTL_4 0xa21c
2547#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT 0x01f80000
2548#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT_S 19
2549
2550#define AR5K_PHY_DAG_CCK_CTL 0xa228
2551#define AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR 0x00000200
2552#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR 0x0001fc00
2553#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR_S 10
2554
2555#define AR5K_PHY_FAST_ADC 0xa24c
2556
2557#define AR5K_PHY_BLUETOOTH 0xa254
2558
2559/*
2560 * Transmit Power Control register
2561 * [2413+]
2562 */
2563#define AR5K_PHY_TPC_RG1 0xa258
2564#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN 0x0000c000
2565#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN_S 14
2566#define AR5K_PHY_TPC_RG1_PDGAIN_1 0x00030000
2567#define AR5K_PHY_TPC_RG1_PDGAIN_1_S 16
2568#define AR5K_PHY_TPC_RG1_PDGAIN_2 0x000c0000
2569#define AR5K_PHY_TPC_RG1_PDGAIN_2_S 18
2570#define AR5K_PHY_TPC_RG1_PDGAIN_3 0x00300000
2571#define AR5K_PHY_TPC_RG1_PDGAIN_3_S 20
2572
2573#define AR5K_PHY_TPC_RG5 0xa26C
2574#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP 0x0000000F
2575#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP_S 0
2576#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1 0x000003F0
2577#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1_S 4
2578#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2 0x0000FC00
2579#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2_S 10
2580#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3 0x003F0000
2581#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3_S 16
2582#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4 0x0FC00000
2583#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4_S 22
2584
2585/*
2586 * PHY PDADC Tx power table
2587 */
2588#define AR5K_PHY_PDADC_TXPOWER_BASE 0xa280
2589#define AR5K_PHY_PDADC_TXPOWER(_n) (AR5K_PHY_PDADC_TXPOWER_BASE + ((_n) << 2))
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
new file mode 100644
index 000000000000..775fdf78554b
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -0,0 +1,1346 @@
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4 * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
5 * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
6 * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *
20 */
21
22#define _ATH5K_RESET
23
24/*****************************\
25 Reset functions and helpers
26\*****************************/
27
28#include <linux/pci.h> /* To determine if a card is pci-e */
29#include <linux/bitops.h> /* For get_bitmask_order */
30#include "ath5k.h"
31#include "reg.h"
32#include "base.h"
33#include "debug.h"
34
35/**
36 * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212
37 *
38 * @ah: the &struct ath5k_hw
39 * @channel: the currently set channel upon reset
40 *
41 * Write the delta slope coefficient (used on pilot tracking ?) for OFDM
42 * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset().
43 *
44 * Since delta slope is floating point we split it on its exponent and
45 * mantissa and provide these values on hw.
46 *
47 * For more infos i think this patent is related
48 * http://www.freepatentsonline.com/7184495.html
49 */
50static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
51 struct ieee80211_channel *channel)
52{
53 /* Get exponent and mantissa and set it */
54 u32 coef_scaled, coef_exp, coef_man,
55 ds_coef_exp, ds_coef_man, clock;
56
57 BUG_ON(!(ah->ah_version == AR5K_AR5212) ||
58 !(channel->hw_value & CHANNEL_OFDM));
59
60 /* Get coefficient
61 * ALGO: coef = (5 * clock * carrier_freq) / 2)
62 * we scale coef by shifting clock value by 24 for
63 * better precision since we use integers */
64 /* TODO: Half/quarter rate */
65 clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO);
66
67 coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq;
68
69 /* Get exponent
70 * ALGO: coef_exp = 14 - highest set bit position */
71 coef_exp = get_bitmask_order(coef_scaled);
72
73 /* Doesn't make sense if it's zero*/
74 if (!coef_exp)
75 return -EINVAL;
76
77 /* Note: we've shifted coef_scaled by 24 */
78 coef_exp = 14 - (coef_exp - 24);
79
80
81 /* Get mantissa (significant digits)
82 * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */
83 coef_man = coef_scaled +
84 (1 << (24 - coef_exp - 1));
85
86 /* Calculate delta slope coefficient exponent
87 * and mantissa (remove scaling) and set them on hw */
88 ds_coef_man = coef_man >> (24 - coef_exp);
89 ds_coef_exp = coef_exp - 16;
90
91 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
92 AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man);
93 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
94 AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
95
96 return 0;
97}
98
99
100/*
101 * index into rates for control rates, we can set it up like this because
102 * this is only used for AR5212 and we know it supports G mode
103 */
104static const unsigned int control_rates[] =
105 { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 };
106
107/**
108 * ath5k_hw_write_rate_duration - fill rate code to duration table
109 *
110 * @ah: the &struct ath5k_hw
111 * @mode: one of enum ath5k_driver_mode
112 *
113 * Write the rate code to duration table upon hw reset. This is a helper for
114 * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on
115 * the hardware, based on current mode, for each rate. The rates which are
116 * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have
117 * different rate code so we write their value twice (one for long preample
118 * and one for short).
119 *
120 * Note: Band doesn't matter here, if we set the values for OFDM it works
121 * on both a and g modes. So all we have to do is set values for all g rates
122 * that include all OFDM and CCK rates. If we operate in turbo or xr/half/
123 * quarter rate mode, we need to use another set of bitrates (that's why we
124 * need the mode parameter) but we don't handle these proprietary modes yet.
125 */
126static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
127 unsigned int mode)
128{
129 struct ath5k_softc *sc = ah->ah_sc;
130 struct ieee80211_rate *rate;
131 unsigned int i;
132
133 /* Write rate duration table */
134 for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) {
135 u32 reg;
136 u16 tx_time;
137
138 rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]];
139
140 /* Set ACK timeout */
141 reg = AR5K_RATE_DUR(rate->hw_value);
142
143 /* An ACK frame consists of 10 bytes. If you add the FCS,
144 * which ieee80211_generic_frame_duration() adds,
145 * its 14 bytes. Note we use the control rate and not the
146 * actual rate for this rate. See mac80211 tx.c
147 * ieee80211_duration() for a brief description of
148 * what rate we should choose to TX ACKs. */
149 tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
150 sc->vif, 10, rate));
151
152 ath5k_hw_reg_write(ah, tx_time, reg);
153
154 if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
155 continue;
156
157 /*
158 * We're not distinguishing short preamble here,
159 * This is true, all we'll get is a longer value here
160 * which is not necessarilly bad. We could use
161 * export ieee80211_frame_duration() but that needs to be
162 * fixed first to be properly used by mac802111 drivers:
163 *
164 * - remove erp stuff and let the routine figure ofdm
165 * erp rates
166 * - remove passing argument ieee80211_local as
167 * drivers don't have access to it
168 * - move drivers using ieee80211_generic_frame_duration()
169 * to this
170 */
171 ath5k_hw_reg_write(ah, tx_time,
172 reg + (AR5K_SET_SHORT_PREAMBLE << 2));
173 }
174}
175
176/*
177 * Reset chipset
178 */
179static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
180{
181 int ret;
182 u32 mask = val ? val : ~0U;
183
184 ATH5K_TRACE(ah->ah_sc);
185
186 /* Read-and-clear RX Descriptor Pointer*/
187 ath5k_hw_reg_read(ah, AR5K_RXDP);
188
189 /*
190 * Reset the device and wait until success
191 */
192 ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL);
193
194 /* Wait at least 128 PCI clocks */
195 udelay(15);
196
197 if (ah->ah_version == AR5K_AR5210) {
198 val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
199 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
200 mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
201 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
202 } else {
203 val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
204 mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
205 }
206
207 ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false);
208
209 /*
210 * Reset configuration register (for hw byte-swap). Note that this
211 * is only set for big endian. We do the necessary magic in
212 * AR5K_INIT_CFG.
213 */
214 if ((val & AR5K_RESET_CTL_PCU) == 0)
215 ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
216
217 return ret;
218}
219
220/*
221 * Sleep control
222 */
223int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
224 bool set_chip, u16 sleep_duration)
225{
226 unsigned int i;
227 u32 staid, data;
228
229 ATH5K_TRACE(ah->ah_sc);
230 staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
231
232 switch (mode) {
233 case AR5K_PM_AUTO:
234 staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
235 /* fallthrough */
236 case AR5K_PM_NETWORK_SLEEP:
237 if (set_chip)
238 ath5k_hw_reg_write(ah,
239 AR5K_SLEEP_CTL_SLE_ALLOW |
240 sleep_duration,
241 AR5K_SLEEP_CTL);
242
243 staid |= AR5K_STA_ID1_PWR_SV;
244 break;
245
246 case AR5K_PM_FULL_SLEEP:
247 if (set_chip)
248 ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
249 AR5K_SLEEP_CTL);
250
251 staid |= AR5K_STA_ID1_PWR_SV;
252 break;
253
254 case AR5K_PM_AWAKE:
255
256 staid &= ~AR5K_STA_ID1_PWR_SV;
257
258 if (!set_chip)
259 goto commit;
260
261 /* Preserve sleep duration */
262 data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
263 if (data & 0xffc00000)
264 data = 0;
265 else
266 data = data & 0xfffcffff;
267
268 ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
269 udelay(15);
270
271 for (i = 50; i > 0; i--) {
272 /* Check if the chip did wake up */
273 if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
274 AR5K_PCICFG_SPWR_DN) == 0)
275 break;
276
277 /* Wait a bit and retry */
278 udelay(200);
279 ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
280 }
281
282 /* Fail if the chip didn't wake up */
283 if (i <= 0)
284 return -EIO;
285
286 break;
287
288 default:
289 return -EINVAL;
290 }
291
292commit:
293 ah->ah_power_mode = mode;
294 ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1);
295
296 return 0;
297}
298
299/*
300 * Bring up MAC + PHY Chips and program PLL
301 * TODO: Half/Quarter rate support
302 */
303int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
304{
305 struct pci_dev *pdev = ah->ah_sc->pdev;
306 u32 turbo, mode, clock, bus_flags;
307 int ret;
308
309 turbo = 0;
310 mode = 0;
311 clock = 0;
312
313 ATH5K_TRACE(ah->ah_sc);
314
315 /* Wakeup the device */
316 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
317 if (ret) {
318 ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
319 return ret;
320 }
321
322 if (ah->ah_version != AR5K_AR5210) {
323 /*
324 * Get channel mode flags
325 */
326
327 if (ah->ah_radio >= AR5K_RF5112) {
328 mode = AR5K_PHY_MODE_RAD_RF5112;
329 clock = AR5K_PHY_PLL_RF5112;
330 } else {
331 mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/
332 clock = AR5K_PHY_PLL_RF5111; /*Zero*/
333 }
334
335 if (flags & CHANNEL_2GHZ) {
336 mode |= AR5K_PHY_MODE_FREQ_2GHZ;
337 clock |= AR5K_PHY_PLL_44MHZ;
338
339 if (flags & CHANNEL_CCK) {
340 mode |= AR5K_PHY_MODE_MOD_CCK;
341 } else if (flags & CHANNEL_OFDM) {
342 /* XXX Dynamic OFDM/CCK is not supported by the
343 * AR5211 so we set MOD_OFDM for plain g (no
344 * CCK headers) operation. We need to test
345 * this, 5211 might support ofdm-only g after
346 * all, there are also initial register values
347 * in the code for g mode (see initvals.c). */
348 if (ah->ah_version == AR5K_AR5211)
349 mode |= AR5K_PHY_MODE_MOD_OFDM;
350 else
351 mode |= AR5K_PHY_MODE_MOD_DYN;
352 } else {
353 ATH5K_ERR(ah->ah_sc,
354 "invalid radio modulation mode\n");
355 return -EINVAL;
356 }
357 } else if (flags & CHANNEL_5GHZ) {
358 mode |= AR5K_PHY_MODE_FREQ_5GHZ;
359
360 if (ah->ah_radio == AR5K_RF5413)
361 clock = AR5K_PHY_PLL_40MHZ_5413;
362 else
363 clock |= AR5K_PHY_PLL_40MHZ;
364
365 if (flags & CHANNEL_OFDM)
366 mode |= AR5K_PHY_MODE_MOD_OFDM;
367 else {
368 ATH5K_ERR(ah->ah_sc,
369 "invalid radio modulation mode\n");
370 return -EINVAL;
371 }
372 } else {
373 ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n");
374 return -EINVAL;
375 }
376
377 if (flags & CHANNEL_TURBO)
378 turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT;
379 } else { /* Reset the device */
380
381 /* ...enable Atheros turbo mode if requested */
382 if (flags & CHANNEL_TURBO)
383 ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE,
384 AR5K_PHY_TURBO);
385 }
386
387 /* reseting PCI on PCI-E cards results card to hang
388 * and always return 0xffff... so we ingore that flag
389 * for PCI-E cards */
390 bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
391
392 /* Reset chipset */
393 if (ah->ah_version == AR5K_AR5210) {
394 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
395 AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
396 AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
397 mdelay(2);
398 } else {
399 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
400 AR5K_RESET_CTL_BASEBAND | bus_flags);
401 }
402 if (ret) {
403 ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
404 return -EIO;
405 }
406
407 /* ...wakeup again!*/
408 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
409 if (ret) {
410 ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
411 return ret;
412 }
413
414 /* ...final warm reset */
415 if (ath5k_hw_nic_reset(ah, 0)) {
416 ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
417 return -EIO;
418 }
419
420 if (ah->ah_version != AR5K_AR5210) {
421
422 /* ...update PLL if needed */
423 if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) {
424 ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
425 udelay(300);
426 }
427
428 /* ...set the PHY operating mode */
429 ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
430 ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
431 }
432
433 return 0;
434}
435
436/*
437 * If there is an external 32KHz crystal available, use it
438 * as ref. clock instead of 32/40MHz clock and baseband clocks
439 * to save power during sleep or restore normal 32/40MHz
440 * operation.
441 *
442 * XXX: When operating on 32KHz certain PHY registers (27 - 31,
443 * 123 - 127) require delay on access.
444 */
445static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
446{
447 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
448 u32 scal, spending, usec32;
449
450 /* Only set 32KHz settings if we have an external
451 * 32KHz crystal present */
452 if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) ||
453 AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) &&
454 enable) {
455
456 /* 1 usec/cycle */
457 AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1);
458 /* Set up tsf increment on each cycle */
459 AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61);
460
461 /* Set baseband sleep control registers
462 * and sleep control rate */
463 ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
464
465 if ((ah->ah_radio == AR5K_RF5112) ||
466 (ah->ah_radio == AR5K_RF5413) ||
467 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
468 spending = 0x14;
469 else
470 spending = 0x18;
471 ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
472
473 if ((ah->ah_radio == AR5K_RF5112) ||
474 (ah->ah_radio == AR5K_RF5413) ||
475 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
476 ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT);
477 ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL);
478 ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK);
479 ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY);
480 AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
481 AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02);
482 } else {
483 ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT);
484 ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL);
485 ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK);
486 ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY);
487 AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
488 AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03);
489 }
490
491 /* Enable sleep clock operation */
492 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG,
493 AR5K_PCICFG_SLEEP_CLOCK_EN);
494
495 } else {
496
497 /* Disable sleep clock operation and
498 * restore default parameters */
499 AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
500 AR5K_PCICFG_SLEEP_CLOCK_EN);
501
502 AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
503 AR5K_PCICFG_SLEEP_CLOCK_RATE, 0);
504
505 ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
506 ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
507
508 if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
509 scal = AR5K_PHY_SCAL_32MHZ_2417;
510 else if (ath5k_eeprom_is_hb63(ah))
511 scal = AR5K_PHY_SCAL_32MHZ_HB63;
512 else
513 scal = AR5K_PHY_SCAL_32MHZ;
514 ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
515
516 ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
517 ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
518
519 if ((ah->ah_radio == AR5K_RF5112) ||
520 (ah->ah_radio == AR5K_RF5413) ||
521 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
522 spending = 0x14;
523 else
524 spending = 0x18;
525 ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
526
527 if ((ah->ah_radio == AR5K_RF5112) ||
528 (ah->ah_radio == AR5K_RF5413))
529 usec32 = 39;
530 else
531 usec32 = 31;
532 AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32);
533
534 AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
535 }
536 return;
537}
538
539static bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
540 struct ieee80211_channel *channel)
541{
542 u8 refclk_freq;
543
544 if ((ah->ah_radio == AR5K_RF5112) ||
545 (ah->ah_radio == AR5K_RF5413) ||
546 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
547 refclk_freq = 40;
548 else
549 refclk_freq = 32;
550
551 if ((channel->center_freq % refclk_freq != 0) &&
552 ((channel->center_freq % refclk_freq < 10) ||
553 (channel->center_freq % refclk_freq > 22)))
554 return true;
555 else
556 return false;
557}
558
559/* TODO: Half/Quarter rate */
560static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
561 struct ieee80211_channel *channel)
562{
563 if (ah->ah_version == AR5K_AR5212 &&
564 ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
565
566 /* Setup ADC control */
567 ath5k_hw_reg_write(ah,
568 (AR5K_REG_SM(2,
569 AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) |
570 AR5K_REG_SM(2,
571 AR5K_PHY_ADC_CTL_INBUFGAIN_ON) |
572 AR5K_PHY_ADC_CTL_PWD_DAC_OFF |
573 AR5K_PHY_ADC_CTL_PWD_ADC_OFF),
574 AR5K_PHY_ADC_CTL);
575
576
577
578 /* Disable barker RSSI threshold */
579 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
580 AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR);
581
582 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
583 AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2);
584
585 /* Set the mute mask */
586 ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
587 }
588
589 /* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */
590 if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B)
591 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH);
592
593 /* Enable DCU double buffering */
594 if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B)
595 AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
596 AR5K_TXCFG_DCU_DBL_BUF_DIS);
597
598 /* Set DAC/ADC delays */
599 if (ah->ah_version == AR5K_AR5212) {
600 u32 scal;
601 if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
602 scal = AR5K_PHY_SCAL_32MHZ_2417;
603 else if (ath5k_eeprom_is_hb63(ah))
604 scal = AR5K_PHY_SCAL_32MHZ_HB63;
605 else
606 scal = AR5K_PHY_SCAL_32MHZ;
607 ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
608 }
609
610 /* Set fast ADC */
611 if ((ah->ah_radio == AR5K_RF5413) ||
612 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
613 u32 fast_adc = true;
614
615 if (channel->center_freq == 2462 ||
616 channel->center_freq == 2467)
617 fast_adc = 0;
618
619 /* Only update if needed */
620 if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != fast_adc)
621 ath5k_hw_reg_write(ah, fast_adc,
622 AR5K_PHY_FAST_ADC);
623 }
624
625 /* Fix for first revision of the RF5112 RF chipset */
626 if (ah->ah_radio == AR5K_RF5112 &&
627 ah->ah_radio_5ghz_revision <
628 AR5K_SREV_RAD_5112A) {
629 u32 data;
630 ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
631 AR5K_PHY_CCKTXCTL);
632 if (channel->hw_value & CHANNEL_5GHZ)
633 data = 0xffb81020;
634 else
635 data = 0xffb80d20;
636 ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
637 }
638
639 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
640 u32 usec_reg;
641 /* 5311 has different tx/rx latency masks
642 * from 5211, since we deal 5311 the same
643 * as 5211 when setting initvals, shift
644 * values here to their proper locations */
645 usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
646 ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 |
647 AR5K_USEC_32 |
648 AR5K_USEC_TX_LATENCY_5211 |
649 AR5K_REG_SM(29,
650 AR5K_USEC_RX_LATENCY_5210)),
651 AR5K_USEC_5211);
652 /* Clear QCU/DCU clock gating register */
653 ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT);
654 /* Set DAC/ADC delays */
655 ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL);
656 /* Enable PCU FIFO corruption ECO */
657 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
658 AR5K_DIAG_SW_ECO_ENABLE);
659 }
660}
661
662static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
663 struct ieee80211_channel *channel, u8 *ant, u8 ee_mode)
664{
665 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
666 s16 cck_ofdm_pwr_delta;
667
668 /* Adjust power delta for channel 14 */
669 if (channel->center_freq == 2484)
670 cck_ofdm_pwr_delta =
671 ((ee->ee_cck_ofdm_power_delta -
672 ee->ee_scaled_cck_delta) * 2) / 10;
673 else
674 cck_ofdm_pwr_delta =
675 (ee->ee_cck_ofdm_power_delta * 2) / 10;
676
677 /* Set CCK to OFDM power delta on tx power
678 * adjustment register */
679 if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
680 if (channel->hw_value == CHANNEL_G)
681 ath5k_hw_reg_write(ah,
682 AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1),
683 AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) |
684 AR5K_REG_SM((cck_ofdm_pwr_delta * -1),
685 AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX),
686 AR5K_PHY_TX_PWR_ADJ);
687 else
688 ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ);
689 } else {
690 /* For older revs we scale power on sw during tx power
691 * setup */
692 ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta;
693 ah->ah_txpower.txp_cck_ofdm_gainf_delta =
694 ee->ee_cck_ofdm_gain_delta;
695 }
696
697 /* Set antenna idle switch table */
698 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL,
699 AR5K_PHY_ANT_CTL_SWTABLE_IDLE,
700 (ah->ah_antenna[ee_mode][0] |
701 AR5K_PHY_ANT_CTL_TXRX_EN));
702
703 /* Set antenna switch table */
704 ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]],
705 AR5K_PHY_ANT_SWITCH_TABLE_0);
706 ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]],
707 AR5K_PHY_ANT_SWITCH_TABLE_1);
708
709 /* Noise floor threshold */
710 ath5k_hw_reg_write(ah,
711 AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
712 AR5K_PHY_NFTHRES);
713
714 if ((channel->hw_value & CHANNEL_TURBO) &&
715 (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) {
716 /* Switch settling time (Turbo) */
717 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
718 AR5K_PHY_SETTLING_SWITCH,
719 ee->ee_switch_settling_turbo[ee_mode]);
720
721 /* Tx/Rx attenuation (Turbo) */
722 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
723 AR5K_PHY_GAIN_TXRX_ATTEN,
724 ee->ee_atn_tx_rx_turbo[ee_mode]);
725
726 /* ADC/PGA desired size (Turbo) */
727 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
728 AR5K_PHY_DESIRED_SIZE_ADC,
729 ee->ee_adc_desired_size_turbo[ee_mode]);
730
731 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
732 AR5K_PHY_DESIRED_SIZE_PGA,
733 ee->ee_pga_desired_size_turbo[ee_mode]);
734
735 /* Tx/Rx margin (Turbo) */
736 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
737 AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
738 ee->ee_margin_tx_rx_turbo[ee_mode]);
739
740 } else {
741 /* Switch settling time */
742 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
743 AR5K_PHY_SETTLING_SWITCH,
744 ee->ee_switch_settling[ee_mode]);
745
746 /* Tx/Rx attenuation */
747 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
748 AR5K_PHY_GAIN_TXRX_ATTEN,
749 ee->ee_atn_tx_rx[ee_mode]);
750
751 /* ADC/PGA desired size */
752 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
753 AR5K_PHY_DESIRED_SIZE_ADC,
754 ee->ee_adc_desired_size[ee_mode]);
755
756 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
757 AR5K_PHY_DESIRED_SIZE_PGA,
758 ee->ee_pga_desired_size[ee_mode]);
759
760 /* Tx/Rx margin */
761 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
762 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
763 AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
764 ee->ee_margin_tx_rx[ee_mode]);
765 }
766
767 /* XPA delays */
768 ath5k_hw_reg_write(ah,
769 (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
770 (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
771 (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
772 (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
773
774 /* XLNA delay */
775 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3,
776 AR5K_PHY_RF_CTL3_TXE2XLNA_ON,
777 ee->ee_tx_end2xlna_enable[ee_mode]);
778
779 /* Thresh64 (ANI) */
780 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF,
781 AR5K_PHY_NF_THRESH62,
782 ee->ee_thr_62[ee_mode]);
783
784
785 /* False detect backoff for channels
786 * that have spur noise. Write the new
787 * cyclic power RSSI threshold. */
788 if (ath5k_hw_chan_has_spur_noise(ah, channel))
789 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
790 AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
791 AR5K_INIT_CYCRSSI_THR1 +
792 ee->ee_false_detect[ee_mode]);
793 else
794 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
795 AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
796 AR5K_INIT_CYCRSSI_THR1);
797
798 /* I/Q correction
799 * TODO: Per channel i/q infos ? */
800 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
801 AR5K_PHY_IQ_CORR_ENABLE |
802 (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) |
803 ee->ee_q_cal[ee_mode]);
804
805 /* Heavy clipping -disable for now */
806 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1)
807 ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE);
808
809 return;
810}
811
812/*
813 * Main reset function
814 */
815int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
816 struct ieee80211_channel *channel, bool change_channel)
817{
818 u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo;
819 u32 phy_tst1;
820 u8 mode, freq, ee_mode, ant[2];
821 int i, ret;
822
823 ATH5K_TRACE(ah->ah_sc);
824
825 s_ant = 0;
826 ee_mode = 0;
827 staid1_flags = 0;
828 tsf_up = 0;
829 tsf_lo = 0;
830 freq = 0;
831 mode = 0;
832
833 /*
834 * Save some registers before a reset
835 */
836 /*DCU/Antenna selection not available on 5210*/
837 if (ah->ah_version != AR5K_AR5210) {
838
839 switch (channel->hw_value & CHANNEL_MODES) {
840 case CHANNEL_A:
841 mode = AR5K_MODE_11A;
842 freq = AR5K_INI_RFGAIN_5GHZ;
843 ee_mode = AR5K_EEPROM_MODE_11A;
844 break;
845 case CHANNEL_G:
846 mode = AR5K_MODE_11G;
847 freq = AR5K_INI_RFGAIN_2GHZ;
848 ee_mode = AR5K_EEPROM_MODE_11G;
849 break;
850 case CHANNEL_B:
851 mode = AR5K_MODE_11B;
852 freq = AR5K_INI_RFGAIN_2GHZ;
853 ee_mode = AR5K_EEPROM_MODE_11B;
854 break;
855 case CHANNEL_T:
856 mode = AR5K_MODE_11A_TURBO;
857 freq = AR5K_INI_RFGAIN_5GHZ;
858 ee_mode = AR5K_EEPROM_MODE_11A;
859 break;
860 case CHANNEL_TG:
861 if (ah->ah_version == AR5K_AR5211) {
862 ATH5K_ERR(ah->ah_sc,
863 "TurboG mode not available on 5211");
864 return -EINVAL;
865 }
866 mode = AR5K_MODE_11G_TURBO;
867 freq = AR5K_INI_RFGAIN_2GHZ;
868 ee_mode = AR5K_EEPROM_MODE_11G;
869 break;
870 case CHANNEL_XR:
871 if (ah->ah_version == AR5K_AR5211) {
872 ATH5K_ERR(ah->ah_sc,
873 "XR mode not available on 5211");
874 return -EINVAL;
875 }
876 mode = AR5K_MODE_XR;
877 freq = AR5K_INI_RFGAIN_5GHZ;
878 ee_mode = AR5K_EEPROM_MODE_11A;
879 break;
880 default:
881 ATH5K_ERR(ah->ah_sc,
882 "invalid channel: %d\n", channel->center_freq);
883 return -EINVAL;
884 }
885
886 if (change_channel) {
887 /*
888 * Save frame sequence count
889 * For revs. after Oahu, only save
890 * seq num for DCU 0 (Global seq num)
891 */
892 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
893
894 for (i = 0; i < 10; i++)
895 s_seq[i] = ath5k_hw_reg_read(ah,
896 AR5K_QUEUE_DCU_SEQNUM(i));
897
898 } else {
899 s_seq[0] = ath5k_hw_reg_read(ah,
900 AR5K_QUEUE_DCU_SEQNUM(0));
901 }
902
903 /* TSF accelerates on AR5211 durring reset
904 * As a workaround save it here and restore
905 * it later so that it's back in time after
906 * reset. This way it'll get re-synced on the
907 * next beacon without breaking ad-hoc.
908 *
909 * On AR5212 TSF is almost preserved across a
910 * reset so it stays back in time anyway and
911 * we don't have to save/restore it.
912 *
913 * XXX: Since this breaks power saving we have
914 * to disable power saving until we receive the
915 * next beacon, so we can resync beacon timers */
916 if (ah->ah_version == AR5K_AR5211) {
917 tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
918 tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
919 }
920 }
921
922 /* Save default antenna */
923 s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
924
925 if (ah->ah_version == AR5K_AR5212) {
926 /* Restore normal 32/40MHz clock operation
927 * to avoid register access delay on certain
928 * PHY registers */
929 ath5k_hw_set_sleep_clock(ah, false);
930
931 /* Since we are going to write rf buffer
932 * check if we have any pending gain_F
933 * optimization settings */
934 if (change_channel && ah->ah_rf_banks != NULL)
935 ath5k_hw_gainf_calibrate(ah);
936 }
937 }
938
939 /*GPIOs*/
940 s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) &
941 AR5K_PCICFG_LEDSTATE;
942 s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
943 s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
944
945 /* AR5K_STA_ID1 flags, only preserve antenna
946 * settings and ack/cts rate mode */
947 staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) &
948 (AR5K_STA_ID1_DEFAULT_ANTENNA |
949 AR5K_STA_ID1_DESC_ANTENNA |
950 AR5K_STA_ID1_RTS_DEF_ANTENNA |
951 AR5K_STA_ID1_ACKCTS_6MB |
952 AR5K_STA_ID1_BASE_RATE_11B |
953 AR5K_STA_ID1_SELFGEN_DEF_ANT);
954
955 /* Wakeup the device */
956 ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
957 if (ret)
958 return ret;
959
960 /*
961 * Initialize operating mode
962 */
963 ah->ah_op_mode = op_mode;
964
965 /* PHY access enable */
966 if (ah->ah_mac_srev >= AR5K_SREV_AR5211)
967 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
968 else
969 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40,
970 AR5K_PHY(0));
971
972 /* Write initial settings */
973 ret = ath5k_hw_write_initvals(ah, mode, change_channel);
974 if (ret)
975 return ret;
976
977 /*
978 * 5211/5212 Specific
979 */
980 if (ah->ah_version != AR5K_AR5210) {
981
982 /*
983 * Write initial RF gain settings
984 * This should work for both 5111/5112
985 */
986 ret = ath5k_hw_rfgain_init(ah, freq);
987 if (ret)
988 return ret;
989
990 mdelay(1);
991
992 /*
993 * Tweak initval settings for revised
994 * chipsets and add some more config
995 * bits
996 */
997 ath5k_hw_tweak_initval_settings(ah, channel);
998
999 /*
1000 * Set TX power (FIXME)
1001 */
1002 ret = ath5k_hw_txpower(ah, channel, ee_mode,
1003 AR5K_TUNE_DEFAULT_TXPOWER);
1004 if (ret)
1005 return ret;
1006
1007 /* Write rate duration table only on AR5212 and if
1008 * virtual interface has already been brought up
1009 * XXX: rethink this after new mode changes to
1010 * mac80211 are integrated */
1011 if (ah->ah_version == AR5K_AR5212 &&
1012 ah->ah_sc->vif != NULL)
1013 ath5k_hw_write_rate_duration(ah, mode);
1014
1015 /*
1016 * Write RF buffer
1017 */
1018 ret = ath5k_hw_rfregs_init(ah, channel, mode);
1019 if (ret)
1020 return ret;
1021
1022
1023 /* Write OFDM timings on 5212*/
1024 if (ah->ah_version == AR5K_AR5212 &&
1025 channel->hw_value & CHANNEL_OFDM) {
1026 ret = ath5k_hw_write_ofdm_timings(ah, channel);
1027 if (ret)
1028 return ret;
1029 }
1030
1031 /*Enable/disable 802.11b mode on 5111
1032 (enable 2111 frequency converter + CCK)*/
1033 if (ah->ah_radio == AR5K_RF5111) {
1034 if (mode == AR5K_MODE_11B)
1035 AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
1036 AR5K_TXCFG_B_MODE);
1037 else
1038 AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
1039 AR5K_TXCFG_B_MODE);
1040 }
1041
1042 /*
1043 * In case a fixed antenna was set as default
1044 * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE
1045 * registers.
1046 */
1047 if (s_ant != 0) {
1048 if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */
1049 ant[0] = ant[1] = AR5K_ANT_FIXED_A;
1050 else /* 2 - Aux */
1051 ant[0] = ant[1] = AR5K_ANT_FIXED_B;
1052 } else {
1053 ant[0] = AR5K_ANT_FIXED_A;
1054 ant[1] = AR5K_ANT_FIXED_B;
1055 }
1056
1057 /* Commit values from EEPROM */
1058 ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode);
1059
1060 } else {
1061 /*
1062 * For 5210 we do all initialization using
1063 * initvals, so we don't have to modify
1064 * any settings (5210 also only supports
1065 * a/aturbo modes)
1066 */
1067 mdelay(1);
1068 /* Disable phy and wait */
1069 ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
1070 mdelay(1);
1071 }
1072
1073 /*
1074 * Restore saved values
1075 */
1076
1077 /*DCU/Antenna selection not available on 5210*/
1078 if (ah->ah_version != AR5K_AR5210) {
1079
1080 if (change_channel) {
1081 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
1082 for (i = 0; i < 10; i++)
1083 ath5k_hw_reg_write(ah, s_seq[i],
1084 AR5K_QUEUE_DCU_SEQNUM(i));
1085 } else {
1086 ath5k_hw_reg_write(ah, s_seq[0],
1087 AR5K_QUEUE_DCU_SEQNUM(0));
1088 }
1089
1090
1091 if (ah->ah_version == AR5K_AR5211) {
1092 ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32);
1093 ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
1094 }
1095 }
1096
1097 ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA);
1098 }
1099
1100 /* Ledstate */
1101 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]);
1102
1103 /* Gpio settings */
1104 ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
1105 ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
1106
1107 /* Restore sta_id flags and preserve our mac address*/
1108 ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_sta_id),
1109 AR5K_STA_ID0);
1110 ath5k_hw_reg_write(ah, staid1_flags | AR5K_HIGH_ID(ah->ah_sta_id),
1111 AR5K_STA_ID1);
1112
1113
1114 /*
1115 * Configure PCU
1116 */
1117
1118 /* Restore bssid and bssid mask */
1119 /* XXX: add ah->aid once mac80211 gives this to us */
1120 ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
1121
1122 /* Set PCU config */
1123 ath5k_hw_set_opmode(ah);
1124
1125 /* Clear any pending interrupts
1126 * PISR/SISR Not available on 5210 */
1127 if (ah->ah_version != AR5K_AR5210)
1128 ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
1129
1130 /* Set RSSI/BRSSI thresholds
1131 *
1132 * Note: If we decide to set this value
1133 * dynamicaly, have in mind that when AR5K_RSSI_THR
1134 * register is read it might return 0x40 if we haven't
1135 * wrote anything to it plus BMISS RSSI threshold is zeroed.
1136 * So doing a save/restore procedure here isn't the right
1137 * choice. Instead store it on ath5k_hw */
1138 ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES |
1139 AR5K_TUNE_BMISS_THRES <<
1140 AR5K_RSSI_THR_BMISS_S),
1141 AR5K_RSSI_THR);
1142
1143 /* MIC QoS support */
1144 if (ah->ah_mac_srev >= AR5K_SREV_AR2413) {
1145 ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL);
1146 ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL);
1147 }
1148
1149 /* QoS NOACK Policy */
1150 if (ah->ah_version == AR5K_AR5212) {
1151 ath5k_hw_reg_write(ah,
1152 AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) |
1153 AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) |
1154 AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET),
1155 AR5K_QOS_NOACK);
1156 }
1157
1158
1159 /*
1160 * Configure PHY
1161 */
1162
1163 /* Set channel on PHY */
1164 ret = ath5k_hw_channel(ah, channel);
1165 if (ret)
1166 return ret;
1167
1168 /*
1169 * Enable the PHY and wait until completion
1170 * This includes BaseBand and Synthesizer
1171 * activation.
1172 */
1173 ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
1174
1175 /*
1176 * On 5211+ read activation -> rx delay
1177 * and use it.
1178 *
1179 * TODO: Half/quarter rate support
1180 */
1181 if (ah->ah_version != AR5K_AR5210) {
1182 u32 delay;
1183 delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
1184 AR5K_PHY_RX_DELAY_M;
1185 delay = (channel->hw_value & CHANNEL_CCK) ?
1186 ((delay << 2) / 22) : (delay / 10);
1187
1188 udelay(100 + (2 * delay));
1189 } else {
1190 mdelay(1);
1191 }
1192
1193 /*
1194 * Perform ADC test to see if baseband is ready
1195 * Set tx hold and check adc test register
1196 */
1197 phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
1198 ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
1199 for (i = 0; i <= 20; i++) {
1200 if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
1201 break;
1202 udelay(200);
1203 }
1204 ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
1205
1206 /*
1207 * Start automatic gain control calibration
1208 *
1209 * During AGC calibration RX path is re-routed to
1210 * a power detector so we don't receive anything.
1211 *
1212 * This method is used to calibrate some static offsets
1213 * used together with on-the fly I/Q calibration (the
1214 * one performed via ath5k_hw_phy_calibrate), that doesn't
1215 * interrupt rx path.
1216 *
1217 * While rx path is re-routed to the power detector we also
1218 * start a noise floor calibration, to measure the
1219 * card's noise floor (the noise we measure when we are not
1220 * transmiting or receiving anything).
1221 *
1222 * If we are in a noisy environment AGC calibration may time
1223 * out and/or noise floor calibration might timeout.
1224 */
1225 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
1226 AR5K_PHY_AGCCTL_CAL);
1227
1228 /* At the same time start I/Q calibration for QAM constellation
1229 * -no need for CCK- */
1230 ah->ah_calibration = false;
1231 if (!(mode == AR5K_MODE_11B)) {
1232 ah->ah_calibration = true;
1233 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
1234 AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
1235 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
1236 AR5K_PHY_IQ_RUN);
1237 }
1238
1239 /* Wait for gain calibration to finish (we check for I/Q calibration
1240 * during ath5k_phy_calibrate) */
1241 if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
1242 AR5K_PHY_AGCCTL_CAL, 0, false)) {
1243 ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
1244 channel->center_freq);
1245 }
1246
1247 /*
1248 * If we run NF calibration before AGC, it always times out.
1249 * Binary HAL starts NF and AGC calibration at the same time
1250 * and only waits for AGC to finish. Also if AGC or NF cal.
1251 * times out, reset doesn't fail on binary HAL. I believe
1252 * that's wrong because since rx path is routed to a detector,
1253 * if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211
1254 * enables noise floor calibration after offset calibration and if noise
1255 * floor calibration fails, reset fails. I believe that's
1256 * a better approach, we just need to find a polling interval
1257 * that suits best, even if reset continues we need to make
1258 * sure that rx path is ready.
1259 */
1260 ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
1261
1262
1263 /*
1264 * Configure QCUs/DCUs
1265 */
1266
1267 /* TODO: HW Compression support for data queues */
1268 /* TODO: Burst prefetch for data queues */
1269
1270 /*
1271 * Reset queues and start beacon timers at the end of the reset routine
1272 * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
1273 * Note: If we want we can assign multiple qcus on one dcu.
1274 */
1275 for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
1276 ret = ath5k_hw_reset_tx_queue(ah, i);
1277 if (ret) {
1278 ATH5K_ERR(ah->ah_sc,
1279 "failed to reset TX queue #%d\n", i);
1280 return ret;
1281 }
1282 }
1283
1284
1285 /*
1286 * Configure DMA/Interrupts
1287 */
1288
1289 /*
1290 * Set Rx/Tx DMA Configuration
1291 *
1292 * Set standard DMA size (128). Note that
1293 * a DMA size of 512 causes rx overruns and tx errors
1294 * on pci-e cards (tested on 5424 but since rx overruns
1295 * also occur on 5416/5418 with madwifi we set 128
1296 * for all PCI-E cards to be safe).
1297 *
1298 * XXX: need to check 5210 for this
1299 * TODO: Check out tx triger level, it's always 64 on dumps but I
1300 * guess we can tweak it and see how it goes ;-)
1301 */
1302 if (ah->ah_version != AR5K_AR5210) {
1303 AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
1304 AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
1305 AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
1306 AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
1307 }
1308
1309 /* Pre-enable interrupts on 5211/5212*/
1310 if (ah->ah_version != AR5K_AR5210)
1311 ath5k_hw_set_imr(ah, ah->ah_imr);
1312
1313 /*
1314 * Setup RFKill interrupt if rfkill flag is set on eeprom.
1315 * TODO: Use gpio pin and polarity infos from eeprom
1316 * TODO: Handle this in ath5k_intr because it'll result
1317 * a nasty interrupt storm.
1318 */
1319#if 0
1320 if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) {
1321 ath5k_hw_set_gpio_input(ah, 0);
1322 ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0);
1323 if (ah->ah_gpio[0] == 0)
1324 ath5k_hw_set_gpio_intr(ah, 0, 1);
1325 else
1326 ath5k_hw_set_gpio_intr(ah, 0, 0);
1327 }
1328#endif
1329
1330 /* Enable 32KHz clock function for AR5212+ chips
1331 * Set clocks to 32KHz operation and use an
1332 * external 32KHz crystal when sleeping if one
1333 * exists */
1334 if (ah->ah_version == AR5K_AR5212)
1335 ath5k_hw_set_sleep_clock(ah, true);
1336
1337 /*
1338 * Disable beacons and reset the register
1339 */
1340 AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE |
1341 AR5K_BEACON_RESET_TSF);
1342
1343 return 0;
1344}
1345
1346#undef _ATH5K_RESET
diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h
new file mode 100644
index 000000000000..e50baff66175
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h
@@ -0,0 +1,1181 @@
1/*
2 * RF Buffer handling functions
3 *
4 * Copyright (c) 2009 Nick Kossifidis <mickflemm@gmail.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20
21/*
22 * There are some special registers on the RF chip
23 * that control various operation settings related mostly to
24 * the analog parts (channel, gain adjustment etc).
25 *
26 * We don't write on those registers directly but
27 * we send a data packet on the chip, using a special register,
28 * that holds all the settings we need. After we 've sent the
29 * data packet, we write on another special register to notify hw
30 * to apply the settings. This is done so that control registers
31 * can be dynamicaly programmed during operation and the settings
32 * are applied faster on the hw.
33 *
34 * We call each data packet an "RF Bank" and all the data we write
35 * (all RF Banks) "RF Buffer". This file holds initial RF Buffer
36 * data for the different RF chips, and various info to match RF
37 * Buffer offsets with specific RF registers so that we can access
38 * them. We tweak these settings on rfregs_init function.
39 *
40 * Also check out reg.h and U.S. Patent 6677779 B1 (about buffer
41 * registers and control registers):
42 *
43 * http://www.google.com/patents?id=qNURAAAAEBAJ
44 */
45
46
47/*
48 * Struct to hold default mode specific RF
49 * register values (RF Banks)
50 */
51struct ath5k_ini_rfbuffer {
52 u8 rfb_bank; /* RF Bank number */
53 u16 rfb_ctrl_register; /* RF Buffer control register */
54 u32 rfb_mode_data[5]; /* RF Buffer data for each mode */
55};
56
57/*
58 * Struct to hold RF Buffer field
59 * infos used to access certain RF
60 * analog registers
61 */
62struct ath5k_rfb_field {
63 u8 len; /* Field length */
64 u16 pos; /* Offset on the raw packet */
65 u8 col; /* Column -used for shifting */
66};
67
68/*
69 * RF analog register definition
70 */
71struct ath5k_rf_reg {
72 u8 bank; /* RF Buffer Bank number */
73 u8 index; /* Register's index on rf_regs_idx */
74 struct ath5k_rfb_field field; /* RF Buffer field for this register */
75};
76
77/* Map RF registers to indexes
78 * We do this to handle common bits and make our
79 * life easier by using an index for each register
80 * instead of a full rfb_field */
81enum ath5k_rf_regs_idx {
82 /* BANK 6 */
83 AR5K_RF_OB_2GHZ = 0,
84 AR5K_RF_OB_5GHZ,
85 AR5K_RF_DB_2GHZ,
86 AR5K_RF_DB_5GHZ,
87 AR5K_RF_FIXED_BIAS_A,
88 AR5K_RF_FIXED_BIAS_B,
89 AR5K_RF_PWD_XPD,
90 AR5K_RF_XPD_SEL,
91 AR5K_RF_XPD_GAIN,
92 AR5K_RF_PD_GAIN_LO,
93 AR5K_RF_PD_GAIN_HI,
94 AR5K_RF_HIGH_VC_CP,
95 AR5K_RF_MID_VC_CP,
96 AR5K_RF_LOW_VC_CP,
97 AR5K_RF_PUSH_UP,
98 AR5K_RF_PAD2GND,
99 AR5K_RF_XB2_LVL,
100 AR5K_RF_XB5_LVL,
101 AR5K_RF_PWD_ICLOBUF_2G,
102 AR5K_RF_PWD_84,
103 AR5K_RF_PWD_90,
104 AR5K_RF_PWD_130,
105 AR5K_RF_PWD_131,
106 AR5K_RF_PWD_132,
107 AR5K_RF_PWD_136,
108 AR5K_RF_PWD_137,
109 AR5K_RF_PWD_138,
110 AR5K_RF_PWD_166,
111 AR5K_RF_PWD_167,
112 AR5K_RF_DERBY_CHAN_SEL_MODE,
113 /* BANK 7 */
114 AR5K_RF_GAIN_I,
115 AR5K_RF_PLO_SEL,
116 AR5K_RF_RFGAIN_SEL,
117 AR5K_RF_RFGAIN_STEP,
118 AR5K_RF_WAIT_S,
119 AR5K_RF_WAIT_I,
120 AR5K_RF_MAX_TIME,
121 AR5K_RF_MIXVGA_OVR,
122 AR5K_RF_MIXGAIN_OVR,
123 AR5K_RF_MIXGAIN_STEP,
124 AR5K_RF_PD_DELAY_A,
125 AR5K_RF_PD_DELAY_B,
126 AR5K_RF_PD_DELAY_XR,
127 AR5K_RF_PD_PERIOD_A,
128 AR5K_RF_PD_PERIOD_B,
129 AR5K_RF_PD_PERIOD_XR,
130};
131
132
133/*******************\
134* RF5111 (Sombrero) *
135\*******************/
136
137/* BANK 6 len pos col */
138#define AR5K_RF5111_OB_2GHZ { 3, 119, 0 }
139#define AR5K_RF5111_DB_2GHZ { 3, 122, 0 }
140
141#define AR5K_RF5111_OB_5GHZ { 3, 104, 0 }
142#define AR5K_RF5111_DB_5GHZ { 3, 107, 0 }
143
144#define AR5K_RF5111_PWD_XPD { 1, 95, 0 }
145#define AR5K_RF5111_XPD_GAIN { 4, 96, 0 }
146
147/* Access to PWD registers */
148#define AR5K_RF5111_PWD(_n) { 1, (135 - _n), 3 }
149
150/* BANK 7 len pos col */
151#define AR5K_RF5111_GAIN_I { 6, 29, 0 }
152#define AR5K_RF5111_PLO_SEL { 1, 4, 0 }
153#define AR5K_RF5111_RFGAIN_SEL { 1, 36, 0 }
154#define AR5K_RF5111_RFGAIN_STEP { 6, 37, 0 }
155/* Only on AR5212 BaseBand and up */
156#define AR5K_RF5111_WAIT_S { 5, 19, 0 }
157#define AR5K_RF5111_WAIT_I { 5, 24, 0 }
158#define AR5K_RF5111_MAX_TIME { 2, 49, 0 }
159
160static const struct ath5k_rf_reg rf_regs_5111[] = {
161 {6, AR5K_RF_OB_2GHZ, AR5K_RF5111_OB_2GHZ},
162 {6, AR5K_RF_DB_2GHZ, AR5K_RF5111_DB_2GHZ},
163 {6, AR5K_RF_OB_5GHZ, AR5K_RF5111_OB_5GHZ},
164 {6, AR5K_RF_DB_5GHZ, AR5K_RF5111_DB_5GHZ},
165 {6, AR5K_RF_PWD_XPD, AR5K_RF5111_PWD_XPD},
166 {6, AR5K_RF_XPD_GAIN, AR5K_RF5111_XPD_GAIN},
167 {6, AR5K_RF_PWD_84, AR5K_RF5111_PWD(84)},
168 {6, AR5K_RF_PWD_90, AR5K_RF5111_PWD(90)},
169 {7, AR5K_RF_GAIN_I, AR5K_RF5111_GAIN_I},
170 {7, AR5K_RF_PLO_SEL, AR5K_RF5111_PLO_SEL},
171 {7, AR5K_RF_RFGAIN_SEL, AR5K_RF5111_RFGAIN_SEL},
172 {7, AR5K_RF_RFGAIN_STEP, AR5K_RF5111_RFGAIN_STEP},
173 {7, AR5K_RF_WAIT_S, AR5K_RF5111_WAIT_S},
174 {7, AR5K_RF_WAIT_I, AR5K_RF5111_WAIT_I},
175 {7, AR5K_RF_MAX_TIME, AR5K_RF5111_MAX_TIME}
176};
177
178/* Default mode specific settings */
179static const struct ath5k_ini_rfbuffer rfb_5111[] = {
180 { 0, 0x989c,
181 /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
182 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
183 { 0, 0x989c,
184 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
185 { 0, 0x989c,
186 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
187 { 0, 0x989c,
188 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
189 { 0, 0x989c,
190 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
191 { 0, 0x989c,
192 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
193 { 0, 0x989c,
194 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
195 { 0, 0x989c,
196 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
197 { 0, 0x989c,
198 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
199 { 0, 0x989c,
200 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
201 { 0, 0x989c,
202 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
203 { 0, 0x989c,
204 { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } },
205 { 0, 0x989c,
206 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
207 { 0, 0x989c,
208 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
209 { 0, 0x989c,
210 { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } },
211 { 0, 0x989c,
212 { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } },
213 { 0, 0x98d4,
214 { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } },
215 { 1, 0x98d4,
216 { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
217 { 2, 0x98d4,
218 { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } },
219 { 3, 0x98d8,
220 { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } },
221 { 6, 0x989c,
222 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
223 { 6, 0x989c,
224 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
225 { 6, 0x989c,
226 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
227 { 6, 0x989c,
228 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
229 { 6, 0x989c,
230 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
231 { 6, 0x989c,
232 { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
233 { 6, 0x989c,
234 { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } },
235 { 6, 0x989c,
236 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
237 { 6, 0x989c,
238 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
239 { 6, 0x989c,
240 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
241 { 6, 0x989c,
242 { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } },
243 { 6, 0x989c,
244 { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } },
245 { 6, 0x989c,
246 { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } },
247 { 6, 0x989c,
248 { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } },
249 { 6, 0x989c,
250 { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } },
251 { 6, 0x989c,
252 { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } },
253 { 6, 0x98d4,
254 { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } },
255 { 7, 0x989c,
256 { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } },
257 { 7, 0x989c,
258 { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } },
259 { 7, 0x989c,
260 { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
261 { 7, 0x989c,
262 { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } },
263 { 7, 0x989c,
264 { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } },
265 { 7, 0x989c,
266 { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } },
267 { 7, 0x989c,
268 { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } },
269 { 7, 0x98cc,
270 { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } },
271};
272
273
274
275/***********************\
276* RF5112/RF2112 (Derby) *
277\***********************/
278
279/* BANK 7 (Common) len pos col */
280#define AR5K_RF5112X_GAIN_I { 6, 14, 0 }
281#define AR5K_RF5112X_MIXVGA_OVR { 1, 36, 0 }
282#define AR5K_RF5112X_MIXGAIN_OVR { 2, 37, 0 }
283#define AR5K_RF5112X_MIXGAIN_STEP { 4, 32, 0 }
284#define AR5K_RF5112X_PD_DELAY_A { 4, 58, 0 }
285#define AR5K_RF5112X_PD_DELAY_B { 4, 62, 0 }
286#define AR5K_RF5112X_PD_DELAY_XR { 4, 66, 0 }
287#define AR5K_RF5112X_PD_PERIOD_A { 4, 70, 0 }
288#define AR5K_RF5112X_PD_PERIOD_B { 4, 74, 0 }
289#define AR5K_RF5112X_PD_PERIOD_XR { 4, 78, 0 }
290
291/* RFX112 (Derby 1) */
292
293/* BANK 6 len pos col */
294#define AR5K_RF5112_OB_2GHZ { 3, 269, 0 }
295#define AR5K_RF5112_DB_2GHZ { 3, 272, 0 }
296
297#define AR5K_RF5112_OB_5GHZ { 3, 261, 0 }
298#define AR5K_RF5112_DB_5GHZ { 3, 264, 0 }
299
300#define AR5K_RF5112_FIXED_BIAS_A { 1, 260, 0 }
301#define AR5K_RF5112_FIXED_BIAS_B { 1, 259, 0 }
302
303#define AR5K_RF5112_XPD_SEL { 1, 284, 0 }
304#define AR5K_RF5112_XPD_GAIN { 2, 252, 0 }
305
306/* Access to PWD registers */
307#define AR5K_RF5112_PWD(_n) { 1, (302 - _n), 3 }
308
309static const struct ath5k_rf_reg rf_regs_5112[] = {
310 {6, AR5K_RF_OB_2GHZ, AR5K_RF5112_OB_2GHZ},
311 {6, AR5K_RF_DB_2GHZ, AR5K_RF5112_DB_2GHZ},
312 {6, AR5K_RF_OB_5GHZ, AR5K_RF5112_OB_5GHZ},
313 {6, AR5K_RF_DB_5GHZ, AR5K_RF5112_DB_5GHZ},
314 {6, AR5K_RF_FIXED_BIAS_A, AR5K_RF5112_FIXED_BIAS_A},
315 {6, AR5K_RF_FIXED_BIAS_B, AR5K_RF5112_FIXED_BIAS_B},
316 {6, AR5K_RF_XPD_SEL, AR5K_RF5112_XPD_SEL},
317 {6, AR5K_RF_XPD_GAIN, AR5K_RF5112_XPD_GAIN},
318 {6, AR5K_RF_PWD_130, AR5K_RF5112_PWD(130)},
319 {6, AR5K_RF_PWD_131, AR5K_RF5112_PWD(131)},
320 {6, AR5K_RF_PWD_132, AR5K_RF5112_PWD(132)},
321 {6, AR5K_RF_PWD_136, AR5K_RF5112_PWD(136)},
322 {6, AR5K_RF_PWD_137, AR5K_RF5112_PWD(137)},
323 {6, AR5K_RF_PWD_138, AR5K_RF5112_PWD(138)},
324 {7, AR5K_RF_GAIN_I, AR5K_RF5112X_GAIN_I},
325 {7, AR5K_RF_MIXVGA_OVR, AR5K_RF5112X_MIXVGA_OVR},
326 {7, AR5K_RF_MIXGAIN_OVR, AR5K_RF5112X_MIXGAIN_OVR},
327 {7, AR5K_RF_MIXGAIN_STEP, AR5K_RF5112X_MIXGAIN_STEP},
328 {7, AR5K_RF_PD_DELAY_A, AR5K_RF5112X_PD_DELAY_A},
329 {7, AR5K_RF_PD_DELAY_B, AR5K_RF5112X_PD_DELAY_B},
330 {7, AR5K_RF_PD_DELAY_XR, AR5K_RF5112X_PD_DELAY_XR},
331 {7, AR5K_RF_PD_PERIOD_A, AR5K_RF5112X_PD_PERIOD_A},
332 {7, AR5K_RF_PD_PERIOD_B, AR5K_RF5112X_PD_PERIOD_B},
333 {7, AR5K_RF_PD_PERIOD_XR, AR5K_RF5112X_PD_PERIOD_XR},
334};
335
336/* Default mode specific settings */
337static const struct ath5k_ini_rfbuffer rfb_5112[] = {
338 { 1, 0x98d4,
339 /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
340 { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
341 { 2, 0x98d0,
342 { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
343 { 3, 0x98dc,
344 { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } },
345 { 6, 0x989c,
346 { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } },
347 { 6, 0x989c,
348 { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
349 { 6, 0x989c,
350 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
351 { 6, 0x989c,
352 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
353 { 6, 0x989c,
354 { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } },
355 { 6, 0x989c,
356 { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } },
357 { 6, 0x989c,
358 { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } },
359 { 6, 0x989c,
360 { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
361 { 6, 0x989c,
362 { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
363 { 6, 0x989c,
364 { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
365 { 6, 0x989c,
366 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
367 { 6, 0x989c,
368 { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
369 { 6, 0x989c,
370 { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
371 { 6, 0x989c,
372 { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
373 { 6, 0x989c,
374 { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } },
375 { 6, 0x989c,
376 { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } },
377 { 6, 0x989c,
378 { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
379 { 6, 0x989c,
380 { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
381 { 6, 0x989c,
382 { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } },
383 { 6, 0x989c,
384 { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } },
385 { 6, 0x989c,
386 { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
387 { 6, 0x989c,
388 { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } },
389 { 6, 0x989c,
390 { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
391 { 6, 0x989c,
392 { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
393 { 6, 0x989c,
394 { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } },
395 { 6, 0x989c,
396 { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } },
397 { 6, 0x989c,
398 { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
399 { 6, 0x989c,
400 { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } },
401 { 6, 0x989c,
402 { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } },
403 { 6, 0x989c,
404 { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } },
405 { 6, 0x989c,
406 { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } },
407 { 6, 0x989c,
408 { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } },
409 { 6, 0x989c,
410 { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } },
411 { 6, 0x989c,
412 { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } },
413 { 6, 0x989c,
414 { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } },
415 { 6, 0x989c,
416 { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } },
417 { 6, 0x989c,
418 { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } },
419 { 6, 0x98d0,
420 { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } },
421 { 7, 0x989c,
422 { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
423 { 7, 0x989c,
424 { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
425 { 7, 0x989c,
426 { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } },
427 { 7, 0x989c,
428 { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
429 { 7, 0x989c,
430 { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } },
431 { 7, 0x989c,
432 { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
433 { 7, 0x989c,
434 { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
435 { 7, 0x989c,
436 { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } },
437 { 7, 0x989c,
438 { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } },
439 { 7, 0x989c,
440 { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
441 { 7, 0x989c,
442 { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
443 { 7, 0x989c,
444 { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
445 { 7, 0x98c4,
446 { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
447};
448
449/* RFX112A (Derby 2) */
450
451/* BANK 6 len pos col */
452#define AR5K_RF5112A_OB_2GHZ { 3, 287, 0 }
453#define AR5K_RF5112A_DB_2GHZ { 3, 290, 0 }
454
455#define AR5K_RF5112A_OB_5GHZ { 3, 279, 0 }
456#define AR5K_RF5112A_DB_5GHZ { 3, 282, 0 }
457
458#define AR5K_RF5112A_FIXED_BIAS_A { 1, 278, 0 }
459#define AR5K_RF5112A_FIXED_BIAS_B { 1, 277, 0 }
460
461#define AR5K_RF5112A_XPD_SEL { 1, 302, 0 }
462#define AR5K_RF5112A_PDGAINLO { 2, 270, 0 }
463#define AR5K_RF5112A_PDGAINHI { 2, 257, 0 }
464
465/* Access to PWD registers */
466#define AR5K_RF5112A_PWD(_n) { 1, (306 - _n), 3 }
467
468/* Voltage regulators */
469#define AR5K_RF5112A_HIGH_VC_CP { 2, 90, 2 }
470#define AR5K_RF5112A_MID_VC_CP { 2, 92, 2 }
471#define AR5K_RF5112A_LOW_VC_CP { 2, 94, 2 }
472#define AR5K_RF5112A_PUSH_UP { 1, 254, 2 }
473
474/* Power consumption */
475#define AR5K_RF5112A_PAD2GND { 1, 281, 1 }
476#define AR5K_RF5112A_XB2_LVL { 2, 1, 3 }
477#define AR5K_RF5112A_XB5_LVL { 2, 3, 3 }
478
479static const struct ath5k_rf_reg rf_regs_5112a[] = {
480 {6, AR5K_RF_OB_2GHZ, AR5K_RF5112A_OB_2GHZ},
481 {6, AR5K_RF_DB_2GHZ, AR5K_RF5112A_DB_2GHZ},
482 {6, AR5K_RF_OB_5GHZ, AR5K_RF5112A_OB_5GHZ},
483 {6, AR5K_RF_DB_5GHZ, AR5K_RF5112A_DB_5GHZ},
484 {6, AR5K_RF_FIXED_BIAS_A, AR5K_RF5112A_FIXED_BIAS_A},
485 {6, AR5K_RF_FIXED_BIAS_B, AR5K_RF5112A_FIXED_BIAS_B},
486 {6, AR5K_RF_XPD_SEL, AR5K_RF5112A_XPD_SEL},
487 {6, AR5K_RF_PD_GAIN_LO, AR5K_RF5112A_PDGAINLO},
488 {6, AR5K_RF_PD_GAIN_HI, AR5K_RF5112A_PDGAINHI},
489 {6, AR5K_RF_PWD_130, AR5K_RF5112A_PWD(130)},
490 {6, AR5K_RF_PWD_131, AR5K_RF5112A_PWD(131)},
491 {6, AR5K_RF_PWD_132, AR5K_RF5112A_PWD(132)},
492 {6, AR5K_RF_PWD_136, AR5K_RF5112A_PWD(136)},
493 {6, AR5K_RF_PWD_137, AR5K_RF5112A_PWD(137)},
494 {6, AR5K_RF_PWD_138, AR5K_RF5112A_PWD(138)},
495 {6, AR5K_RF_PWD_166, AR5K_RF5112A_PWD(166)},
496 {6, AR5K_RF_PWD_167, AR5K_RF5112A_PWD(167)},
497 {6, AR5K_RF_HIGH_VC_CP, AR5K_RF5112A_HIGH_VC_CP},
498 {6, AR5K_RF_MID_VC_CP, AR5K_RF5112A_MID_VC_CP},
499 {6, AR5K_RF_LOW_VC_CP, AR5K_RF5112A_LOW_VC_CP},
500 {6, AR5K_RF_PUSH_UP, AR5K_RF5112A_PUSH_UP},
501 {6, AR5K_RF_PAD2GND, AR5K_RF5112A_PAD2GND},
502 {6, AR5K_RF_XB2_LVL, AR5K_RF5112A_XB2_LVL},
503 {6, AR5K_RF_XB5_LVL, AR5K_RF5112A_XB5_LVL},
504 {7, AR5K_RF_GAIN_I, AR5K_RF5112X_GAIN_I},
505 {7, AR5K_RF_MIXVGA_OVR, AR5K_RF5112X_MIXVGA_OVR},
506 {7, AR5K_RF_MIXGAIN_OVR, AR5K_RF5112X_MIXGAIN_OVR},
507 {7, AR5K_RF_MIXGAIN_STEP, AR5K_RF5112X_MIXGAIN_STEP},
508 {7, AR5K_RF_PD_DELAY_A, AR5K_RF5112X_PD_DELAY_A},
509 {7, AR5K_RF_PD_DELAY_B, AR5K_RF5112X_PD_DELAY_B},
510 {7, AR5K_RF_PD_DELAY_XR, AR5K_RF5112X_PD_DELAY_XR},
511 {7, AR5K_RF_PD_PERIOD_A, AR5K_RF5112X_PD_PERIOD_A},
512 {7, AR5K_RF_PD_PERIOD_B, AR5K_RF5112X_PD_PERIOD_B},
513 {7, AR5K_RF_PD_PERIOD_XR, AR5K_RF5112X_PD_PERIOD_XR},
514};
515
516/* Default mode specific settings */
517static const struct ath5k_ini_rfbuffer rfb_5112a[] = {
518 { 1, 0x98d4,
519 /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
520 { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
521 { 2, 0x98d0,
522 { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
523 { 3, 0x98dc,
524 { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
525 { 6, 0x989c,
526 { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
527 { 6, 0x989c,
528 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
529 { 6, 0x989c,
530 { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } },
531 { 6, 0x989c,
532 { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
533 { 6, 0x989c,
534 { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
535 { 6, 0x989c,
536 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
537 { 6, 0x989c,
538 { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } },
539 { 6, 0x989c,
540 { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } },
541 { 6, 0x989c,
542 { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } },
543 { 6, 0x989c,
544 { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } },
545 { 6, 0x989c,
546 { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } },
547 { 6, 0x989c,
548 { 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 } },
549 { 6, 0x989c,
550 { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } },
551 { 6, 0x989c,
552 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
553 { 6, 0x989c,
554 { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } },
555 { 6, 0x989c,
556 { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
557 { 6, 0x989c,
558 { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } },
559 { 6, 0x989c,
560 { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
561 { 6, 0x989c,
562 { 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 } },
563 { 6, 0x989c,
564 { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
565 { 6, 0x989c,
566 { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } },
567 { 6, 0x989c,
568 { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } },
569 { 6, 0x989c,
570 { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } },
571 { 6, 0x989c,
572 { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
573 { 6, 0x989c,
574 { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
575 { 6, 0x989c,
576 { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } },
577 { 6, 0x989c,
578 { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } },
579 { 6, 0x989c,
580 { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
581 { 6, 0x989c,
582 { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } },
583 { 6, 0x989c,
584 { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } },
585 { 6, 0x989c,
586 { 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 } },
587 { 6, 0x989c,
588 { 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 } },
589 { 6, 0x989c,
590 { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
591 { 6, 0x989c,
592 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
593 { 6, 0x989c,
594 { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } },
595 { 6, 0x989c,
596 { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } },
597 { 6, 0x989c,
598 { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } },
599 { 6, 0x989c,
600 { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } },
601 { 6, 0x989c,
602 { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } },
603 { 6, 0x98d8,
604 { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } },
605 { 7, 0x989c,
606 { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
607 { 7, 0x989c,
608 { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
609 { 7, 0x989c,
610 { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } },
611 { 7, 0x989c,
612 { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
613 { 7, 0x989c,
614 { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } },
615 { 7, 0x989c,
616 { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
617 { 7, 0x989c,
618 { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
619 { 7, 0x989c,
620 { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } },
621 { 7, 0x989c,
622 { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } },
623 { 7, 0x989c,
624 { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
625 { 7, 0x989c,
626 { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
627 { 7, 0x989c,
628 { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
629 { 7, 0x98c4,
630 { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
631};
632
633
634
635/******************\
636* RF2413 (Griffin) *
637\******************/
638
639/* BANK 6 len pos col */
640#define AR5K_RF2413_OB_2GHZ { 3, 168, 0 }
641#define AR5K_RF2413_DB_2GHZ { 3, 165, 0 }
642
643static const struct ath5k_rf_reg rf_regs_2413[] = {
644 {6, AR5K_RF_OB_2GHZ, AR5K_RF2413_OB_2GHZ},
645 {6, AR5K_RF_DB_2GHZ, AR5K_RF2413_DB_2GHZ},
646};
647
648/* Default mode specific settings
649 * XXX: a/aTurbo ???
650 */
651static const struct ath5k_ini_rfbuffer rfb_2413[] = {
652 { 1, 0x98d4,
653 /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
654 { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
655 { 2, 0x98d0,
656 { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
657 { 3, 0x98dc,
658 { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
659 { 6, 0x989c,
660 { 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 } },
661 { 6, 0x989c,
662 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
663 { 6, 0x989c,
664 { 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 } },
665 { 6, 0x989c,
666 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
667 { 6, 0x989c,
668 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
669 { 6, 0x989c,
670 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
671 { 6, 0x989c,
672 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
673 { 6, 0x989c,
674 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
675 { 6, 0x989c,
676 { 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 } },
677 { 6, 0x989c,
678 { 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 } },
679 { 6, 0x989c,
680 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
681 { 6, 0x989c,
682 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
683 { 6, 0x989c,
684 { 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 } },
685 { 6, 0x989c,
686 { 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 } },
687 { 6, 0x989c,
688 { 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 } },
689 { 6, 0x989c,
690 { 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 } },
691 { 6, 0x989c,
692 { 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 } },
693 { 6, 0x989c,
694 { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } },
695 { 6, 0x989c,
696 { 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 } },
697 { 6, 0x989c,
698 { 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 } },
699 { 6, 0x989c,
700 { 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 } },
701 { 6, 0x989c,
702 { 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 } },
703 { 6, 0x989c,
704 { 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f } },
705 { 6, 0x989c,
706 { 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 } },
707 { 6, 0x989c,
708 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
709 { 6, 0x989c,
710 { 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 } },
711 { 6, 0x98d8,
712 { 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 } },
713 { 7, 0x989c,
714 { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
715 { 7, 0x989c,
716 { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
717 { 7, 0x98cc,
718 { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
719};
720
721
722
723/***************************\
724* RF2315/RF2316 (Cobra SoC) *
725\***************************/
726
727/* BANK 6 len pos col */
728#define AR5K_RF2316_OB_2GHZ { 3, 178, 0 }
729#define AR5K_RF2316_DB_2GHZ { 3, 175, 0 }
730
731static const struct ath5k_rf_reg rf_regs_2316[] = {
732 {6, AR5K_RF_OB_2GHZ, AR5K_RF2316_OB_2GHZ},
733 {6, AR5K_RF_DB_2GHZ, AR5K_RF2316_DB_2GHZ},
734};
735
736/* Default mode specific settings */
737static const struct ath5k_ini_rfbuffer rfb_2316[] = {
738 { 1, 0x98d4,
739 /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
740 { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
741 { 2, 0x98d0,
742 { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
743 { 3, 0x98dc,
744 { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
745 { 6, 0x989c,
746 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
747 { 6, 0x989c,
748 { 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 } },
749 { 6, 0x989c,
750 { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
751 { 6, 0x989c,
752 { 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 } },
753 { 6, 0x989c,
754 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
755 { 6, 0x989c,
756 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
757 { 6, 0x989c,
758 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
759 { 6, 0x989c,
760 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
761 { 6, 0x989c,
762 { 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 } },
763 { 6, 0x989c,
764 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
765 { 6, 0x989c,
766 { 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 } },
767 { 6, 0x989c,
768 { 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 } },
769 { 6, 0x989c,
770 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
771 { 6, 0x989c,
772 { 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 } },
773 { 6, 0x989c,
774 { 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 } },
775 { 6, 0x989c,
776 { 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 } },
777 { 6, 0x989c,
778 { 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 } },
779 { 6, 0x989c,
780 { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
781 { 6, 0x989c,
782 { 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 } },
783 { 6, 0x989c,
784 { 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 } },
785 { 6, 0x989c,
786 { 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 } },
787 { 6, 0x989c,
788 { 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 } },
789 { 6, 0x989c,
790 { 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d } },
791 { 6, 0x989c,
792 { 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 } },
793 { 6, 0x989c,
794 { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
795 { 6, 0x989c,
796 { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
797 { 6, 0x989c,
798 { 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 } },
799 { 6, 0x989c,
800 { 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 } },
801 { 6, 0x98c0,
802 { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
803 { 7, 0x989c,
804 { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
805 { 7, 0x989c,
806 { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
807 { 7, 0x98cc,
808 { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
809};
810
811
812
813/******************************\
814* RF5413/RF5424 (Eagle/Condor) *
815\******************************/
816
817/* BANK 6 len pos col */
818#define AR5K_RF5413_OB_2GHZ { 3, 241, 0 }
819#define AR5K_RF5413_DB_2GHZ { 3, 238, 0 }
820
821#define AR5K_RF5413_OB_5GHZ { 3, 247, 0 }
822#define AR5K_RF5413_DB_5GHZ { 3, 244, 0 }
823
824#define AR5K_RF5413_PWD_ICLOBUF2G { 3, 131, 3 }
825#define AR5K_RF5413_DERBY_CHAN_SEL_MODE { 1, 291, 2 }
826
827static const struct ath5k_rf_reg rf_regs_5413[] = {
828 {6, AR5K_RF_OB_2GHZ, AR5K_RF5413_OB_2GHZ},
829 {6, AR5K_RF_DB_2GHZ, AR5K_RF5413_DB_2GHZ},
830 {6, AR5K_RF_OB_5GHZ, AR5K_RF5413_OB_5GHZ},
831 {6, AR5K_RF_DB_5GHZ, AR5K_RF5413_DB_5GHZ},
832 {6, AR5K_RF_PWD_ICLOBUF_2G, AR5K_RF5413_PWD_ICLOBUF2G},
833 {6, AR5K_RF_DERBY_CHAN_SEL_MODE, AR5K_RF5413_DERBY_CHAN_SEL_MODE},
834};
835
836/* Default mode specific settings */
837static const struct ath5k_ini_rfbuffer rfb_5413[] = {
838 { 1, 0x98d4,
839 /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
840 { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
841 { 2, 0x98d0,
842 { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
843 { 3, 0x98dc,
844 { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } },
845 { 6, 0x989c,
846 { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } },
847 { 6, 0x989c,
848 { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } },
849 { 6, 0x989c,
850 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
851 { 6, 0x989c,
852 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
853 { 6, 0x989c,
854 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
855 { 6, 0x989c,
856 { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } },
857 { 6, 0x989c,
858 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
859 { 6, 0x989c,
860 { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } },
861 { 6, 0x989c,
862 { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } },
863 { 6, 0x989c,
864 { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
865 { 6, 0x989c,
866 { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
867 { 6, 0x989c,
868 { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } },
869 { 6, 0x989c,
870 { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
871 { 6, 0x989c,
872 { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
873 { 6, 0x989c,
874 { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
875 { 6, 0x989c,
876 { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
877 { 6, 0x989c,
878 { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } },
879 { 6, 0x989c,
880 { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } },
881 { 6, 0x989c,
882 { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } },
883 { 6, 0x989c,
884 { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } },
885 { 6, 0x989c,
886 { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } },
887 { 6, 0x989c,
888 { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } },
889 { 6, 0x989c,
890 { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
891 { 6, 0x989c,
892 { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } },
893 { 6, 0x989c,
894 { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
895 { 6, 0x989c,
896 { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } },
897 { 6, 0x989c,
898 { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } },
899 { 6, 0x989c,
900 { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } },
901 { 6, 0x989c,
902 { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } },
903 { 6, 0x989c,
904 { 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 } },
905 { 6, 0x989c,
906 { 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da } },
907 { 6, 0x989c,
908 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
909 { 6, 0x989c,
910 { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } },
911 { 6, 0x989c,
912 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
913 { 6, 0x989c,
914 { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } },
915 { 6, 0x989c,
916 { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 } },
917 { 6, 0x98c8,
918 { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } },
919 { 7, 0x989c,
920 { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
921 { 7, 0x989c,
922 { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
923 { 7, 0x98cc,
924 { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
925};
926
927
928
929/***************************\
930* RF2425/RF2417 (Swan/Nala) *
931* AR2317 (Spider SoC) *
932\***************************/
933
934/* BANK 6 len pos col */
935#define AR5K_RF2425_OB_2GHZ { 3, 193, 0 }
936#define AR5K_RF2425_DB_2GHZ { 3, 190, 0 }
937
938static const struct ath5k_rf_reg rf_regs_2425[] = {
939 {6, AR5K_RF_OB_2GHZ, AR5K_RF2425_OB_2GHZ},
940 {6, AR5K_RF_DB_2GHZ, AR5K_RF2425_DB_2GHZ},
941};
942
943/* Default mode specific settings
944 * XXX: a/aTurbo ?
945 */
946static const struct ath5k_ini_rfbuffer rfb_2425[] = {
947 { 1, 0x98d4,
948 /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
949 { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
950 { 2, 0x98d0,
951 { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } },
952 { 3, 0x98dc,
953 { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
954 { 6, 0x989c,
955 { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
956 { 6, 0x989c,
957 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
958 { 6, 0x989c,
959 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
960 { 6, 0x989c,
961 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
962 { 6, 0x989c,
963 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
964 { 6, 0x989c,
965 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
966 { 6, 0x989c,
967 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
968 { 6, 0x989c,
969 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
970 { 6, 0x989c,
971 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
972 { 6, 0x989c,
973 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
974 { 6, 0x989c,
975 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
976 { 6, 0x989c,
977 { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
978 { 6, 0x989c,
979 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
980 { 6, 0x989c,
981 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
982 { 6, 0x989c,
983 { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
984 { 6, 0x989c,
985 { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
986 { 6, 0x989c,
987 { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
988 { 6, 0x989c,
989 { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
990 { 6, 0x989c,
991 { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } },
992 { 6, 0x989c,
993 { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } },
994 { 6, 0x989c,
995 { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
996 { 6, 0x989c,
997 { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } },
998 { 6, 0x989c,
999 { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
1000 { 6, 0x989c,
1001 { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
1002 { 6, 0x989c,
1003 { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
1004 { 6, 0x989c,
1005 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1006 { 6, 0x989c,
1007 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1008 { 6, 0x989c,
1009 { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
1010 { 6, 0x989c,
1011 { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } },
1012 { 6, 0x98c4,
1013 { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
1014 { 7, 0x989c,
1015 { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
1016 { 7, 0x989c,
1017 { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
1018 { 7, 0x98cc,
1019 { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
1020};
1021
1022/*
1023 * TODO: Handle the few differences with swan during
1024 * bank modification and get rid of this
1025 */
1026static const struct ath5k_ini_rfbuffer rfb_2317[] = {
1027 { 1, 0x98d4,
1028 /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
1029 { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
1030 { 2, 0x98d0,
1031 { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
1032 { 3, 0x98dc,
1033 { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
1034 { 6, 0x989c,
1035 { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
1036 { 6, 0x989c,
1037 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1038 { 6, 0x989c,
1039 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1040 { 6, 0x989c,
1041 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1042 { 6, 0x989c,
1043 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1044 { 6, 0x989c,
1045 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1046 { 6, 0x989c,
1047 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1048 { 6, 0x989c,
1049 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1050 { 6, 0x989c,
1051 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1052 { 6, 0x989c,
1053 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1054 { 6, 0x989c,
1055 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1056 { 6, 0x989c,
1057 { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
1058 { 6, 0x989c,
1059 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1060 { 6, 0x989c,
1061 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1062 { 6, 0x989c,
1063 { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
1064 { 6, 0x989c,
1065 { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
1066 { 6, 0x989c,
1067 { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
1068 { 6, 0x989c,
1069 { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
1070 { 6, 0x989c,
1071 { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } },
1072 { 6, 0x989c,
1073 { 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 } },
1074 { 6, 0x989c,
1075 { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
1076 { 6, 0x989c,
1077 { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } },
1078 { 6, 0x989c,
1079 { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
1080 { 6, 0x989c,
1081 { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
1082 { 6, 0x989c,
1083 { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
1084 { 6, 0x989c,
1085 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1086 { 6, 0x989c,
1087 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1088 { 6, 0x989c,
1089 { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
1090 { 6, 0x989c,
1091 { 0x00009688, 0x00009688, 0x00009688, 0x00009688, 0x00009688 } },
1092 { 6, 0x98c4,
1093 { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
1094 { 7, 0x989c,
1095 { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
1096 { 7, 0x989c,
1097 { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
1098 { 7, 0x98cc,
1099 { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
1100};
1101
1102/*
1103 * TODO: Handle the few differences with swan during
1104 * bank modification and get rid of this
1105 * XXX: a/aTurbo ?
1106 */
1107static const struct ath5k_ini_rfbuffer rfb_2417[] = {
1108 { 1, 0x98d4,
1109 /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
1110 { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
1111 { 2, 0x98d0,
1112 { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } },
1113 { 3, 0x98dc,
1114 { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
1115 { 6, 0x989c,
1116 { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
1117 { 6, 0x989c,
1118 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1119 { 6, 0x989c,
1120 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1121 { 6, 0x989c,
1122 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1123 { 6, 0x989c,
1124 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1125 { 6, 0x989c,
1126 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1127 { 6, 0x989c,
1128 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1129 { 6, 0x989c,
1130 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1131 { 6, 0x989c,
1132 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1133 { 6, 0x989c,
1134 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1135 { 6, 0x989c,
1136 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1137 { 6, 0x989c,
1138 { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
1139 { 6, 0x989c,
1140 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1141 { 6, 0x989c,
1142 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1143 { 6, 0x989c,
1144 { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
1145 { 6, 0x989c,
1146 { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
1147 { 6, 0x989c,
1148 { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
1149 { 6, 0x989c,
1150 { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
1151 { 6, 0x989c,
1152 { 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 } },
1153 { 6, 0x989c,
1154 { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } },
1155 { 6, 0x989c,
1156 { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
1157 { 6, 0x989c,
1158 { 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a } },
1159 { 6, 0x989c,
1160 { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
1161 { 6, 0x989c,
1162 { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
1163 { 6, 0x989c,
1164 { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
1165 { 6, 0x989c,
1166 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1167 { 6, 0x989c,
1168 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
1169 { 6, 0x989c,
1170 { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
1171 { 6, 0x989c,
1172 { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } },
1173 { 6, 0x98c4,
1174 { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
1175 { 7, 0x989c,
1176 { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
1177 { 7, 0x989c,
1178 { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
1179 { 7, 0x98cc,
1180 { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
1181};
diff --git a/drivers/net/wireless/ath/ath5k/rfgain.h b/drivers/net/wireless/ath/ath5k/rfgain.h
new file mode 100644
index 000000000000..1354d8c392c8
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/rfgain.h
@@ -0,0 +1,516 @@
1/*
2 * RF Gain optimization
3 *
4 * Copyright (c) 2004-2009 Reyk Floeter <reyk@openbsd.org>
5 * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 */
20
21/*
22 * Mode-specific RF Gain table (64bytes) for RF5111/5112
23 * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial
24 * RF Gain values are included in AR5K_AR5210_INI)
25 */
26struct ath5k_ini_rfgain {
27 u16 rfg_register; /* RF Gain register address */
28 u32 rfg_value[2]; /* [freq (see below)] */
29};
30
31/* Initial RF Gain settings for RF5111 */
32static const struct ath5k_ini_rfgain rfgain_5111[] = {
33 /* 5Ghz 2Ghz */
34 { AR5K_RF_GAIN(0), { 0x000001a9, 0x00000000 } },
35 { AR5K_RF_GAIN(1), { 0x000001e9, 0x00000040 } },
36 { AR5K_RF_GAIN(2), { 0x00000029, 0x00000080 } },
37 { AR5K_RF_GAIN(3), { 0x00000069, 0x00000150 } },
38 { AR5K_RF_GAIN(4), { 0x00000199, 0x00000190 } },
39 { AR5K_RF_GAIN(5), { 0x000001d9, 0x000001d0 } },
40 { AR5K_RF_GAIN(6), { 0x00000019, 0x00000010 } },
41 { AR5K_RF_GAIN(7), { 0x00000059, 0x00000044 } },
42 { AR5K_RF_GAIN(8), { 0x00000099, 0x00000084 } },
43 { AR5K_RF_GAIN(9), { 0x000001a5, 0x00000148 } },
44 { AR5K_RF_GAIN(10), { 0x000001e5, 0x00000188 } },
45 { AR5K_RF_GAIN(11), { 0x00000025, 0x000001c8 } },
46 { AR5K_RF_GAIN(12), { 0x000001c8, 0x00000014 } },
47 { AR5K_RF_GAIN(13), { 0x00000008, 0x00000042 } },
48 { AR5K_RF_GAIN(14), { 0x00000048, 0x00000082 } },
49 { AR5K_RF_GAIN(15), { 0x00000088, 0x00000178 } },
50 { AR5K_RF_GAIN(16), { 0x00000198, 0x000001b8 } },
51 { AR5K_RF_GAIN(17), { 0x000001d8, 0x000001f8 } },
52 { AR5K_RF_GAIN(18), { 0x00000018, 0x00000012 } },
53 { AR5K_RF_GAIN(19), { 0x00000058, 0x00000052 } },
54 { AR5K_RF_GAIN(20), { 0x00000098, 0x00000092 } },
55 { AR5K_RF_GAIN(21), { 0x000001a4, 0x0000017c } },
56 { AR5K_RF_GAIN(22), { 0x000001e4, 0x000001bc } },
57 { AR5K_RF_GAIN(23), { 0x00000024, 0x000001fc } },
58 { AR5K_RF_GAIN(24), { 0x00000064, 0x0000000a } },
59 { AR5K_RF_GAIN(25), { 0x000000a4, 0x0000004a } },
60 { AR5K_RF_GAIN(26), { 0x000000e4, 0x0000008a } },
61 { AR5K_RF_GAIN(27), { 0x0000010a, 0x0000015a } },
62 { AR5K_RF_GAIN(28), { 0x0000014a, 0x0000019a } },
63 { AR5K_RF_GAIN(29), { 0x0000018a, 0x000001da } },
64 { AR5K_RF_GAIN(30), { 0x000001ca, 0x0000000e } },
65 { AR5K_RF_GAIN(31), { 0x0000000a, 0x0000004e } },
66 { AR5K_RF_GAIN(32), { 0x0000004a, 0x0000008e } },
67 { AR5K_RF_GAIN(33), { 0x0000008a, 0x0000015e } },
68 { AR5K_RF_GAIN(34), { 0x000001ba, 0x0000019e } },
69 { AR5K_RF_GAIN(35), { 0x000001fa, 0x000001de } },
70 { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000009 } },
71 { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000049 } },
72 { AR5K_RF_GAIN(38), { 0x00000186, 0x00000089 } },
73 { AR5K_RF_GAIN(39), { 0x000001c6, 0x00000179 } },
74 { AR5K_RF_GAIN(40), { 0x00000006, 0x000001b9 } },
75 { AR5K_RF_GAIN(41), { 0x00000046, 0x000001f9 } },
76 { AR5K_RF_GAIN(42), { 0x00000086, 0x00000039 } },
77 { AR5K_RF_GAIN(43), { 0x000000c6, 0x00000079 } },
78 { AR5K_RF_GAIN(44), { 0x000000c6, 0x000000b9 } },
79 { AR5K_RF_GAIN(45), { 0x000000c6, 0x000001bd } },
80 { AR5K_RF_GAIN(46), { 0x000000c6, 0x000001fd } },
81 { AR5K_RF_GAIN(47), { 0x000000c6, 0x0000003d } },
82 { AR5K_RF_GAIN(48), { 0x000000c6, 0x0000007d } },
83 { AR5K_RF_GAIN(49), { 0x000000c6, 0x000000bd } },
84 { AR5K_RF_GAIN(50), { 0x000000c6, 0x000000fd } },
85 { AR5K_RF_GAIN(51), { 0x000000c6, 0x000000fd } },
86 { AR5K_RF_GAIN(52), { 0x000000c6, 0x000000fd } },
87 { AR5K_RF_GAIN(53), { 0x000000c6, 0x000000fd } },
88 { AR5K_RF_GAIN(54), { 0x000000c6, 0x000000fd } },
89 { AR5K_RF_GAIN(55), { 0x000000c6, 0x000000fd } },
90 { AR5K_RF_GAIN(56), { 0x000000c6, 0x000000fd } },
91 { AR5K_RF_GAIN(57), { 0x000000c6, 0x000000fd } },
92 { AR5K_RF_GAIN(58), { 0x000000c6, 0x000000fd } },
93 { AR5K_RF_GAIN(59), { 0x000000c6, 0x000000fd } },
94 { AR5K_RF_GAIN(60), { 0x000000c6, 0x000000fd } },
95 { AR5K_RF_GAIN(61), { 0x000000c6, 0x000000fd } },
96 { AR5K_RF_GAIN(62), { 0x000000c6, 0x000000fd } },
97 { AR5K_RF_GAIN(63), { 0x000000c6, 0x000000fd } },
98};
99
100/* Initial RF Gain settings for RF5112 */
101static const struct ath5k_ini_rfgain rfgain_5112[] = {
102 /* 5Ghz 2Ghz */
103 { AR5K_RF_GAIN(0), { 0x00000007, 0x00000007 } },
104 { AR5K_RF_GAIN(1), { 0x00000047, 0x00000047 } },
105 { AR5K_RF_GAIN(2), { 0x00000087, 0x00000087 } },
106 { AR5K_RF_GAIN(3), { 0x000001a0, 0x000001a0 } },
107 { AR5K_RF_GAIN(4), { 0x000001e0, 0x000001e0 } },
108 { AR5K_RF_GAIN(5), { 0x00000020, 0x00000020 } },
109 { AR5K_RF_GAIN(6), { 0x00000060, 0x00000060 } },
110 { AR5K_RF_GAIN(7), { 0x000001a1, 0x000001a1 } },
111 { AR5K_RF_GAIN(8), { 0x000001e1, 0x000001e1 } },
112 { AR5K_RF_GAIN(9), { 0x00000021, 0x00000021 } },
113 { AR5K_RF_GAIN(10), { 0x00000061, 0x00000061 } },
114 { AR5K_RF_GAIN(11), { 0x00000162, 0x00000162 } },
115 { AR5K_RF_GAIN(12), { 0x000001a2, 0x000001a2 } },
116 { AR5K_RF_GAIN(13), { 0x000001e2, 0x000001e2 } },
117 { AR5K_RF_GAIN(14), { 0x00000022, 0x00000022 } },
118 { AR5K_RF_GAIN(15), { 0x00000062, 0x00000062 } },
119 { AR5K_RF_GAIN(16), { 0x00000163, 0x00000163 } },
120 { AR5K_RF_GAIN(17), { 0x000001a3, 0x000001a3 } },
121 { AR5K_RF_GAIN(18), { 0x000001e3, 0x000001e3 } },
122 { AR5K_RF_GAIN(19), { 0x00000023, 0x00000023 } },
123 { AR5K_RF_GAIN(20), { 0x00000063, 0x00000063 } },
124 { AR5K_RF_GAIN(21), { 0x00000184, 0x00000184 } },
125 { AR5K_RF_GAIN(22), { 0x000001c4, 0x000001c4 } },
126 { AR5K_RF_GAIN(23), { 0x00000004, 0x00000004 } },
127 { AR5K_RF_GAIN(24), { 0x000001ea, 0x0000000b } },
128 { AR5K_RF_GAIN(25), { 0x0000002a, 0x0000004b } },
129 { AR5K_RF_GAIN(26), { 0x0000006a, 0x0000008b } },
130 { AR5K_RF_GAIN(27), { 0x000000aa, 0x000001ac } },
131 { AR5K_RF_GAIN(28), { 0x000001ab, 0x000001ec } },
132 { AR5K_RF_GAIN(29), { 0x000001eb, 0x0000002c } },
133 { AR5K_RF_GAIN(30), { 0x0000002b, 0x00000012 } },
134 { AR5K_RF_GAIN(31), { 0x0000006b, 0x00000052 } },
135 { AR5K_RF_GAIN(32), { 0x000000ab, 0x00000092 } },
136 { AR5K_RF_GAIN(33), { 0x000001ac, 0x00000193 } },
137 { AR5K_RF_GAIN(34), { 0x000001ec, 0x000001d3 } },
138 { AR5K_RF_GAIN(35), { 0x0000002c, 0x00000013 } },
139 { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000053 } },
140 { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000093 } },
141 { AR5K_RF_GAIN(38), { 0x000000ba, 0x00000194 } },
142 { AR5K_RF_GAIN(39), { 0x000001bb, 0x000001d4 } },
143 { AR5K_RF_GAIN(40), { 0x000001fb, 0x00000014 } },
144 { AR5K_RF_GAIN(41), { 0x0000003b, 0x0000003a } },
145 { AR5K_RF_GAIN(42), { 0x0000007b, 0x0000007a } },
146 { AR5K_RF_GAIN(43), { 0x000000bb, 0x000000ba } },
147 { AR5K_RF_GAIN(44), { 0x000001bc, 0x000001bb } },
148 { AR5K_RF_GAIN(45), { 0x000001fc, 0x000001fb } },
149 { AR5K_RF_GAIN(46), { 0x0000003c, 0x0000003b } },
150 { AR5K_RF_GAIN(47), { 0x0000007c, 0x0000007b } },
151 { AR5K_RF_GAIN(48), { 0x000000bc, 0x000000bb } },
152 { AR5K_RF_GAIN(49), { 0x000000fc, 0x000001bc } },
153 { AR5K_RF_GAIN(50), { 0x000000fc, 0x000001fc } },
154 { AR5K_RF_GAIN(51), { 0x000000fc, 0x0000003c } },
155 { AR5K_RF_GAIN(52), { 0x000000fc, 0x0000007c } },
156 { AR5K_RF_GAIN(53), { 0x000000fc, 0x000000bc } },
157 { AR5K_RF_GAIN(54), { 0x000000fc, 0x000000fc } },
158 { AR5K_RF_GAIN(55), { 0x000000fc, 0x000000fc } },
159 { AR5K_RF_GAIN(56), { 0x000000fc, 0x000000fc } },
160 { AR5K_RF_GAIN(57), { 0x000000fc, 0x000000fc } },
161 { AR5K_RF_GAIN(58), { 0x000000fc, 0x000000fc } },
162 { AR5K_RF_GAIN(59), { 0x000000fc, 0x000000fc } },
163 { AR5K_RF_GAIN(60), { 0x000000fc, 0x000000fc } },
164 { AR5K_RF_GAIN(61), { 0x000000fc, 0x000000fc } },
165 { AR5K_RF_GAIN(62), { 0x000000fc, 0x000000fc } },
166 { AR5K_RF_GAIN(63), { 0x000000fc, 0x000000fc } },
167};
168
169/* Initial RF Gain settings for RF2413 */
170static const struct ath5k_ini_rfgain rfgain_2413[] = {
171 { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
172 { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } },
173 { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } },
174 { AR5K_RF_GAIN(3), { 0x00000000, 0x00000181 } },
175 { AR5K_RF_GAIN(4), { 0x00000000, 0x000001c1 } },
176 { AR5K_RF_GAIN(5), { 0x00000000, 0x00000001 } },
177 { AR5K_RF_GAIN(6), { 0x00000000, 0x00000041 } },
178 { AR5K_RF_GAIN(7), { 0x00000000, 0x00000081 } },
179 { AR5K_RF_GAIN(8), { 0x00000000, 0x00000168 } },
180 { AR5K_RF_GAIN(9), { 0x00000000, 0x000001a8 } },
181 { AR5K_RF_GAIN(10), { 0x00000000, 0x000001e8 } },
182 { AR5K_RF_GAIN(11), { 0x00000000, 0x00000028 } },
183 { AR5K_RF_GAIN(12), { 0x00000000, 0x00000068 } },
184 { AR5K_RF_GAIN(13), { 0x00000000, 0x00000189 } },
185 { AR5K_RF_GAIN(14), { 0x00000000, 0x000001c9 } },
186 { AR5K_RF_GAIN(15), { 0x00000000, 0x00000009 } },
187 { AR5K_RF_GAIN(16), { 0x00000000, 0x00000049 } },
188 { AR5K_RF_GAIN(17), { 0x00000000, 0x00000089 } },
189 { AR5K_RF_GAIN(18), { 0x00000000, 0x00000190 } },
190 { AR5K_RF_GAIN(19), { 0x00000000, 0x000001d0 } },
191 { AR5K_RF_GAIN(20), { 0x00000000, 0x00000010 } },
192 { AR5K_RF_GAIN(21), { 0x00000000, 0x00000050 } },
193 { AR5K_RF_GAIN(22), { 0x00000000, 0x00000090 } },
194 { AR5K_RF_GAIN(23), { 0x00000000, 0x00000191 } },
195 { AR5K_RF_GAIN(24), { 0x00000000, 0x000001d1 } },
196 { AR5K_RF_GAIN(25), { 0x00000000, 0x00000011 } },
197 { AR5K_RF_GAIN(26), { 0x00000000, 0x00000051 } },
198 { AR5K_RF_GAIN(27), { 0x00000000, 0x00000091 } },
199 { AR5K_RF_GAIN(28), { 0x00000000, 0x00000178 } },
200 { AR5K_RF_GAIN(29), { 0x00000000, 0x000001b8 } },
201 { AR5K_RF_GAIN(30), { 0x00000000, 0x000001f8 } },
202 { AR5K_RF_GAIN(31), { 0x00000000, 0x00000038 } },
203 { AR5K_RF_GAIN(32), { 0x00000000, 0x00000078 } },
204 { AR5K_RF_GAIN(33), { 0x00000000, 0x00000199 } },
205 { AR5K_RF_GAIN(34), { 0x00000000, 0x000001d9 } },
206 { AR5K_RF_GAIN(35), { 0x00000000, 0x00000019 } },
207 { AR5K_RF_GAIN(36), { 0x00000000, 0x00000059 } },
208 { AR5K_RF_GAIN(37), { 0x00000000, 0x00000099 } },
209 { AR5K_RF_GAIN(38), { 0x00000000, 0x000000d9 } },
210 { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f9 } },
211 { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f9 } },
212 { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f9 } },
213 { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f9 } },
214 { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f9 } },
215 { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f9 } },
216 { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f9 } },
217 { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f9 } },
218 { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f9 } },
219 { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f9 } },
220 { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f9 } },
221 { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f9 } },
222 { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f9 } },
223 { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f9 } },
224 { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f9 } },
225 { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f9 } },
226 { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f9 } },
227 { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f9 } },
228 { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f9 } },
229 { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f9 } },
230 { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f9 } },
231 { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f9 } },
232 { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f9 } },
233 { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f9 } },
234 { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f9 } },
235};
236
237/* Initial RF Gain settings for AR2316 */
238static const struct ath5k_ini_rfgain rfgain_2316[] = {
239 { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
240 { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } },
241 { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } },
242 { AR5K_RF_GAIN(3), { 0x00000000, 0x000000c0 } },
243 { AR5K_RF_GAIN(4), { 0x00000000, 0x000000e0 } },
244 { AR5K_RF_GAIN(5), { 0x00000000, 0x000000e0 } },
245 { AR5K_RF_GAIN(6), { 0x00000000, 0x00000128 } },
246 { AR5K_RF_GAIN(7), { 0x00000000, 0x00000128 } },
247 { AR5K_RF_GAIN(8), { 0x00000000, 0x00000128 } },
248 { AR5K_RF_GAIN(9), { 0x00000000, 0x00000168 } },
249 { AR5K_RF_GAIN(10), { 0x00000000, 0x000001a8 } },
250 { AR5K_RF_GAIN(11), { 0x00000000, 0x000001e8 } },
251 { AR5K_RF_GAIN(12), { 0x00000000, 0x00000028 } },
252 { AR5K_RF_GAIN(13), { 0x00000000, 0x00000068 } },
253 { AR5K_RF_GAIN(14), { 0x00000000, 0x000000a8 } },
254 { AR5K_RF_GAIN(15), { 0x00000000, 0x000000e8 } },
255 { AR5K_RF_GAIN(16), { 0x00000000, 0x000000e8 } },
256 { AR5K_RF_GAIN(17), { 0x00000000, 0x00000130 } },
257 { AR5K_RF_GAIN(18), { 0x00000000, 0x00000130 } },
258 { AR5K_RF_GAIN(19), { 0x00000000, 0x00000170 } },
259 { AR5K_RF_GAIN(20), { 0x00000000, 0x000001b0 } },
260 { AR5K_RF_GAIN(21), { 0x00000000, 0x000001f0 } },
261 { AR5K_RF_GAIN(22), { 0x00000000, 0x00000030 } },
262 { AR5K_RF_GAIN(23), { 0x00000000, 0x00000070 } },
263 { AR5K_RF_GAIN(24), { 0x00000000, 0x000000b0 } },
264 { AR5K_RF_GAIN(25), { 0x00000000, 0x000000f0 } },
265 { AR5K_RF_GAIN(26), { 0x00000000, 0x000000f0 } },
266 { AR5K_RF_GAIN(27), { 0x00000000, 0x000000f0 } },
267 { AR5K_RF_GAIN(28), { 0x00000000, 0x000000f0 } },
268 { AR5K_RF_GAIN(29), { 0x00000000, 0x000000f0 } },
269 { AR5K_RF_GAIN(30), { 0x00000000, 0x000000f0 } },
270 { AR5K_RF_GAIN(31), { 0x00000000, 0x000000f0 } },
271 { AR5K_RF_GAIN(32), { 0x00000000, 0x000000f0 } },
272 { AR5K_RF_GAIN(33), { 0x00000000, 0x000000f0 } },
273 { AR5K_RF_GAIN(34), { 0x00000000, 0x000000f0 } },
274 { AR5K_RF_GAIN(35), { 0x00000000, 0x000000f0 } },
275 { AR5K_RF_GAIN(36), { 0x00000000, 0x000000f0 } },
276 { AR5K_RF_GAIN(37), { 0x00000000, 0x000000f0 } },
277 { AR5K_RF_GAIN(38), { 0x00000000, 0x000000f0 } },
278 { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f0 } },
279 { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f0 } },
280 { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f0 } },
281 { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f0 } },
282 { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f0 } },
283 { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f0 } },
284 { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f0 } },
285 { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f0 } },
286 { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f0 } },
287 { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f0 } },
288 { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f0 } },
289 { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f0 } },
290 { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f0 } },
291 { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f0 } },
292 { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f0 } },
293 { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f0 } },
294 { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f0 } },
295 { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f0 } },
296 { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f0 } },
297 { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f0 } },
298 { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f0 } },
299 { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f0 } },
300 { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f0 } },
301 { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f0 } },
302 { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f0 } },
303};
304
305
306/* Initial RF Gain settings for RF5413 */
307static const struct ath5k_ini_rfgain rfgain_5413[] = {
308 /* 5Ghz 2Ghz */
309 { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
310 { AR5K_RF_GAIN(1), { 0x00000040, 0x00000040 } },
311 { AR5K_RF_GAIN(2), { 0x00000080, 0x00000080 } },
312 { AR5K_RF_GAIN(3), { 0x000001a1, 0x00000161 } },
313 { AR5K_RF_GAIN(4), { 0x000001e1, 0x000001a1 } },
314 { AR5K_RF_GAIN(5), { 0x00000021, 0x000001e1 } },
315 { AR5K_RF_GAIN(6), { 0x00000061, 0x00000021 } },
316 { AR5K_RF_GAIN(7), { 0x00000188, 0x00000061 } },
317 { AR5K_RF_GAIN(8), { 0x000001c8, 0x00000188 } },
318 { AR5K_RF_GAIN(9), { 0x00000008, 0x000001c8 } },
319 { AR5K_RF_GAIN(10), { 0x00000048, 0x00000008 } },
320 { AR5K_RF_GAIN(11), { 0x00000088, 0x00000048 } },
321 { AR5K_RF_GAIN(12), { 0x000001a9, 0x00000088 } },
322 { AR5K_RF_GAIN(13), { 0x000001e9, 0x00000169 } },
323 { AR5K_RF_GAIN(14), { 0x00000029, 0x000001a9 } },
324 { AR5K_RF_GAIN(15), { 0x00000069, 0x000001e9 } },
325 { AR5K_RF_GAIN(16), { 0x000001d0, 0x00000029 } },
326 { AR5K_RF_GAIN(17), { 0x00000010, 0x00000069 } },
327 { AR5K_RF_GAIN(18), { 0x00000050, 0x00000190 } },
328 { AR5K_RF_GAIN(19), { 0x00000090, 0x000001d0 } },
329 { AR5K_RF_GAIN(20), { 0x000001b1, 0x00000010 } },
330 { AR5K_RF_GAIN(21), { 0x000001f1, 0x00000050 } },
331 { AR5K_RF_GAIN(22), { 0x00000031, 0x00000090 } },
332 { AR5K_RF_GAIN(23), { 0x00000071, 0x00000171 } },
333 { AR5K_RF_GAIN(24), { 0x000001b8, 0x000001b1 } },
334 { AR5K_RF_GAIN(25), { 0x000001f8, 0x000001f1 } },
335 { AR5K_RF_GAIN(26), { 0x00000038, 0x00000031 } },
336 { AR5K_RF_GAIN(27), { 0x00000078, 0x00000071 } },
337 { AR5K_RF_GAIN(28), { 0x00000199, 0x00000198 } },
338 { AR5K_RF_GAIN(29), { 0x000001d9, 0x000001d8 } },
339 { AR5K_RF_GAIN(30), { 0x00000019, 0x00000018 } },
340 { AR5K_RF_GAIN(31), { 0x00000059, 0x00000058 } },
341 { AR5K_RF_GAIN(32), { 0x00000099, 0x00000098 } },
342 { AR5K_RF_GAIN(33), { 0x000000d9, 0x00000179 } },
343 { AR5K_RF_GAIN(34), { 0x000000f9, 0x000001b9 } },
344 { AR5K_RF_GAIN(35), { 0x000000f9, 0x000001f9 } },
345 { AR5K_RF_GAIN(36), { 0x000000f9, 0x00000039 } },
346 { AR5K_RF_GAIN(37), { 0x000000f9, 0x00000079 } },
347 { AR5K_RF_GAIN(38), { 0x000000f9, 0x000000b9 } },
348 { AR5K_RF_GAIN(39), { 0x000000f9, 0x000000f9 } },
349 { AR5K_RF_GAIN(40), { 0x000000f9, 0x000000f9 } },
350 { AR5K_RF_GAIN(41), { 0x000000f9, 0x000000f9 } },
351 { AR5K_RF_GAIN(42), { 0x000000f9, 0x000000f9 } },
352 { AR5K_RF_GAIN(43), { 0x000000f9, 0x000000f9 } },
353 { AR5K_RF_GAIN(44), { 0x000000f9, 0x000000f9 } },
354 { AR5K_RF_GAIN(45), { 0x000000f9, 0x000000f9 } },
355 { AR5K_RF_GAIN(46), { 0x000000f9, 0x000000f9 } },
356 { AR5K_RF_GAIN(47), { 0x000000f9, 0x000000f9 } },
357 { AR5K_RF_GAIN(48), { 0x000000f9, 0x000000f9 } },
358 { AR5K_RF_GAIN(49), { 0x000000f9, 0x000000f9 } },
359 { AR5K_RF_GAIN(50), { 0x000000f9, 0x000000f9 } },
360 { AR5K_RF_GAIN(51), { 0x000000f9, 0x000000f9 } },
361 { AR5K_RF_GAIN(52), { 0x000000f9, 0x000000f9 } },
362 { AR5K_RF_GAIN(53), { 0x000000f9, 0x000000f9 } },
363 { AR5K_RF_GAIN(54), { 0x000000f9, 0x000000f9 } },
364 { AR5K_RF_GAIN(55), { 0x000000f9, 0x000000f9 } },
365 { AR5K_RF_GAIN(56), { 0x000000f9, 0x000000f9 } },
366 { AR5K_RF_GAIN(57), { 0x000000f9, 0x000000f9 } },
367 { AR5K_RF_GAIN(58), { 0x000000f9, 0x000000f9 } },
368 { AR5K_RF_GAIN(59), { 0x000000f9, 0x000000f9 } },
369 { AR5K_RF_GAIN(60), { 0x000000f9, 0x000000f9 } },
370 { AR5K_RF_GAIN(61), { 0x000000f9, 0x000000f9 } },
371 { AR5K_RF_GAIN(62), { 0x000000f9, 0x000000f9 } },
372 { AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } },
373};
374
375
376/* Initial RF Gain settings for RF2425 */
377static const struct ath5k_ini_rfgain rfgain_2425[] = {
378 { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
379 { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } },
380 { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } },
381 { AR5K_RF_GAIN(3), { 0x00000000, 0x00000181 } },
382 { AR5K_RF_GAIN(4), { 0x00000000, 0x000001c1 } },
383 { AR5K_RF_GAIN(5), { 0x00000000, 0x00000001 } },
384 { AR5K_RF_GAIN(6), { 0x00000000, 0x00000041 } },
385 { AR5K_RF_GAIN(7), { 0x00000000, 0x00000081 } },
386 { AR5K_RF_GAIN(8), { 0x00000000, 0x00000188 } },
387 { AR5K_RF_GAIN(9), { 0x00000000, 0x000001c8 } },
388 { AR5K_RF_GAIN(10), { 0x00000000, 0x00000008 } },
389 { AR5K_RF_GAIN(11), { 0x00000000, 0x00000048 } },
390 { AR5K_RF_GAIN(12), { 0x00000000, 0x00000088 } },
391 { AR5K_RF_GAIN(13), { 0x00000000, 0x00000189 } },
392 { AR5K_RF_GAIN(14), { 0x00000000, 0x000001c9 } },
393 { AR5K_RF_GAIN(15), { 0x00000000, 0x00000009 } },
394 { AR5K_RF_GAIN(16), { 0x00000000, 0x00000049 } },
395 { AR5K_RF_GAIN(17), { 0x00000000, 0x00000089 } },
396 { AR5K_RF_GAIN(18), { 0x00000000, 0x000001b0 } },
397 { AR5K_RF_GAIN(19), { 0x00000000, 0x000001f0 } },
398 { AR5K_RF_GAIN(20), { 0x00000000, 0x00000030 } },
399 { AR5K_RF_GAIN(21), { 0x00000000, 0x00000070 } },
400 { AR5K_RF_GAIN(22), { 0x00000000, 0x00000171 } },
401 { AR5K_RF_GAIN(23), { 0x00000000, 0x000001b1 } },
402 { AR5K_RF_GAIN(24), { 0x00000000, 0x000001f1 } },
403 { AR5K_RF_GAIN(25), { 0x00000000, 0x00000031 } },
404 { AR5K_RF_GAIN(26), { 0x00000000, 0x00000071 } },
405 { AR5K_RF_GAIN(27), { 0x00000000, 0x000001b8 } },
406 { AR5K_RF_GAIN(28), { 0x00000000, 0x000001f8 } },
407 { AR5K_RF_GAIN(29), { 0x00000000, 0x00000038 } },
408 { AR5K_RF_GAIN(30), { 0x00000000, 0x00000078 } },
409 { AR5K_RF_GAIN(31), { 0x00000000, 0x000000b8 } },
410 { AR5K_RF_GAIN(32), { 0x00000000, 0x000001b9 } },
411 { AR5K_RF_GAIN(33), { 0x00000000, 0x000001f9 } },
412 { AR5K_RF_GAIN(34), { 0x00000000, 0x00000039 } },
413 { AR5K_RF_GAIN(35), { 0x00000000, 0x00000079 } },
414 { AR5K_RF_GAIN(36), { 0x00000000, 0x000000b9 } },
415 { AR5K_RF_GAIN(37), { 0x00000000, 0x000000f9 } },
416 { AR5K_RF_GAIN(38), { 0x00000000, 0x000000f9 } },
417 { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f9 } },
418 { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f9 } },
419 { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f9 } },
420 { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f9 } },
421 { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f9 } },
422 { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f9 } },
423 { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f9 } },
424 { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f9 } },
425 { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f9 } },
426 { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f9 } },
427 { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f9 } },
428 { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f9 } },
429 { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f9 } },
430 { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f9 } },
431 { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f9 } },
432 { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f9 } },
433 { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f9 } },
434 { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f9 } },
435 { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f9 } },
436 { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f9 } },
437 { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f9 } },
438 { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f9 } },
439 { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f9 } },
440 { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f9 } },
441 { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f9 } },
442};
443
444#define AR5K_GAIN_CRN_FIX_BITS_5111 4
445#define AR5K_GAIN_CRN_FIX_BITS_5112 7
446#define AR5K_GAIN_CRN_MAX_FIX_BITS AR5K_GAIN_CRN_FIX_BITS_5112
447#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN 15
448#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN 20
449#define AR5K_GAIN_CCK_PROBE_CORR 5
450#define AR5K_GAIN_CCK_OFDM_GAIN_DELTA 15
451#define AR5K_GAIN_STEP_COUNT 10
452
453/* Check if our current measurement is inside our
454 * current variable attenuation window */
455#define AR5K_GAIN_CHECK_ADJUST(_g) \
456 ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
457
458struct ath5k_gain_opt_step {
459 s8 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS];
460 s8 gos_gain;
461};
462
463struct ath5k_gain_opt {
464 u8 go_default;
465 u8 go_steps_count;
466 const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT];
467};
468
469/*
470 * Parameters on gos_param:
471 * 1) Tx clip PHY register
472 * 2) PWD 90 RF register
473 * 3) PWD 84 RF register
474 * 4) RFGainSel RF register
475 */
476static const struct ath5k_gain_opt rfgain_opt_5111 = {
477 4,
478 9,
479 {
480 { { 4, 1, 1, 1 }, 6 },
481 { { 4, 0, 1, 1 }, 4 },
482 { { 3, 1, 1, 1 }, 3 },
483 { { 4, 0, 0, 1 }, 1 },
484 { { 4, 1, 1, 0 }, 0 },
485 { { 4, 0, 1, 0 }, -2 },
486 { { 3, 1, 1, 0 }, -3 },
487 { { 4, 0, 0, 0 }, -4 },
488 { { 2, 1, 1, 0 }, -6 }
489 }
490};
491
492/*
493 * Parameters on gos_param:
494 * 1) Mixgain ovr RF register
495 * 2) PWD 138 RF register
496 * 3) PWD 137 RF register
497 * 4) PWD 136 RF register
498 * 5) PWD 132 RF register
499 * 6) PWD 131 RF register
500 * 7) PWD 130 RF register
501 */
502static const struct ath5k_gain_opt rfgain_opt_5112 = {
503 1,
504 8,
505 {
506 { { 3, 0, 0, 0, 0, 0, 0 }, 6 },
507 { { 2, 0, 0, 0, 0, 0, 0 }, 0 },
508 { { 1, 0, 0, 0, 0, 0, 0 }, -3 },
509 { { 0, 0, 0, 0, 0, 0, 0 }, -6 },
510 { { 0, 1, 1, 0, 0, 0, 0 }, -8 },
511 { { 0, 1, 1, 0, 1, 1, 0 }, -10 },
512 { { 0, 1, 0, 1, 1, 1, 0 }, -13 },
513 { { 0, 1, 0, 1, 1, 0, 1 }, -16 },
514 }
515};
516
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
new file mode 100644
index 000000000000..0ed1ac312aa6
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -0,0 +1,24 @@
1config ATH9K
2 tristate "Atheros 802.11n wireless cards support"
3 depends on PCI && MAC80211 && WLAN_80211
4 depends on RFKILL || RFKILL=n
5 select ATH_COMMON
6 select MAC80211_LEDS
7 select LEDS_CLASS
8 select NEW_LEDS
9 ---help---
10 This module adds support for wireless adapters based on
11 Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets.
12
13 If you choose to build a module, it'll be called ath9k.
14
15config ATH9K_DEBUG
16 bool "Atheros ath9k debugging"
17 depends on ATH9K
18 ---help---
19 Say Y, if you need ath9k to display debug messages.
20 Pass the debug mask as a module parameter:
21
22 modprobe ath9k debug=0x00002000
23
24 Look in ath9k/core.h for possible debug masks
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
new file mode 100644
index 000000000000..783bc39eb2ff
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -0,0 +1,18 @@
1ath9k-y += hw.o \
2 eeprom.o \
3 mac.o \
4 calib.o \
5 ani.o \
6 phy.o \
7 beacon.o \
8 main.o \
9 recv.o \
10 xmit.o \
11 virtual.o \
12 rc.o
13
14ath9k-$(CONFIG_PCI) += pci.o
15ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
16ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o
17
18obj-$(CONFIG_ATH9K) += ath9k.o
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
new file mode 100644
index 000000000000..0e65c51ba176
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -0,0 +1,192 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
4 * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <linux/nl80211.h>
20#include <linux/platform_device.h>
21#include <linux/ath9k_platform.h>
22#include "ath9k.h"
23
24/* return bus cachesize in 4B word units */
25static void ath_ahb_read_cachesize(struct ath_softc *sc, int *csz)
26{
27 *csz = L1_CACHE_BYTES >> 2;
28}
29
30static void ath_ahb_cleanup(struct ath_softc *sc)
31{
32 iounmap(sc->mem);
33}
34
35static bool ath_ahb_eeprom_read(struct ath_hw *ah, u32 off, u16 *data)
36{
37 struct ath_softc *sc = ah->ah_sc;
38 struct platform_device *pdev = to_platform_device(sc->dev);
39 struct ath9k_platform_data *pdata;
40
41 pdata = (struct ath9k_platform_data *) pdev->dev.platform_data;
42 if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
43 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
44 "%s: flash read failed, offset %08x is out of range\n",
45 __func__, off);
46 return false;
47 }
48
49 *data = pdata->eeprom_data[off];
50 return true;
51}
52
53static struct ath_bus_ops ath_ahb_bus_ops = {
54 .read_cachesize = ath_ahb_read_cachesize,
55 .cleanup = ath_ahb_cleanup,
56
57 .eeprom_read = ath_ahb_eeprom_read,
58};
59
60static int ath_ahb_probe(struct platform_device *pdev)
61{
62 void __iomem *mem;
63 struct ath_wiphy *aphy;
64 struct ath_softc *sc;
65 struct ieee80211_hw *hw;
66 struct resource *res;
67 int irq;
68 int ret = 0;
69 struct ath_hw *ah;
70
71 if (!pdev->dev.platform_data) {
72 dev_err(&pdev->dev, "no platform data specified\n");
73 ret = -EINVAL;
74 goto err_out;
75 }
76
77 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
78 if (res == NULL) {
79 dev_err(&pdev->dev, "no memory resource found\n");
80 ret = -ENXIO;
81 goto err_out;
82 }
83
84 mem = ioremap_nocache(res->start, res->end - res->start + 1);
85 if (mem == NULL) {
86 dev_err(&pdev->dev, "ioremap failed\n");
87 ret = -ENOMEM;
88 goto err_out;
89 }
90
91 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
92 if (res == NULL) {
93 dev_err(&pdev->dev, "no IRQ resource found\n");
94 ret = -ENXIO;
95 goto err_iounmap;
96 }
97
98 irq = res->start;
99
100 hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) +
101 sizeof(struct ath_softc), &ath9k_ops);
102 if (hw == NULL) {
103 dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
104 ret = -ENOMEM;
105 goto err_iounmap;
106 }
107
108 SET_IEEE80211_DEV(hw, &pdev->dev);
109 platform_set_drvdata(pdev, hw);
110
111 aphy = hw->priv;
112 sc = (struct ath_softc *) (aphy + 1);
113 aphy->sc = sc;
114 aphy->hw = hw;
115 sc->pri_wiphy = aphy;
116 sc->hw = hw;
117 sc->dev = &pdev->dev;
118 sc->mem = mem;
119 sc->bus_ops = &ath_ahb_bus_ops;
120 sc->irq = irq;
121
122 ret = ath_attach(AR5416_AR9100_DEVID, sc);
123 if (ret != 0) {
124 dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
125 ret = -ENODEV;
126 goto err_free_hw;
127 }
128
129 ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
130 if (ret) {
131 dev_err(&pdev->dev, "request_irq failed, err=%d\n", ret);
132 ret = -EIO;
133 goto err_detach;
134 }
135
136 ah = sc->sc_ah;
137 printk(KERN_INFO
138 "%s: Atheros AR%s MAC/BB Rev:%x, "
139 "AR%s RF Rev:%x, mem=0x%lx, irq=%d\n",
140 wiphy_name(hw->wiphy),
141 ath_mac_bb_name(ah->hw_version.macVersion),
142 ah->hw_version.macRev,
143 ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)),
144 ah->hw_version.phyRev,
145 (unsigned long)mem, irq);
146
147 return 0;
148
149 err_detach:
150 ath_detach(sc);
151 err_free_hw:
152 ieee80211_free_hw(hw);
153 platform_set_drvdata(pdev, NULL);
154 err_iounmap:
155 iounmap(mem);
156 err_out:
157 return ret;
158}
159
160static int ath_ahb_remove(struct platform_device *pdev)
161{
162 struct ieee80211_hw *hw = platform_get_drvdata(pdev);
163
164 if (hw) {
165 struct ath_wiphy *aphy = hw->priv;
166 struct ath_softc *sc = aphy->sc;
167
168 ath_cleanup(sc);
169 platform_set_drvdata(pdev, NULL);
170 }
171
172 return 0;
173}
174
175static struct platform_driver ath_ahb_driver = {
176 .probe = ath_ahb_probe,
177 .remove = ath_ahb_remove,
178 .driver = {
179 .name = "ath9k",
180 .owner = THIS_MODULE,
181 },
182};
183
184int ath_ahb_init(void)
185{
186 return platform_driver_register(&ath_ahb_driver);
187}
188
189void ath_ahb_exit(void)
190{
191 platform_driver_unregister(&ath_ahb_driver);
192}
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
new file mode 100644
index 000000000000..1aeafb511ddd
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -0,0 +1,822 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "ath9k.h"
18
19static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
20 struct ath9k_channel *chan)
21{
22 int i;
23
24 for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
25 if (ah->ani[i].c &&
26 ah->ani[i].c->channel == chan->channel)
27 return i;
28 if (ah->ani[i].c == NULL) {
29 ah->ani[i].c = chan;
30 return i;
31 }
32 }
33
34 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
35 "No more channel states left. Using channel 0\n");
36
37 return 0;
38}
39
40static bool ath9k_hw_ani_control(struct ath_hw *ah,
41 enum ath9k_ani_cmd cmd, int param)
42{
43 struct ar5416AniState *aniState = ah->curani;
44
45 switch (cmd & ah->ani_function) {
46 case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
47 u32 level = param;
48
49 if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
50 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
51 "level out of range (%u > %u)\n",
52 level,
53 (unsigned)ARRAY_SIZE(ah->totalSizeDesired));
54 return false;
55 }
56
57 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
58 AR_PHY_DESIRED_SZ_TOT_DES,
59 ah->totalSizeDesired[level]);
60 REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
61 AR_PHY_AGC_CTL1_COARSE_LOW,
62 ah->coarse_low[level]);
63 REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
64 AR_PHY_AGC_CTL1_COARSE_HIGH,
65 ah->coarse_high[level]);
66 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
67 AR_PHY_FIND_SIG_FIRPWR,
68 ah->firpwr[level]);
69
70 if (level > aniState->noiseImmunityLevel)
71 ah->stats.ast_ani_niup++;
72 else if (level < aniState->noiseImmunityLevel)
73 ah->stats.ast_ani_nidown++;
74 aniState->noiseImmunityLevel = level;
75 break;
76 }
77 case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
78 const int m1ThreshLow[] = { 127, 50 };
79 const int m2ThreshLow[] = { 127, 40 };
80 const int m1Thresh[] = { 127, 0x4d };
81 const int m2Thresh[] = { 127, 0x40 };
82 const int m2CountThr[] = { 31, 16 };
83 const int m2CountThrLow[] = { 63, 48 };
84 u32 on = param ? 1 : 0;
85
86 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
87 AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
88 m1ThreshLow[on]);
89 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
90 AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
91 m2ThreshLow[on]);
92 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
93 AR_PHY_SFCORR_M1_THRESH,
94 m1Thresh[on]);
95 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
96 AR_PHY_SFCORR_M2_THRESH,
97 m2Thresh[on]);
98 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
99 AR_PHY_SFCORR_M2COUNT_THR,
100 m2CountThr[on]);
101 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
102 AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
103 m2CountThrLow[on]);
104
105 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
106 AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
107 m1ThreshLow[on]);
108 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
109 AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
110 m2ThreshLow[on]);
111 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
112 AR_PHY_SFCORR_EXT_M1_THRESH,
113 m1Thresh[on]);
114 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
115 AR_PHY_SFCORR_EXT_M2_THRESH,
116 m2Thresh[on]);
117
118 if (on)
119 REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
120 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
121 else
122 REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
123 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
124
125 if (!on != aniState->ofdmWeakSigDetectOff) {
126 if (on)
127 ah->stats.ast_ani_ofdmon++;
128 else
129 ah->stats.ast_ani_ofdmoff++;
130 aniState->ofdmWeakSigDetectOff = !on;
131 }
132 break;
133 }
134 case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
135 const int weakSigThrCck[] = { 8, 6 };
136 u32 high = param ? 1 : 0;
137
138 REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
139 AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
140 weakSigThrCck[high]);
141 if (high != aniState->cckWeakSigThreshold) {
142 if (high)
143 ah->stats.ast_ani_cckhigh++;
144 else
145 ah->stats.ast_ani_ccklow++;
146 aniState->cckWeakSigThreshold = high;
147 }
148 break;
149 }
150 case ATH9K_ANI_FIRSTEP_LEVEL:{
151 const int firstep[] = { 0, 4, 8 };
152 u32 level = param;
153
154 if (level >= ARRAY_SIZE(firstep)) {
155 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
156 "level out of range (%u > %u)\n",
157 level,
158 (unsigned) ARRAY_SIZE(firstep));
159 return false;
160 }
161 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
162 AR_PHY_FIND_SIG_FIRSTEP,
163 firstep[level]);
164 if (level > aniState->firstepLevel)
165 ah->stats.ast_ani_stepup++;
166 else if (level < aniState->firstepLevel)
167 ah->stats.ast_ani_stepdown++;
168 aniState->firstepLevel = level;
169 break;
170 }
171 case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
172 const int cycpwrThr1[] =
173 { 2, 4, 6, 8, 10, 12, 14, 16 };
174 u32 level = param;
175
176 if (level >= ARRAY_SIZE(cycpwrThr1)) {
177 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
178 "level out of range (%u > %u)\n",
179 level,
180 (unsigned)
181 ARRAY_SIZE(cycpwrThr1));
182 return false;
183 }
184 REG_RMW_FIELD(ah, AR_PHY_TIMING5,
185 AR_PHY_TIMING5_CYCPWR_THR1,
186 cycpwrThr1[level]);
187 if (level > aniState->spurImmunityLevel)
188 ah->stats.ast_ani_spurup++;
189 else if (level < aniState->spurImmunityLevel)
190 ah->stats.ast_ani_spurdown++;
191 aniState->spurImmunityLevel = level;
192 break;
193 }
194 case ATH9K_ANI_PRESENT:
195 break;
196 default:
197 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
198 "invalid cmd %u\n", cmd);
199 return false;
200 }
201
202 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "ANI parameters:\n");
203 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
204 "noiseImmunityLevel=%d, spurImmunityLevel=%d, "
205 "ofdmWeakSigDetectOff=%d\n",
206 aniState->noiseImmunityLevel, aniState->spurImmunityLevel,
207 !aniState->ofdmWeakSigDetectOff);
208 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
209 "cckWeakSigThreshold=%d, "
210 "firstepLevel=%d, listenTime=%d\n",
211 aniState->cckWeakSigThreshold, aniState->firstepLevel,
212 aniState->listenTime);
213 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
214 "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
215 aniState->cycleCount, aniState->ofdmPhyErrCount,
216 aniState->cckPhyErrCount);
217
218 return true;
219}
220
221static void ath9k_hw_update_mibstats(struct ath_hw *ah,
222 struct ath9k_mib_stats *stats)
223{
224 stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
225 stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
226 stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
227 stats->rts_good += REG_READ(ah, AR_RTS_OK);
228 stats->beacons += REG_READ(ah, AR_BEACON_CNT);
229}
230
231static void ath9k_ani_restart(struct ath_hw *ah)
232{
233 struct ar5416AniState *aniState;
234
235 if (!DO_ANI(ah))
236 return;
237
238 aniState = ah->curani;
239
240 aniState->listenTime = 0;
241 if (ah->has_hw_phycounters) {
242 if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
243 aniState->ofdmPhyErrBase = 0;
244 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
245 "OFDM Trigger is too high for hw counters\n");
246 } else {
247 aniState->ofdmPhyErrBase =
248 AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
249 }
250 if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
251 aniState->cckPhyErrBase = 0;
252 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
253 "CCK Trigger is too high for hw counters\n");
254 } else {
255 aniState->cckPhyErrBase =
256 AR_PHY_COUNTMAX - aniState->cckTrigHigh;
257 }
258 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
259 "Writing ofdmbase=%u cckbase=%u\n",
260 aniState->ofdmPhyErrBase,
261 aniState->cckPhyErrBase);
262 REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
263 REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
264 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
265 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
266
267 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
268 }
269 aniState->ofdmPhyErrCount = 0;
270 aniState->cckPhyErrCount = 0;
271}
272
273static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
274{
275 struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
276 struct ar5416AniState *aniState;
277 int32_t rssi;
278
279 if (!DO_ANI(ah))
280 return;
281
282 aniState = ah->curani;
283
284 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
285 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
286 aniState->noiseImmunityLevel + 1)) {
287 return;
288 }
289 }
290
291 if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
292 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
293 aniState->spurImmunityLevel + 1)) {
294 return;
295 }
296 }
297
298 if (ah->opmode == NL80211_IFTYPE_AP) {
299 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
300 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
301 aniState->firstepLevel + 1);
302 }
303 return;
304 }
305 rssi = BEACON_RSSI(ah);
306 if (rssi > aniState->rssiThrHigh) {
307 if (!aniState->ofdmWeakSigDetectOff) {
308 if (ath9k_hw_ani_control(ah,
309 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
310 false)) {
311 ath9k_hw_ani_control(ah,
312 ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
313 return;
314 }
315 }
316 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
317 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
318 aniState->firstepLevel + 1);
319 return;
320 }
321 } else if (rssi > aniState->rssiThrLow) {
322 if (aniState->ofdmWeakSigDetectOff)
323 ath9k_hw_ani_control(ah,
324 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
325 true);
326 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
327 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
328 aniState->firstepLevel + 1);
329 return;
330 } else {
331 if (conf->channel->band == IEEE80211_BAND_2GHZ) {
332 if (!aniState->ofdmWeakSigDetectOff)
333 ath9k_hw_ani_control(ah,
334 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
335 false);
336 if (aniState->firstepLevel > 0)
337 ath9k_hw_ani_control(ah,
338 ATH9K_ANI_FIRSTEP_LEVEL, 0);
339 return;
340 }
341 }
342}
343
344static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
345{
346 struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
347 struct ar5416AniState *aniState;
348 int32_t rssi;
349
350 if (!DO_ANI(ah))
351 return;
352
353 aniState = ah->curani;
354 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
355 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
356 aniState->noiseImmunityLevel + 1)) {
357 return;
358 }
359 }
360 if (ah->opmode == NL80211_IFTYPE_AP) {
361 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
362 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
363 aniState->firstepLevel + 1);
364 }
365 return;
366 }
367 rssi = BEACON_RSSI(ah);
368 if (rssi > aniState->rssiThrLow) {
369 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
370 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
371 aniState->firstepLevel + 1);
372 } else {
373 if (conf->channel->band == IEEE80211_BAND_2GHZ) {
374 if (aniState->firstepLevel > 0)
375 ath9k_hw_ani_control(ah,
376 ATH9K_ANI_FIRSTEP_LEVEL, 0);
377 }
378 }
379}
380
381static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
382{
383 struct ar5416AniState *aniState;
384 int32_t rssi;
385
386 aniState = ah->curani;
387
388 if (ah->opmode == NL80211_IFTYPE_AP) {
389 if (aniState->firstepLevel > 0) {
390 if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
391 aniState->firstepLevel - 1))
392 return;
393 }
394 } else {
395 rssi = BEACON_RSSI(ah);
396 if (rssi > aniState->rssiThrHigh) {
397 /* XXX: Handle me */
398 } else if (rssi > aniState->rssiThrLow) {
399 if (aniState->ofdmWeakSigDetectOff) {
400 if (ath9k_hw_ani_control(ah,
401 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
402 true) == true)
403 return;
404 }
405 if (aniState->firstepLevel > 0) {
406 if (ath9k_hw_ani_control(ah,
407 ATH9K_ANI_FIRSTEP_LEVEL,
408 aniState->firstepLevel - 1) == true)
409 return;
410 }
411 } else {
412 if (aniState->firstepLevel > 0) {
413 if (ath9k_hw_ani_control(ah,
414 ATH9K_ANI_FIRSTEP_LEVEL,
415 aniState->firstepLevel - 1) == true)
416 return;
417 }
418 }
419 }
420
421 if (aniState->spurImmunityLevel > 0) {
422 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
423 aniState->spurImmunityLevel - 1))
424 return;
425 }
426
427 if (aniState->noiseImmunityLevel > 0) {
428 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
429 aniState->noiseImmunityLevel - 1);
430 return;
431 }
432}
433
434static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
435{
436 struct ar5416AniState *aniState;
437 u32 txFrameCount, rxFrameCount, cycleCount;
438 int32_t listenTime;
439
440 txFrameCount = REG_READ(ah, AR_TFCNT);
441 rxFrameCount = REG_READ(ah, AR_RFCNT);
442 cycleCount = REG_READ(ah, AR_CCCNT);
443
444 aniState = ah->curani;
445 if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
446
447 listenTime = 0;
448 ah->stats.ast_ani_lzero++;
449 } else {
450 int32_t ccdelta = cycleCount - aniState->cycleCount;
451 int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
452 int32_t tfdelta = txFrameCount - aniState->txFrameCount;
453 listenTime = (ccdelta - rfdelta - tfdelta) / 44000;
454 }
455 aniState->cycleCount = cycleCount;
456 aniState->txFrameCount = txFrameCount;
457 aniState->rxFrameCount = rxFrameCount;
458
459 return listenTime;
460}
461
462void ath9k_ani_reset(struct ath_hw *ah)
463{
464 struct ar5416AniState *aniState;
465 struct ath9k_channel *chan = ah->curchan;
466 int index;
467
468 if (!DO_ANI(ah))
469 return;
470
471 index = ath9k_hw_get_ani_channel_idx(ah, chan);
472 aniState = &ah->ani[index];
473 ah->curani = aniState;
474
475 if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION
476 && ah->opmode != NL80211_IFTYPE_ADHOC) {
477 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
478 "Reset ANI state opmode %u\n", ah->opmode);
479 ah->stats.ast_ani_reset++;
480
481 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
482 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
483 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
484 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
485 !ATH9K_ANI_USE_OFDM_WEAK_SIG);
486 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
487 ATH9K_ANI_CCK_WEAK_SIG_THR);
488
489 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
490 ATH9K_RX_FILTER_PHYERR);
491
492 if (ah->opmode == NL80211_IFTYPE_AP) {
493 ah->curani->ofdmTrigHigh =
494 ah->config.ofdm_trig_high;
495 ah->curani->ofdmTrigLow =
496 ah->config.ofdm_trig_low;
497 ah->curani->cckTrigHigh =
498 ah->config.cck_trig_high;
499 ah->curani->cckTrigLow =
500 ah->config.cck_trig_low;
501 }
502 ath9k_ani_restart(ah);
503 return;
504 }
505
506 if (aniState->noiseImmunityLevel != 0)
507 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
508 aniState->noiseImmunityLevel);
509 if (aniState->spurImmunityLevel != 0)
510 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
511 aniState->spurImmunityLevel);
512 if (aniState->ofdmWeakSigDetectOff)
513 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
514 !aniState->ofdmWeakSigDetectOff);
515 if (aniState->cckWeakSigThreshold)
516 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
517 aniState->cckWeakSigThreshold);
518 if (aniState->firstepLevel != 0)
519 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
520 aniState->firstepLevel);
521 if (ah->has_hw_phycounters) {
522 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
523 ~ATH9K_RX_FILTER_PHYERR);
524 ath9k_ani_restart(ah);
525 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
526 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
527
528 } else {
529 ath9k_ani_restart(ah);
530 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
531 ATH9K_RX_FILTER_PHYERR);
532 }
533}
534
535void ath9k_hw_ani_monitor(struct ath_hw *ah,
536 const struct ath9k_node_stats *stats,
537 struct ath9k_channel *chan)
538{
539 struct ar5416AniState *aniState;
540 int32_t listenTime;
541
542 if (!DO_ANI(ah))
543 return;
544
545 aniState = ah->curani;
546 ah->stats.ast_nodestats = *stats;
547
548 listenTime = ath9k_hw_ani_get_listen_time(ah);
549 if (listenTime < 0) {
550 ah->stats.ast_ani_lneg++;
551 ath9k_ani_restart(ah);
552 return;
553 }
554
555 aniState->listenTime += listenTime;
556
557 if (ah->has_hw_phycounters) {
558 u32 phyCnt1, phyCnt2;
559 u32 ofdmPhyErrCnt, cckPhyErrCnt;
560
561 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
562
563 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
564 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
565
566 if (phyCnt1 < aniState->ofdmPhyErrBase ||
567 phyCnt2 < aniState->cckPhyErrBase) {
568 if (phyCnt1 < aniState->ofdmPhyErrBase) {
569 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
570 "phyCnt1 0x%x, resetting "
571 "counter value to 0x%x\n",
572 phyCnt1, aniState->ofdmPhyErrBase);
573 REG_WRITE(ah, AR_PHY_ERR_1,
574 aniState->ofdmPhyErrBase);
575 REG_WRITE(ah, AR_PHY_ERR_MASK_1,
576 AR_PHY_ERR_OFDM_TIMING);
577 }
578 if (phyCnt2 < aniState->cckPhyErrBase) {
579 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
580 "phyCnt2 0x%x, resetting "
581 "counter value to 0x%x\n",
582 phyCnt2, aniState->cckPhyErrBase);
583 REG_WRITE(ah, AR_PHY_ERR_2,
584 aniState->cckPhyErrBase);
585 REG_WRITE(ah, AR_PHY_ERR_MASK_2,
586 AR_PHY_ERR_CCK_TIMING);
587 }
588 return;
589 }
590
591 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
592 ah->stats.ast_ani_ofdmerrs +=
593 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
594 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
595
596 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
597 ah->stats.ast_ani_cckerrs +=
598 cckPhyErrCnt - aniState->cckPhyErrCount;
599 aniState->cckPhyErrCount = cckPhyErrCnt;
600 }
601
602 if (aniState->listenTime > 5 * ah->aniperiod) {
603 if (aniState->ofdmPhyErrCount <= aniState->listenTime *
604 aniState->ofdmTrigLow / 1000 &&
605 aniState->cckPhyErrCount <= aniState->listenTime *
606 aniState->cckTrigLow / 1000)
607 ath9k_hw_ani_lower_immunity(ah);
608 ath9k_ani_restart(ah);
609 } else if (aniState->listenTime > ah->aniperiod) {
610 if (aniState->ofdmPhyErrCount > aniState->listenTime *
611 aniState->ofdmTrigHigh / 1000) {
612 ath9k_hw_ani_ofdm_err_trigger(ah);
613 ath9k_ani_restart(ah);
614 } else if (aniState->cckPhyErrCount >
615 aniState->listenTime * aniState->cckTrigHigh /
616 1000) {
617 ath9k_hw_ani_cck_err_trigger(ah);
618 ath9k_ani_restart(ah);
619 }
620 }
621}
622
623bool ath9k_hw_phycounters(struct ath_hw *ah)
624{
625 return ah->has_hw_phycounters ? true : false;
626}
627
628void ath9k_enable_mib_counters(struct ath_hw *ah)
629{
630 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n");
631
632 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
633
634 REG_WRITE(ah, AR_FILT_OFDM, 0);
635 REG_WRITE(ah, AR_FILT_CCK, 0);
636 REG_WRITE(ah, AR_MIBC,
637 ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
638 & 0x0f);
639 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
640 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
641}
642
643/* Freeze the MIB counters, get the stats and then clear them */
644void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
645{
646 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disable MIB counters\n");
647 REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
648 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
649 REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
650 REG_WRITE(ah, AR_FILT_OFDM, 0);
651 REG_WRITE(ah, AR_FILT_CCK, 0);
652}
653
654u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
655 u32 *rxc_pcnt,
656 u32 *rxf_pcnt,
657 u32 *txf_pcnt)
658{
659 static u32 cycles, rx_clear, rx_frame, tx_frame;
660 u32 good = 1;
661
662 u32 rc = REG_READ(ah, AR_RCCNT);
663 u32 rf = REG_READ(ah, AR_RFCNT);
664 u32 tf = REG_READ(ah, AR_TFCNT);
665 u32 cc = REG_READ(ah, AR_CCCNT);
666
667 if (cycles == 0 || cycles > cc) {
668 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
669 "cycle counter wrap. ExtBusy = 0\n");
670 good = 0;
671 } else {
672 u32 cc_d = cc - cycles;
673 u32 rc_d = rc - rx_clear;
674 u32 rf_d = rf - rx_frame;
675 u32 tf_d = tf - tx_frame;
676
677 if (cc_d != 0) {
678 *rxc_pcnt = rc_d * 100 / cc_d;
679 *rxf_pcnt = rf_d * 100 / cc_d;
680 *txf_pcnt = tf_d * 100 / cc_d;
681 } else {
682 good = 0;
683 }
684 }
685
686 cycles = cc;
687 rx_frame = rf;
688 rx_clear = rc;
689 tx_frame = tf;
690
691 return good;
692}
693
694/*
695 * Process a MIB interrupt. We may potentially be invoked because
696 * any of the MIB counters overflow/trigger so don't assume we're
697 * here because a PHY error counter triggered.
698 */
699void ath9k_hw_procmibevent(struct ath_hw *ah,
700 const struct ath9k_node_stats *stats)
701{
702 u32 phyCnt1, phyCnt2;
703
704 /* Reset these counters regardless */
705 REG_WRITE(ah, AR_FILT_OFDM, 0);
706 REG_WRITE(ah, AR_FILT_CCK, 0);
707 if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
708 REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
709
710 /* Clear the mib counters and save them in the stats */
711 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
712 ah->stats.ast_nodestats = *stats;
713
714 if (!DO_ANI(ah))
715 return;
716
717 /* NB: these are not reset-on-read */
718 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
719 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
720 if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
721 ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
722 struct ar5416AniState *aniState = ah->curani;
723 u32 ofdmPhyErrCnt, cckPhyErrCnt;
724
725 /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
726 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
727 ah->stats.ast_ani_ofdmerrs +=
728 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
729 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
730
731 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
732 ah->stats.ast_ani_cckerrs +=
733 cckPhyErrCnt - aniState->cckPhyErrCount;
734 aniState->cckPhyErrCount = cckPhyErrCnt;
735
736 /*
737 * NB: figure out which counter triggered. If both
738 * trigger we'll only deal with one as the processing
739 * clobbers the error counter so the trigger threshold
740 * check will never be true.
741 */
742 if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
743 ath9k_hw_ani_ofdm_err_trigger(ah);
744 if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
745 ath9k_hw_ani_cck_err_trigger(ah);
746 /* NB: always restart to insure the h/w counters are reset */
747 ath9k_ani_restart(ah);
748 }
749}
750
751void ath9k_hw_ani_setup(struct ath_hw *ah)
752{
753 int i;
754
755 const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
756 const int coarseHigh[] = { -14, -14, -14, -14, -12 };
757 const int coarseLow[] = { -64, -64, -64, -64, -70 };
758 const int firpwr[] = { -78, -78, -78, -78, -80 };
759
760 for (i = 0; i < 5; i++) {
761 ah->totalSizeDesired[i] = totalSizeDesired[i];
762 ah->coarse_high[i] = coarseHigh[i];
763 ah->coarse_low[i] = coarseLow[i];
764 ah->firpwr[i] = firpwr[i];
765 }
766}
767
768void ath9k_hw_ani_attach(struct ath_hw *ah)
769{
770 int i;
771
772 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Attach ANI\n");
773
774 ah->has_hw_phycounters = 1;
775
776 memset(ah->ani, 0, sizeof(ah->ani));
777 for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
778 ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH;
779 ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW;
780 ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH;
781 ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW;
782 ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
783 ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
784 ah->ani[i].ofdmWeakSigDetectOff =
785 !ATH9K_ANI_USE_OFDM_WEAK_SIG;
786 ah->ani[i].cckWeakSigThreshold =
787 ATH9K_ANI_CCK_WEAK_SIG_THR;
788 ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
789 ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
790 if (ah->has_hw_phycounters) {
791 ah->ani[i].ofdmPhyErrBase =
792 AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
793 ah->ani[i].cckPhyErrBase =
794 AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
795 }
796 }
797 if (ah->has_hw_phycounters) {
798 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
799 "Setting OfdmErrBase = 0x%08x\n",
800 ah->ani[0].ofdmPhyErrBase);
801 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
802 ah->ani[0].cckPhyErrBase);
803
804 REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
805 REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
806 ath9k_enable_mib_counters(ah);
807 }
808 ah->aniperiod = ATH9K_ANI_PERIOD;
809 if (ah->config.enable_ani)
810 ah->proc_phyerr |= HAL_PROCESS_ANI;
811}
812
813void ath9k_hw_ani_detach(struct ath_hw *ah)
814{
815 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detach ANI\n");
816
817 if (ah->has_hw_phycounters) {
818 ath9k_hw_disable_mib_counters(ah);
819 REG_WRITE(ah, AR_PHY_ERR_1, 0);
820 REG_WRITE(ah, AR_PHY_ERR_2, 0);
821 }
822}
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
new file mode 100644
index 000000000000..08b4e7ed5ff0
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -0,0 +1,138 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef ANI_H
18#define ANI_H
19
20#define HAL_PROCESS_ANI 0x00000001
21#define ATH9K_RSSI_EP_MULTIPLIER (1<<7)
22
23#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI))
24
25#define HAL_EP_RND(x, mul) \
26 ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
27#define BEACON_RSSI(ahp) \
28 HAL_EP_RND(ahp->stats.ast_nodestats.ns_avgbrssi, \
29 ATH9K_RSSI_EP_MULTIPLIER)
30
31#define ATH9K_ANI_OFDM_TRIG_HIGH 500
32#define ATH9K_ANI_OFDM_TRIG_LOW 200
33#define ATH9K_ANI_CCK_TRIG_HIGH 200
34#define ATH9K_ANI_CCK_TRIG_LOW 100
35#define ATH9K_ANI_NOISE_IMMUNE_LVL 4
36#define ATH9K_ANI_USE_OFDM_WEAK_SIG true
37#define ATH9K_ANI_CCK_WEAK_SIG_THR false
38#define ATH9K_ANI_SPUR_IMMUNE_LVL 7
39#define ATH9K_ANI_FIRSTEP_LVL 0
40#define ATH9K_ANI_RSSI_THR_HIGH 40
41#define ATH9K_ANI_RSSI_THR_LOW 7
42#define ATH9K_ANI_PERIOD 100
43
44#define HAL_NOISE_IMMUNE_MAX 4
45#define HAL_SPUR_IMMUNE_MAX 7
46#define HAL_FIRST_STEP_MAX 2
47
48enum ath9k_ani_cmd {
49 ATH9K_ANI_PRESENT = 0x1,
50 ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2,
51 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION = 0x4,
52 ATH9K_ANI_CCK_WEAK_SIGNAL_THR = 0x8,
53 ATH9K_ANI_FIRSTEP_LEVEL = 0x10,
54 ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20,
55 ATH9K_ANI_MODE = 0x40,
56 ATH9K_ANI_PHYERR_RESET = 0x80,
57 ATH9K_ANI_ALL = 0xff
58};
59
60struct ath9k_mib_stats {
61 u32 ackrcv_bad;
62 u32 rts_bad;
63 u32 rts_good;
64 u32 fcs_bad;
65 u32 beacons;
66};
67
68struct ath9k_node_stats {
69 u32 ns_avgbrssi;
70 u32 ns_avgrssi;
71 u32 ns_avgtxrssi;
72 u32 ns_avgtxrate;
73};
74
75struct ar5416AniState {
76 struct ath9k_channel *c;
77 u8 noiseImmunityLevel;
78 u8 spurImmunityLevel;
79 u8 firstepLevel;
80 u8 ofdmWeakSigDetectOff;
81 u8 cckWeakSigThreshold;
82 u32 listenTime;
83 u32 ofdmTrigHigh;
84 u32 ofdmTrigLow;
85 int32_t cckTrigHigh;
86 int32_t cckTrigLow;
87 int32_t rssiThrLow;
88 int32_t rssiThrHigh;
89 u32 noiseFloor;
90 u32 txFrameCount;
91 u32 rxFrameCount;
92 u32 cycleCount;
93 u32 ofdmPhyErrCount;
94 u32 cckPhyErrCount;
95 u32 ofdmPhyErrBase;
96 u32 cckPhyErrBase;
97 int16_t pktRssi[2];
98 int16_t ofdmErrRssi[2];
99 int16_t cckErrRssi[2];
100};
101
102struct ar5416Stats {
103 u32 ast_ani_niup;
104 u32 ast_ani_nidown;
105 u32 ast_ani_spurup;
106 u32 ast_ani_spurdown;
107 u32 ast_ani_ofdmon;
108 u32 ast_ani_ofdmoff;
109 u32 ast_ani_cckhigh;
110 u32 ast_ani_ccklow;
111 u32 ast_ani_stepup;
112 u32 ast_ani_stepdown;
113 u32 ast_ani_ofdmerrs;
114 u32 ast_ani_cckerrs;
115 u32 ast_ani_reset;
116 u32 ast_ani_lzero;
117 u32 ast_ani_lneg;
118 struct ath9k_mib_stats ast_mibstats;
119 struct ath9k_node_stats ast_nodestats;
120};
121#define ah_mibStats stats.ast_mibstats
122
123void ath9k_ani_reset(struct ath_hw *ah);
124void ath9k_hw_ani_monitor(struct ath_hw *ah,
125 const struct ath9k_node_stats *stats,
126 struct ath9k_channel *chan);
127bool ath9k_hw_phycounters(struct ath_hw *ah);
128void ath9k_enable_mib_counters(struct ath_hw *ah);
129void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
130u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
131 u32 *rxf_pcnt, u32 *txf_pcnt);
132void ath9k_hw_procmibevent(struct ath_hw *ah,
133 const struct ath9k_node_stats *stats);
134void ath9k_hw_ani_setup(struct ath_hw *ah);
135void ath9k_hw_ani_attach(struct ath_hw *ah);
136void ath9k_hw_ani_detach(struct ath_hw *ah);
137
138#endif /* ANI_H */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
new file mode 100644
index 000000000000..c92d46fa9d51
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -0,0 +1,730 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef ATH9K_H
18#define ATH9K_H
19
20#include <linux/etherdevice.h>
21#include <linux/device.h>
22#include <net/mac80211.h>
23#include <linux/leds.h>
24#include <linux/rfkill.h>
25
26#include "hw.h"
27#include "rc.h"
28#include "debug.h"
29
30struct ath_node;
31
32/* Macro to expand scalars to 64-bit objects */
33
34#define ito64(x) (sizeof(x) == 8) ? \
35 (((unsigned long long int)(x)) & (0xff)) : \
36 (sizeof(x) == 16) ? \
37 (((unsigned long long int)(x)) & 0xffff) : \
38 ((sizeof(x) == 32) ? \
39 (((unsigned long long int)(x)) & 0xffffffff) : \
40 (unsigned long long int)(x))
41
42/* increment with wrap-around */
43#define INCR(_l, _sz) do { \
44 (_l)++; \
45 (_l) &= ((_sz) - 1); \
46 } while (0)
47
48/* decrement with wrap-around */
49#define DECR(_l, _sz) do { \
50 (_l)--; \
51 (_l) &= ((_sz) - 1); \
52 } while (0)
53
54#define A_MAX(a, b) ((a) > (b) ? (a) : (b))
55
56#define ASSERT(exp) BUG_ON(!(exp))
57
58#define TSF_TO_TU(_h,_l) \
59 ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
60
61#define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i))
62
63static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
64
65struct ath_config {
66 u32 ath_aggr_prot;
67 u16 txpowlimit;
68 u8 cabqReadytime;
69};
70
71/*************************/
72/* Descriptor Management */
73/*************************/
74
75#define ATH_TXBUF_RESET(_bf) do { \
76 (_bf)->bf_stale = false; \
77 (_bf)->bf_lastbf = NULL; \
78 (_bf)->bf_next = NULL; \
79 memset(&((_bf)->bf_state), 0, \
80 sizeof(struct ath_buf_state)); \
81 } while (0)
82
83#define ATH_RXBUF_RESET(_bf) do { \
84 (_bf)->bf_stale = false; \
85 } while (0)
86
87/**
88 * enum buffer_type - Buffer type flags
89 *
90 * @BUF_HT: Send this buffer using HT capabilities
91 * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
92 * @BUF_AGGR: Indicates whether the buffer can be aggregated
93 * (used in aggregation scheduling)
94 * @BUF_RETRY: Indicates whether the buffer is retried
95 * @BUF_XRETRY: To denote excessive retries of the buffer
96 */
97enum buffer_type {
98 BUF_HT = BIT(1),
99 BUF_AMPDU = BIT(2),
100 BUF_AGGR = BIT(3),
101 BUF_RETRY = BIT(4),
102 BUF_XRETRY = BIT(5),
103};
104
105struct ath_buf_state {
106 int bfs_nframes;
107 u16 bfs_al;
108 u16 bfs_frmlen;
109 int bfs_seqno;
110 int bfs_tidno;
111 int bfs_retries;
112 u8 bf_type;
113 u32 bfs_keyix;
114 enum ath9k_key_type bfs_keytype;
115};
116
117#define bf_nframes bf_state.bfs_nframes
118#define bf_al bf_state.bfs_al
119#define bf_frmlen bf_state.bfs_frmlen
120#define bf_retries bf_state.bfs_retries
121#define bf_seqno bf_state.bfs_seqno
122#define bf_tidno bf_state.bfs_tidno
123#define bf_keyix bf_state.bfs_keyix
124#define bf_keytype bf_state.bfs_keytype
125#define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT)
126#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU)
127#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
128#define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY)
129#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY)
130
131struct ath_buf {
132 struct list_head list;
133 struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or
134 an aggregate) */
135 struct ath_buf *bf_next; /* next subframe in the aggregate */
136 struct sk_buff *bf_mpdu; /* enclosing frame structure */
137 struct ath_desc *bf_desc; /* virtual addr of desc */
138 dma_addr_t bf_daddr; /* physical addr of desc */
139 dma_addr_t bf_buf_addr; /* physical addr of data buffer */
140 bool bf_stale;
141 u16 bf_flags;
142 struct ath_buf_state bf_state;
143 dma_addr_t bf_dmacontext;
144};
145
146struct ath_descdma {
147 struct ath_desc *dd_desc;
148 dma_addr_t dd_desc_paddr;
149 u32 dd_desc_len;
150 struct ath_buf *dd_bufptr;
151};
152
153int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
154 struct list_head *head, const char *name,
155 int nbuf, int ndesc);
156void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
157 struct list_head *head);
158
159/***********/
160/* RX / TX */
161/***********/
162
163#define ATH_MAX_ANTENNA 3
164#define ATH_RXBUF 512
165#define WME_NUM_TID 16
166#define ATH_TXBUF 512
167#define ATH_TXMAXTRY 13
168#define ATH_11N_TXMAXTRY 10
169#define ATH_MGT_TXMAXTRY 4
170#define WME_BA_BMP_SIZE 64
171#define WME_MAX_BA WME_BA_BMP_SIZE
172#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
173
174#define TID_TO_WME_AC(_tid) \
175 ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
176 (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
177 (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
178 WME_AC_VO)
179
180#define WME_AC_BE 0
181#define WME_AC_BK 1
182#define WME_AC_VI 2
183#define WME_AC_VO 3
184#define WME_NUM_AC 4
185
186#define ADDBA_EXCHANGE_ATTEMPTS 10
187#define ATH_AGGR_DELIM_SZ 4
188#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
189/* number of delimiters for encryption padding */
190#define ATH_AGGR_ENCRYPTDELIM 10
191/* minimum h/w qdepth to be sustained to maximize aggregation */
192#define ATH_AGGR_MIN_QDEPTH 2
193#define ATH_AMPDU_SUBFRAME_DEFAULT 32
194#define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1)
195#define ATH_AMPDU_LIMIT_DEFAULT ATH_AMPDU_LIMIT_MAX
196
197#define IEEE80211_SEQ_SEQ_SHIFT 4
198#define IEEE80211_SEQ_MAX 4096
199#define IEEE80211_MIN_AMPDU_BUF 0x8
200#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
201#define IEEE80211_WEP_IVLEN 3
202#define IEEE80211_WEP_KIDLEN 1
203#define IEEE80211_WEP_CRCLEN 4
204#define IEEE80211_MAX_MPDU_LEN (3840 + FCS_LEN + \
205 (IEEE80211_WEP_IVLEN + \
206 IEEE80211_WEP_KIDLEN + \
207 IEEE80211_WEP_CRCLEN))
208
209/* return whether a bit at index _n in bitmap _bm is set
210 * _sz is the size of the bitmap */
211#define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \
212 ((_bm)[(_n) >> 5] & (1 << ((_n) & 31))))
213
214/* return block-ack bitmap index given sequence and starting sequence */
215#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1))
216
217/* returns delimiter padding required given the packet length */
218#define ATH_AGGR_GET_NDELIM(_len) \
219 (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \
220 (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
221
222#define BAW_WITHIN(_start, _bawsz, _seqno) \
223 ((((_seqno) - (_start)) & 4095) < (_bawsz))
224
225#define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum)
226#define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low)
227#define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA)
228#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)])
229
230enum ATH_AGGR_STATUS {
231 ATH_AGGR_DONE,
232 ATH_AGGR_BAW_CLOSED,
233 ATH_AGGR_LIMITED,
234};
235
236struct ath_txq {
237 u32 axq_qnum;
238 u32 *axq_link;
239 struct list_head axq_q;
240 spinlock_t axq_lock;
241 u32 axq_depth;
242 u8 axq_aggr_depth;
243 u32 axq_totalqueued;
244 bool stopped;
245 struct ath_buf *axq_linkbuf;
246
247 /* first desc of the last descriptor that contains CTS */
248 struct ath_desc *axq_lastdsWithCTS;
249
250 /* final desc of the gating desc that determines whether
251 lastdsWithCTS has been DMA'ed or not */
252 struct ath_desc *axq_gatingds;
253
254 struct list_head axq_acq;
255};
256
257#define AGGR_CLEANUP BIT(1)
258#define AGGR_ADDBA_COMPLETE BIT(2)
259#define AGGR_ADDBA_PROGRESS BIT(3)
260
261struct ath_atx_tid {
262 struct list_head list;
263 struct list_head buf_q;
264 struct ath_node *an;
265 struct ath_atx_ac *ac;
266 struct ath_buf *tx_buf[ATH_TID_MAX_BUFS];
267 u16 seq_start;
268 u16 seq_next;
269 u16 baw_size;
270 int tidno;
271 int baw_head; /* first un-acked tx buffer */
272 int baw_tail; /* next unused tx buffer slot */
273 int sched;
274 int paused;
275 u8 state;
276 int addba_exchangeattempts;
277};
278
279struct ath_atx_ac {
280 int sched;
281 int qnum;
282 struct list_head list;
283 struct list_head tid_q;
284};
285
286struct ath_tx_control {
287 struct ath_txq *txq;
288 int if_id;
289 enum ath9k_internal_frame_type frame_type;
290};
291
292#define ATH_TX_ERROR 0x01
293#define ATH_TX_XRETRY 0x02
294#define ATH_TX_BAR 0x04
295
296struct ath_node {
297 struct ath_softc *an_sc;
298 struct ath_atx_tid tid[WME_NUM_TID];
299 struct ath_atx_ac ac[WME_NUM_AC];
300 u16 maxampdu;
301 u8 mpdudensity;
302};
303
304struct ath_tx {
305 u16 seq_no;
306 u32 txqsetup;
307 int hwq_map[ATH9K_WME_AC_VO+1];
308 spinlock_t txbuflock;
309 struct list_head txbuf;
310 struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
311 struct ath_descdma txdma;
312};
313
314struct ath_rx {
315 u8 defant;
316 u8 rxotherant;
317 u32 *rxlink;
318 int bufsize;
319 unsigned int rxfilter;
320 spinlock_t rxflushlock;
321 spinlock_t rxbuflock;
322 struct list_head rxbuf;
323 struct ath_descdma rxdma;
324};
325
326int ath_startrecv(struct ath_softc *sc);
327bool ath_stoprecv(struct ath_softc *sc);
328void ath_flushrecv(struct ath_softc *sc);
329u32 ath_calcrxfilter(struct ath_softc *sc);
330int ath_rx_init(struct ath_softc *sc, int nbufs);
331void ath_rx_cleanup(struct ath_softc *sc);
332int ath_rx_tasklet(struct ath_softc *sc, int flush);
333struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
334void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
335int ath_tx_setup(struct ath_softc *sc, int haltype);
336void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
337void ath_draintxq(struct ath_softc *sc,
338 struct ath_txq *txq, bool retry_tx);
339void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
340void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
341void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
342int ath_tx_init(struct ath_softc *sc, int nbufs);
343void ath_tx_cleanup(struct ath_softc *sc);
344struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb);
345int ath_txq_update(struct ath_softc *sc, int qnum,
346 struct ath9k_tx_queue_info *q);
347int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
348 struct ath_tx_control *txctl);
349void ath_tx_tasklet(struct ath_softc *sc);
350void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
351bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
352int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
353 u16 tid, u16 *ssn);
354int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
355void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
356
357/********/
358/* VIFs */
359/********/
360
361struct ath_vif {
362 int av_bslot;
363 __le64 tsf_adjust; /* TSF adjustment for staggered beacons */
364 enum nl80211_iftype av_opmode;
365 struct ath_buf *av_bcbuf;
366 struct ath_tx_control av_btxctl;
367 u8 bssid[ETH_ALEN]; /* current BSSID from config_interface */
368};
369
370/*******************/
371/* Beacon Handling */
372/*******************/
373
374/*
375 * Regardless of the number of beacons we stagger, (i.e. regardless of the
376 * number of BSSIDs) if a given beacon does not go out even after waiting this
377 * number of beacon intervals, the game's up.
378 */
379#define BSTUCK_THRESH (9 * ATH_BCBUF)
380#define ATH_BCBUF 4
381#define ATH_DEFAULT_BINTVAL 100 /* TU */
382#define ATH_DEFAULT_BMISS_LIMIT 10
383#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024)
384
385struct ath_beacon_config {
386 u16 beacon_interval;
387 u16 listen_interval;
388 u16 dtim_period;
389 u16 bmiss_timeout;
390 u8 dtim_count;
391};
392
393struct ath_beacon {
394 enum {
395 OK, /* no change needed */
396 UPDATE, /* update pending */
397 COMMIT /* beacon sent, commit change */
398 } updateslot; /* slot time update fsm */
399
400 u32 beaconq;
401 u32 bmisscnt;
402 u32 ast_be_xmit;
403 u64 bc_tstamp;
404 struct ieee80211_vif *bslot[ATH_BCBUF];
405 struct ath_wiphy *bslot_aphy[ATH_BCBUF];
406 int slottime;
407 int slotupdate;
408 struct ath9k_tx_queue_info beacon_qi;
409 struct ath_descdma bdma;
410 struct ath_txq *cabq;
411 struct list_head bbuf;
412};
413
414void ath_beacon_tasklet(unsigned long data);
415void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
416int ath_beaconq_setup(struct ath_hw *ah);
417int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif);
418void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
419
420/*******/
421/* ANI */
422/*******/
423
424#define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */
425#define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */
426#define ATH_ANI_POLLINTERVAL 100 /* 100 ms */
427#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
428#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
429
430struct ath_ani {
431 bool caldone;
432 int16_t noise_floor;
433 unsigned int longcal_timer;
434 unsigned int shortcal_timer;
435 unsigned int resetcal_timer;
436 unsigned int checkani_timer;
437 struct timer_list timer;
438};
439
440/********************/
441/* LED Control */
442/********************/
443
444#define ATH_LED_PIN 1
445#define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */
446#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */
447
448enum ath_led_type {
449 ATH_LED_RADIO,
450 ATH_LED_ASSOC,
451 ATH_LED_TX,
452 ATH_LED_RX
453};
454
455struct ath_led {
456 struct ath_softc *sc;
457 struct led_classdev led_cdev;
458 enum ath_led_type led_type;
459 char name[32];
460 bool registered;
461};
462
463/* Rfkill */
464#define ATH_RFKILL_POLL_INTERVAL 2000 /* msecs */
465
466struct ath_rfkill {
467 struct rfkill *rfkill;
468 struct delayed_work rfkill_poll;
469 char rfkill_name[32];
470};
471
472/********************/
473/* Main driver core */
474/********************/
475
476/*
477 * Default cache line size, in bytes.
478 * Used when PCI device not fully initialized by bootrom/BIOS
479*/
480#define DEFAULT_CACHELINE 32
481#define ATH_DEFAULT_NOISE_FLOOR -95
482#define ATH_REGCLASSIDS_MAX 10
483#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
484#define ATH_MAX_SW_RETRIES 10
485#define ATH_CHAN_MAX 255
486#define IEEE80211_WEP_NKID 4 /* number of key ids */
487
488/*
489 * The key cache is used for h/w cipher state and also for
490 * tracking station state such as the current tx antenna.
491 * We also setup a mapping table between key cache slot indices
492 * and station state to short-circuit node lookups on rx.
493 * Different parts have different size key caches. We handle
494 * up to ATH_KEYMAX entries (could dynamically allocate state).
495 */
496#define ATH_KEYMAX 128 /* max key cache size we handle */
497
498#define ATH_TXPOWER_MAX 100 /* .5 dBm units */
499#define ATH_RSSI_DUMMY_MARKER 0x127
500#define ATH_RATE_DUMMY_MARKER 0
501
502#define SC_OP_INVALID BIT(0)
503#define SC_OP_BEACONS BIT(1)
504#define SC_OP_RXAGGR BIT(2)
505#define SC_OP_TXAGGR BIT(3)
506#define SC_OP_FULL_RESET BIT(4)
507#define SC_OP_PREAMBLE_SHORT BIT(5)
508#define SC_OP_PROTECT_ENABLE BIT(6)
509#define SC_OP_RXFLUSH BIT(7)
510#define SC_OP_LED_ASSOCIATED BIT(8)
511#define SC_OP_RFKILL_REGISTERED BIT(9)
512#define SC_OP_RFKILL_SW_BLOCKED BIT(10)
513#define SC_OP_RFKILL_HW_BLOCKED BIT(11)
514#define SC_OP_WAIT_FOR_BEACON BIT(12)
515#define SC_OP_LED_ON BIT(13)
516#define SC_OP_SCANNING BIT(14)
517#define SC_OP_TSF_RESET BIT(15)
518
519struct ath_bus_ops {
520 void (*read_cachesize)(struct ath_softc *sc, int *csz);
521 void (*cleanup)(struct ath_softc *sc);
522 bool (*eeprom_read)(struct ath_hw *ah, u32 off, u16 *data);
523};
524
525struct ath_wiphy;
526
527struct ath_softc {
528 struct ieee80211_hw *hw;
529 struct device *dev;
530
531 spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */
532 struct ath_wiphy *pri_wiphy;
533 struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may
534 * have NULL entries */
535 int num_sec_wiphy; /* number of sec_wiphy pointers in the array */
536 int chan_idx;
537 int chan_is_ht;
538 struct ath_wiphy *next_wiphy;
539 struct work_struct chan_work;
540 int wiphy_select_failures;
541 unsigned long wiphy_select_first_fail;
542 struct delayed_work wiphy_work;
543 unsigned long wiphy_scheduler_int;
544 int wiphy_scheduler_index;
545
546 struct tasklet_struct intr_tq;
547 struct tasklet_struct bcon_tasklet;
548 struct ath_hw *sc_ah;
549 void __iomem *mem;
550 int irq;
551 spinlock_t sc_resetlock;
552 spinlock_t sc_serial_rw;
553 struct mutex mutex;
554
555 u8 curbssid[ETH_ALEN];
556 u8 bssidmask[ETH_ALEN];
557 u32 intrstatus;
558 u32 sc_flags; /* SC_OP_* */
559 u16 curtxpow;
560 u16 curaid;
561 u16 cachelsz;
562 u8 nbcnvifs;
563 u16 nvifs;
564 u8 tx_chainmask;
565 u8 rx_chainmask;
566 u32 keymax;
567 DECLARE_BITMAP(keymap, ATH_KEYMAX);
568 u8 splitmic;
569 atomic_t ps_usecount;
570 enum ath9k_int imask;
571 enum ath9k_ht_extprotspacing ht_extprotspacing;
572 enum ath9k_ht_macmode tx_chan_width;
573
574 struct ath_config config;
575 struct ath_rx rx;
576 struct ath_tx tx;
577 struct ath_beacon beacon;
578 struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
579 struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX];
580 struct ath_rate_table *cur_rate_table;
581 struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
582
583 struct ath_led radio_led;
584 struct ath_led assoc_led;
585 struct ath_led tx_led;
586 struct ath_led rx_led;
587 struct delayed_work ath_led_blink_work;
588 int led_on_duration;
589 int led_off_duration;
590 int led_on_cnt;
591 int led_off_cnt;
592
593 struct ath_rfkill rf_kill;
594 struct ath_ani ani;
595 struct ath9k_node_stats nodestats;
596#ifdef CONFIG_ATH9K_DEBUG
597 struct ath9k_debug debug;
598#endif
599 struct ath_bus_ops *bus_ops;
600};
601
602struct ath_wiphy {
603 struct ath_softc *sc; /* shared for all virtual wiphys */
604 struct ieee80211_hw *hw;
605 enum ath_wiphy_state {
606 ATH_WIPHY_INACTIVE,
607 ATH_WIPHY_ACTIVE,
608 ATH_WIPHY_PAUSING,
609 ATH_WIPHY_PAUSED,
610 ATH_WIPHY_SCAN,
611 } state;
612 int chan_idx;
613 int chan_is_ht;
614};
615
616int ath_reset(struct ath_softc *sc, bool retry_tx);
617int ath_get_hal_qnum(u16 queue, struct ath_softc *sc);
618int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
619int ath_cabq_update(struct ath_softc *);
620
621static inline void ath_read_cachesize(struct ath_softc *sc, int *csz)
622{
623 sc->bus_ops->read_cachesize(sc, csz);
624}
625
626static inline void ath_bus_cleanup(struct ath_softc *sc)
627{
628 sc->bus_ops->cleanup(sc);
629}
630
631extern struct ieee80211_ops ath9k_ops;
632
633irqreturn_t ath_isr(int irq, void *dev);
634void ath_cleanup(struct ath_softc *sc);
635int ath_attach(u16 devid, struct ath_softc *sc);
636void ath_detach(struct ath_softc *sc);
637const char *ath_mac_bb_name(u32 mac_bb_version);
638const char *ath_rf_name(u16 rf_version);
639void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
640void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
641 struct ath9k_channel *ichan);
642void ath_update_chainmask(struct ath_softc *sc, int is_ht);
643int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
644 struct ath9k_channel *hchan);
645void ath_radio_enable(struct ath_softc *sc);
646void ath_radio_disable(struct ath_softc *sc);
647
648#ifdef CONFIG_PCI
649int ath_pci_init(void);
650void ath_pci_exit(void);
651#else
652static inline int ath_pci_init(void) { return 0; };
653static inline void ath_pci_exit(void) {};
654#endif
655
656#ifdef CONFIG_ATHEROS_AR71XX
657int ath_ahb_init(void);
658void ath_ahb_exit(void);
659#else
660static inline int ath_ahb_init(void) { return 0; };
661static inline void ath_ahb_exit(void) {};
662#endif
663
664static inline void ath9k_ps_wakeup(struct ath_softc *sc)
665{
666 if (atomic_inc_return(&sc->ps_usecount) == 1)
667 if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) {
668 sc->sc_ah->restore_mode = sc->sc_ah->power_mode;
669 ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
670 }
671}
672
673static inline void ath9k_ps_restore(struct ath_softc *sc)
674{
675 if (atomic_dec_and_test(&sc->ps_usecount))
676 if ((sc->hw->conf.flags & IEEE80211_CONF_PS) &&
677 !(sc->sc_flags & SC_OP_WAIT_FOR_BEACON))
678 ath9k_hw_setpower(sc->sc_ah,
679 sc->sc_ah->restore_mode);
680}
681
682
683void ath9k_set_bssid_mask(struct ieee80211_hw *hw);
684int ath9k_wiphy_add(struct ath_softc *sc);
685int ath9k_wiphy_del(struct ath_wiphy *aphy);
686void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb);
687int ath9k_wiphy_pause(struct ath_wiphy *aphy);
688int ath9k_wiphy_unpause(struct ath_wiphy *aphy);
689int ath9k_wiphy_select(struct ath_wiphy *aphy);
690void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int);
691void ath9k_wiphy_chan_work(struct work_struct *work);
692bool ath9k_wiphy_started(struct ath_softc *sc);
693void ath9k_wiphy_pause_all_forced(struct ath_softc *sc,
694 struct ath_wiphy *selected);
695bool ath9k_wiphy_scanning(struct ath_softc *sc);
696void ath9k_wiphy_work(struct work_struct *work);
697
698/*
699 * Read and write, they both share the same lock. We do this to serialize
700 * reads and writes on Atheros 802.11n PCI devices only. This is required
701 * as the FIFO on these devices can only accept sanely 2 requests. After
702 * that the device goes bananas. Serializing the reads/writes prevents this
703 * from happening.
704 */
705
706static inline void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val)
707{
708 if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
709 unsigned long flags;
710 spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags);
711 iowrite32(val, ah->ah_sc->mem + reg_offset);
712 spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags);
713 } else
714 iowrite32(val, ah->ah_sc->mem + reg_offset);
715}
716
717static inline unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset)
718{
719 u32 val;
720 if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
721 unsigned long flags;
722 spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags);
723 val = ioread32(ah->ah_sc->mem + reg_offset);
724 spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags);
725 } else
726 val = ioread32(ah->ah_sc->mem + reg_offset);
727 return val;
728}
729
730#endif /* ATH9K_H */
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
new file mode 100644
index 000000000000..eb4759fc6a0d
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -0,0 +1,743 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "ath9k.h"
18
19#define FUDGE 2
20
21/*
22 * This function will modify certain transmit queue properties depending on
23 * the operating mode of the station (AP or AdHoc). Parameters are AIFS
24 * settings and channel width min/max
25*/
26static int ath_beaconq_config(struct ath_softc *sc)
27{
28 struct ath_hw *ah = sc->sc_ah;
29 struct ath9k_tx_queue_info qi;
30
31 ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
32 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
33 /* Always burst out beacon and CAB traffic. */
34 qi.tqi_aifs = 1;
35 qi.tqi_cwmin = 0;
36 qi.tqi_cwmax = 0;
37 } else {
38 /* Adhoc mode; important thing is to use 2x cwmin. */
39 qi.tqi_aifs = sc->beacon.beacon_qi.tqi_aifs;
40 qi.tqi_cwmin = 2*sc->beacon.beacon_qi.tqi_cwmin;
41 qi.tqi_cwmax = sc->beacon.beacon_qi.tqi_cwmax;
42 }
43
44 if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
45 DPRINTF(sc, ATH_DBG_FATAL,
46 "Unable to update h/w beacon queue parameters\n");
47 return 0;
48 } else {
49 ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
50 return 1;
51 }
52}
53
54/*
55 * Associates the beacon frame buffer with a transmit descriptor. Will set
56 * up all required antenna switch parameters, rate codes, and channel flags.
57 * Beacons are always sent out at the lowest rate, and are not retried.
58*/
59static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
60 struct ath_buf *bf)
61{
62 struct sk_buff *skb = bf->bf_mpdu;
63 struct ath_hw *ah = sc->sc_ah;
64 struct ath_desc *ds;
65 struct ath9k_11n_rate_series series[4];
66 struct ath_rate_table *rt;
67 int flags, antenna, ctsrate = 0, ctsduration = 0;
68 u8 rate;
69
70 ds = bf->bf_desc;
71 flags = ATH9K_TXDESC_NOACK;
72
73 if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
74 (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) &&
75 (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
76 ds->ds_link = bf->bf_daddr; /* self-linked */
77 flags |= ATH9K_TXDESC_VEOL;
78 /* Let hardware handle antenna switching. */
79 antenna = 0;
80 } else {
81 ds->ds_link = 0;
82 /*
83 * Switch antenna every beacon.
84 * Should only switch every beacon period, not for every SWBA
85 * XXX assumes two antennae
86 */
87 antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1);
88 }
89
90 ds->ds_data = bf->bf_buf_addr;
91
92 rt = sc->cur_rate_table;
93 rate = rt->info[0].ratecode;
94 if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
95 rate |= rt->info[0].short_preamble;
96
97 ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN,
98 ATH9K_PKT_TYPE_BEACON,
99 MAX_RATE_POWER,
100 ATH9K_TXKEYIX_INVALID,
101 ATH9K_KEY_TYPE_CLEAR,
102 flags);
103
104 /* NB: beacon's BufLen must be a multiple of 4 bytes */
105 ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4),
106 true, true, ds);
107
108 memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
109 series[0].Tries = 1;
110 series[0].Rate = rate;
111 series[0].ChSel = sc->tx_chainmask;
112 series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
113 ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
114 series, 4, 0);
115}
116
117static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
118 struct ieee80211_vif *vif)
119{
120 struct ath_wiphy *aphy = hw->priv;
121 struct ath_softc *sc = aphy->sc;
122 struct ath_buf *bf;
123 struct ath_vif *avp;
124 struct sk_buff *skb;
125 struct ath_txq *cabq;
126 struct ieee80211_tx_info *info;
127 int cabq_depth;
128
129 if (aphy->state != ATH_WIPHY_ACTIVE)
130 return NULL;
131
132 avp = (void *)vif->drv_priv;
133 cabq = sc->beacon.cabq;
134
135 if (avp->av_bcbuf == NULL)
136 return NULL;
137
138 /* Release the old beacon first */
139
140 bf = avp->av_bcbuf;
141 skb = bf->bf_mpdu;
142 if (skb) {
143 dma_unmap_single(sc->dev, bf->bf_dmacontext,
144 skb->len, DMA_TO_DEVICE);
145 dev_kfree_skb_any(skb);
146 }
147
148 /* Get a new beacon from mac80211 */
149
150 skb = ieee80211_beacon_get(hw, vif);
151 bf->bf_mpdu = skb;
152 if (skb == NULL)
153 return NULL;
154 ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
155 avp->tsf_adjust;
156
157 info = IEEE80211_SKB_CB(skb);
158 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
159 /*
160 * TODO: make sure the seq# gets assigned properly (vs. other
161 * TX frames)
162 */
163 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
164 sc->tx.seq_no += 0x10;
165 hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
166 hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
167 }
168
169 bf->bf_buf_addr = bf->bf_dmacontext =
170 dma_map_single(sc->dev, skb->data,
171 skb->len, DMA_TO_DEVICE);
172 if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
173 dev_kfree_skb_any(skb);
174 bf->bf_mpdu = NULL;
175 DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error on beaconing\n");
176 return NULL;
177 }
178
179 skb = ieee80211_get_buffered_bc(hw, vif);
180
181 /*
182 * if the CABQ traffic from previous DTIM is pending and the current
183 * beacon is also a DTIM.
184 * 1) if there is only one vif let the cab traffic continue.
185 * 2) if there are more than one vif and we are using staggered
186 * beacons, then drain the cabq by dropping all the frames in
187 * the cabq so that the current vifs cab traffic can be scheduled.
188 */
189 spin_lock_bh(&cabq->axq_lock);
190 cabq_depth = cabq->axq_depth;
191 spin_unlock_bh(&cabq->axq_lock);
192
193 if (skb && cabq_depth) {
194 if (sc->nvifs > 1) {
195 DPRINTF(sc, ATH_DBG_BEACON,
196 "Flushing previous cabq traffic\n");
197 ath_draintxq(sc, cabq, false);
198 }
199 }
200
201 ath_beacon_setup(sc, avp, bf);
202
203 while (skb) {
204 ath_tx_cabq(hw, skb);
205 skb = ieee80211_get_buffered_bc(hw, vif);
206 }
207
208 return bf;
209}
210
211/*
212 * Startup beacon transmission for adhoc mode when they are sent entirely
213 * by the hardware using the self-linked descriptor + veol trick.
214*/
215static void ath_beacon_start_adhoc(struct ath_softc *sc,
216 struct ieee80211_vif *vif)
217{
218 struct ath_hw *ah = sc->sc_ah;
219 struct ath_buf *bf;
220 struct ath_vif *avp;
221 struct sk_buff *skb;
222
223 avp = (void *)vif->drv_priv;
224
225 if (avp->av_bcbuf == NULL)
226 return;
227
228 bf = avp->av_bcbuf;
229 skb = bf->bf_mpdu;
230
231 ath_beacon_setup(sc, avp, bf);
232
233 /* NB: caller is known to have already stopped tx dma */
234 ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
235 ath9k_hw_txstart(ah, sc->beacon.beaconq);
236 DPRINTF(sc, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n",
237 sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc);
238}
239
240int ath_beaconq_setup(struct ath_hw *ah)
241{
242 struct ath9k_tx_queue_info qi;
243
244 memset(&qi, 0, sizeof(qi));
245 qi.tqi_aifs = 1;
246 qi.tqi_cwmin = 0;
247 qi.tqi_cwmax = 0;
248 /* NB: don't enable any interrupts */
249 return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
250}
251
252int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
253{
254 struct ath_softc *sc = aphy->sc;
255 struct ath_vif *avp;
256 struct ath_buf *bf;
257 struct sk_buff *skb;
258 __le64 tstamp;
259
260 avp = (void *)vif->drv_priv;
261
262 /* Allocate a beacon descriptor if we haven't done so. */
263 if (!avp->av_bcbuf) {
264 /* Allocate beacon state for hostap/ibss. We know
265 * a buffer is available. */
266 avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf,
267 struct ath_buf, list);
268 list_del(&avp->av_bcbuf->list);
269
270 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP ||
271 !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
272 int slot;
273 /*
274 * Assign the vif to a beacon xmit slot. As
275 * above, this cannot fail to find one.
276 */
277 avp->av_bslot = 0;
278 for (slot = 0; slot < ATH_BCBUF; slot++)
279 if (sc->beacon.bslot[slot] == NULL) {
280 /*
281 * XXX hack, space out slots to better
282 * deal with misses
283 */
284 if (slot+1 < ATH_BCBUF &&
285 sc->beacon.bslot[slot+1] == NULL) {
286 avp->av_bslot = slot+1;
287 break;
288 }
289 avp->av_bslot = slot;
290 /* NB: keep looking for a double slot */
291 }
292 BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
293 sc->beacon.bslot[avp->av_bslot] = vif;
294 sc->beacon.bslot_aphy[avp->av_bslot] = aphy;
295 sc->nbcnvifs++;
296 }
297 }
298
299 /* release the previous beacon frame, if it already exists. */
300 bf = avp->av_bcbuf;
301 if (bf->bf_mpdu != NULL) {
302 skb = bf->bf_mpdu;
303 dma_unmap_single(sc->dev, bf->bf_dmacontext,
304 skb->len, DMA_TO_DEVICE);
305 dev_kfree_skb_any(skb);
306 bf->bf_mpdu = NULL;
307 }
308
309 /* NB: the beacon data buffer must be 32-bit aligned. */
310 skb = ieee80211_beacon_get(sc->hw, vif);
311 if (skb == NULL) {
312 DPRINTF(sc, ATH_DBG_BEACON, "cannot get skb\n");
313 return -ENOMEM;
314 }
315
316 tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
317 sc->beacon.bc_tstamp = le64_to_cpu(tstamp);
318 /* Calculate a TSF adjustment factor required for staggered beacons. */
319 if (avp->av_bslot > 0) {
320 u64 tsfadjust;
321 int intval;
322
323 intval = sc->hw->conf.beacon_int ?
324 sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
325
326 /*
327 * Calculate the TSF offset for this beacon slot, i.e., the
328 * number of usecs that need to be added to the timestamp field
329 * in Beacon and Probe Response frames. Beacon slot 0 is
330 * processed at the correct offset, so it does not require TSF
331 * adjustment. Other slots are adjusted to get the timestamp
332 * close to the TBTT for the BSS.
333 */
334 tsfadjust = intval * avp->av_bslot / ATH_BCBUF;
335 avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
336
337 DPRINTF(sc, ATH_DBG_BEACON,
338 "stagger beacons, bslot %d intval %u tsfadjust %llu\n",
339 avp->av_bslot, intval, (unsigned long long)tsfadjust);
340
341 ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
342 avp->tsf_adjust;
343 } else
344 avp->tsf_adjust = cpu_to_le64(0);
345
346 bf->bf_mpdu = skb;
347 bf->bf_buf_addr = bf->bf_dmacontext =
348 dma_map_single(sc->dev, skb->data,
349 skb->len, DMA_TO_DEVICE);
350 if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
351 dev_kfree_skb_any(skb);
352 bf->bf_mpdu = NULL;
353 DPRINTF(sc, ATH_DBG_FATAL,
354 "dma_mapping_error on beacon alloc\n");
355 return -ENOMEM;
356 }
357
358 return 0;
359}
360
361void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
362{
363 if (avp->av_bcbuf != NULL) {
364 struct ath_buf *bf;
365
366 if (avp->av_bslot != -1) {
367 sc->beacon.bslot[avp->av_bslot] = NULL;
368 sc->beacon.bslot_aphy[avp->av_bslot] = NULL;
369 sc->nbcnvifs--;
370 }
371
372 bf = avp->av_bcbuf;
373 if (bf->bf_mpdu != NULL) {
374 struct sk_buff *skb = bf->bf_mpdu;
375 dma_unmap_single(sc->dev, bf->bf_dmacontext,
376 skb->len, DMA_TO_DEVICE);
377 dev_kfree_skb_any(skb);
378 bf->bf_mpdu = NULL;
379 }
380 list_add_tail(&bf->list, &sc->beacon.bbuf);
381
382 avp->av_bcbuf = NULL;
383 }
384}
385
386void ath_beacon_tasklet(unsigned long data)
387{
388 struct ath_softc *sc = (struct ath_softc *)data;
389 struct ath_hw *ah = sc->sc_ah;
390 struct ath_buf *bf = NULL;
391 struct ieee80211_vif *vif;
392 struct ath_wiphy *aphy;
393 int slot;
394 u32 bfaddr, bc = 0, tsftu;
395 u64 tsf;
396 u16 intval;
397
398 /*
399 * Check if the previous beacon has gone out. If
400 * not don't try to post another, skip this period
401 * and wait for the next. Missed beacons indicate
402 * a problem and should not occur. If we miss too
403 * many consecutive beacons reset the device.
404 */
405 if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
406 sc->beacon.bmisscnt++;
407
408 if (sc->beacon.bmisscnt < BSTUCK_THRESH) {
409 DPRINTF(sc, ATH_DBG_BEACON,
410 "missed %u consecutive beacons\n",
411 sc->beacon.bmisscnt);
412 } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
413 DPRINTF(sc, ATH_DBG_BEACON,
414 "beacon is officially stuck\n");
415 ath_reset(sc, false);
416 }
417
418 return;
419 }
420
421 if (sc->beacon.bmisscnt != 0) {
422 DPRINTF(sc, ATH_DBG_BEACON,
423 "resume beacon xmit after %u misses\n",
424 sc->beacon.bmisscnt);
425 sc->beacon.bmisscnt = 0;
426 }
427
428 /*
429 * Generate beacon frames. we are sending frames
430 * staggered so calculate the slot for this frame based
431 * on the tsf to safeguard against missing an swba.
432 */
433
434 intval = sc->hw->conf.beacon_int ?
435 sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
436
437 tsf = ath9k_hw_gettsf64(ah);
438 tsftu = TSF_TO_TU(tsf>>32, tsf);
439 slot = ((tsftu % intval) * ATH_BCBUF) / intval;
440 /*
441 * Reverse the slot order to get slot 0 on the TBTT offset that does
442 * not require TSF adjustment and other slots adding
443 * slot/ATH_BCBUF * beacon_int to timestamp. For example, with
444 * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 ..
445 * and slot 0 is at correct offset to TBTT.
446 */
447 slot = ATH_BCBUF - slot - 1;
448 vif = sc->beacon.bslot[slot];
449 aphy = sc->beacon.bslot_aphy[slot];
450
451 DPRINTF(sc, ATH_DBG_BEACON,
452 "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
453 slot, tsf, tsftu, intval, vif);
454
455 bfaddr = 0;
456 if (vif) {
457 bf = ath_beacon_generate(aphy->hw, vif);
458 if (bf != NULL) {
459 bfaddr = bf->bf_daddr;
460 bc = 1;
461 }
462 }
463
464 /*
465 * Handle slot time change when a non-ERP station joins/leaves
466 * an 11g network. The 802.11 layer notifies us via callback,
467 * we mark updateslot, then wait one beacon before effecting
468 * the change. This gives associated stations at least one
469 * beacon interval to note the state change.
470 *
471 * NB: The slot time change state machine is clocked according
472 * to whether we are bursting or staggering beacons. We
473 * recognize the request to update and record the current
474 * slot then don't transition until that slot is reached
475 * again. If we miss a beacon for that slot then we'll be
476 * slow to transition but we'll be sure at least one beacon
477 * interval has passed. When bursting slot is always left
478 * set to ATH_BCBUF so this check is a noop.
479 */
480 if (sc->beacon.updateslot == UPDATE) {
481 sc->beacon.updateslot = COMMIT; /* commit next beacon */
482 sc->beacon.slotupdate = slot;
483 } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) {
484 ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime);
485 sc->beacon.updateslot = OK;
486 }
487 if (bfaddr != 0) {
488 /*
489 * Stop any current dma and put the new frame(s) on the queue.
490 * This should never fail since we check above that no frames
491 * are still pending on the queue.
492 */
493 if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
494 DPRINTF(sc, ATH_DBG_FATAL,
495 "beacon queue %u did not stop?\n", sc->beacon.beaconq);
496 }
497
498 /* NB: cabq traffic should already be queued and primed */
499 ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
500 ath9k_hw_txstart(ah, sc->beacon.beaconq);
501
502 sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */
503 }
504}
505
506/*
507 * For multi-bss ap support beacons are either staggered evenly over N slots or
508 * burst together. For the former arrange for the SWBA to be delivered for each
509 * slot. Slots that are not occupied will generate nothing.
510 */
511static void ath_beacon_config_ap(struct ath_softc *sc,
512 struct ath_beacon_config *conf,
513 struct ath_vif *avp)
514{
515 u32 nexttbtt, intval;
516
517 /* Configure the timers only when the TSF has to be reset */
518
519 if (!(sc->sc_flags & SC_OP_TSF_RESET))
520 return;
521
522 /* NB: the beacon interval is kept internally in TU's */
523 intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
524 intval /= ATH_BCBUF; /* for staggered beacons */
525 nexttbtt = intval;
526 intval |= ATH9K_BEACON_RESET_TSF;
527
528 /*
529 * In AP mode we enable the beacon timers and SWBA interrupts to
530 * prepare beacon frames.
531 */
532 intval |= ATH9K_BEACON_ENA;
533 sc->imask |= ATH9K_INT_SWBA;
534 ath_beaconq_config(sc);
535
536 /* Set the computed AP beacon timers */
537
538 ath9k_hw_set_interrupts(sc->sc_ah, 0);
539 ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval);
540 sc->beacon.bmisscnt = 0;
541 ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
542
543 /* Clear the reset TSF flag, so that subsequent beacon updation
544 will not reset the HW TSF. */
545
546 sc->sc_flags &= ~SC_OP_TSF_RESET;
547}
548
549/*
550 * This sets up the beacon timers according to the timestamp of the last
551 * received beacon and the current TSF, configures PCF and DTIM
552 * handling, programs the sleep registers so the hardware will wakeup in
553 * time to receive beacons, and configures the beacon miss handling so
554 * we'll receive a BMISS interrupt when we stop seeing beacons from the AP
555 * we've associated with.
556 */
557static void ath_beacon_config_sta(struct ath_softc *sc,
558 struct ath_beacon_config *conf,
559 struct ath_vif *avp)
560{
561 struct ath9k_beacon_state bs;
562 int dtimperiod, dtimcount, sleepduration;
563 int cfpperiod, cfpcount;
564 u32 nexttbtt = 0, intval, tsftu;
565 u64 tsf;
566
567 memset(&bs, 0, sizeof(bs));
568 intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
569
570 /*
571 * Setup dtim and cfp parameters according to
572 * last beacon we received (which may be none).
573 */
574 dtimperiod = conf->dtim_period;
575 if (dtimperiod <= 0) /* NB: 0 if not known */
576 dtimperiod = 1;
577 dtimcount = conf->dtim_count;
578 if (dtimcount >= dtimperiod) /* NB: sanity check */
579 dtimcount = 0;
580 cfpperiod = 1; /* NB: no PCF support yet */
581 cfpcount = 0;
582
583 sleepduration = conf->listen_interval * intval;
584 if (sleepduration <= 0)
585 sleepduration = intval;
586
587 /*
588 * Pull nexttbtt forward to reflect the current
589 * TSF and calculate dtim+cfp state for the result.
590 */
591 tsf = ath9k_hw_gettsf64(sc->sc_ah);
592 tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
593 do {
594 nexttbtt += intval;
595 if (--dtimcount < 0) {
596 dtimcount = dtimperiod - 1;
597 if (--cfpcount < 0)
598 cfpcount = cfpperiod - 1;
599 }
600 } while (nexttbtt < tsftu);
601
602 bs.bs_intval = intval;
603 bs.bs_nexttbtt = nexttbtt;
604 bs.bs_dtimperiod = dtimperiod*intval;
605 bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
606 bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
607 bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
608 bs.bs_cfpmaxduration = 0;
609
610 /*
611 * Calculate the number of consecutive beacons to miss* before taking
612 * a BMISS interrupt. The configuration is specified in TU so we only
613 * need calculate based on the beacon interval. Note that we clamp the
614 * result to at most 15 beacons.
615 */
616 if (sleepduration > intval) {
617 bs.bs_bmissthreshold = conf->listen_interval *
618 ATH_DEFAULT_BMISS_LIMIT / 2;
619 } else {
620 bs.bs_bmissthreshold = DIV_ROUND_UP(conf->bmiss_timeout, intval);
621 if (bs.bs_bmissthreshold > 15)
622 bs.bs_bmissthreshold = 15;
623 else if (bs.bs_bmissthreshold <= 0)
624 bs.bs_bmissthreshold = 1;
625 }
626
627 /*
628 * Calculate sleep duration. The configuration is given in ms.
629 * We ensure a multiple of the beacon period is used. Also, if the sleep
630 * duration is greater than the DTIM period then it makes senses
631 * to make it a multiple of that.
632 *
633 * XXX fixed at 100ms
634 */
635
636 bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
637 if (bs.bs_sleepduration > bs.bs_dtimperiod)
638 bs.bs_sleepduration = bs.bs_dtimperiod;
639
640 /* TSF out of range threshold fixed at 1 second */
641 bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
642
643 DPRINTF(sc, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
644 DPRINTF(sc, ATH_DBG_BEACON,
645 "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
646 bs.bs_bmissthreshold, bs.bs_sleepduration,
647 bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
648
649 /* Set the computed STA beacon timers */
650
651 ath9k_hw_set_interrupts(sc->sc_ah, 0);
652 ath9k_hw_set_sta_beacon_timers(sc->sc_ah, &bs);
653 sc->imask |= ATH9K_INT_BMISS;
654 ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
655}
656
657static void ath_beacon_config_adhoc(struct ath_softc *sc,
658 struct ath_beacon_config *conf,
659 struct ath_vif *avp,
660 struct ieee80211_vif *vif)
661{
662 u64 tsf;
663 u32 tsftu, intval, nexttbtt;
664
665 intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
666
667 /* Pull nexttbtt forward to reflect the current TSF */
668
669 nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp);
670 if (nexttbtt == 0)
671 nexttbtt = intval;
672 else if (intval)
673 nexttbtt = roundup(nexttbtt, intval);
674
675 tsf = ath9k_hw_gettsf64(sc->sc_ah);
676 tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE;
677 do {
678 nexttbtt += intval;
679 } while (nexttbtt < tsftu);
680
681 DPRINTF(sc, ATH_DBG_BEACON,
682 "IBSS nexttbtt %u intval %u (%u)\n",
683 nexttbtt, intval, conf->beacon_interval);
684
685 /*
686 * In IBSS mode enable the beacon timers but only enable SWBA interrupts
687 * if we need to manually prepare beacon frames. Otherwise we use a
688 * self-linked tx descriptor and let the hardware deal with things.
689 */
690 intval |= ATH9K_BEACON_ENA;
691 if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL))
692 sc->imask |= ATH9K_INT_SWBA;
693
694 ath_beaconq_config(sc);
695
696 /* Set the computed ADHOC beacon timers */
697
698 ath9k_hw_set_interrupts(sc->sc_ah, 0);
699 ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval);
700 sc->beacon.bmisscnt = 0;
701 ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
702
703 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)
704 ath_beacon_start_adhoc(sc, vif);
705}
706
707void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
708{
709 struct ath_beacon_config conf;
710
711 /* Setup the beacon configuration parameters */
712
713 memset(&conf, 0, sizeof(struct ath_beacon_config));
714 conf.beacon_interval = sc->hw->conf.beacon_int ?
715 sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
716 conf.listen_interval = 1;
717 conf.dtim_period = conf.beacon_interval;
718 conf.dtim_count = 1;
719 conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval;
720
721 if (vif) {
722 struct ath_vif *avp = (struct ath_vif *)vif->drv_priv;
723
724 switch(avp->av_opmode) {
725 case NL80211_IFTYPE_AP:
726 ath_beacon_config_ap(sc, &conf, avp);
727 break;
728 case NL80211_IFTYPE_ADHOC:
729 case NL80211_IFTYPE_MESH_POINT:
730 ath_beacon_config_adhoc(sc, &conf, avp, vif);
731 break;
732 case NL80211_IFTYPE_STATION:
733 ath_beacon_config_sta(sc, &conf, avp);
734 break;
735 default:
736 DPRINTF(sc, ATH_DBG_CONFIG,
737 "Unsupported beaconing mode\n");
738 return;
739 }
740
741 sc->sc_flags |= SC_OP_BEACONS;
742 }
743}
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
new file mode 100644
index 000000000000..e2d62e97131c
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -0,0 +1,1060 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "ath9k.h"
18
19/* We can tune this as we go by monitoring really low values */
20#define ATH9K_NF_TOO_LOW -60
21
22/* AR5416 may return very high value (like -31 dBm), in those cases the nf
23 * is incorrect and we should use the static NF value. Later we can try to
24 * find out why they are reporting these values */
25
26static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf)
27{
28 if (nf > ATH9K_NF_TOO_LOW) {
29 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
30 "noise floor value detected (%d) is "
31 "lower than what we think is a "
32 "reasonable value (%d)\n",
33 nf, ATH9K_NF_TOO_LOW);
34 return false;
35 }
36 return true;
37}
38
39static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
40{
41 int16_t nfval;
42 int16_t sort[ATH9K_NF_CAL_HIST_MAX];
43 int i, j;
44
45 for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
46 sort[i] = nfCalBuffer[i];
47
48 for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
49 for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
50 if (sort[j] > sort[j - 1]) {
51 nfval = sort[j];
52 sort[j] = sort[j - 1];
53 sort[j - 1] = nfval;
54 }
55 }
56 }
57 nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
58
59 return nfval;
60}
61
62static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
63 int16_t *nfarray)
64{
65 int i;
66
67 for (i = 0; i < NUM_NF_READINGS; i++) {
68 h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
69
70 if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
71 h[i].currIndex = 0;
72
73 if (h[i].invalidNFcount > 0) {
74 if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE ||
75 nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
76 h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
77 } else {
78 h[i].invalidNFcount--;
79 h[i].privNF = nfarray[i];
80 }
81 } else {
82 h[i].privNF =
83 ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
84 }
85 }
86 return;
87}
88
89static void ath9k_hw_do_getnf(struct ath_hw *ah,
90 int16_t nfarray[NUM_NF_READINGS])
91{
92 int16_t nf;
93
94 if (AR_SREV_9280_10_OR_LATER(ah))
95 nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
96 else
97 nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
98
99 if (nf & 0x100)
100 nf = 0 - ((nf ^ 0x1ff) + 1);
101 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
102 "NF calibrated [ctl] [chain 0] is %d\n", nf);
103 nfarray[0] = nf;
104
105 if (!AR_SREV_9285(ah)) {
106 if (AR_SREV_9280_10_OR_LATER(ah))
107 nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
108 AR9280_PHY_CH1_MINCCA_PWR);
109 else
110 nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
111 AR_PHY_CH1_MINCCA_PWR);
112
113 if (nf & 0x100)
114 nf = 0 - ((nf ^ 0x1ff) + 1);
115 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
116 "NF calibrated [ctl] [chain 1] is %d\n", nf);
117 nfarray[1] = nf;
118
119 if (!AR_SREV_9280(ah)) {
120 nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
121 AR_PHY_CH2_MINCCA_PWR);
122 if (nf & 0x100)
123 nf = 0 - ((nf ^ 0x1ff) + 1);
124 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
125 "NF calibrated [ctl] [chain 2] is %d\n", nf);
126 nfarray[2] = nf;
127 }
128 }
129
130 if (AR_SREV_9280_10_OR_LATER(ah))
131 nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
132 AR9280_PHY_EXT_MINCCA_PWR);
133 else
134 nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
135 AR_PHY_EXT_MINCCA_PWR);
136
137 if (nf & 0x100)
138 nf = 0 - ((nf ^ 0x1ff) + 1);
139 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
140 "NF calibrated [ext] [chain 0] is %d\n", nf);
141 nfarray[3] = nf;
142
143 if (!AR_SREV_9285(ah)) {
144 if (AR_SREV_9280_10_OR_LATER(ah))
145 nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
146 AR9280_PHY_CH1_EXT_MINCCA_PWR);
147 else
148 nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
149 AR_PHY_CH1_EXT_MINCCA_PWR);
150
151 if (nf & 0x100)
152 nf = 0 - ((nf ^ 0x1ff) + 1);
153 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
154 "NF calibrated [ext] [chain 1] is %d\n", nf);
155 nfarray[4] = nf;
156
157 if (!AR_SREV_9280(ah)) {
158 nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
159 AR_PHY_CH2_EXT_MINCCA_PWR);
160 if (nf & 0x100)
161 nf = 0 - ((nf ^ 0x1ff) + 1);
162 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
163 "NF calibrated [ext] [chain 2] is %d\n", nf);
164 nfarray[5] = nf;
165 }
166 }
167}
168
169static bool getNoiseFloorThresh(struct ath_hw *ah,
170 enum ieee80211_band band,
171 int16_t *nft)
172{
173 switch (band) {
174 case IEEE80211_BAND_5GHZ:
175 *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5);
176 break;
177 case IEEE80211_BAND_2GHZ:
178 *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2);
179 break;
180 default:
181 BUG_ON(1);
182 return false;
183 }
184
185 return true;
186}
187
188static void ath9k_hw_setup_calibration(struct ath_hw *ah,
189 struct hal_cal_list *currCal)
190{
191 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
192 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
193 currCal->calData->calCountMax);
194
195 switch (currCal->calData->calType) {
196 case IQ_MISMATCH_CAL:
197 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
198 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
199 "starting IQ Mismatch Calibration\n");
200 break;
201 case ADC_GAIN_CAL:
202 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
203 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
204 "starting ADC Gain Calibration\n");
205 break;
206 case ADC_DC_CAL:
207 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
208 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
209 "starting ADC DC Calibration\n");
210 break;
211 case ADC_DC_INIT_CAL:
212 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
213 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
214 "starting Init ADC DC Calibration\n");
215 break;
216 }
217
218 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
219 AR_PHY_TIMING_CTRL4_DO_CAL);
220}
221
222static void ath9k_hw_reset_calibration(struct ath_hw *ah,
223 struct hal_cal_list *currCal)
224{
225 int i;
226
227 ath9k_hw_setup_calibration(ah, currCal);
228
229 currCal->calState = CAL_RUNNING;
230
231 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
232 ah->meas0.sign[i] = 0;
233 ah->meas1.sign[i] = 0;
234 ah->meas2.sign[i] = 0;
235 ah->meas3.sign[i] = 0;
236 }
237
238 ah->cal_samples = 0;
239}
240
241static void ath9k_hw_per_calibration(struct ath_hw *ah,
242 struct ath9k_channel *ichan,
243 u8 rxchainmask,
244 struct hal_cal_list *currCal,
245 bool *isCalDone)
246{
247 *isCalDone = false;
248
249 if (currCal->calState == CAL_RUNNING) {
250 if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
251 AR_PHY_TIMING_CTRL4_DO_CAL)) {
252
253 currCal->calData->calCollect(ah);
254 ah->cal_samples++;
255
256 if (ah->cal_samples >= currCal->calData->calNumSamples) {
257 int i, numChains = 0;
258 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
259 if (rxchainmask & (1 << i))
260 numChains++;
261 }
262
263 currCal->calData->calPostProc(ah, numChains);
264 ichan->CalValid |= currCal->calData->calType;
265 currCal->calState = CAL_DONE;
266 *isCalDone = true;
267 } else {
268 ath9k_hw_setup_calibration(ah, currCal);
269 }
270 }
271 } else if (!(ichan->CalValid & currCal->calData->calType)) {
272 ath9k_hw_reset_calibration(ah, currCal);
273 }
274}
275
276/* Assumes you are talking about the currently configured channel */
277static bool ath9k_hw_iscal_supported(struct ath_hw *ah,
278 enum hal_cal_types calType)
279{
280 struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
281
282 switch (calType & ah->supp_cals) {
283 case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
284 return true;
285 case ADC_GAIN_CAL:
286 case ADC_DC_CAL:
287 if (conf->channel->band == IEEE80211_BAND_5GHZ &&
288 conf_is_ht20(conf))
289 return true;
290 break;
291 }
292 return false;
293}
294
295static void ath9k_hw_iqcal_collect(struct ath_hw *ah)
296{
297 int i;
298
299 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
300 ah->totalPowerMeasI[i] +=
301 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
302 ah->totalPowerMeasQ[i] +=
303 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
304 ah->totalIqCorrMeas[i] +=
305 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
306 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
307 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
308 ah->cal_samples, i, ah->totalPowerMeasI[i],
309 ah->totalPowerMeasQ[i],
310 ah->totalIqCorrMeas[i]);
311 }
312}
313
314static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah)
315{
316 int i;
317
318 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
319 ah->totalAdcIOddPhase[i] +=
320 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
321 ah->totalAdcIEvenPhase[i] +=
322 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
323 ah->totalAdcQOddPhase[i] +=
324 REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
325 ah->totalAdcQEvenPhase[i] +=
326 REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
327
328 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
329 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
330 "oddq=0x%08x; evenq=0x%08x;\n",
331 ah->cal_samples, i,
332 ah->totalAdcIOddPhase[i],
333 ah->totalAdcIEvenPhase[i],
334 ah->totalAdcQOddPhase[i],
335 ah->totalAdcQEvenPhase[i]);
336 }
337}
338
339static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah)
340{
341 int i;
342
343 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
344 ah->totalAdcDcOffsetIOddPhase[i] +=
345 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
346 ah->totalAdcDcOffsetIEvenPhase[i] +=
347 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
348 ah->totalAdcDcOffsetQOddPhase[i] +=
349 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
350 ah->totalAdcDcOffsetQEvenPhase[i] +=
351 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
352
353 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
354 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
355 "oddq=0x%08x; evenq=0x%08x;\n",
356 ah->cal_samples, i,
357 ah->totalAdcDcOffsetIOddPhase[i],
358 ah->totalAdcDcOffsetIEvenPhase[i],
359 ah->totalAdcDcOffsetQOddPhase[i],
360 ah->totalAdcDcOffsetQEvenPhase[i]);
361 }
362}
363
364static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
365{
366 u32 powerMeasQ, powerMeasI, iqCorrMeas;
367 u32 qCoffDenom, iCoffDenom;
368 int32_t qCoff, iCoff;
369 int iqCorrNeg, i;
370
371 for (i = 0; i < numChains; i++) {
372 powerMeasI = ah->totalPowerMeasI[i];
373 powerMeasQ = ah->totalPowerMeasQ[i];
374 iqCorrMeas = ah->totalIqCorrMeas[i];
375
376 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
377 "Starting IQ Cal and Correction for Chain %d\n",
378 i);
379
380 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
381 "Orignal: Chn %diq_corr_meas = 0x%08x\n",
382 i, ah->totalIqCorrMeas[i]);
383
384 iqCorrNeg = 0;
385
386 if (iqCorrMeas > 0x80000000) {
387 iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
388 iqCorrNeg = 1;
389 }
390
391 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
392 "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
393 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
394 "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
395 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
396 iqCorrNeg);
397
398 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
399 qCoffDenom = powerMeasQ / 64;
400
401 if (powerMeasQ != 0) {
402 iCoff = iqCorrMeas / iCoffDenom;
403 qCoff = powerMeasI / qCoffDenom - 64;
404 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
405 "Chn %d iCoff = 0x%08x\n", i, iCoff);
406 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
407 "Chn %d qCoff = 0x%08x\n", i, qCoff);
408
409 iCoff = iCoff & 0x3f;
410 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
411 "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
412 if (iqCorrNeg == 0x0)
413 iCoff = 0x40 - iCoff;
414
415 if (qCoff > 15)
416 qCoff = 15;
417 else if (qCoff <= -16)
418 qCoff = 16;
419
420 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
421 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
422 i, iCoff, qCoff);
423
424 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
425 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
426 iCoff);
427 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
428 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
429 qCoff);
430 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
431 "IQ Cal and Correction done for Chain %d\n",
432 i);
433 }
434 }
435
436 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
437 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
438}
439
440static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
441{
442 u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
443 u32 qGainMismatch, iGainMismatch, val, i;
444
445 for (i = 0; i < numChains; i++) {
446 iOddMeasOffset = ah->totalAdcIOddPhase[i];
447 iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
448 qOddMeasOffset = ah->totalAdcQOddPhase[i];
449 qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
450
451 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
452 "Starting ADC Gain Cal for Chain %d\n", i);
453
454 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
455 "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
456 iOddMeasOffset);
457 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
458 "Chn %d pwr_meas_even_i = 0x%08x\n", i,
459 iEvenMeasOffset);
460 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
461 "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
462 qOddMeasOffset);
463 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
464 "Chn %d pwr_meas_even_q = 0x%08x\n", i,
465 qEvenMeasOffset);
466
467 if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
468 iGainMismatch =
469 ((iEvenMeasOffset * 32) /
470 iOddMeasOffset) & 0x3f;
471 qGainMismatch =
472 ((qOddMeasOffset * 32) /
473 qEvenMeasOffset) & 0x3f;
474
475 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
476 "Chn %d gain_mismatch_i = 0x%08x\n", i,
477 iGainMismatch);
478 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
479 "Chn %d gain_mismatch_q = 0x%08x\n", i,
480 qGainMismatch);
481
482 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
483 val &= 0xfffff000;
484 val |= (qGainMismatch) | (iGainMismatch << 6);
485 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
486
487 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
488 "ADC Gain Cal done for Chain %d\n", i);
489 }
490 }
491
492 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
493 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
494 AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
495}
496
497static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
498{
499 u32 iOddMeasOffset, iEvenMeasOffset, val, i;
500 int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
501 const struct hal_percal_data *calData =
502 ah->cal_list_curr->calData;
503 u32 numSamples =
504 (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
505
506 for (i = 0; i < numChains; i++) {
507 iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
508 iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
509 qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
510 qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
511
512 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
513 "Starting ADC DC Offset Cal for Chain %d\n", i);
514
515 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
516 "Chn %d pwr_meas_odd_i = %d\n", i,
517 iOddMeasOffset);
518 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
519 "Chn %d pwr_meas_even_i = %d\n", i,
520 iEvenMeasOffset);
521 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
522 "Chn %d pwr_meas_odd_q = %d\n", i,
523 qOddMeasOffset);
524 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
525 "Chn %d pwr_meas_even_q = %d\n", i,
526 qEvenMeasOffset);
527
528 iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
529 numSamples) & 0x1ff;
530 qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
531 numSamples) & 0x1ff;
532
533 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
534 "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
535 iDcMismatch);
536 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
537 "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
538 qDcMismatch);
539
540 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
541 val &= 0xc0000fff;
542 val |= (qDcMismatch << 12) | (iDcMismatch << 21);
543 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
544
545 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
546 "ADC DC Offset Cal done for Chain %d\n", i);
547 }
548
549 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
550 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
551 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
552}
553
554/* This is done for the currently configured channel */
555bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
556{
557 struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
558 struct hal_cal_list *currCal = ah->cal_list_curr;
559
560 if (!ah->curchan)
561 return true;
562
563 if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
564 return true;
565
566 if (currCal == NULL)
567 return true;
568
569 if (currCal->calState != CAL_DONE) {
570 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
571 "Calibration state incorrect, %d\n",
572 currCal->calState);
573 return true;
574 }
575
576 if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType))
577 return true;
578
579 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
580 "Resetting Cal %d state for channel %u\n",
581 currCal->calData->calType, conf->channel->center_freq);
582
583 ah->curchan->CalValid &= ~currCal->calData->calType;
584 currCal->calState = CAL_WAITING;
585
586 return false;
587}
588
589void ath9k_hw_start_nfcal(struct ath_hw *ah)
590{
591 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
592 AR_PHY_AGC_CONTROL_ENABLE_NF);
593 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
594 AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
595 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
596}
597
598void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
599{
600 struct ath9k_nfcal_hist *h;
601 int i, j;
602 int32_t val;
603 const u32 ar5416_cca_regs[6] = {
604 AR_PHY_CCA,
605 AR_PHY_CH1_CCA,
606 AR_PHY_CH2_CCA,
607 AR_PHY_EXT_CCA,
608 AR_PHY_CH1_EXT_CCA,
609 AR_PHY_CH2_EXT_CCA
610 };
611 u8 chainmask;
612
613 if (AR_SREV_9285(ah))
614 chainmask = 0x9;
615 else if (AR_SREV_9280(ah))
616 chainmask = 0x1B;
617 else
618 chainmask = 0x3F;
619
620 h = ah->nfCalHist;
621
622 for (i = 0; i < NUM_NF_READINGS; i++) {
623 if (chainmask & (1 << i)) {
624 val = REG_READ(ah, ar5416_cca_regs[i]);
625 val &= 0xFFFFFE00;
626 val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
627 REG_WRITE(ah, ar5416_cca_regs[i], val);
628 }
629 }
630
631 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
632 AR_PHY_AGC_CONTROL_ENABLE_NF);
633 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
634 AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
635 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
636
637 for (j = 0; j < 1000; j++) {
638 if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
639 AR_PHY_AGC_CONTROL_NF) == 0)
640 break;
641 udelay(10);
642 }
643
644 for (i = 0; i < NUM_NF_READINGS; i++) {
645 if (chainmask & (1 << i)) {
646 val = REG_READ(ah, ar5416_cca_regs[i]);
647 val &= 0xFFFFFE00;
648 val |= (((u32) (-50) << 1) & 0x1ff);
649 REG_WRITE(ah, ar5416_cca_regs[i], val);
650 }
651 }
652}
653
654int16_t ath9k_hw_getnf(struct ath_hw *ah,
655 struct ath9k_channel *chan)
656{
657 int16_t nf, nfThresh;
658 int16_t nfarray[NUM_NF_READINGS] = { 0 };
659 struct ath9k_nfcal_hist *h;
660 struct ieee80211_channel *c = chan->chan;
661
662 chan->channelFlags &= (~CHANNEL_CW_INT);
663 if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
664 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
665 "NF did not complete in calibration window\n");
666 nf = 0;
667 chan->rawNoiseFloor = nf;
668 return chan->rawNoiseFloor;
669 } else {
670 ath9k_hw_do_getnf(ah, nfarray);
671 nf = nfarray[0];
672 if (getNoiseFloorThresh(ah, c->band, &nfThresh)
673 && nf > nfThresh) {
674 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
675 "noise floor failed detected; "
676 "detected %d, threshold %d\n",
677 nf, nfThresh);
678 chan->channelFlags |= CHANNEL_CW_INT;
679 }
680 }
681
682 h = ah->nfCalHist;
683
684 ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
685 chan->rawNoiseFloor = h[0].privNF;
686
687 return chan->rawNoiseFloor;
688}
689
690void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah)
691{
692 int i, j;
693
694 for (i = 0; i < NUM_NF_READINGS; i++) {
695 ah->nfCalHist[i].currIndex = 0;
696 ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE;
697 ah->nfCalHist[i].invalidNFcount =
698 AR_PHY_CCA_FILTERWINDOW_LENGTH;
699 for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
700 ah->nfCalHist[i].nfCalBuffer[j] =
701 AR_PHY_CCA_MAX_GOOD_VALUE;
702 }
703 }
704}
705
706s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
707{
708 s16 nf;
709
710 if (chan->rawNoiseFloor == 0)
711 nf = -96;
712 else
713 nf = chan->rawNoiseFloor;
714
715 if (!ath9k_hw_nf_in_range(ah, nf))
716 nf = ATH_DEFAULT_NOISE_FLOOR;
717
718 return nf;
719}
720
721static void ath9k_olc_temp_compensation(struct ath_hw *ah)
722{
723 u32 rddata, i;
724 int delta, currPDADC, regval;
725
726 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
727
728 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
729
730 if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
731 delta = (currPDADC - ah->initPDADC + 4) / 8;
732 else
733 delta = (currPDADC - ah->initPDADC + 5) / 10;
734
735 if (delta != ah->PDADCdelta) {
736 ah->PDADCdelta = delta;
737 for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
738 regval = ah->originalGain[i] - delta;
739 if (regval < 0)
740 regval = 0;
741
742 REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4,
743 AR_PHY_TX_GAIN, regval);
744 }
745 }
746}
747
748static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
749{
750
751 u32 regVal;
752 int i, offset, offs_6_1, offs_0;
753 u32 ccomp_org, reg_field;
754 u32 regList[][2] = {
755 { 0x786c, 0 },
756 { 0x7854, 0 },
757 { 0x7820, 0 },
758 { 0x7824, 0 },
759 { 0x7868, 0 },
760 { 0x783c, 0 },
761 { 0x7838, 0 },
762 };
763
764 if (AR_SREV_9285_11(ah)) {
765 REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
766 udelay(10);
767 }
768
769 for (i = 0; i < ARRAY_SIZE(regList); i++)
770 regList[i][1] = REG_READ(ah, regList[i][0]);
771
772 regVal = REG_READ(ah, 0x7834);
773 regVal &= (~(0x1));
774 REG_WRITE(ah, 0x7834, regVal);
775 regVal = REG_READ(ah, 0x9808);
776 regVal |= (0x1 << 27);
777 REG_WRITE(ah, 0x9808, regVal);
778
779 REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
780 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
781 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
782 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
783 REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
784 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
785 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
786 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 1);
787 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
788 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
789 REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
790 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
791 ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
792 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 7);
793
794 REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
795 udelay(30);
796 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
797 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
798
799 for (i = 6; i > 0; i--) {
800 regVal = REG_READ(ah, 0x7834);
801 regVal |= (1 << (19 + i));
802 REG_WRITE(ah, 0x7834, regVal);
803 udelay(1);
804 regVal = REG_READ(ah, 0x7834);
805 regVal &= (~(0x1 << (19 + i)));
806 reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
807 regVal |= (reg_field << (19 + i));
808 REG_WRITE(ah, 0x7834, regVal);
809 }
810
811 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
812 udelay(1);
813 reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
814 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
815 offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
816 offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
817
818 offset = (offs_6_1<<1) | offs_0;
819 offset = offset - 0;
820 offs_6_1 = offset>>1;
821 offs_0 = offset & 1;
822
823 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
824 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
825
826 regVal = REG_READ(ah, 0x7834);
827 regVal |= 0x1;
828 REG_WRITE(ah, 0x7834, regVal);
829 regVal = REG_READ(ah, 0x9808);
830 regVal &= (~(0x1 << 27));
831 REG_WRITE(ah, 0x9808, regVal);
832
833 for (i = 0; i < ARRAY_SIZE(regList); i++)
834 REG_WRITE(ah, regList[i][0], regList[i][1]);
835
836 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
837
838 if (AR_SREV_9285_11(ah))
839 REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
840
841}
842
843bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
844 u8 rxchainmask, bool longcal,
845 bool *isCalDone)
846{
847 struct hal_cal_list *currCal = ah->cal_list_curr;
848
849 *isCalDone = true;
850
851 if (currCal &&
852 (currCal->calState == CAL_RUNNING ||
853 currCal->calState == CAL_WAITING)) {
854 ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal,
855 isCalDone);
856 if (*isCalDone) {
857 ah->cal_list_curr = currCal = currCal->calNext;
858
859 if (currCal->calState == CAL_WAITING) {
860 *isCalDone = false;
861 ath9k_hw_reset_calibration(ah, currCal);
862 }
863 }
864 }
865
866 if (longcal) {
867 if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
868 ath9k_hw_9285_pa_cal(ah);
869
870 if (OLC_FOR_AR9280_20_LATER)
871 ath9k_olc_temp_compensation(ah);
872 ath9k_hw_getnf(ah, chan);
873 ath9k_hw_loadnf(ah, ah->curchan);
874 ath9k_hw_start_nfcal(ah);
875
876 if (chan->channelFlags & CHANNEL_CW_INT)
877 chan->channelFlags &= ~CHANNEL_CW_INT;
878 }
879
880 return true;
881}
882
883static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
884{
885 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
886 if (chan->channelFlags & CHANNEL_HT20) {
887 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
888 REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
889 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
890 AR_PHY_AGC_CONTROL_FLTR_CAL);
891 REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
892 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
893 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
894 AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
895 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset "
896 "calibration failed to complete in "
897 "1ms; noisy ??\n");
898 return false;
899 }
900 REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
901 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
902 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
903 }
904 REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
905 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
906 REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
907 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
908 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
909 0, AH_WAIT_TIMEOUT)) {
910 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration "
911 "failed to complete in 1ms; noisy ??\n");
912 return false;
913 }
914
915 REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
916 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
917 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
918
919 return true;
920}
921
922bool ath9k_hw_init_cal(struct ath_hw *ah,
923 struct ath9k_channel *chan)
924{
925 if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
926 if (!ar9285_clc(ah, chan))
927 return false;
928 } else if (AR_SREV_9280_10_OR_LATER(ah)) {
929 REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
930 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
931 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
932
933 /* Kick off the cal */
934 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
935 REG_READ(ah, AR_PHY_AGC_CONTROL) |
936 AR_PHY_AGC_CONTROL_CAL);
937
938 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
939 AR_PHY_AGC_CONTROL_CAL, 0,
940 AH_WAIT_TIMEOUT)) {
941 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
942 "offset calibration failed to complete in 1ms; "
943 "noisy environment?\n");
944 return false;
945 }
946
947 REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
948 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
949 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
950 }
951
952 /* Calibrate the AGC */
953 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
954 REG_READ(ah, AR_PHY_AGC_CONTROL) |
955 AR_PHY_AGC_CONTROL_CAL);
956
957 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
958 0, AH_WAIT_TIMEOUT)) {
959 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
960 "offset calibration failed to complete in 1ms; "
961 "noisy environment?\n");
962 return false;
963 }
964
965 if (AR_SREV_9280_10_OR_LATER(ah)) {
966 REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
967 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
968 }
969
970 /* Do PA Calibration */
971 if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
972 ath9k_hw_9285_pa_cal(ah);
973
974 /* Do NF Calibration */
975 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
976 REG_READ(ah, AR_PHY_AGC_CONTROL) |
977 AR_PHY_AGC_CONTROL_NF);
978
979 ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
980
981 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
982 if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
983 INIT_CAL(&ah->adcgain_caldata);
984 INSERT_CAL(ah, &ah->adcgain_caldata);
985 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
986 "enabling ADC Gain Calibration.\n");
987 }
988 if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
989 INIT_CAL(&ah->adcdc_caldata);
990 INSERT_CAL(ah, &ah->adcdc_caldata);
991 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
992 "enabling ADC DC Calibration.\n");
993 }
994 if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
995 INIT_CAL(&ah->iq_caldata);
996 INSERT_CAL(ah, &ah->iq_caldata);
997 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
998 "enabling IQ Calibration.\n");
999 }
1000
1001 ah->cal_list_curr = ah->cal_list;
1002
1003 if (ah->cal_list_curr)
1004 ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
1005 }
1006
1007 chan->CalValid = 0;
1008
1009 return true;
1010}
1011
1012const struct hal_percal_data iq_cal_multi_sample = {
1013 IQ_MISMATCH_CAL,
1014 MAX_CAL_SAMPLES,
1015 PER_MIN_LOG_COUNT,
1016 ath9k_hw_iqcal_collect,
1017 ath9k_hw_iqcalibrate
1018};
1019const struct hal_percal_data iq_cal_single_sample = {
1020 IQ_MISMATCH_CAL,
1021 MIN_CAL_SAMPLES,
1022 PER_MAX_LOG_COUNT,
1023 ath9k_hw_iqcal_collect,
1024 ath9k_hw_iqcalibrate
1025};
1026const struct hal_percal_data adc_gain_cal_multi_sample = {
1027 ADC_GAIN_CAL,
1028 MAX_CAL_SAMPLES,
1029 PER_MIN_LOG_COUNT,
1030 ath9k_hw_adc_gaincal_collect,
1031 ath9k_hw_adc_gaincal_calibrate
1032};
1033const struct hal_percal_data adc_gain_cal_single_sample = {
1034 ADC_GAIN_CAL,
1035 MIN_CAL_SAMPLES,
1036 PER_MAX_LOG_COUNT,
1037 ath9k_hw_adc_gaincal_collect,
1038 ath9k_hw_adc_gaincal_calibrate
1039};
1040const struct hal_percal_data adc_dc_cal_multi_sample = {
1041 ADC_DC_CAL,
1042 MAX_CAL_SAMPLES,
1043 PER_MIN_LOG_COUNT,
1044 ath9k_hw_adc_dccal_collect,
1045 ath9k_hw_adc_dccal_calibrate
1046};
1047const struct hal_percal_data adc_dc_cal_single_sample = {
1048 ADC_DC_CAL,
1049 MIN_CAL_SAMPLES,
1050 PER_MAX_LOG_COUNT,
1051 ath9k_hw_adc_dccal_collect,
1052 ath9k_hw_adc_dccal_calibrate
1053};
1054const struct hal_percal_data adc_init_dc_cal = {
1055 ADC_DC_INIT_CAL,
1056 MIN_CAL_SAMPLES,
1057 INIT_LOG_COUNT,
1058 ath9k_hw_adc_dccal_collect,
1059 ath9k_hw_adc_dccal_calibrate
1060};
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
new file mode 100644
index 000000000000..1c74bd50700d
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -0,0 +1,124 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef CALIB_H
18#define CALIB_H
19
20extern const struct hal_percal_data iq_cal_multi_sample;
21extern const struct hal_percal_data iq_cal_single_sample;
22extern const struct hal_percal_data adc_gain_cal_multi_sample;
23extern const struct hal_percal_data adc_gain_cal_single_sample;
24extern const struct hal_percal_data adc_dc_cal_multi_sample;
25extern const struct hal_percal_data adc_dc_cal_single_sample;
26extern const struct hal_percal_data adc_init_dc_cal;
27
28#define AR_PHY_CCA_MAX_GOOD_VALUE -85
29#define AR_PHY_CCA_MAX_HIGH_VALUE -62
30#define AR_PHY_CCA_MIN_BAD_VALUE -140
31#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3
32#define AR_PHY_CCA_FILTERWINDOW_LENGTH 5
33
34#define NUM_NF_READINGS 6
35#define ATH9K_NF_CAL_HIST_MAX 5
36
37struct ar5416IniArray {
38 u32 *ia_array;
39 u32 ia_rows;
40 u32 ia_columns;
41};
42
43#define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \
44 (iniarray)->ia_array = (u32 *)(array); \
45 (iniarray)->ia_rows = (rows); \
46 (iniarray)->ia_columns = (columns); \
47 } while (0)
48
49#define INI_RA(iniarray, row, column) \
50 (((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)])
51
52#define INIT_CAL(_perCal) do { \
53 (_perCal)->calState = CAL_WAITING; \
54 (_perCal)->calNext = NULL; \
55 } while (0)
56
57#define INSERT_CAL(_ahp, _perCal) \
58 do { \
59 if ((_ahp)->cal_list_last == NULL) { \
60 (_ahp)->cal_list = \
61 (_ahp)->cal_list_last = (_perCal); \
62 ((_ahp)->cal_list_last)->calNext = (_perCal); \
63 } else { \
64 ((_ahp)->cal_list_last)->calNext = (_perCal); \
65 (_ahp)->cal_list_last = (_perCal); \
66 (_perCal)->calNext = (_ahp)->cal_list; \
67 } \
68 } while (0)
69
70enum hal_cal_types {
71 ADC_DC_INIT_CAL = 0x1,
72 ADC_GAIN_CAL = 0x2,
73 ADC_DC_CAL = 0x4,
74 IQ_MISMATCH_CAL = 0x8
75};
76
77enum hal_cal_state {
78 CAL_INACTIVE,
79 CAL_WAITING,
80 CAL_RUNNING,
81 CAL_DONE
82};
83
84#define MIN_CAL_SAMPLES 1
85#define MAX_CAL_SAMPLES 64
86#define INIT_LOG_COUNT 5
87#define PER_MIN_LOG_COUNT 2
88#define PER_MAX_LOG_COUNT 10
89
90struct hal_percal_data {
91 enum hal_cal_types calType;
92 u32 calNumSamples;
93 u32 calCountMax;
94 void (*calCollect) (struct ath_hw *);
95 void (*calPostProc) (struct ath_hw *, u8);
96};
97
98struct hal_cal_list {
99 const struct hal_percal_data *calData;
100 enum hal_cal_state calState;
101 struct hal_cal_list *calNext;
102};
103
104struct ath9k_nfcal_hist {
105 int16_t nfCalBuffer[ATH9K_NF_CAL_HIST_MAX];
106 u8 currIndex;
107 int16_t privNF;
108 u8 invalidNFcount;
109};
110
111bool ath9k_hw_reset_calvalid(struct ath_hw *ah);
112void ath9k_hw_start_nfcal(struct ath_hw *ah);
113void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
114int16_t ath9k_hw_getnf(struct ath_hw *ah,
115 struct ath9k_channel *chan);
116void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah);
117s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
118bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
119 u8 rxchainmask, bool longcal,
120 bool *isCalDone);
121bool ath9k_hw_init_cal(struct ath_hw *ah,
122 struct ath9k_channel *chan);
123
124#endif /* CALIB_H */
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
new file mode 100644
index 000000000000..97df20cbf528
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -0,0 +1,562 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <asm/unaligned.h>
18
19#include "ath9k.h"
20
21static unsigned int ath9k_debug = DBG_DEFAULT;
22module_param_named(debug, ath9k_debug, uint, 0);
23
24static struct dentry *ath9k_debugfs_root;
25
26void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...)
27{
28 if (!sc)
29 return;
30
31 if (sc->debug.debug_mask & dbg_mask) {
32 va_list args;
33
34 va_start(args, fmt);
35 printk(KERN_DEBUG "ath9k: ");
36 vprintk(fmt, args);
37 va_end(args);
38 }
39}
40
41static int ath9k_debugfs_open(struct inode *inode, struct file *file)
42{
43 file->private_data = inode->i_private;
44 return 0;
45}
46
47static ssize_t read_file_dma(struct file *file, char __user *user_buf,
48 size_t count, loff_t *ppos)
49{
50 struct ath_softc *sc = file->private_data;
51 struct ath_hw *ah = sc->sc_ah;
52 char buf[1024];
53 unsigned int len = 0;
54 u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
55 int i, qcuOffset = 0, dcuOffset = 0;
56 u32 *qcuBase = &val[0], *dcuBase = &val[4];
57
58 REG_WRITE(ah, AR_MACMISC,
59 ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
60 (AR_MACMISC_MISC_OBS_BUS_1 <<
61 AR_MACMISC_MISC_OBS_BUS_MSB_S)));
62
63 len += snprintf(buf + len, sizeof(buf) - len,
64 "Raw DMA Debug values:\n");
65
66 for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
67 if (i % 4 == 0)
68 len += snprintf(buf + len, sizeof(buf) - len, "\n");
69
70 val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32)));
71 len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ",
72 i, val[i]);
73 }
74
75 len += snprintf(buf + len, sizeof(buf) - len, "\n\n");
76 len += snprintf(buf + len, sizeof(buf) - len,
77 "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
78
79 for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) {
80 if (i == 8) {
81 qcuOffset = 0;
82 qcuBase++;
83 }
84
85 if (i == 6) {
86 dcuOffset = 0;
87 dcuBase++;
88 }
89
90 len += snprintf(buf + len, sizeof(buf) - len,
91 "%2d %2x %1x %2x %2x\n",
92 i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
93 (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
94 val[2] & (0x7 << (i * 3)) >> (i * 3),
95 (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
96 }
97
98 len += snprintf(buf + len, sizeof(buf) - len, "\n");
99
100 len += snprintf(buf + len, sizeof(buf) - len,
101 "qcu_stitch state: %2x qcu_fetch state: %2x\n",
102 (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
103 len += snprintf(buf + len, sizeof(buf) - len,
104 "qcu_complete state: %2x dcu_complete state: %2x\n",
105 (val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
106 len += snprintf(buf + len, sizeof(buf) - len,
107 "dcu_arb state: %2x dcu_fp state: %2x\n",
108 (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
109 len += snprintf(buf + len, sizeof(buf) - len,
110 "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n",
111 (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
112 len += snprintf(buf + len, sizeof(buf) - len,
113 "txfifo_valid_0: %1d txfifo_valid_1: %1d\n",
114 (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
115 len += snprintf(buf + len, sizeof(buf) - len,
116 "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n",
117 (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
118
119 len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n",
120 REG_READ(ah, AR_OBS_BUS_1));
121 len += snprintf(buf + len, sizeof(buf) - len,
122 "AR_CR: 0x%x \n", REG_READ(ah, AR_CR));
123
124 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
125}
126
127static const struct file_operations fops_dma = {
128 .read = read_file_dma,
129 .open = ath9k_debugfs_open,
130 .owner = THIS_MODULE
131};
132
133
134void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
135{
136 if (status)
137 sc->debug.stats.istats.total++;
138 if (status & ATH9K_INT_RX)
139 sc->debug.stats.istats.rxok++;
140 if (status & ATH9K_INT_RXEOL)
141 sc->debug.stats.istats.rxeol++;
142 if (status & ATH9K_INT_RXORN)
143 sc->debug.stats.istats.rxorn++;
144 if (status & ATH9K_INT_TX)
145 sc->debug.stats.istats.txok++;
146 if (status & ATH9K_INT_TXURN)
147 sc->debug.stats.istats.txurn++;
148 if (status & ATH9K_INT_MIB)
149 sc->debug.stats.istats.mib++;
150 if (status & ATH9K_INT_RXPHY)
151 sc->debug.stats.istats.rxphyerr++;
152 if (status & ATH9K_INT_RXKCM)
153 sc->debug.stats.istats.rx_keycache_miss++;
154 if (status & ATH9K_INT_SWBA)
155 sc->debug.stats.istats.swba++;
156 if (status & ATH9K_INT_BMISS)
157 sc->debug.stats.istats.bmiss++;
158 if (status & ATH9K_INT_BNR)
159 sc->debug.stats.istats.bnr++;
160 if (status & ATH9K_INT_CST)
161 sc->debug.stats.istats.cst++;
162 if (status & ATH9K_INT_GTT)
163 sc->debug.stats.istats.gtt++;
164 if (status & ATH9K_INT_TIM)
165 sc->debug.stats.istats.tim++;
166 if (status & ATH9K_INT_CABEND)
167 sc->debug.stats.istats.cabend++;
168 if (status & ATH9K_INT_DTIMSYNC)
169 sc->debug.stats.istats.dtimsync++;
170 if (status & ATH9K_INT_DTIM)
171 sc->debug.stats.istats.dtim++;
172}
173
174static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
175 size_t count, loff_t *ppos)
176{
177 struct ath_softc *sc = file->private_data;
178 char buf[512];
179 unsigned int len = 0;
180
181 len += snprintf(buf + len, sizeof(buf) - len,
182 "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok);
183 len += snprintf(buf + len, sizeof(buf) - len,
184 "%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol);
185 len += snprintf(buf + len, sizeof(buf) - len,
186 "%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn);
187 len += snprintf(buf + len, sizeof(buf) - len,
188 "%8s: %10u\n", "TX", sc->debug.stats.istats.txok);
189 len += snprintf(buf + len, sizeof(buf) - len,
190 "%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn);
191 len += snprintf(buf + len, sizeof(buf) - len,
192 "%8s: %10u\n", "MIB", sc->debug.stats.istats.mib);
193 len += snprintf(buf + len, sizeof(buf) - len,
194 "%8s: %10u\n", "RXPHY", sc->debug.stats.istats.rxphyerr);
195 len += snprintf(buf + len, sizeof(buf) - len,
196 "%8s: %10u\n", "RXKCM", sc->debug.stats.istats.rx_keycache_miss);
197 len += snprintf(buf + len, sizeof(buf) - len,
198 "%8s: %10u\n", "SWBA", sc->debug.stats.istats.swba);
199 len += snprintf(buf + len, sizeof(buf) - len,
200 "%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss);
201 len += snprintf(buf + len, sizeof(buf) - len,
202 "%8s: %10u\n", "BNR", sc->debug.stats.istats.bnr);
203 len += snprintf(buf + len, sizeof(buf) - len,
204 "%8s: %10u\n", "CST", sc->debug.stats.istats.cst);
205 len += snprintf(buf + len, sizeof(buf) - len,
206 "%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt);
207 len += snprintf(buf + len, sizeof(buf) - len,
208 "%8s: %10u\n", "TIM", sc->debug.stats.istats.tim);
209 len += snprintf(buf + len, sizeof(buf) - len,
210 "%8s: %10u\n", "CABEND", sc->debug.stats.istats.cabend);
211 len += snprintf(buf + len, sizeof(buf) - len,
212 "%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync);
213 len += snprintf(buf + len, sizeof(buf) - len,
214 "%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim);
215 len += snprintf(buf + len, sizeof(buf) - len,
216 "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total);
217
218 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
219}
220
221static const struct file_operations fops_interrupt = {
222 .read = read_file_interrupt,
223 .open = ath9k_debugfs_open,
224 .owner = THIS_MODULE
225};
226
227static void ath_debug_stat_11n_rc(struct ath_softc *sc, struct sk_buff *skb)
228{
229 struct ath_tx_info_priv *tx_info_priv = NULL;
230 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
231 struct ieee80211_tx_rate *rates = tx_info->status.rates;
232 int final_ts_idx, idx;
233
234 tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
235 final_ts_idx = tx_info_priv->tx.ts_rateindex;
236 idx = sc->cur_rate_table->info[rates[final_ts_idx].idx].dot11rate;
237
238 sc->debug.stats.n_rcstats[idx].success++;
239}
240
241static void ath_debug_stat_legacy_rc(struct ath_softc *sc, struct sk_buff *skb)
242{
243 struct ath_tx_info_priv *tx_info_priv = NULL;
244 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
245 struct ieee80211_tx_rate *rates = tx_info->status.rates;
246 int final_ts_idx, idx;
247
248 tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
249 final_ts_idx = tx_info_priv->tx.ts_rateindex;
250 idx = rates[final_ts_idx].idx;
251
252 sc->debug.stats.legacy_rcstats[idx].success++;
253}
254
255void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb)
256{
257 if (conf_is_ht(&sc->hw->conf))
258 ath_debug_stat_11n_rc(sc, skb);
259 else
260 ath_debug_stat_legacy_rc(sc, skb);
261}
262
263/* FIXME: legacy rates, later on .. */
264void ath_debug_stat_retries(struct ath_softc *sc, int rix,
265 int xretries, int retries, u8 per)
266{
267 if (conf_is_ht(&sc->hw->conf)) {
268 int idx = sc->cur_rate_table->info[rix].dot11rate;
269
270 sc->debug.stats.n_rcstats[idx].xretries += xretries;
271 sc->debug.stats.n_rcstats[idx].retries += retries;
272 sc->debug.stats.n_rcstats[idx].per = per;
273 }
274}
275
276static ssize_t ath_read_file_stat_11n_rc(struct file *file,
277 char __user *user_buf,
278 size_t count, loff_t *ppos)
279{
280 struct ath_softc *sc = file->private_data;
281 char buf[1024];
282 unsigned int len = 0;
283 int i = 0;
284
285 len += sprintf(buf, "%7s %13s %8s %8s %6s\n\n", "Rate", "Success",
286 "Retries", "XRetries", "PER");
287
288 for (i = 0; i <= 15; i++) {
289 len += snprintf(buf + len, sizeof(buf) - len,
290 "%5s%3d: %8u %8u %8u %8u\n", "MCS", i,
291 sc->debug.stats.n_rcstats[i].success,
292 sc->debug.stats.n_rcstats[i].retries,
293 sc->debug.stats.n_rcstats[i].xretries,
294 sc->debug.stats.n_rcstats[i].per);
295 }
296
297 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
298}
299
300static ssize_t ath_read_file_stat_legacy_rc(struct file *file,
301 char __user *user_buf,
302 size_t count, loff_t *ppos)
303{
304 struct ath_softc *sc = file->private_data;
305 char buf[512];
306 unsigned int len = 0;
307 int i = 0;
308
309 len += sprintf(buf, "%7s %13s\n\n", "Rate", "Success");
310
311 for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) {
312 len += snprintf(buf + len, sizeof(buf) - len, "%5u: %12u\n",
313 sc->cur_rate_table->info[i].ratekbps / 1000,
314 sc->debug.stats.legacy_rcstats[i].success);
315 }
316
317 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
318}
319
320static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
321 size_t count, loff_t *ppos)
322{
323 struct ath_softc *sc = file->private_data;
324
325 if (sc->cur_rate_table == NULL)
326 return 0;
327
328 if (conf_is_ht(&sc->hw->conf))
329 return ath_read_file_stat_11n_rc(file, user_buf, count, ppos);
330 else
331 return ath_read_file_stat_legacy_rc(file, user_buf, count ,ppos);
332}
333
334static const struct file_operations fops_rcstat = {
335 .read = read_file_rcstat,
336 .open = ath9k_debugfs_open,
337 .owner = THIS_MODULE
338};
339
340static const char * ath_wiphy_state_str(enum ath_wiphy_state state)
341{
342 switch (state) {
343 case ATH_WIPHY_INACTIVE:
344 return "INACTIVE";
345 case ATH_WIPHY_ACTIVE:
346 return "ACTIVE";
347 case ATH_WIPHY_PAUSING:
348 return "PAUSING";
349 case ATH_WIPHY_PAUSED:
350 return "PAUSED";
351 case ATH_WIPHY_SCAN:
352 return "SCAN";
353 }
354 return "?";
355}
356
357static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
358 size_t count, loff_t *ppos)
359{
360 struct ath_softc *sc = file->private_data;
361 char buf[512];
362 unsigned int len = 0;
363 int i;
364 u8 addr[ETH_ALEN];
365
366 len += snprintf(buf + len, sizeof(buf) - len,
367 "primary: %s (%s chan=%d ht=%d)\n",
368 wiphy_name(sc->pri_wiphy->hw->wiphy),
369 ath_wiphy_state_str(sc->pri_wiphy->state),
370 sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht);
371 for (i = 0; i < sc->num_sec_wiphy; i++) {
372 struct ath_wiphy *aphy = sc->sec_wiphy[i];
373 if (aphy == NULL)
374 continue;
375 len += snprintf(buf + len, sizeof(buf) - len,
376 "secondary: %s (%s chan=%d ht=%d)\n",
377 wiphy_name(aphy->hw->wiphy),
378 ath_wiphy_state_str(aphy->state),
379 aphy->chan_idx, aphy->chan_is_ht);
380 }
381
382 put_unaligned_le32(REG_READ(sc->sc_ah, AR_STA_ID0), addr);
383 put_unaligned_le16(REG_READ(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4);
384 len += snprintf(buf + len, sizeof(buf) - len,
385 "addr: %pM\n", addr);
386 put_unaligned_le32(REG_READ(sc->sc_ah, AR_BSSMSKL), addr);
387 put_unaligned_le16(REG_READ(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4);
388 len += snprintf(buf + len, sizeof(buf) - len,
389 "addrmask: %pM\n", addr);
390
391 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
392}
393
394static struct ath_wiphy * get_wiphy(struct ath_softc *sc, const char *name)
395{
396 int i;
397 if (strcmp(name, wiphy_name(sc->pri_wiphy->hw->wiphy)) == 0)
398 return sc->pri_wiphy;
399 for (i = 0; i < sc->num_sec_wiphy; i++) {
400 struct ath_wiphy *aphy = sc->sec_wiphy[i];
401 if (aphy && strcmp(name, wiphy_name(aphy->hw->wiphy)) == 0)
402 return aphy;
403 }
404 return NULL;
405}
406
407static int del_wiphy(struct ath_softc *sc, const char *name)
408{
409 struct ath_wiphy *aphy = get_wiphy(sc, name);
410 if (!aphy)
411 return -ENOENT;
412 return ath9k_wiphy_del(aphy);
413}
414
415static int pause_wiphy(struct ath_softc *sc, const char *name)
416{
417 struct ath_wiphy *aphy = get_wiphy(sc, name);
418 if (!aphy)
419 return -ENOENT;
420 return ath9k_wiphy_pause(aphy);
421}
422
423static int unpause_wiphy(struct ath_softc *sc, const char *name)
424{
425 struct ath_wiphy *aphy = get_wiphy(sc, name);
426 if (!aphy)
427 return -ENOENT;
428 return ath9k_wiphy_unpause(aphy);
429}
430
431static int select_wiphy(struct ath_softc *sc, const char *name)
432{
433 struct ath_wiphy *aphy = get_wiphy(sc, name);
434 if (!aphy)
435 return -ENOENT;
436 return ath9k_wiphy_select(aphy);
437}
438
439static int schedule_wiphy(struct ath_softc *sc, const char *msec)
440{
441 ath9k_wiphy_set_scheduler(sc, simple_strtoul(msec, NULL, 0));
442 return 0;
443}
444
445static ssize_t write_file_wiphy(struct file *file, const char __user *user_buf,
446 size_t count, loff_t *ppos)
447{
448 struct ath_softc *sc = file->private_data;
449 char buf[50];
450 size_t len;
451
452 len = min(count, sizeof(buf) - 1);
453 if (copy_from_user(buf, user_buf, len))
454 return -EFAULT;
455 buf[len] = '\0';
456 if (len > 0 && buf[len - 1] == '\n')
457 buf[len - 1] = '\0';
458
459 if (strncmp(buf, "add", 3) == 0) {
460 int res = ath9k_wiphy_add(sc);
461 if (res < 0)
462 return res;
463 } else if (strncmp(buf, "del=", 4) == 0) {
464 int res = del_wiphy(sc, buf + 4);
465 if (res < 0)
466 return res;
467 } else if (strncmp(buf, "pause=", 6) == 0) {
468 int res = pause_wiphy(sc, buf + 6);
469 if (res < 0)
470 return res;
471 } else if (strncmp(buf, "unpause=", 8) == 0) {
472 int res = unpause_wiphy(sc, buf + 8);
473 if (res < 0)
474 return res;
475 } else if (strncmp(buf, "select=", 7) == 0) {
476 int res = select_wiphy(sc, buf + 7);
477 if (res < 0)
478 return res;
479 } else if (strncmp(buf, "schedule=", 9) == 0) {
480 int res = schedule_wiphy(sc, buf + 9);
481 if (res < 0)
482 return res;
483 } else
484 return -EOPNOTSUPP;
485
486 return count;
487}
488
489static const struct file_operations fops_wiphy = {
490 .read = read_file_wiphy,
491 .write = write_file_wiphy,
492 .open = ath9k_debugfs_open,
493 .owner = THIS_MODULE
494};
495
496
497int ath9k_init_debug(struct ath_softc *sc)
498{
499 sc->debug.debug_mask = ath9k_debug;
500
501 if (!ath9k_debugfs_root)
502 return -ENOENT;
503
504 sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
505 ath9k_debugfs_root);
506 if (!sc->debug.debugfs_phy)
507 goto err;
508
509 sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUGO,
510 sc->debug.debugfs_phy, sc, &fops_dma);
511 if (!sc->debug.debugfs_dma)
512 goto err;
513
514 sc->debug.debugfs_interrupt = debugfs_create_file("interrupt",
515 S_IRUGO,
516 sc->debug.debugfs_phy,
517 sc, &fops_interrupt);
518 if (!sc->debug.debugfs_interrupt)
519 goto err;
520
521 sc->debug.debugfs_rcstat = debugfs_create_file("rcstat",
522 S_IRUGO,
523 sc->debug.debugfs_phy,
524 sc, &fops_rcstat);
525 if (!sc->debug.debugfs_rcstat)
526 goto err;
527
528 sc->debug.debugfs_wiphy = debugfs_create_file(
529 "wiphy", S_IRUGO | S_IWUSR, sc->debug.debugfs_phy, sc,
530 &fops_wiphy);
531 if (!sc->debug.debugfs_wiphy)
532 goto err;
533
534 return 0;
535err:
536 ath9k_exit_debug(sc);
537 return -ENOMEM;
538}
539
540void ath9k_exit_debug(struct ath_softc *sc)
541{
542 debugfs_remove(sc->debug.debugfs_wiphy);
543 debugfs_remove(sc->debug.debugfs_rcstat);
544 debugfs_remove(sc->debug.debugfs_interrupt);
545 debugfs_remove(sc->debug.debugfs_dma);
546 debugfs_remove(sc->debug.debugfs_phy);
547}
548
549int ath9k_debug_create_root(void)
550{
551 ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
552 if (!ath9k_debugfs_root)
553 return -ENOENT;
554
555 return 0;
556}
557
558void ath9k_debug_remove_root(void)
559{
560 debugfs_remove(ath9k_debugfs_root);
561 ath9k_debugfs_root = NULL;
562}
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
new file mode 100644
index 000000000000..23298b90b52b
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -0,0 +1,161 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef DEBUG_H
18#define DEBUG_H
19
20enum ATH_DEBUG {
21 ATH_DBG_RESET = 0x00000001,
22 ATH_DBG_QUEUE = 0x00000002,
23 ATH_DBG_EEPROM = 0x00000004,
24 ATH_DBG_CALIBRATE = 0x00000008,
25 ATH_DBG_INTERRUPT = 0x00000010,
26 ATH_DBG_REGULATORY = 0x00000020,
27 ATH_DBG_ANI = 0x00000040,
28 ATH_DBG_XMIT = 0x00000080,
29 ATH_DBG_BEACON = 0x00000100,
30 ATH_DBG_CONFIG = 0x00000200,
31 ATH_DBG_FATAL = 0x00000400,
32 ATH_DBG_ANY = 0xffffffff
33};
34
35#define DBG_DEFAULT (ATH_DBG_FATAL)
36
37#ifdef CONFIG_ATH9K_DEBUG
38
39/**
40 * struct ath_interrupt_stats - Contains statistics about interrupts
41 * @total: Total no. of interrupts generated so far
42 * @rxok: RX with no errors
43 * @rxeol: RX with no more RXDESC available
44 * @rxorn: RX FIFO overrun
45 * @txok: TX completed at the requested rate
46 * @txurn: TX FIFO underrun
47 * @mib: MIB regs reaching its threshold
48 * @rxphyerr: RX with phy errors
49 * @rx_keycache_miss: RX with key cache misses
50 * @swba: Software Beacon Alert
51 * @bmiss: Beacon Miss
52 * @bnr: Beacon Not Ready
53 * @cst: Carrier Sense TImeout
54 * @gtt: Global TX Timeout
55 * @tim: RX beacon TIM occurrence
56 * @cabend: RX End of CAB traffic
57 * @dtimsync: DTIM sync lossage
58 * @dtim: RX Beacon with DTIM
59 */
60struct ath_interrupt_stats {
61 u32 total;
62 u32 rxok;
63 u32 rxeol;
64 u32 rxorn;
65 u32 txok;
66 u32 txeol;
67 u32 txurn;
68 u32 mib;
69 u32 rxphyerr;
70 u32 rx_keycache_miss;
71 u32 swba;
72 u32 bmiss;
73 u32 bnr;
74 u32 cst;
75 u32 gtt;
76 u32 tim;
77 u32 cabend;
78 u32 dtimsync;
79 u32 dtim;
80};
81
82struct ath_legacy_rc_stats {
83 u32 success;
84};
85
86struct ath_11n_rc_stats {
87 u32 success;
88 u32 retries;
89 u32 xretries;
90 u8 per;
91};
92
93struct ath_stats {
94 struct ath_interrupt_stats istats;
95 struct ath_legacy_rc_stats legacy_rcstats[12]; /* max(11a,11b,11g) */
96 struct ath_11n_rc_stats n_rcstats[16]; /* 0..15 MCS rates */
97};
98
99struct ath9k_debug {
100 int debug_mask;
101 struct dentry *debugfs_phy;
102 struct dentry *debugfs_dma;
103 struct dentry *debugfs_interrupt;
104 struct dentry *debugfs_rcstat;
105 struct dentry *debugfs_wiphy;
106 struct ath_stats stats;
107};
108
109void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...);
110int ath9k_init_debug(struct ath_softc *sc);
111void ath9k_exit_debug(struct ath_softc *sc);
112int ath9k_debug_create_root(void);
113void ath9k_debug_remove_root(void);
114void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
115void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb);
116void ath_debug_stat_retries(struct ath_softc *sc, int rix,
117 int xretries, int retries, u8 per);
118
119#else
120
121static inline void DPRINTF(struct ath_softc *sc, int dbg_mask,
122 const char *fmt, ...)
123{
124}
125
126static inline int ath9k_init_debug(struct ath_softc *sc)
127{
128 return 0;
129}
130
131static inline void ath9k_exit_debug(struct ath_softc *sc)
132{
133}
134
135static inline int ath9k_debug_create_root(void)
136{
137 return 0;
138}
139
140static inline void ath9k_debug_remove_root(void)
141{
142}
143
144static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
145 enum ath9k_int status)
146{
147}
148
149static inline void ath_debug_stat_rc(struct ath_softc *sc,
150 struct sk_buff *skb)
151{
152}
153
154static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix,
155 int xretries, int retries, u8 per)
156{
157}
158
159#endif /* CONFIG_ATH9K_DEBUG */
160
161#endif /* DEBUG_H */
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
new file mode 100644
index 000000000000..44fee5ae8925
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -0,0 +1,2813 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "ath9k.h"
18
19static void ath9k_hw_analog_shift_rmw(struct ath_hw *ah,
20 u32 reg, u32 mask,
21 u32 shift, u32 val)
22{
23 u32 regVal;
24
25 regVal = REG_READ(ah, reg) & ~mask;
26 regVal |= (val << shift) & mask;
27
28 REG_WRITE(ah, reg, regVal);
29
30 if (ah->config.analog_shiftreg)
31 udelay(100);
32
33 return;
34}
35
36static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
37{
38
39 if (fbin == AR5416_BCHAN_UNUSED)
40 return fbin;
41
42 return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
43}
44
45static inline int16_t ath9k_hw_interpolate(u16 target,
46 u16 srcLeft, u16 srcRight,
47 int16_t targetLeft,
48 int16_t targetRight)
49{
50 int16_t rv;
51
52 if (srcRight == srcLeft) {
53 rv = targetLeft;
54 } else {
55 rv = (int16_t) (((target - srcLeft) * targetRight +
56 (srcRight - target) * targetLeft) /
57 (srcRight - srcLeft));
58 }
59 return rv;
60}
61
62static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList,
63 u16 listSize, u16 *indexL,
64 u16 *indexR)
65{
66 u16 i;
67
68 if (target <= pList[0]) {
69 *indexL = *indexR = 0;
70 return true;
71 }
72 if (target >= pList[listSize - 1]) {
73 *indexL = *indexR = (u16) (listSize - 1);
74 return true;
75 }
76
77 for (i = 0; i < listSize - 1; i++) {
78 if (pList[i] == target) {
79 *indexL = *indexR = i;
80 return true;
81 }
82 if (target < pList[i + 1]) {
83 *indexL = i;
84 *indexR = (u16) (i + 1);
85 return false;
86 }
87 }
88 return false;
89}
90
91static inline bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
92{
93 struct ath_softc *sc = ah->ah_sc;
94
95 return sc->bus_ops->eeprom_read(ah, off, data);
96}
97
98static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
99 u8 *pVpdList, u16 numIntercepts,
100 u8 *pRetVpdList)
101{
102 u16 i, k;
103 u8 currPwr = pwrMin;
104 u16 idxL = 0, idxR = 0;
105
106 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
107 ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
108 numIntercepts, &(idxL),
109 &(idxR));
110 if (idxR < 1)
111 idxR = 1;
112 if (idxL == numIntercepts - 1)
113 idxL = (u16) (numIntercepts - 2);
114 if (pPwrList[idxL] == pPwrList[idxR])
115 k = pVpdList[idxL];
116 else
117 k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] +
118 (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
119 (pPwrList[idxR] - pPwrList[idxL]));
120 pRetVpdList[i] = (u8) k;
121 currPwr += 2;
122 }
123
124 return true;
125}
126
127static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
128 struct ath9k_channel *chan,
129 struct cal_target_power_leg *powInfo,
130 u16 numChannels,
131 struct cal_target_power_leg *pNewPower,
132 u16 numRates, bool isExtTarget)
133{
134 struct chan_centers centers;
135 u16 clo, chi;
136 int i;
137 int matchIndex = -1, lowIndex = -1;
138 u16 freq;
139
140 ath9k_hw_get_channel_centers(ah, chan, &centers);
141 freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
142
143 if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
144 IS_CHAN_2GHZ(chan))) {
145 matchIndex = 0;
146 } else {
147 for (i = 0; (i < numChannels) &&
148 (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
149 if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
150 IS_CHAN_2GHZ(chan))) {
151 matchIndex = i;
152 break;
153 } else if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
154 IS_CHAN_2GHZ(chan))) &&
155 (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
156 IS_CHAN_2GHZ(chan)))) {
157 lowIndex = i - 1;
158 break;
159 }
160 }
161 if ((matchIndex == -1) && (lowIndex == -1))
162 matchIndex = i - 1;
163 }
164
165 if (matchIndex != -1) {
166 *pNewPower = powInfo[matchIndex];
167 } else {
168 clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
169 IS_CHAN_2GHZ(chan));
170 chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
171 IS_CHAN_2GHZ(chan));
172
173 for (i = 0; i < numRates; i++) {
174 pNewPower->tPow2x[i] =
175 (u8)ath9k_hw_interpolate(freq, clo, chi,
176 powInfo[lowIndex].tPow2x[i],
177 powInfo[lowIndex + 1].tPow2x[i]);
178 }
179 }
180}
181
182static void ath9k_get_txgain_index(struct ath_hw *ah,
183 struct ath9k_channel *chan,
184 struct calDataPerFreqOpLoop *rawDatasetOpLoop,
185 u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx)
186{
187 u8 pcdac, i = 0;
188 u16 idxL = 0, idxR = 0, numPiers;
189 bool match;
190 struct chan_centers centers;
191
192 ath9k_hw_get_channel_centers(ah, chan, &centers);
193
194 for (numPiers = 0; numPiers < availPiers; numPiers++)
195 if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
196 break;
197
198 match = ath9k_hw_get_lower_upper_index(
199 (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
200 calChans, numPiers, &idxL, &idxR);
201 if (match) {
202 pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
203 *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
204 } else {
205 pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
206 *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
207 rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
208 }
209
210 while (pcdac > ah->originalGain[i] &&
211 i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
212 i++;
213
214 *pcdacIdx = i;
215 return;
216}
217
218static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
219 u32 initTxGain,
220 int txPower,
221 u8 *pPDADCValues)
222{
223 u32 i;
224 u32 offset;
225
226 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
227 AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
228 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
229 AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
230
231 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
232 AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
233
234 offset = txPower;
235 for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
236 if (i < offset)
237 pPDADCValues[i] = 0x0;
238 else
239 pPDADCValues[i] = 0xFF;
240}
241
242
243
244
245static void ath9k_hw_get_target_powers(struct ath_hw *ah,
246 struct ath9k_channel *chan,
247 struct cal_target_power_ht *powInfo,
248 u16 numChannels,
249 struct cal_target_power_ht *pNewPower,
250 u16 numRates, bool isHt40Target)
251{
252 struct chan_centers centers;
253 u16 clo, chi;
254 int i;
255 int matchIndex = -1, lowIndex = -1;
256 u16 freq;
257
258 ath9k_hw_get_channel_centers(ah, chan, &centers);
259 freq = isHt40Target ? centers.synth_center : centers.ctl_center;
260
261 if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
262 matchIndex = 0;
263 } else {
264 for (i = 0; (i < numChannels) &&
265 (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
266 if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
267 IS_CHAN_2GHZ(chan))) {
268 matchIndex = i;
269 break;
270 } else
271 if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
272 IS_CHAN_2GHZ(chan))) &&
273 (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
274 IS_CHAN_2GHZ(chan)))) {
275 lowIndex = i - 1;
276 break;
277 }
278 }
279 if ((matchIndex == -1) && (lowIndex == -1))
280 matchIndex = i - 1;
281 }
282
283 if (matchIndex != -1) {
284 *pNewPower = powInfo[matchIndex];
285 } else {
286 clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
287 IS_CHAN_2GHZ(chan));
288 chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
289 IS_CHAN_2GHZ(chan));
290
291 for (i = 0; i < numRates; i++) {
292 pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq,
293 clo, chi,
294 powInfo[lowIndex].tPow2x[i],
295 powInfo[lowIndex + 1].tPow2x[i]);
296 }
297 }
298}
299
300static u16 ath9k_hw_get_max_edge_power(u16 freq,
301 struct cal_ctl_edges *pRdEdgesPower,
302 bool is2GHz, int num_band_edges)
303{
304 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
305 int i;
306
307 for (i = 0; (i < num_band_edges) &&
308 (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
309 if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
310 twiceMaxEdgePower = pRdEdgesPower[i].tPower;
311 break;
312 } else if ((i > 0) &&
313 (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
314 is2GHz))) {
315 if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
316 is2GHz) < freq &&
317 pRdEdgesPower[i - 1].flag) {
318 twiceMaxEdgePower =
319 pRdEdgesPower[i - 1].tPower;
320 }
321 break;
322 }
323 }
324
325 return twiceMaxEdgePower;
326}
327
328/****************************************/
329/* EEPROM Operations for 4K sized cards */
330/****************************************/
331
332static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
333{
334 return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF);
335}
336
337static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
338{
339 return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF);
340}
341
342static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
343{
344#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
345 u16 *eep_data = (u16 *)&ah->eeprom.map4k;
346 int addr, eep_start_loc = 0;
347
348 eep_start_loc = 64;
349
350 if (!ath9k_hw_use_flash(ah)) {
351 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
352 "Reading from EEPROM, not flash\n");
353 }
354
355 for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
356 if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
357 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
358 "Unable to read eeprom region \n");
359 return false;
360 }
361 eep_data++;
362 }
363
364 return true;
365#undef SIZE_EEPROM_4K
366}
367
368static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
369{
370#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
371 struct ar5416_eeprom_4k *eep =
372 (struct ar5416_eeprom_4k *) &ah->eeprom.map4k;
373 u16 *eepdata, temp, magic, magic2;
374 u32 sum = 0, el;
375 bool need_swap = false;
376 int i, addr;
377
378
379 if (!ath9k_hw_use_flash(ah)) {
380 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
381 &magic)) {
382 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
383 "Reading Magic # failed\n");
384 return false;
385 }
386
387 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
388 "Read Magic = 0x%04X\n", magic);
389
390 if (magic != AR5416_EEPROM_MAGIC) {
391 magic2 = swab16(magic);
392
393 if (magic2 == AR5416_EEPROM_MAGIC) {
394 need_swap = true;
395 eepdata = (u16 *) (&ah->eeprom);
396
397 for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
398 temp = swab16(*eepdata);
399 *eepdata = temp;
400 eepdata++;
401 }
402 } else {
403 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
404 "Invalid EEPROM Magic. "
405 "endianness mismatch.\n");
406 return -EINVAL;
407 }
408 }
409 }
410
411 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
412 need_swap ? "True" : "False");
413
414 if (need_swap)
415 el = swab16(ah->eeprom.map4k.baseEepHeader.length);
416 else
417 el = ah->eeprom.map4k.baseEepHeader.length;
418
419 if (el > sizeof(struct ar5416_eeprom_4k))
420 el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
421 else
422 el = el / sizeof(u16);
423
424 eepdata = (u16 *)(&ah->eeprom);
425
426 for (i = 0; i < el; i++)
427 sum ^= *eepdata++;
428
429 if (need_swap) {
430 u32 integer;
431 u16 word;
432
433 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
434 "EEPROM Endianness is not native.. Changing\n");
435
436 word = swab16(eep->baseEepHeader.length);
437 eep->baseEepHeader.length = word;
438
439 word = swab16(eep->baseEepHeader.checksum);
440 eep->baseEepHeader.checksum = word;
441
442 word = swab16(eep->baseEepHeader.version);
443 eep->baseEepHeader.version = word;
444
445 word = swab16(eep->baseEepHeader.regDmn[0]);
446 eep->baseEepHeader.regDmn[0] = word;
447
448 word = swab16(eep->baseEepHeader.regDmn[1]);
449 eep->baseEepHeader.regDmn[1] = word;
450
451 word = swab16(eep->baseEepHeader.rfSilent);
452 eep->baseEepHeader.rfSilent = word;
453
454 word = swab16(eep->baseEepHeader.blueToothOptions);
455 eep->baseEepHeader.blueToothOptions = word;
456
457 word = swab16(eep->baseEepHeader.deviceCap);
458 eep->baseEepHeader.deviceCap = word;
459
460 integer = swab32(eep->modalHeader.antCtrlCommon);
461 eep->modalHeader.antCtrlCommon = integer;
462
463 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
464 integer = swab32(eep->modalHeader.antCtrlChain[i]);
465 eep->modalHeader.antCtrlChain[i] = integer;
466 }
467
468 for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
469 word = swab16(eep->modalHeader.spurChans[i].spurChan);
470 eep->modalHeader.spurChans[i].spurChan = word;
471 }
472 }
473
474 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
475 ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
476 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
477 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
478 sum, ah->eep_ops->get_eeprom_ver(ah));
479 return -EINVAL;
480 }
481
482 return 0;
483#undef EEPROM_4K_SIZE
484}
485
486static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
487 enum eeprom_param param)
488{
489 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
490 struct modal_eep_4k_header *pModal = &eep->modalHeader;
491 struct base_eep_header_4k *pBase = &eep->baseEepHeader;
492
493 switch (param) {
494 case EEP_NFTHRESH_2:
495 return pModal->noiseFloorThreshCh[0];
496 case AR_EEPROM_MAC(0):
497 return pBase->macAddr[0] << 8 | pBase->macAddr[1];
498 case AR_EEPROM_MAC(1):
499 return pBase->macAddr[2] << 8 | pBase->macAddr[3];
500 case AR_EEPROM_MAC(2):
501 return pBase->macAddr[4] << 8 | pBase->macAddr[5];
502 case EEP_REG_0:
503 return pBase->regDmn[0];
504 case EEP_REG_1:
505 return pBase->regDmn[1];
506 case EEP_OP_CAP:
507 return pBase->deviceCap;
508 case EEP_OP_MODE:
509 return pBase->opCapFlags;
510 case EEP_RF_SILENT:
511 return pBase->rfSilent;
512 case EEP_OB_2:
513 return pModal->ob_01;
514 case EEP_DB_2:
515 return pModal->db1_01;
516 case EEP_MINOR_REV:
517 return pBase->version & AR5416_EEP_VER_MINOR_MASK;
518 case EEP_TX_MASK:
519 return pBase->txMask;
520 case EEP_RX_MASK:
521 return pBase->rxMask;
522 case EEP_FRAC_N_5G:
523 return 0;
524 default:
525 return 0;
526 }
527}
528
529static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
530 struct ath9k_channel *chan,
531 struct cal_data_per_freq_4k *pRawDataSet,
532 u8 *bChans, u16 availPiers,
533 u16 tPdGainOverlap, int16_t *pMinCalPower,
534 u16 *pPdGainBoundaries, u8 *pPDADCValues,
535 u16 numXpdGains)
536{
537#define TMP_VAL_VPD_TABLE \
538 ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
539 int i, j, k;
540 int16_t ss;
541 u16 idxL = 0, idxR = 0, numPiers;
542 static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
543 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
544 static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
545 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
546 static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
547 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
548
549 u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
550 u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
551 u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
552 int16_t vpdStep;
553 int16_t tmpVal;
554 u16 sizeCurrVpdTable, maxIndex, tgtIndex;
555 bool match;
556 int16_t minDelta = 0;
557 struct chan_centers centers;
558#define PD_GAIN_BOUNDARY_DEFAULT 58;
559
560 ath9k_hw_get_channel_centers(ah, chan, &centers);
561
562 for (numPiers = 0; numPiers < availPiers; numPiers++) {
563 if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
564 break;
565 }
566
567 match = ath9k_hw_get_lower_upper_index(
568 (u8)FREQ2FBIN(centers.synth_center,
569 IS_CHAN_2GHZ(chan)), bChans, numPiers,
570 &idxL, &idxR);
571
572 if (match) {
573 for (i = 0; i < numXpdGains; i++) {
574 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
575 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
576 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
577 pRawDataSet[idxL].pwrPdg[i],
578 pRawDataSet[idxL].vpdPdg[i],
579 AR5416_EEP4K_PD_GAIN_ICEPTS,
580 vpdTableI[i]);
581 }
582 } else {
583 for (i = 0; i < numXpdGains; i++) {
584 pVpdL = pRawDataSet[idxL].vpdPdg[i];
585 pPwrL = pRawDataSet[idxL].pwrPdg[i];
586 pVpdR = pRawDataSet[idxR].vpdPdg[i];
587 pPwrR = pRawDataSet[idxR].pwrPdg[i];
588
589 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
590
591 maxPwrT4[i] =
592 min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1],
593 pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]);
594
595
596 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
597 pPwrL, pVpdL,
598 AR5416_EEP4K_PD_GAIN_ICEPTS,
599 vpdTableL[i]);
600 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
601 pPwrR, pVpdR,
602 AR5416_EEP4K_PD_GAIN_ICEPTS,
603 vpdTableR[i]);
604
605 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
606 vpdTableI[i][j] =
607 (u8)(ath9k_hw_interpolate((u16)
608 FREQ2FBIN(centers.
609 synth_center,
610 IS_CHAN_2GHZ
611 (chan)),
612 bChans[idxL], bChans[idxR],
613 vpdTableL[i][j], vpdTableR[i][j]));
614 }
615 }
616 }
617
618 *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
619
620 k = 0;
621
622 for (i = 0; i < numXpdGains; i++) {
623 if (i == (numXpdGains - 1))
624 pPdGainBoundaries[i] =
625 (u16)(maxPwrT4[i] / 2);
626 else
627 pPdGainBoundaries[i] =
628 (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
629
630 pPdGainBoundaries[i] =
631 min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
632
633 if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
634 minDelta = pPdGainBoundaries[0] - 23;
635 pPdGainBoundaries[0] = 23;
636 } else {
637 minDelta = 0;
638 }
639
640 if (i == 0) {
641 if (AR_SREV_9280_10_OR_LATER(ah))
642 ss = (int16_t)(0 - (minPwrT4[i] / 2));
643 else
644 ss = 0;
645 } else {
646 ss = (int16_t)((pPdGainBoundaries[i - 1] -
647 (minPwrT4[i] / 2)) -
648 tPdGainOverlap + 1 + minDelta);
649 }
650 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
651 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
652
653 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
654 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
655 pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
656 ss++;
657 }
658
659 sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
660 tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
661 (minPwrT4[i] / 2));
662 maxIndex = (tgtIndex < sizeCurrVpdTable) ?
663 tgtIndex : sizeCurrVpdTable;
664
665 while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1)))
666 pPDADCValues[k++] = vpdTableI[i][ss++];
667
668 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
669 vpdTableI[i][sizeCurrVpdTable - 2]);
670 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
671
672 if (tgtIndex >= maxIndex) {
673 while ((ss <= tgtIndex) &&
674 (k < (AR5416_NUM_PDADC_VALUES - 1))) {
675 tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
676 pPDADCValues[k++] = (u8)((tmpVal > 255) ?
677 255 : tmpVal);
678 ss++;
679 }
680 }
681 }
682
683 while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) {
684 pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT;
685 i++;
686 }
687
688 while (k < AR5416_NUM_PDADC_VALUES) {
689 pPDADCValues[k] = pPDADCValues[k - 1];
690 k++;
691 }
692
693 return;
694#undef TMP_VAL_VPD_TABLE
695}
696
697static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
698 struct ath9k_channel *chan,
699 int16_t *pTxPowerIndexOffset)
700{
701 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
702 struct cal_data_per_freq_4k *pRawDataset;
703 u8 *pCalBChans = NULL;
704 u16 pdGainOverlap_t2;
705 static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
706 u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK];
707 u16 numPiers, i, j;
708 int16_t tMinCalPower;
709 u16 numXpdGain, xpdMask;
710 u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
711 u32 reg32, regOffset, regChainOffset;
712
713 xpdMask = pEepData->modalHeader.xpdGain;
714
715 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
716 AR5416_EEP_MINOR_VER_2) {
717 pdGainOverlap_t2 =
718 pEepData->modalHeader.pdGainOverlap;
719 } else {
720 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
721 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
722 }
723
724 pCalBChans = pEepData->calFreqPier2G;
725 numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS;
726
727 numXpdGain = 0;
728
729 for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) {
730 if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) {
731 if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)
732 break;
733 xpdGainValues[numXpdGain] =
734 (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i);
735 numXpdGain++;
736 }
737 }
738
739 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
740 (numXpdGain - 1) & 0x3);
741 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
742 xpdGainValues[0]);
743 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
744 xpdGainValues[1]);
745 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
746
747 for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
748 if (AR_SREV_5416_20_OR_LATER(ah) &&
749 (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
750 (i != 0)) {
751 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
752 } else
753 regChainOffset = i * 0x1000;
754
755 if (pEepData->baseEepHeader.txMask & (1 << i)) {
756 pRawDataset = pEepData->calPierData2G[i];
757
758 ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
759 pRawDataset, pCalBChans,
760 numPiers, pdGainOverlap_t2,
761 &tMinCalPower, gainBoundaries,
762 pdadcValues, numXpdGain);
763
764 if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
765 REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
766 SM(pdGainOverlap_t2,
767 AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
768 | SM(gainBoundaries[0],
769 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
770 | SM(gainBoundaries[1],
771 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
772 | SM(gainBoundaries[2],
773 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
774 | SM(gainBoundaries[3],
775 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
776 }
777
778 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
779 for (j = 0; j < 32; j++) {
780 reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
781 ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
782 ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
783 ((pdadcValues[4 * j + 3] & 0xFF) << 24);
784 REG_WRITE(ah, regOffset, reg32);
785
786 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
787 "PDADC (%d,%4x): %4.4x %8.8x\n",
788 i, regChainOffset, regOffset,
789 reg32);
790 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
791 "PDADC: Chain %d | "
792 "PDADC %3d Value %3d | "
793 "PDADC %3d Value %3d | "
794 "PDADC %3d Value %3d | "
795 "PDADC %3d Value %3d |\n",
796 i, 4 * j, pdadcValues[4 * j],
797 4 * j + 1, pdadcValues[4 * j + 1],
798 4 * j + 2, pdadcValues[4 * j + 2],
799 4 * j + 3,
800 pdadcValues[4 * j + 3]);
801
802 regOffset += 4;
803 }
804 }
805 }
806
807 *pTxPowerIndexOffset = 0;
808
809 return true;
810}
811
812static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
813 struct ath9k_channel *chan,
814 int16_t *ratesArray,
815 u16 cfgCtl,
816 u16 AntennaReduction,
817 u16 twiceMaxRegulatoryPower,
818 u16 powerLimit)
819{
820 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
821 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
822 static const u16 tpScaleReductionTable[5] =
823 { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
824
825 int i;
826 int16_t twiceLargestAntenna;
827 struct cal_ctl_data_4k *rep;
828 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
829 0, { 0, 0, 0, 0}
830 };
831 struct cal_target_power_leg targetPowerOfdmExt = {
832 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
833 0, { 0, 0, 0, 0 }
834 };
835 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
836 0, {0, 0, 0, 0}
837 };
838 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
839 u16 ctlModesFor11g[] =
840 { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
841 CTL_2GHT40
842 };
843 u16 numCtlModes, *pCtlMode, ctlMode, freq;
844 struct chan_centers centers;
845 int tx_chainmask;
846 u16 twiceMinEdgePower;
847
848 tx_chainmask = ah->txchainmask;
849
850 ath9k_hw_get_channel_centers(ah, chan, &centers);
851
852 twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
853
854 twiceLargestAntenna = (int16_t)min(AntennaReduction -
855 twiceLargestAntenna, 0);
856
857 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
858
859 if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
860 maxRegAllowedPower -=
861 (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
862 }
863
864 scaledPower = min(powerLimit, maxRegAllowedPower);
865 scaledPower = max((u16)0, scaledPower);
866
867 numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
868 pCtlMode = ctlModesFor11g;
869
870 ath9k_hw_get_legacy_target_powers(ah, chan,
871 pEepData->calTargetPowerCck,
872 AR5416_NUM_2G_CCK_TARGET_POWERS,
873 &targetPowerCck, 4, false);
874 ath9k_hw_get_legacy_target_powers(ah, chan,
875 pEepData->calTargetPower2G,
876 AR5416_NUM_2G_20_TARGET_POWERS,
877 &targetPowerOfdm, 4, false);
878 ath9k_hw_get_target_powers(ah, chan,
879 pEepData->calTargetPower2GHT20,
880 AR5416_NUM_2G_20_TARGET_POWERS,
881 &targetPowerHt20, 8, false);
882
883 if (IS_CHAN_HT40(chan)) {
884 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
885 ath9k_hw_get_target_powers(ah, chan,
886 pEepData->calTargetPower2GHT40,
887 AR5416_NUM_2G_40_TARGET_POWERS,
888 &targetPowerHt40, 8, true);
889 ath9k_hw_get_legacy_target_powers(ah, chan,
890 pEepData->calTargetPowerCck,
891 AR5416_NUM_2G_CCK_TARGET_POWERS,
892 &targetPowerCckExt, 4, true);
893 ath9k_hw_get_legacy_target_powers(ah, chan,
894 pEepData->calTargetPower2G,
895 AR5416_NUM_2G_20_TARGET_POWERS,
896 &targetPowerOfdmExt, 4, true);
897 }
898
899 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
900 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
901 (pCtlMode[ctlMode] == CTL_2GHT40);
902 if (isHt40CtlMode)
903 freq = centers.synth_center;
904 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
905 freq = centers.ext_center;
906 else
907 freq = centers.ctl_center;
908
909 if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
910 ah->eep_ops->get_eeprom_rev(ah) <= 2)
911 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
912
913 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
914 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
915 "EXT_ADDITIVE %d\n",
916 ctlMode, numCtlModes, isHt40CtlMode,
917 (pCtlMode[ctlMode] & EXT_ADDITIVE));
918
919 for (i = 0; (i < AR5416_NUM_CTLS) &&
920 pEepData->ctlIndex[i]; i++) {
921 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
922 " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
923 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
924 "chan %d\n",
925 i, cfgCtl, pCtlMode[ctlMode],
926 pEepData->ctlIndex[i], chan->channel);
927
928 if ((((cfgCtl & ~CTL_MODE_M) |
929 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
930 pEepData->ctlIndex[i]) ||
931 (((cfgCtl & ~CTL_MODE_M) |
932 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
933 ((pEepData->ctlIndex[i] & CTL_MODE_M) |
934 SD_NO_CTL))) {
935 rep = &(pEepData->ctlData[i]);
936
937 twiceMinEdgePower =
938 ath9k_hw_get_max_edge_power(freq,
939 rep->ctlEdges[ar5416_get_ntxchains
940 (tx_chainmask) - 1],
941 IS_CHAN_2GHZ(chan),
942 AR5416_EEP4K_NUM_BAND_EDGES);
943
944 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
945 " MATCH-EE_IDX %d: ch %d is2 %d "
946 "2xMinEdge %d chainmask %d chains %d\n",
947 i, freq, IS_CHAN_2GHZ(chan),
948 twiceMinEdgePower, tx_chainmask,
949 ar5416_get_ntxchains
950 (tx_chainmask));
951 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
952 twiceMaxEdgePower =
953 min(twiceMaxEdgePower,
954 twiceMinEdgePower);
955 } else {
956 twiceMaxEdgePower = twiceMinEdgePower;
957 break;
958 }
959 }
960 }
961
962 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
963
964 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
965 " SEL-Min ctlMode %d pCtlMode %d "
966 "2xMaxEdge %d sP %d minCtlPwr %d\n",
967 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
968 scaledPower, minCtlPower);
969
970 switch (pCtlMode[ctlMode]) {
971 case CTL_11B:
972 for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
973 i++) {
974 targetPowerCck.tPow2x[i] =
975 min((u16)targetPowerCck.tPow2x[i],
976 minCtlPower);
977 }
978 break;
979 case CTL_11G:
980 for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
981 i++) {
982 targetPowerOfdm.tPow2x[i] =
983 min((u16)targetPowerOfdm.tPow2x[i],
984 minCtlPower);
985 }
986 break;
987 case CTL_2GHT20:
988 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
989 i++) {
990 targetPowerHt20.tPow2x[i] =
991 min((u16)targetPowerHt20.tPow2x[i],
992 minCtlPower);
993 }
994 break;
995 case CTL_11B_EXT:
996 targetPowerCckExt.tPow2x[0] = min((u16)
997 targetPowerCckExt.tPow2x[0],
998 minCtlPower);
999 break;
1000 case CTL_11G_EXT:
1001 targetPowerOfdmExt.tPow2x[0] = min((u16)
1002 targetPowerOfdmExt.tPow2x[0],
1003 minCtlPower);
1004 break;
1005 case CTL_2GHT40:
1006 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
1007 i++) {
1008 targetPowerHt40.tPow2x[i] =
1009 min((u16)targetPowerHt40.tPow2x[i],
1010 minCtlPower);
1011 }
1012 break;
1013 default:
1014 break;
1015 }
1016 }
1017
1018 ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
1019 ratesArray[rate18mb] = ratesArray[rate24mb] =
1020 targetPowerOfdm.tPow2x[0];
1021 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
1022 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
1023 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
1024 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
1025
1026 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
1027 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
1028
1029 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
1030 ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
1031 ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
1032 ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
1033
1034 if (IS_CHAN_HT40(chan)) {
1035 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
1036 ratesArray[rateHt40_0 + i] =
1037 targetPowerHt40.tPow2x[i];
1038 }
1039 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
1040 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
1041 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
1042 ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
1043 }
1044 return true;
1045}
1046
1047static int ath9k_hw_4k_set_txpower(struct ath_hw *ah,
1048 struct ath9k_channel *chan,
1049 u16 cfgCtl,
1050 u8 twiceAntennaReduction,
1051 u8 twiceMaxRegulatoryPower,
1052 u8 powerLimit)
1053{
1054 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
1055 struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
1056 int16_t ratesArray[Ar5416RateSize];
1057 int16_t txPowerIndexOffset = 0;
1058 u8 ht40PowerIncForPdadc = 2;
1059 int i;
1060
1061 memset(ratesArray, 0, sizeof(ratesArray));
1062
1063 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1064 AR5416_EEP_MINOR_VER_2) {
1065 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
1066 }
1067
1068 if (!ath9k_hw_set_4k_power_per_rate_table(ah, chan,
1069 &ratesArray[0], cfgCtl,
1070 twiceAntennaReduction,
1071 twiceMaxRegulatoryPower,
1072 powerLimit)) {
1073 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1074 "ath9k_hw_set_txpower: unable to set "
1075 "tx power per rate table\n");
1076 return -EIO;
1077 }
1078
1079 if (!ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset)) {
1080 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1081 "ath9k_hw_set_txpower: unable to set power table\n");
1082 return -EIO;
1083 }
1084
1085 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
1086 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
1087 if (ratesArray[i] > AR5416_MAX_RATE_POWER)
1088 ratesArray[i] = AR5416_MAX_RATE_POWER;
1089 }
1090
1091 if (AR_SREV_9280_10_OR_LATER(ah)) {
1092 for (i = 0; i < Ar5416RateSize; i++)
1093 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
1094 }
1095
1096 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
1097 ATH9K_POW_SM(ratesArray[rate18mb], 24)
1098 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
1099 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
1100 | ATH9K_POW_SM(ratesArray[rate6mb], 0));
1101 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
1102 ATH9K_POW_SM(ratesArray[rate54mb], 24)
1103 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
1104 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
1105 | ATH9K_POW_SM(ratesArray[rate24mb], 0));
1106
1107 if (IS_CHAN_2GHZ(chan)) {
1108 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
1109 ATH9K_POW_SM(ratesArray[rate2s], 24)
1110 | ATH9K_POW_SM(ratesArray[rate2l], 16)
1111 | ATH9K_POW_SM(ratesArray[rateXr], 8)
1112 | ATH9K_POW_SM(ratesArray[rate1l], 0));
1113 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
1114 ATH9K_POW_SM(ratesArray[rate11s], 24)
1115 | ATH9K_POW_SM(ratesArray[rate11l], 16)
1116 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
1117 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
1118 }
1119
1120 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
1121 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
1122 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
1123 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
1124 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
1125 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
1126 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
1127 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
1128 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
1129 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
1130
1131 if (IS_CHAN_HT40(chan)) {
1132 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
1133 ATH9K_POW_SM(ratesArray[rateHt40_3] +
1134 ht40PowerIncForPdadc, 24)
1135 | ATH9K_POW_SM(ratesArray[rateHt40_2] +
1136 ht40PowerIncForPdadc, 16)
1137 | ATH9K_POW_SM(ratesArray[rateHt40_1] +
1138 ht40PowerIncForPdadc, 8)
1139 | ATH9K_POW_SM(ratesArray[rateHt40_0] +
1140 ht40PowerIncForPdadc, 0));
1141 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
1142 ATH9K_POW_SM(ratesArray[rateHt40_7] +
1143 ht40PowerIncForPdadc, 24)
1144 | ATH9K_POW_SM(ratesArray[rateHt40_6] +
1145 ht40PowerIncForPdadc, 16)
1146 | ATH9K_POW_SM(ratesArray[rateHt40_5] +
1147 ht40PowerIncForPdadc, 8)
1148 | ATH9K_POW_SM(ratesArray[rateHt40_4] +
1149 ht40PowerIncForPdadc, 0));
1150
1151 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
1152 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
1153 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
1154 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
1155 | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
1156 }
1157
1158 i = rate6mb;
1159
1160 if (IS_CHAN_HT40(chan))
1161 i = rateHt40_0;
1162 else if (IS_CHAN_HT20(chan))
1163 i = rateHt20_0;
1164
1165 if (AR_SREV_9280_10_OR_LATER(ah))
1166 ah->regulatory.max_power_level =
1167 ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
1168 else
1169 ah->regulatory.max_power_level = ratesArray[i];
1170
1171 return 0;
1172}
1173
1174static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
1175 struct ath9k_channel *chan)
1176{
1177 struct modal_eep_4k_header *pModal;
1178 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
1179 u8 biaslevel;
1180
1181 if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
1182 return;
1183
1184 if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
1185 return;
1186
1187 pModal = &eep->modalHeader;
1188
1189 if (pModal->xpaBiasLvl != 0xff) {
1190 biaslevel = pModal->xpaBiasLvl;
1191 INI_RA(&ah->iniAddac, 7, 1) =
1192 (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
1193 }
1194}
1195
1196static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
1197 struct modal_eep_4k_header *pModal,
1198 struct ar5416_eeprom_4k *eep,
1199 u8 txRxAttenLocal, int regChainOffset)
1200{
1201 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
1202 pModal->antCtrlChain[0]);
1203
1204 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
1205 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
1206 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
1207 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
1208 SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
1209 SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
1210
1211 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1212 AR5416_EEP_MINOR_VER_3) {
1213 txRxAttenLocal = pModal->txRxAttenCh[0];
1214
1215 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1216 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
1217 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1218 AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
1219 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1220 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
1221 pModal->xatten2Margin[0]);
1222 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1223 AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
1224 }
1225
1226 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
1227 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
1228 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
1229 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
1230
1231 if (AR_SREV_9285_11(ah))
1232 REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
1233}
1234
1235static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
1236 struct ath9k_channel *chan)
1237{
1238 struct modal_eep_4k_header *pModal;
1239 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
1240 u8 txRxAttenLocal;
1241 u8 ob[5], db1[5], db2[5];
1242 u8 ant_div_control1, ant_div_control2;
1243 u32 regVal;
1244
1245 pModal = &eep->modalHeader;
1246 txRxAttenLocal = 23;
1247
1248 REG_WRITE(ah, AR_PHY_SWITCH_COM,
1249 ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
1250
1251 /* Single chain for 4K EEPROM*/
1252 ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0);
1253
1254 /* Initialize Ant Diversity settings from EEPROM */
1255 if (pModal->version == 3) {
1256 ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf);
1257 ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf);
1258 regVal = REG_READ(ah, 0x99ac);
1259 regVal &= (~(0x7f000000));
1260 regVal |= ((ant_div_control1 & 0x1) << 24);
1261 regVal |= (((ant_div_control1 >> 1) & 0x1) << 29);
1262 regVal |= (((ant_div_control1 >> 2) & 0x1) << 30);
1263 regVal |= ((ant_div_control2 & 0x3) << 25);
1264 regVal |= (((ant_div_control2 >> 2) & 0x3) << 27);
1265 REG_WRITE(ah, 0x99ac, regVal);
1266 regVal = REG_READ(ah, 0x99ac);
1267 regVal = REG_READ(ah, 0xa208);
1268 regVal &= (~(0x1 << 13));
1269 regVal |= (((ant_div_control1 >> 3) & 0x1) << 13);
1270 REG_WRITE(ah, 0xa208, regVal);
1271 regVal = REG_READ(ah, 0xa208);
1272 }
1273
1274 if (pModal->version >= 2) {
1275 ob[0] = (pModal->ob_01 & 0xf);
1276 ob[1] = (pModal->ob_01 >> 4) & 0xf;
1277 ob[2] = (pModal->ob_234 & 0xf);
1278 ob[3] = ((pModal->ob_234 >> 4) & 0xf);
1279 ob[4] = ((pModal->ob_234 >> 8) & 0xf);
1280
1281 db1[0] = (pModal->db1_01 & 0xf);
1282 db1[1] = ((pModal->db1_01 >> 4) & 0xf);
1283 db1[2] = (pModal->db1_234 & 0xf);
1284 db1[3] = ((pModal->db1_234 >> 4) & 0xf);
1285 db1[4] = ((pModal->db1_234 >> 8) & 0xf);
1286
1287 db2[0] = (pModal->db2_01 & 0xf);
1288 db2[1] = ((pModal->db2_01 >> 4) & 0xf);
1289 db2[2] = (pModal->db2_234 & 0xf);
1290 db2[3] = ((pModal->db2_234 >> 4) & 0xf);
1291 db2[4] = ((pModal->db2_234 >> 8) & 0xf);
1292
1293 } else if (pModal->version == 1) {
1294 ob[0] = (pModal->ob_01 & 0xf);
1295 ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf;
1296 db1[0] = (pModal->db1_01 & 0xf);
1297 db1[1] = db1[2] = db1[3] =
1298 db1[4] = ((pModal->db1_01 >> 4) & 0xf);
1299 db2[0] = (pModal->db2_01 & 0xf);
1300 db2[1] = db2[2] = db2[3] =
1301 db2[4] = ((pModal->db2_01 >> 4) & 0xf);
1302 } else {
1303 int i;
1304 for (i = 0; i < 5; i++) {
1305 ob[i] = pModal->ob_01;
1306 db1[i] = pModal->db1_01;
1307 db2[i] = pModal->db1_01;
1308 }
1309 }
1310
1311 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1312 AR9285_AN_RF2G3_OB_0, AR9285_AN_RF2G3_OB_0_S, ob[0]);
1313 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1314 AR9285_AN_RF2G3_OB_1, AR9285_AN_RF2G3_OB_1_S, ob[1]);
1315 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1316 AR9285_AN_RF2G3_OB_2, AR9285_AN_RF2G3_OB_2_S, ob[2]);
1317 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1318 AR9285_AN_RF2G3_OB_3, AR9285_AN_RF2G3_OB_3_S, ob[3]);
1319 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1320 AR9285_AN_RF2G3_OB_4, AR9285_AN_RF2G3_OB_4_S, ob[4]);
1321
1322 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1323 AR9285_AN_RF2G3_DB1_0, AR9285_AN_RF2G3_DB1_0_S, db1[0]);
1324 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1325 AR9285_AN_RF2G3_DB1_1, AR9285_AN_RF2G3_DB1_1_S, db1[1]);
1326 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1327 AR9285_AN_RF2G3_DB1_2, AR9285_AN_RF2G3_DB1_2_S, db1[2]);
1328 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
1329 AR9285_AN_RF2G4_DB1_3, AR9285_AN_RF2G4_DB1_3_S, db1[3]);
1330 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
1331 AR9285_AN_RF2G4_DB1_4, AR9285_AN_RF2G4_DB1_4_S, db1[4]);
1332
1333 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
1334 AR9285_AN_RF2G4_DB2_0, AR9285_AN_RF2G4_DB2_0_S, db2[0]);
1335 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
1336 AR9285_AN_RF2G4_DB2_1, AR9285_AN_RF2G4_DB2_1_S, db2[1]);
1337 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
1338 AR9285_AN_RF2G4_DB2_2, AR9285_AN_RF2G4_DB2_2_S, db2[2]);
1339 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
1340 AR9285_AN_RF2G4_DB2_3, AR9285_AN_RF2G4_DB2_3_S, db2[3]);
1341 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
1342 AR9285_AN_RF2G4_DB2_4, AR9285_AN_RF2G4_DB2_4_S, db2[4]);
1343
1344
1345 if (AR_SREV_9285_11(ah))
1346 REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
1347
1348 REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
1349 pModal->switchSettling);
1350 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
1351 pModal->adcDesiredSize);
1352
1353 REG_WRITE(ah, AR_PHY_RF_CTL4,
1354 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
1355 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
1356 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |
1357 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
1358
1359 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
1360 pModal->txEndToRxOn);
1361 REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
1362 pModal->thresh62);
1363 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
1364 pModal->thresh62);
1365
1366 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1367 AR5416_EEP_MINOR_VER_2) {
1368 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
1369 pModal->txFrameToDataStart);
1370 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
1371 pModal->txFrameToPaOn);
1372 }
1373
1374 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1375 AR5416_EEP_MINOR_VER_3) {
1376 if (IS_CHAN_HT40(chan))
1377 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
1378 AR_PHY_SETTLING_SWITCH,
1379 pModal->swSettleHt40);
1380 }
1381}
1382
1383static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
1384 struct ath9k_channel *chan)
1385{
1386 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
1387 struct modal_eep_4k_header *pModal = &eep->modalHeader;
1388
1389 return pModal->antCtrlCommon & 0xFFFF;
1390}
1391
1392static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah,
1393 enum ieee80211_band freq_band)
1394{
1395 return 1;
1396}
1397
1398static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
1399{
1400#define EEP_MAP4K_SPURCHAN \
1401 (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
1402
1403 u16 spur_val = AR_NO_SPUR;
1404
1405 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
1406 "Getting spur idx %d is2Ghz. %d val %x\n",
1407 i, is2GHz, ah->config.spurchans[i][is2GHz]);
1408
1409 switch (ah->config.spurmode) {
1410 case SPUR_DISABLE:
1411 break;
1412 case SPUR_ENABLE_IOCTL:
1413 spur_val = ah->config.spurchans[i][is2GHz];
1414 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
1415 "Getting spur val from new loc. %d\n", spur_val);
1416 break;
1417 case SPUR_ENABLE_EEPROM:
1418 spur_val = EEP_MAP4K_SPURCHAN;
1419 break;
1420 }
1421
1422 return spur_val;
1423
1424#undef EEP_MAP4K_SPURCHAN
1425}
1426
1427static struct eeprom_ops eep_4k_ops = {
1428 .check_eeprom = ath9k_hw_4k_check_eeprom,
1429 .get_eeprom = ath9k_hw_4k_get_eeprom,
1430 .fill_eeprom = ath9k_hw_4k_fill_eeprom,
1431 .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver,
1432 .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,
1433 .get_num_ant_config = ath9k_hw_4k_get_num_ant_config,
1434 .get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg,
1435 .set_board_values = ath9k_hw_4k_set_board_values,
1436 .set_addac = ath9k_hw_4k_set_addac,
1437 .set_txpower = ath9k_hw_4k_set_txpower,
1438 .get_spur_channel = ath9k_hw_4k_get_spur_channel
1439};
1440
1441/************************************************/
1442/* EEPROM Operations for non-4K (Default) cards */
1443/************************************************/
1444
1445static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah)
1446{
1447 return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF);
1448}
1449
1450static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
1451{
1452 return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF);
1453}
1454
1455static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
1456{
1457#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
1458 u16 *eep_data = (u16 *)&ah->eeprom.def;
1459 int addr, ar5416_eep_start_loc = 0x100;
1460
1461 for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
1462 if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
1463 eep_data)) {
1464 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
1465 "Unable to read eeprom region\n");
1466 return false;
1467 }
1468 eep_data++;
1469 }
1470 return true;
1471#undef SIZE_EEPROM_DEF
1472}
1473
1474static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
1475{
1476 struct ar5416_eeprom_def *eep =
1477 (struct ar5416_eeprom_def *) &ah->eeprom.def;
1478 u16 *eepdata, temp, magic, magic2;
1479 u32 sum = 0, el;
1480 bool need_swap = false;
1481 int i, addr, size;
1482
1483 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
1484 DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n");
1485 return false;
1486 }
1487
1488 if (!ath9k_hw_use_flash(ah)) {
1489 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1490 "Read Magic = 0x%04X\n", magic);
1491
1492 if (magic != AR5416_EEPROM_MAGIC) {
1493 magic2 = swab16(magic);
1494
1495 if (magic2 == AR5416_EEPROM_MAGIC) {
1496 size = sizeof(struct ar5416_eeprom_def);
1497 need_swap = true;
1498 eepdata = (u16 *) (&ah->eeprom);
1499
1500 for (addr = 0; addr < size / sizeof(u16); addr++) {
1501 temp = swab16(*eepdata);
1502 *eepdata = temp;
1503 eepdata++;
1504 }
1505 } else {
1506 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
1507 "Invalid EEPROM Magic. "
1508 "Endianness mismatch.\n");
1509 return -EINVAL;
1510 }
1511 }
1512 }
1513
1514 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
1515 need_swap ? "True" : "False");
1516
1517 if (need_swap)
1518 el = swab16(ah->eeprom.def.baseEepHeader.length);
1519 else
1520 el = ah->eeprom.def.baseEepHeader.length;
1521
1522 if (el > sizeof(struct ar5416_eeprom_def))
1523 el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
1524 else
1525 el = el / sizeof(u16);
1526
1527 eepdata = (u16 *)(&ah->eeprom);
1528
1529 for (i = 0; i < el; i++)
1530 sum ^= *eepdata++;
1531
1532 if (need_swap) {
1533 u32 integer, j;
1534 u16 word;
1535
1536 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1537 "EEPROM Endianness is not native.. Changing.\n");
1538
1539 word = swab16(eep->baseEepHeader.length);
1540 eep->baseEepHeader.length = word;
1541
1542 word = swab16(eep->baseEepHeader.checksum);
1543 eep->baseEepHeader.checksum = word;
1544
1545 word = swab16(eep->baseEepHeader.version);
1546 eep->baseEepHeader.version = word;
1547
1548 word = swab16(eep->baseEepHeader.regDmn[0]);
1549 eep->baseEepHeader.regDmn[0] = word;
1550
1551 word = swab16(eep->baseEepHeader.regDmn[1]);
1552 eep->baseEepHeader.regDmn[1] = word;
1553
1554 word = swab16(eep->baseEepHeader.rfSilent);
1555 eep->baseEepHeader.rfSilent = word;
1556
1557 word = swab16(eep->baseEepHeader.blueToothOptions);
1558 eep->baseEepHeader.blueToothOptions = word;
1559
1560 word = swab16(eep->baseEepHeader.deviceCap);
1561 eep->baseEepHeader.deviceCap = word;
1562
1563 for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
1564 struct modal_eep_header *pModal =
1565 &eep->modalHeader[j];
1566 integer = swab32(pModal->antCtrlCommon);
1567 pModal->antCtrlCommon = integer;
1568
1569 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1570 integer = swab32(pModal->antCtrlChain[i]);
1571 pModal->antCtrlChain[i] = integer;
1572 }
1573
1574 for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
1575 word = swab16(pModal->spurChans[i].spurChan);
1576 pModal->spurChans[i].spurChan = word;
1577 }
1578 }
1579 }
1580
1581 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
1582 ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
1583 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
1584 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
1585 sum, ah->eep_ops->get_eeprom_ver(ah));
1586 return -EINVAL;
1587 }
1588
1589 return 0;
1590}
1591
1592static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
1593 enum eeprom_param param)
1594{
1595 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
1596 struct modal_eep_header *pModal = eep->modalHeader;
1597 struct base_eep_header *pBase = &eep->baseEepHeader;
1598
1599 switch (param) {
1600 case EEP_NFTHRESH_5:
1601 return pModal[0].noiseFloorThreshCh[0];
1602 case EEP_NFTHRESH_2:
1603 return pModal[1].noiseFloorThreshCh[0];
1604 case AR_EEPROM_MAC(0):
1605 return pBase->macAddr[0] << 8 | pBase->macAddr[1];
1606 case AR_EEPROM_MAC(1):
1607 return pBase->macAddr[2] << 8 | pBase->macAddr[3];
1608 case AR_EEPROM_MAC(2):
1609 return pBase->macAddr[4] << 8 | pBase->macAddr[5];
1610 case EEP_REG_0:
1611 return pBase->regDmn[0];
1612 case EEP_REG_1:
1613 return pBase->regDmn[1];
1614 case EEP_OP_CAP:
1615 return pBase->deviceCap;
1616 case EEP_OP_MODE:
1617 return pBase->opCapFlags;
1618 case EEP_RF_SILENT:
1619 return pBase->rfSilent;
1620 case EEP_OB_5:
1621 return pModal[0].ob;
1622 case EEP_DB_5:
1623 return pModal[0].db;
1624 case EEP_OB_2:
1625 return pModal[1].ob;
1626 case EEP_DB_2:
1627 return pModal[1].db;
1628 case EEP_MINOR_REV:
1629 return AR5416_VER_MASK;
1630 case EEP_TX_MASK:
1631 return pBase->txMask;
1632 case EEP_RX_MASK:
1633 return pBase->rxMask;
1634 case EEP_RXGAIN_TYPE:
1635 return pBase->rxGainType;
1636 case EEP_TXGAIN_TYPE:
1637 return pBase->txGainType;
1638 case EEP_OL_PWRCTRL:
1639 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1640 return pBase->openLoopPwrCntl ? true : false;
1641 else
1642 return false;
1643 case EEP_RC_CHAIN_MASK:
1644 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1645 return pBase->rcChainMask;
1646 else
1647 return 0;
1648 case EEP_DAC_HPWR_5G:
1649 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
1650 return pBase->dacHiPwrMode_5G;
1651 else
1652 return 0;
1653 case EEP_FRAC_N_5G:
1654 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
1655 return pBase->frac_n_5g;
1656 else
1657 return 0;
1658 default:
1659 return 0;
1660 }
1661}
1662
1663static void ath9k_hw_def_set_gain(struct ath_hw *ah,
1664 struct modal_eep_header *pModal,
1665 struct ar5416_eeprom_def *eep,
1666 u8 txRxAttenLocal, int regChainOffset, int i)
1667{
1668 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
1669 txRxAttenLocal = pModal->txRxAttenCh[i];
1670
1671 if (AR_SREV_9280_10_OR_LATER(ah)) {
1672 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1673 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
1674 pModal->bswMargin[i]);
1675 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1676 AR_PHY_GAIN_2GHZ_XATTEN1_DB,
1677 pModal->bswAtten[i]);
1678 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1679 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
1680 pModal->xatten2Margin[i]);
1681 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1682 AR_PHY_GAIN_2GHZ_XATTEN2_DB,
1683 pModal->xatten2Db[i]);
1684 } else {
1685 REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1686 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
1687 ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
1688 | SM(pModal-> bswMargin[i],
1689 AR_PHY_GAIN_2GHZ_BSW_MARGIN));
1690 REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1691 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
1692 ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
1693 | SM(pModal->bswAtten[i],
1694 AR_PHY_GAIN_2GHZ_BSW_ATTEN));
1695 }
1696 }
1697
1698 if (AR_SREV_9280_10_OR_LATER(ah)) {
1699 REG_RMW_FIELD(ah,
1700 AR_PHY_RXGAIN + regChainOffset,
1701 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
1702 REG_RMW_FIELD(ah,
1703 AR_PHY_RXGAIN + regChainOffset,
1704 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]);
1705 } else {
1706 REG_WRITE(ah,
1707 AR_PHY_RXGAIN + regChainOffset,
1708 (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) &
1709 ~AR_PHY_RXGAIN_TXRX_ATTEN)
1710 | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN));
1711 REG_WRITE(ah,
1712 AR_PHY_GAIN_2GHZ + regChainOffset,
1713 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
1714 ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
1715 SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
1716 }
1717}
1718
1719static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
1720 struct ath9k_channel *chan)
1721{
1722 struct modal_eep_header *pModal;
1723 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
1724 int i, regChainOffset;
1725 u8 txRxAttenLocal;
1726
1727 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
1728 txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
1729
1730 REG_WRITE(ah, AR_PHY_SWITCH_COM,
1731 ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
1732
1733 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1734 if (AR_SREV_9280(ah)) {
1735 if (i >= 2)
1736 break;
1737 }
1738
1739 if (AR_SREV_5416_20_OR_LATER(ah) &&
1740 (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
1741 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
1742 else
1743 regChainOffset = i * 0x1000;
1744
1745 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
1746 pModal->antCtrlChain[i]);
1747
1748 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
1749 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
1750 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
1751 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
1752 SM(pModal->iqCalICh[i],
1753 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
1754 SM(pModal->iqCalQCh[i],
1755 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
1756
1757 if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
1758 ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
1759 regChainOffset, i);
1760 }
1761
1762 if (AR_SREV_9280_10_OR_LATER(ah)) {
1763 if (IS_CHAN_2GHZ(chan)) {
1764 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
1765 AR_AN_RF2G1_CH0_OB,
1766 AR_AN_RF2G1_CH0_OB_S,
1767 pModal->ob);
1768 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
1769 AR_AN_RF2G1_CH0_DB,
1770 AR_AN_RF2G1_CH0_DB_S,
1771 pModal->db);
1772 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
1773 AR_AN_RF2G1_CH1_OB,
1774 AR_AN_RF2G1_CH1_OB_S,
1775 pModal->ob_ch1);
1776 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
1777 AR_AN_RF2G1_CH1_DB,
1778 AR_AN_RF2G1_CH1_DB_S,
1779 pModal->db_ch1);
1780 } else {
1781 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
1782 AR_AN_RF5G1_CH0_OB5,
1783 AR_AN_RF5G1_CH0_OB5_S,
1784 pModal->ob);
1785 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
1786 AR_AN_RF5G1_CH0_DB5,
1787 AR_AN_RF5G1_CH0_DB5_S,
1788 pModal->db);
1789 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
1790 AR_AN_RF5G1_CH1_OB5,
1791 AR_AN_RF5G1_CH1_OB5_S,
1792 pModal->ob_ch1);
1793 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
1794 AR_AN_RF5G1_CH1_DB5,
1795 AR_AN_RF5G1_CH1_DB5_S,
1796 pModal->db_ch1);
1797 }
1798 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
1799 AR_AN_TOP2_XPABIAS_LVL,
1800 AR_AN_TOP2_XPABIAS_LVL_S,
1801 pModal->xpaBiasLvl);
1802 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
1803 AR_AN_TOP2_LOCALBIAS,
1804 AR_AN_TOP2_LOCALBIAS_S,
1805 pModal->local_bias);
1806 REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
1807 pModal->force_xpaon);
1808 }
1809
1810 REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
1811 pModal->switchSettling);
1812 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
1813 pModal->adcDesiredSize);
1814
1815 if (!AR_SREV_9280_10_OR_LATER(ah))
1816 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
1817 AR_PHY_DESIRED_SZ_PGA,
1818 pModal->pgaDesiredSize);
1819
1820 REG_WRITE(ah, AR_PHY_RF_CTL4,
1821 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
1822 | SM(pModal->txEndToXpaOff,
1823 AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
1824 | SM(pModal->txFrameToXpaOn,
1825 AR_PHY_RF_CTL4_FRAME_XPAA_ON)
1826 | SM(pModal->txFrameToXpaOn,
1827 AR_PHY_RF_CTL4_FRAME_XPAB_ON));
1828
1829 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
1830 pModal->txEndToRxOn);
1831
1832 if (AR_SREV_9280_10_OR_LATER(ah)) {
1833 REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
1834 pModal->thresh62);
1835 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
1836 AR_PHY_EXT_CCA0_THRESH62,
1837 pModal->thresh62);
1838 } else {
1839 REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
1840 pModal->thresh62);
1841 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
1842 AR_PHY_EXT_CCA_THRESH62,
1843 pModal->thresh62);
1844 }
1845
1846 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
1847 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
1848 AR_PHY_TX_END_DATA_START,
1849 pModal->txFrameToDataStart);
1850 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
1851 pModal->txFrameToPaOn);
1852 }
1853
1854 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
1855 if (IS_CHAN_HT40(chan))
1856 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
1857 AR_PHY_SETTLING_SWITCH,
1858 pModal->swSettleHt40);
1859 }
1860
1861 if (AR_SREV_9280_20_OR_LATER(ah) &&
1862 AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1863 REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
1864 AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
1865 pModal->miscBits);
1866
1867
1868 if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
1869 if (IS_CHAN_2GHZ(chan))
1870 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
1871 eep->baseEepHeader.dacLpMode);
1872 else if (eep->baseEepHeader.dacHiPwrMode_5G)
1873 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);
1874 else
1875 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
1876 eep->baseEepHeader.dacLpMode);
1877
1878 REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
1879 pModal->miscBits >> 2);
1880
1881 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
1882 AR_PHY_TX_DESIRED_SCALE_CCK,
1883 eep->baseEepHeader.desiredScaleCCK);
1884 }
1885}
1886
1887static void ath9k_hw_def_set_addac(struct ath_hw *ah,
1888 struct ath9k_channel *chan)
1889{
1890#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
1891 struct modal_eep_header *pModal;
1892 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
1893 u8 biaslevel;
1894
1895 if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
1896 return;
1897
1898 if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
1899 return;
1900
1901 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
1902
1903 if (pModal->xpaBiasLvl != 0xff) {
1904 biaslevel = pModal->xpaBiasLvl;
1905 } else {
1906 u16 resetFreqBin, freqBin, freqCount = 0;
1907 struct chan_centers centers;
1908
1909 ath9k_hw_get_channel_centers(ah, chan, &centers);
1910
1911 resetFreqBin = FREQ2FBIN(centers.synth_center,
1912 IS_CHAN_2GHZ(chan));
1913 freqBin = XPA_LVL_FREQ(0) & 0xff;
1914 biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14);
1915
1916 freqCount++;
1917
1918 while (freqCount < 3) {
1919 if (XPA_LVL_FREQ(freqCount) == 0x0)
1920 break;
1921
1922 freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
1923 if (resetFreqBin >= freqBin)
1924 biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14);
1925 else
1926 break;
1927 freqCount++;
1928 }
1929 }
1930
1931 if (IS_CHAN_2GHZ(chan)) {
1932 INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac,
1933 7, 1) & (~0x18)) | biaslevel << 3;
1934 } else {
1935 INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac,
1936 6, 1) & (~0xc0)) | biaslevel << 6;
1937 }
1938#undef XPA_LVL_FREQ
1939}
1940
1941static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
1942 struct ath9k_channel *chan,
1943 struct cal_data_per_freq *pRawDataSet,
1944 u8 *bChans, u16 availPiers,
1945 u16 tPdGainOverlap, int16_t *pMinCalPower,
1946 u16 *pPdGainBoundaries, u8 *pPDADCValues,
1947 u16 numXpdGains)
1948{
1949 int i, j, k;
1950 int16_t ss;
1951 u16 idxL = 0, idxR = 0, numPiers;
1952 static u8 vpdTableL[AR5416_NUM_PD_GAINS]
1953 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
1954 static u8 vpdTableR[AR5416_NUM_PD_GAINS]
1955 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
1956 static u8 vpdTableI[AR5416_NUM_PD_GAINS]
1957 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
1958
1959 u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
1960 u8 minPwrT4[AR5416_NUM_PD_GAINS];
1961 u8 maxPwrT4[AR5416_NUM_PD_GAINS];
1962 int16_t vpdStep;
1963 int16_t tmpVal;
1964 u16 sizeCurrVpdTable, maxIndex, tgtIndex;
1965 bool match;
1966 int16_t minDelta = 0;
1967 struct chan_centers centers;
1968
1969 ath9k_hw_get_channel_centers(ah, chan, &centers);
1970
1971 for (numPiers = 0; numPiers < availPiers; numPiers++) {
1972 if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
1973 break;
1974 }
1975
1976 match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
1977 IS_CHAN_2GHZ(chan)),
1978 bChans, numPiers, &idxL, &idxR);
1979
1980 if (match) {
1981 for (i = 0; i < numXpdGains; i++) {
1982 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
1983 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
1984 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
1985 pRawDataSet[idxL].pwrPdg[i],
1986 pRawDataSet[idxL].vpdPdg[i],
1987 AR5416_PD_GAIN_ICEPTS,
1988 vpdTableI[i]);
1989 }
1990 } else {
1991 for (i = 0; i < numXpdGains; i++) {
1992 pVpdL = pRawDataSet[idxL].vpdPdg[i];
1993 pPwrL = pRawDataSet[idxL].pwrPdg[i];
1994 pVpdR = pRawDataSet[idxR].vpdPdg[i];
1995 pPwrR = pRawDataSet[idxR].pwrPdg[i];
1996
1997 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
1998
1999 maxPwrT4[i] =
2000 min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
2001 pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
2002
2003
2004 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
2005 pPwrL, pVpdL,
2006 AR5416_PD_GAIN_ICEPTS,
2007 vpdTableL[i]);
2008 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
2009 pPwrR, pVpdR,
2010 AR5416_PD_GAIN_ICEPTS,
2011 vpdTableR[i]);
2012
2013 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
2014 vpdTableI[i][j] =
2015 (u8)(ath9k_hw_interpolate((u16)
2016 FREQ2FBIN(centers.
2017 synth_center,
2018 IS_CHAN_2GHZ
2019 (chan)),
2020 bChans[idxL], bChans[idxR],
2021 vpdTableL[i][j], vpdTableR[i][j]));
2022 }
2023 }
2024 }
2025
2026 *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
2027
2028 k = 0;
2029
2030 for (i = 0; i < numXpdGains; i++) {
2031 if (i == (numXpdGains - 1))
2032 pPdGainBoundaries[i] =
2033 (u16)(maxPwrT4[i] / 2);
2034 else
2035 pPdGainBoundaries[i] =
2036 (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
2037
2038 pPdGainBoundaries[i] =
2039 min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
2040
2041 if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
2042 minDelta = pPdGainBoundaries[0] - 23;
2043 pPdGainBoundaries[0] = 23;
2044 } else {
2045 minDelta = 0;
2046 }
2047
2048 if (i == 0) {
2049 if (AR_SREV_9280_10_OR_LATER(ah))
2050 ss = (int16_t)(0 - (minPwrT4[i] / 2));
2051 else
2052 ss = 0;
2053 } else {
2054 ss = (int16_t)((pPdGainBoundaries[i - 1] -
2055 (minPwrT4[i] / 2)) -
2056 tPdGainOverlap + 1 + minDelta);
2057 }
2058 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
2059 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
2060
2061 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
2062 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
2063 pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
2064 ss++;
2065 }
2066
2067 sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
2068 tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
2069 (minPwrT4[i] / 2));
2070 maxIndex = (tgtIndex < sizeCurrVpdTable) ?
2071 tgtIndex : sizeCurrVpdTable;
2072
2073 while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
2074 pPDADCValues[k++] = vpdTableI[i][ss++];
2075 }
2076
2077 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
2078 vpdTableI[i][sizeCurrVpdTable - 2]);
2079 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
2080
2081 if (tgtIndex > maxIndex) {
2082 while ((ss <= tgtIndex) &&
2083 (k < (AR5416_NUM_PDADC_VALUES - 1))) {
2084 tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
2085 (ss - maxIndex + 1) * vpdStep));
2086 pPDADCValues[k++] = (u8)((tmpVal > 255) ?
2087 255 : tmpVal);
2088 ss++;
2089 }
2090 }
2091 }
2092
2093 while (i < AR5416_PD_GAINS_IN_MASK) {
2094 pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
2095 i++;
2096 }
2097
2098 while (k < AR5416_NUM_PDADC_VALUES) {
2099 pPDADCValues[k] = pPDADCValues[k - 1];
2100 k++;
2101 }
2102
2103 return;
2104}
2105
2106static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
2107 struct ath9k_channel *chan,
2108 int16_t *pTxPowerIndexOffset)
2109{
2110#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
2111#define SM_PDGAIN_B(x, y) \
2112 SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
2113
2114 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
2115 struct cal_data_per_freq *pRawDataset;
2116 u8 *pCalBChans = NULL;
2117 u16 pdGainOverlap_t2;
2118 static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
2119 u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
2120 u16 numPiers, i, j;
2121 int16_t tMinCalPower;
2122 u16 numXpdGain, xpdMask;
2123 u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
2124 u32 reg32, regOffset, regChainOffset;
2125 int16_t modalIdx;
2126
2127 modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
2128 xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
2129
2130 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
2131 AR5416_EEP_MINOR_VER_2) {
2132 pdGainOverlap_t2 =
2133 pEepData->modalHeader[modalIdx].pdGainOverlap;
2134 } else {
2135 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
2136 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
2137 }
2138
2139 if (IS_CHAN_2GHZ(chan)) {
2140 pCalBChans = pEepData->calFreqPier2G;
2141 numPiers = AR5416_NUM_2G_CAL_PIERS;
2142 } else {
2143 pCalBChans = pEepData->calFreqPier5G;
2144 numPiers = AR5416_NUM_5G_CAL_PIERS;
2145 }
2146
2147 if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) {
2148 pRawDataset = pEepData->calPierData2G[0];
2149 ah->initPDADC = ((struct calDataPerFreqOpLoop *)
2150 pRawDataset)->vpdPdg[0][0];
2151 }
2152
2153 numXpdGain = 0;
2154
2155 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
2156 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
2157 if (numXpdGain >= AR5416_NUM_PD_GAINS)
2158 break;
2159 xpdGainValues[numXpdGain] =
2160 (u16)(AR5416_PD_GAINS_IN_MASK - i);
2161 numXpdGain++;
2162 }
2163 }
2164
2165 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
2166 (numXpdGain - 1) & 0x3);
2167 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
2168 xpdGainValues[0]);
2169 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
2170 xpdGainValues[1]);
2171 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
2172 xpdGainValues[2]);
2173
2174 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
2175 if (AR_SREV_5416_20_OR_LATER(ah) &&
2176 (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
2177 (i != 0)) {
2178 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
2179 } else
2180 regChainOffset = i * 0x1000;
2181
2182 if (pEepData->baseEepHeader.txMask & (1 << i)) {
2183 if (IS_CHAN_2GHZ(chan))
2184 pRawDataset = pEepData->calPierData2G[i];
2185 else
2186 pRawDataset = pEepData->calPierData5G[i];
2187
2188
2189 if (OLC_FOR_AR9280_20_LATER) {
2190 u8 pcdacIdx;
2191 u8 txPower;
2192
2193 ath9k_get_txgain_index(ah, chan,
2194 (struct calDataPerFreqOpLoop *)pRawDataset,
2195 pCalBChans, numPiers, &txPower, &pcdacIdx);
2196 ath9k_olc_get_pdadcs(ah, pcdacIdx,
2197 txPower/2, pdadcValues);
2198 } else {
2199 ath9k_hw_get_def_gain_boundaries_pdadcs(ah,
2200 chan, pRawDataset,
2201 pCalBChans, numPiers,
2202 pdGainOverlap_t2,
2203 &tMinCalPower,
2204 gainBoundaries,
2205 pdadcValues,
2206 numXpdGain);
2207 }
2208
2209 if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
2210 if (OLC_FOR_AR9280_20_LATER) {
2211 REG_WRITE(ah,
2212 AR_PHY_TPCRG5 + regChainOffset,
2213 SM(0x6,
2214 AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
2215 SM_PD_GAIN(1) | SM_PD_GAIN(2) |
2216 SM_PD_GAIN(3) | SM_PD_GAIN(4));
2217 } else {
2218 REG_WRITE(ah,
2219 AR_PHY_TPCRG5 + regChainOffset,
2220 SM(pdGainOverlap_t2,
2221 AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
2222 SM_PDGAIN_B(0, 1) |
2223 SM_PDGAIN_B(1, 2) |
2224 SM_PDGAIN_B(2, 3) |
2225 SM_PDGAIN_B(3, 4));
2226 }
2227 }
2228
2229 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
2230 for (j = 0; j < 32; j++) {
2231 reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
2232 ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
2233 ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
2234 ((pdadcValues[4 * j + 3] & 0xFF) << 24);
2235 REG_WRITE(ah, regOffset, reg32);
2236
2237 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2238 "PDADC (%d,%4x): %4.4x %8.8x\n",
2239 i, regChainOffset, regOffset,
2240 reg32);
2241 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2242 "PDADC: Chain %d | PDADC %3d "
2243 "Value %3d | PDADC %3d Value %3d | "
2244 "PDADC %3d Value %3d | PDADC %3d "
2245 "Value %3d |\n",
2246 i, 4 * j, pdadcValues[4 * j],
2247 4 * j + 1, pdadcValues[4 * j + 1],
2248 4 * j + 2, pdadcValues[4 * j + 2],
2249 4 * j + 3,
2250 pdadcValues[4 * j + 3]);
2251
2252 regOffset += 4;
2253 }
2254 }
2255 }
2256
2257 *pTxPowerIndexOffset = 0;
2258
2259 return true;
2260#undef SM_PD_GAIN
2261#undef SM_PDGAIN_B
2262}
2263
2264static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
2265 struct ath9k_channel *chan,
2266 int16_t *ratesArray,
2267 u16 cfgCtl,
2268 u16 AntennaReduction,
2269 u16 twiceMaxRegulatoryPower,
2270 u16 powerLimit)
2271{
2272#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
2273#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
2274
2275 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
2276 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
2277 static const u16 tpScaleReductionTable[5] =
2278 { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
2279
2280 int i;
2281 int16_t twiceLargestAntenna;
2282 struct cal_ctl_data *rep;
2283 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
2284 0, { 0, 0, 0, 0}
2285 };
2286 struct cal_target_power_leg targetPowerOfdmExt = {
2287 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
2288 0, { 0, 0, 0, 0 }
2289 };
2290 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
2291 0, {0, 0, 0, 0}
2292 };
2293 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
2294 u16 ctlModesFor11a[] =
2295 { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
2296 u16 ctlModesFor11g[] =
2297 { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
2298 CTL_2GHT40
2299 };
2300 u16 numCtlModes, *pCtlMode, ctlMode, freq;
2301 struct chan_centers centers;
2302 int tx_chainmask;
2303 u16 twiceMinEdgePower;
2304
2305 tx_chainmask = ah->txchainmask;
2306
2307 ath9k_hw_get_channel_centers(ah, chan, &centers);
2308
2309 twiceLargestAntenna = max(
2310 pEepData->modalHeader
2311 [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
2312 pEepData->modalHeader
2313 [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
2314
2315 twiceLargestAntenna = max((u8)twiceLargestAntenna,
2316 pEepData->modalHeader
2317 [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
2318
2319 twiceLargestAntenna = (int16_t)min(AntennaReduction -
2320 twiceLargestAntenna, 0);
2321
2322 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
2323
2324 if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
2325 maxRegAllowedPower -=
2326 (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
2327 }
2328
2329 scaledPower = min(powerLimit, maxRegAllowedPower);
2330
2331 switch (ar5416_get_ntxchains(tx_chainmask)) {
2332 case 1:
2333 break;
2334 case 2:
2335 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
2336 break;
2337 case 3:
2338 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
2339 break;
2340 }
2341
2342 scaledPower = max((u16)0, scaledPower);
2343
2344 if (IS_CHAN_2GHZ(chan)) {
2345 numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
2346 SUB_NUM_CTL_MODES_AT_2G_40;
2347 pCtlMode = ctlModesFor11g;
2348
2349 ath9k_hw_get_legacy_target_powers(ah, chan,
2350 pEepData->calTargetPowerCck,
2351 AR5416_NUM_2G_CCK_TARGET_POWERS,
2352 &targetPowerCck, 4, false);
2353 ath9k_hw_get_legacy_target_powers(ah, chan,
2354 pEepData->calTargetPower2G,
2355 AR5416_NUM_2G_20_TARGET_POWERS,
2356 &targetPowerOfdm, 4, false);
2357 ath9k_hw_get_target_powers(ah, chan,
2358 pEepData->calTargetPower2GHT20,
2359 AR5416_NUM_2G_20_TARGET_POWERS,
2360 &targetPowerHt20, 8, false);
2361
2362 if (IS_CHAN_HT40(chan)) {
2363 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
2364 ath9k_hw_get_target_powers(ah, chan,
2365 pEepData->calTargetPower2GHT40,
2366 AR5416_NUM_2G_40_TARGET_POWERS,
2367 &targetPowerHt40, 8, true);
2368 ath9k_hw_get_legacy_target_powers(ah, chan,
2369 pEepData->calTargetPowerCck,
2370 AR5416_NUM_2G_CCK_TARGET_POWERS,
2371 &targetPowerCckExt, 4, true);
2372 ath9k_hw_get_legacy_target_powers(ah, chan,
2373 pEepData->calTargetPower2G,
2374 AR5416_NUM_2G_20_TARGET_POWERS,
2375 &targetPowerOfdmExt, 4, true);
2376 }
2377 } else {
2378 numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
2379 SUB_NUM_CTL_MODES_AT_5G_40;
2380 pCtlMode = ctlModesFor11a;
2381
2382 ath9k_hw_get_legacy_target_powers(ah, chan,
2383 pEepData->calTargetPower5G,
2384 AR5416_NUM_5G_20_TARGET_POWERS,
2385 &targetPowerOfdm, 4, false);
2386 ath9k_hw_get_target_powers(ah, chan,
2387 pEepData->calTargetPower5GHT20,
2388 AR5416_NUM_5G_20_TARGET_POWERS,
2389 &targetPowerHt20, 8, false);
2390
2391 if (IS_CHAN_HT40(chan)) {
2392 numCtlModes = ARRAY_SIZE(ctlModesFor11a);
2393 ath9k_hw_get_target_powers(ah, chan,
2394 pEepData->calTargetPower5GHT40,
2395 AR5416_NUM_5G_40_TARGET_POWERS,
2396 &targetPowerHt40, 8, true);
2397 ath9k_hw_get_legacy_target_powers(ah, chan,
2398 pEepData->calTargetPower5G,
2399 AR5416_NUM_5G_20_TARGET_POWERS,
2400 &targetPowerOfdmExt, 4, true);
2401 }
2402 }
2403
2404 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
2405 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
2406 (pCtlMode[ctlMode] == CTL_2GHT40);
2407 if (isHt40CtlMode)
2408 freq = centers.synth_center;
2409 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
2410 freq = centers.ext_center;
2411 else
2412 freq = centers.ctl_center;
2413
2414 if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
2415 ah->eep_ops->get_eeprom_rev(ah) <= 2)
2416 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
2417
2418 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2419 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
2420 "EXT_ADDITIVE %d\n",
2421 ctlMode, numCtlModes, isHt40CtlMode,
2422 (pCtlMode[ctlMode] & EXT_ADDITIVE));
2423
2424 for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
2425 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2426 " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
2427 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
2428 "chan %d\n",
2429 i, cfgCtl, pCtlMode[ctlMode],
2430 pEepData->ctlIndex[i], chan->channel);
2431
2432 if ((((cfgCtl & ~CTL_MODE_M) |
2433 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2434 pEepData->ctlIndex[i]) ||
2435 (((cfgCtl & ~CTL_MODE_M) |
2436 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2437 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
2438 rep = &(pEepData->ctlData[i]);
2439
2440 twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
2441 rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
2442 IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
2443
2444 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2445 " MATCH-EE_IDX %d: ch %d is2 %d "
2446 "2xMinEdge %d chainmask %d chains %d\n",
2447 i, freq, IS_CHAN_2GHZ(chan),
2448 twiceMinEdgePower, tx_chainmask,
2449 ar5416_get_ntxchains
2450 (tx_chainmask));
2451 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
2452 twiceMaxEdgePower = min(twiceMaxEdgePower,
2453 twiceMinEdgePower);
2454 } else {
2455 twiceMaxEdgePower = twiceMinEdgePower;
2456 break;
2457 }
2458 }
2459 }
2460
2461 minCtlPower = min(twiceMaxEdgePower, scaledPower);
2462
2463 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2464 " SEL-Min ctlMode %d pCtlMode %d "
2465 "2xMaxEdge %d sP %d minCtlPwr %d\n",
2466 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
2467 scaledPower, minCtlPower);
2468
2469 switch (pCtlMode[ctlMode]) {
2470 case CTL_11B:
2471 for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
2472 targetPowerCck.tPow2x[i] =
2473 min((u16)targetPowerCck.tPow2x[i],
2474 minCtlPower);
2475 }
2476 break;
2477 case CTL_11A:
2478 case CTL_11G:
2479 for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
2480 targetPowerOfdm.tPow2x[i] =
2481 min((u16)targetPowerOfdm.tPow2x[i],
2482 minCtlPower);
2483 }
2484 break;
2485 case CTL_5GHT20:
2486 case CTL_2GHT20:
2487 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
2488 targetPowerHt20.tPow2x[i] =
2489 min((u16)targetPowerHt20.tPow2x[i],
2490 minCtlPower);
2491 }
2492 break;
2493 case CTL_11B_EXT:
2494 targetPowerCckExt.tPow2x[0] = min((u16)
2495 targetPowerCckExt.tPow2x[0],
2496 minCtlPower);
2497 break;
2498 case CTL_11A_EXT:
2499 case CTL_11G_EXT:
2500 targetPowerOfdmExt.tPow2x[0] = min((u16)
2501 targetPowerOfdmExt.tPow2x[0],
2502 minCtlPower);
2503 break;
2504 case CTL_5GHT40:
2505 case CTL_2GHT40:
2506 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
2507 targetPowerHt40.tPow2x[i] =
2508 min((u16)targetPowerHt40.tPow2x[i],
2509 minCtlPower);
2510 }
2511 break;
2512 default:
2513 break;
2514 }
2515 }
2516
2517 ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
2518 ratesArray[rate18mb] = ratesArray[rate24mb] =
2519 targetPowerOfdm.tPow2x[0];
2520 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
2521 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
2522 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
2523 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
2524
2525 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
2526 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
2527
2528 if (IS_CHAN_2GHZ(chan)) {
2529 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
2530 ratesArray[rate2s] = ratesArray[rate2l] =
2531 targetPowerCck.tPow2x[1];
2532 ratesArray[rate5_5s] = ratesArray[rate5_5l] =
2533 targetPowerCck.tPow2x[2];
2534 ;
2535 ratesArray[rate11s] = ratesArray[rate11l] =
2536 targetPowerCck.tPow2x[3];
2537 ;
2538 }
2539 if (IS_CHAN_HT40(chan)) {
2540 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
2541 ratesArray[rateHt40_0 + i] =
2542 targetPowerHt40.tPow2x[i];
2543 }
2544 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
2545 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
2546 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
2547 if (IS_CHAN_2GHZ(chan)) {
2548 ratesArray[rateExtCck] =
2549 targetPowerCckExt.tPow2x[0];
2550 }
2551 }
2552 return true;
2553}
2554
2555static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
2556 struct ath9k_channel *chan,
2557 u16 cfgCtl,
2558 u8 twiceAntennaReduction,
2559 u8 twiceMaxRegulatoryPower,
2560 u8 powerLimit)
2561{
2562#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
2563 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
2564 struct modal_eep_header *pModal =
2565 &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
2566 int16_t ratesArray[Ar5416RateSize];
2567 int16_t txPowerIndexOffset = 0;
2568 u8 ht40PowerIncForPdadc = 2;
2569 int i, cck_ofdm_delta = 0;
2570
2571 memset(ratesArray, 0, sizeof(ratesArray));
2572
2573 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
2574 AR5416_EEP_MINOR_VER_2) {
2575 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
2576 }
2577
2578 if (!ath9k_hw_set_def_power_per_rate_table(ah, chan,
2579 &ratesArray[0], cfgCtl,
2580 twiceAntennaReduction,
2581 twiceMaxRegulatoryPower,
2582 powerLimit)) {
2583 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2584 "ath9k_hw_set_txpower: unable to set "
2585 "tx power per rate table\n");
2586 return -EIO;
2587 }
2588
2589 if (!ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset)) {
2590 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2591 "ath9k_hw_set_txpower: unable to set power table\n");
2592 return -EIO;
2593 }
2594
2595 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
2596 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
2597 if (ratesArray[i] > AR5416_MAX_RATE_POWER)
2598 ratesArray[i] = AR5416_MAX_RATE_POWER;
2599 }
2600
2601 if (AR_SREV_9280_10_OR_LATER(ah)) {
2602 for (i = 0; i < Ar5416RateSize; i++)
2603 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
2604 }
2605
2606 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
2607 ATH9K_POW_SM(ratesArray[rate18mb], 24)
2608 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
2609 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
2610 | ATH9K_POW_SM(ratesArray[rate6mb], 0));
2611 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
2612 ATH9K_POW_SM(ratesArray[rate54mb], 24)
2613 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
2614 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
2615 | ATH9K_POW_SM(ratesArray[rate24mb], 0));
2616
2617 if (IS_CHAN_2GHZ(chan)) {
2618 if (OLC_FOR_AR9280_20_LATER) {
2619 cck_ofdm_delta = 2;
2620 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
2621 ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
2622 | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
2623 | ATH9K_POW_SM(ratesArray[rateXr], 8)
2624 | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
2625 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
2626 ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
2627 | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
2628 | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
2629 | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
2630 } else {
2631 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
2632 ATH9K_POW_SM(ratesArray[rate2s], 24)
2633 | ATH9K_POW_SM(ratesArray[rate2l], 16)
2634 | ATH9K_POW_SM(ratesArray[rateXr], 8)
2635 | ATH9K_POW_SM(ratesArray[rate1l], 0));
2636 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
2637 ATH9K_POW_SM(ratesArray[rate11s], 24)
2638 | ATH9K_POW_SM(ratesArray[rate11l], 16)
2639 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
2640 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
2641 }
2642 }
2643
2644 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
2645 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
2646 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
2647 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
2648 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
2649 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
2650 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
2651 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
2652 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
2653 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
2654
2655 if (IS_CHAN_HT40(chan)) {
2656 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
2657 ATH9K_POW_SM(ratesArray[rateHt40_3] +
2658 ht40PowerIncForPdadc, 24)
2659 | ATH9K_POW_SM(ratesArray[rateHt40_2] +
2660 ht40PowerIncForPdadc, 16)
2661 | ATH9K_POW_SM(ratesArray[rateHt40_1] +
2662 ht40PowerIncForPdadc, 8)
2663 | ATH9K_POW_SM(ratesArray[rateHt40_0] +
2664 ht40PowerIncForPdadc, 0));
2665 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
2666 ATH9K_POW_SM(ratesArray[rateHt40_7] +
2667 ht40PowerIncForPdadc, 24)
2668 | ATH9K_POW_SM(ratesArray[rateHt40_6] +
2669 ht40PowerIncForPdadc, 16)
2670 | ATH9K_POW_SM(ratesArray[rateHt40_5] +
2671 ht40PowerIncForPdadc, 8)
2672 | ATH9K_POW_SM(ratesArray[rateHt40_4] +
2673 ht40PowerIncForPdadc, 0));
2674 if (OLC_FOR_AR9280_20_LATER) {
2675 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
2676 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
2677 | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
2678 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
2679 | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
2680 } else {
2681 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
2682 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
2683 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
2684 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
2685 | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
2686 }
2687 }
2688
2689 REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
2690 ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
2691 | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
2692
2693 i = rate6mb;
2694
2695 if (IS_CHAN_HT40(chan))
2696 i = rateHt40_0;
2697 else if (IS_CHAN_HT20(chan))
2698 i = rateHt20_0;
2699
2700 if (AR_SREV_9280_10_OR_LATER(ah))
2701 ah->regulatory.max_power_level =
2702 ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
2703 else
2704 ah->regulatory.max_power_level = ratesArray[i];
2705
2706 switch(ar5416_get_ntxchains(ah->txchainmask)) {
2707 case 1:
2708 break;
2709 case 2:
2710 ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
2711 break;
2712 case 3:
2713 ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
2714 break;
2715 default:
2716 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2717 "Invalid chainmask configuration\n");
2718 break;
2719 }
2720
2721 return 0;
2722}
2723
2724static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
2725 enum ieee80211_band freq_band)
2726{
2727 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
2728 struct modal_eep_header *pModal =
2729 &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]);
2730 struct base_eep_header *pBase = &eep->baseEepHeader;
2731 u8 num_ant_config;
2732
2733 num_ant_config = 1;
2734
2735 if (pBase->version >= 0x0E0D)
2736 if (pModal->useAnt1)
2737 num_ant_config += 1;
2738
2739 return num_ant_config;
2740}
2741
2742static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah,
2743 struct ath9k_channel *chan)
2744{
2745 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
2746 struct modal_eep_header *pModal =
2747 &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
2748
2749 return pModal->antCtrlCommon & 0xFFFF;
2750}
2751
2752static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
2753{
2754#define EEP_DEF_SPURCHAN \
2755 (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
2756
2757 u16 spur_val = AR_NO_SPUR;
2758
2759 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2760 "Getting spur idx %d is2Ghz. %d val %x\n",
2761 i, is2GHz, ah->config.spurchans[i][is2GHz]);
2762
2763 switch (ah->config.spurmode) {
2764 case SPUR_DISABLE:
2765 break;
2766 case SPUR_ENABLE_IOCTL:
2767 spur_val = ah->config.spurchans[i][is2GHz];
2768 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2769 "Getting spur val from new loc. %d\n", spur_val);
2770 break;
2771 case SPUR_ENABLE_EEPROM:
2772 spur_val = EEP_DEF_SPURCHAN;
2773 break;
2774 }
2775
2776 return spur_val;
2777
2778#undef EEP_DEF_SPURCHAN
2779}
2780
2781static struct eeprom_ops eep_def_ops = {
2782 .check_eeprom = ath9k_hw_def_check_eeprom,
2783 .get_eeprom = ath9k_hw_def_get_eeprom,
2784 .fill_eeprom = ath9k_hw_def_fill_eeprom,
2785 .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver,
2786 .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev,
2787 .get_num_ant_config = ath9k_hw_def_get_num_ant_config,
2788 .get_eeprom_antenna_cfg = ath9k_hw_def_get_eeprom_antenna_cfg,
2789 .set_board_values = ath9k_hw_def_set_board_values,
2790 .set_addac = ath9k_hw_def_set_addac,
2791 .set_txpower = ath9k_hw_def_set_txpower,
2792 .get_spur_channel = ath9k_hw_def_get_spur_channel
2793};
2794
2795int ath9k_hw_eeprom_attach(struct ath_hw *ah)
2796{
2797 int status;
2798
2799 if (AR_SREV_9285(ah)) {
2800 ah->eep_map = EEP_MAP_4KBITS;
2801 ah->eep_ops = &eep_4k_ops;
2802 } else {
2803 ah->eep_map = EEP_MAP_DEFAULT;
2804 ah->eep_ops = &eep_def_ops;
2805 }
2806
2807 if (!ah->eep_ops->fill_eeprom(ah))
2808 return -EIO;
2809
2810 status = ah->eep_ops->check_eeprom(ah);
2811
2812 return status;
2813}
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
new file mode 100644
index 000000000000..9a7715df5cff
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -0,0 +1,509 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef EEPROM_H
18#define EEPROM_H
19
20#include <net/wireless.h>
21
22#define AH_USE_EEPROM 0x1
23
24#ifdef __BIG_ENDIAN
25#define AR5416_EEPROM_MAGIC 0x5aa5
26#else
27#define AR5416_EEPROM_MAGIC 0xa55a
28#endif
29
30#define CTRY_DEBUG 0x1ff
31#define CTRY_DEFAULT 0
32
33#define AR_EEPROM_EEPCAP_COMPRESS_DIS 0x0001
34#define AR_EEPROM_EEPCAP_AES_DIS 0x0002
35#define AR_EEPROM_EEPCAP_FASTFRAME_DIS 0x0004
36#define AR_EEPROM_EEPCAP_BURST_DIS 0x0008
37#define AR_EEPROM_EEPCAP_MAXQCU 0x01F0
38#define AR_EEPROM_EEPCAP_MAXQCU_S 4
39#define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN 0x0200
40#define AR_EEPROM_EEPCAP_KC_ENTRIES 0xF000
41#define AR_EEPROM_EEPCAP_KC_ENTRIES_S 12
42
43#define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND 0x0040
44#define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080
45#define AR_EEPROM_EEREGCAP_EN_KK_U2 0x0100
46#define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200
47#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400
48#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A 0x0800
49
50#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0 0x4000
51#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000
52
53#define AR5416_EEPROM_MAGIC_OFFSET 0x0
54#define AR5416_EEPROM_S 2
55#define AR5416_EEPROM_OFFSET 0x2000
56#define AR5416_EEPROM_MAX 0xae0
57
58#define AR5416_EEPROM_START_ADDR \
59 (AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200
60
61#define SD_NO_CTL 0xE0
62#define NO_CTL 0xff
63#define CTL_MODE_M 7
64#define CTL_11A 0
65#define CTL_11B 1
66#define CTL_11G 2
67#define CTL_2GHT20 5
68#define CTL_5GHT20 6
69#define CTL_2GHT40 7
70#define CTL_5GHT40 8
71
72#define EXT_ADDITIVE (0x8000)
73#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
74#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
75#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
76
77#define SUB_NUM_CTL_MODES_AT_5G_40 2
78#define SUB_NUM_CTL_MODES_AT_2G_40 3
79
80#define INCREASE_MAXPOW_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
81#define INCREASE_MAXPOW_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
82
83/*
84 * For AR9285 and later chipsets, the following bits are not being programmed
85 * in EEPROM and so need to be enabled always.
86 *
87 * Bit 0: en_fcc_mid
88 * Bit 1: en_jap_mid
89 * Bit 2: en_fcc_dfs_ht40
90 * Bit 3: en_jap_ht40
91 * Bit 4: en_jap_dfs_ht40
92 */
93#define AR9285_RDEXT_DEFAULT 0x1F
94
95#define AR_EEPROM_MAC(i) (0x1d+(i))
96#define ATH9K_POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
97#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
98#define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM))
99
100#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
101#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
102 ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
103
104#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c
105#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2
106#define AR_EEPROM_RFSILENT_POLARITY 0x0002
107#define AR_EEPROM_RFSILENT_POLARITY_S 1
108
109#define EEP_RFSILENT_ENABLED 0x0001
110#define EEP_RFSILENT_ENABLED_S 0
111#define EEP_RFSILENT_POLARITY 0x0002
112#define EEP_RFSILENT_POLARITY_S 1
113#define EEP_RFSILENT_GPIO_SEL 0x001c
114#define EEP_RFSILENT_GPIO_SEL_S 2
115
116#define AR5416_OPFLAGS_11A 0x01
117#define AR5416_OPFLAGS_11G 0x02
118#define AR5416_OPFLAGS_N_5G_HT40 0x04
119#define AR5416_OPFLAGS_N_2G_HT40 0x08
120#define AR5416_OPFLAGS_N_5G_HT20 0x10
121#define AR5416_OPFLAGS_N_2G_HT20 0x20
122
123#define AR5416_EEP_NO_BACK_VER 0x1
124#define AR5416_EEP_VER 0xE
125#define AR5416_EEP_VER_MINOR_MASK 0x0FFF
126#define AR5416_EEP_MINOR_VER_2 0x2
127#define AR5416_EEP_MINOR_VER_3 0x3
128#define AR5416_EEP_MINOR_VER_7 0x7
129#define AR5416_EEP_MINOR_VER_9 0x9
130#define AR5416_EEP_MINOR_VER_16 0x10
131#define AR5416_EEP_MINOR_VER_17 0x11
132#define AR5416_EEP_MINOR_VER_19 0x13
133#define AR5416_EEP_MINOR_VER_20 0x14
134#define AR5416_EEP_MINOR_VER_22 0x16
135
136#define AR5416_NUM_5G_CAL_PIERS 8
137#define AR5416_NUM_2G_CAL_PIERS 4
138#define AR5416_NUM_5G_20_TARGET_POWERS 8
139#define AR5416_NUM_5G_40_TARGET_POWERS 8
140#define AR5416_NUM_2G_CCK_TARGET_POWERS 3
141#define AR5416_NUM_2G_20_TARGET_POWERS 4
142#define AR5416_NUM_2G_40_TARGET_POWERS 4
143#define AR5416_NUM_CTLS 24
144#define AR5416_NUM_BAND_EDGES 8
145#define AR5416_NUM_PD_GAINS 4
146#define AR5416_PD_GAINS_IN_MASK 4
147#define AR5416_PD_GAIN_ICEPTS 5
148#define AR5416_EEPROM_MODAL_SPURS 5
149#define AR5416_MAX_RATE_POWER 63
150#define AR5416_NUM_PDADC_VALUES 128
151#define AR5416_BCHAN_UNUSED 0xFF
152#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
153#define AR5416_MAX_CHAINS 3
154#define AR5416_PWR_TABLE_OFFSET -5
155
156/* Rx gain type values */
157#define AR5416_EEP_RXGAIN_23DB_BACKOFF 0
158#define AR5416_EEP_RXGAIN_13DB_BACKOFF 1
159#define AR5416_EEP_RXGAIN_ORIG 2
160
161/* Tx gain type values */
162#define AR5416_EEP_TXGAIN_ORIGINAL 0
163#define AR5416_EEP_TXGAIN_HIGH_POWER 1
164
165#define AR5416_EEP4K_START_LOC 64
166#define AR5416_EEP4K_NUM_2G_CAL_PIERS 3
167#define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3
168#define AR5416_EEP4K_NUM_2G_20_TARGET_POWERS 3
169#define AR5416_EEP4K_NUM_2G_40_TARGET_POWERS 3
170#define AR5416_EEP4K_NUM_CTLS 12
171#define AR5416_EEP4K_NUM_BAND_EDGES 4
172#define AR5416_EEP4K_NUM_PD_GAINS 2
173#define AR5416_EEP4K_PD_GAINS_IN_MASK 4
174#define AR5416_EEP4K_PD_GAIN_ICEPTS 5
175#define AR5416_EEP4K_MAX_CHAINS 1
176
177#define AR9280_TX_GAIN_TABLE_SIZE 22
178
179enum eeprom_param {
180 EEP_NFTHRESH_5,
181 EEP_NFTHRESH_2,
182 EEP_MAC_MSW,
183 EEP_MAC_MID,
184 EEP_MAC_LSW,
185 EEP_REG_0,
186 EEP_REG_1,
187 EEP_OP_CAP,
188 EEP_OP_MODE,
189 EEP_RF_SILENT,
190 EEP_OB_5,
191 EEP_DB_5,
192 EEP_OB_2,
193 EEP_DB_2,
194 EEP_MINOR_REV,
195 EEP_TX_MASK,
196 EEP_RX_MASK,
197 EEP_RXGAIN_TYPE,
198 EEP_TXGAIN_TYPE,
199 EEP_OL_PWRCTRL,
200 EEP_RC_CHAIN_MASK,
201 EEP_DAC_HPWR_5G,
202 EEP_FRAC_N_5G
203};
204
205enum ar5416_rates {
206 rate6mb, rate9mb, rate12mb, rate18mb,
207 rate24mb, rate36mb, rate48mb, rate54mb,
208 rate1l, rate2l, rate2s, rate5_5l,
209 rate5_5s, rate11l, rate11s, rateXr,
210 rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3,
211 rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7,
212 rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3,
213 rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7,
214 rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm,
215 Ar5416RateSize
216};
217
218enum ath9k_hal_freq_band {
219 ATH9K_HAL_FREQ_BAND_5GHZ = 0,
220 ATH9K_HAL_FREQ_BAND_2GHZ = 1
221};
222
223struct base_eep_header {
224 u16 length;
225 u16 checksum;
226 u16 version;
227 u8 opCapFlags;
228 u8 eepMisc;
229 u16 regDmn[2];
230 u8 macAddr[6];
231 u8 rxMask;
232 u8 txMask;
233 u16 rfSilent;
234 u16 blueToothOptions;
235 u16 deviceCap;
236 u32 binBuildNumber;
237 u8 deviceType;
238 u8 pwdclkind;
239 u8 futureBase_1[2];
240 u8 rxGainType;
241 u8 dacHiPwrMode_5G;
242 u8 openLoopPwrCntl;
243 u8 dacLpMode;
244 u8 txGainType;
245 u8 rcChainMask;
246 u8 desiredScaleCCK;
247 u8 power_table_offset;
248 u8 frac_n_5g;
249 u8 futureBase_3[21];
250} __packed;
251
252struct base_eep_header_4k {
253 u16 length;
254 u16 checksum;
255 u16 version;
256 u8 opCapFlags;
257 u8 eepMisc;
258 u16 regDmn[2];
259 u8 macAddr[6];
260 u8 rxMask;
261 u8 txMask;
262 u16 rfSilent;
263 u16 blueToothOptions;
264 u16 deviceCap;
265 u32 binBuildNumber;
266 u8 deviceType;
267 u8 txGainType;
268} __packed;
269
270
271struct spur_chan {
272 u16 spurChan;
273 u8 spurRangeLow;
274 u8 spurRangeHigh;
275} __packed;
276
277struct modal_eep_header {
278 u32 antCtrlChain[AR5416_MAX_CHAINS];
279 u32 antCtrlCommon;
280 u8 antennaGainCh[AR5416_MAX_CHAINS];
281 u8 switchSettling;
282 u8 txRxAttenCh[AR5416_MAX_CHAINS];
283 u8 rxTxMarginCh[AR5416_MAX_CHAINS];
284 u8 adcDesiredSize;
285 u8 pgaDesiredSize;
286 u8 xlnaGainCh[AR5416_MAX_CHAINS];
287 u8 txEndToXpaOff;
288 u8 txEndToRxOn;
289 u8 txFrameToXpaOn;
290 u8 thresh62;
291 u8 noiseFloorThreshCh[AR5416_MAX_CHAINS];
292 u8 xpdGain;
293 u8 xpd;
294 u8 iqCalICh[AR5416_MAX_CHAINS];
295 u8 iqCalQCh[AR5416_MAX_CHAINS];
296 u8 pdGainOverlap;
297 u8 ob;
298 u8 db;
299 u8 xpaBiasLvl;
300 u8 pwrDecreaseFor2Chain;
301 u8 pwrDecreaseFor3Chain;
302 u8 txFrameToDataStart;
303 u8 txFrameToPaOn;
304 u8 ht40PowerIncForPdadc;
305 u8 bswAtten[AR5416_MAX_CHAINS];
306 u8 bswMargin[AR5416_MAX_CHAINS];
307 u8 swSettleHt40;
308 u8 xatten2Db[AR5416_MAX_CHAINS];
309 u8 xatten2Margin[AR5416_MAX_CHAINS];
310 u8 ob_ch1;
311 u8 db_ch1;
312 u8 useAnt1:1,
313 force_xpaon:1,
314 local_bias:1,
315 femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1;
316 u8 miscBits;
317 u16 xpaBiasLvlFreq[3];
318 u8 futureModal[6];
319
320 struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
321} __packed;
322
323struct calDataPerFreqOpLoop {
324 u8 pwrPdg[2][5];
325 u8 vpdPdg[2][5];
326 u8 pcdac[2][5];
327 u8 empty[2][5];
328} __packed;
329
330struct modal_eep_4k_header {
331 u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
332 u32 antCtrlCommon;
333 u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS];
334 u8 switchSettling;
335 u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS];
336 u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS];
337 u8 adcDesiredSize;
338 u8 pgaDesiredSize;
339 u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS];
340 u8 txEndToXpaOff;
341 u8 txEndToRxOn;
342 u8 txFrameToXpaOn;
343 u8 thresh62;
344 u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS];
345 u8 xpdGain;
346 u8 xpd;
347 u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS];
348 u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS];
349 u8 pdGainOverlap;
350 u8 ob_01;
351 u8 db1_01;
352 u8 xpaBiasLvl;
353 u8 txFrameToDataStart;
354 u8 txFrameToPaOn;
355 u8 ht40PowerIncForPdadc;
356 u8 bswAtten[AR5416_EEP4K_MAX_CHAINS];
357 u8 bswMargin[AR5416_EEP4K_MAX_CHAINS];
358 u8 swSettleHt40;
359 u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS];
360 u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS];
361 u8 db2_01;
362 u8 version;
363 u16 ob_234;
364 u16 db1_234;
365 u16 db2_234;
366 u8 futureModal[4];
367
368 struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
369} __packed;
370
371
372struct cal_data_per_freq {
373 u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
374 u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
375} __packed;
376
377struct cal_data_per_freq_4k {
378 u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
379 u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
380} __packed;
381
382struct cal_target_power_leg {
383 u8 bChannel;
384 u8 tPow2x[4];
385} __packed;
386
387struct cal_target_power_ht {
388 u8 bChannel;
389 u8 tPow2x[8];
390} __packed;
391
392
393#ifdef __BIG_ENDIAN_BITFIELD
394struct cal_ctl_edges {
395 u8 bChannel;
396 u8 flag:2, tPower:6;
397} __packed;
398#else
399struct cal_ctl_edges {
400 u8 bChannel;
401 u8 tPower:6, flag:2;
402} __packed;
403#endif
404
405struct cal_ctl_data {
406 struct cal_ctl_edges
407 ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
408} __packed;
409
410struct cal_ctl_data_4k {
411 struct cal_ctl_edges
412 ctlEdges[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_BAND_EDGES];
413} __packed;
414
415struct ar5416_eeprom_def {
416 struct base_eep_header baseEepHeader;
417 u8 custData[64];
418 struct modal_eep_header modalHeader[2];
419 u8 calFreqPier5G[AR5416_NUM_5G_CAL_PIERS];
420 u8 calFreqPier2G[AR5416_NUM_2G_CAL_PIERS];
421 struct cal_data_per_freq
422 calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS];
423 struct cal_data_per_freq
424 calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
425 struct cal_target_power_leg
426 calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS];
427 struct cal_target_power_ht
428 calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS];
429 struct cal_target_power_ht
430 calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS];
431 struct cal_target_power_leg
432 calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS];
433 struct cal_target_power_leg
434 calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS];
435 struct cal_target_power_ht
436 calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS];
437 struct cal_target_power_ht
438 calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS];
439 u8 ctlIndex[AR5416_NUM_CTLS];
440 struct cal_ctl_data ctlData[AR5416_NUM_CTLS];
441 u8 padding;
442} __packed;
443
444struct ar5416_eeprom_4k {
445 struct base_eep_header_4k baseEepHeader;
446 u8 custData[20];
447 struct modal_eep_4k_header modalHeader;
448 u8 calFreqPier2G[AR5416_EEP4K_NUM_2G_CAL_PIERS];
449 struct cal_data_per_freq_4k
450 calPierData2G[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_2G_CAL_PIERS];
451 struct cal_target_power_leg
452 calTargetPowerCck[AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS];
453 struct cal_target_power_leg
454 calTargetPower2G[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
455 struct cal_target_power_ht
456 calTargetPower2GHT20[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
457 struct cal_target_power_ht
458 calTargetPower2GHT40[AR5416_EEP4K_NUM_2G_40_TARGET_POWERS];
459 u8 ctlIndex[AR5416_EEP4K_NUM_CTLS];
460 struct cal_ctl_data_4k ctlData[AR5416_EEP4K_NUM_CTLS];
461 u8 padding;
462} __packed;
463
464enum reg_ext_bitmap {
465 REG_EXT_JAPAN_MIDBAND = 1,
466 REG_EXT_FCC_DFS_HT40 = 2,
467 REG_EXT_JAPAN_NONDFS_HT40 = 3,
468 REG_EXT_JAPAN_DFS_HT40 = 4
469};
470
471struct ath9k_country_entry {
472 u16 countryCode;
473 u16 regDmnEnum;
474 u16 regDmn5G;
475 u16 regDmn2G;
476 u8 isMultidomain;
477 u8 iso[3];
478};
479
480enum ath9k_eep_map {
481 EEP_MAP_DEFAULT = 0x0,
482 EEP_MAP_4KBITS,
483 EEP_MAP_MAX
484};
485
486struct eeprom_ops {
487 int (*check_eeprom)(struct ath_hw *hw);
488 u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param);
489 bool (*fill_eeprom)(struct ath_hw *hw);
490 int (*get_eeprom_ver)(struct ath_hw *hw);
491 int (*get_eeprom_rev)(struct ath_hw *hw);
492 u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band);
493 u16 (*get_eeprom_antenna_cfg)(struct ath_hw *hw,
494 struct ath9k_channel *chan);
495 void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
496 void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
497 int (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
498 u16 cfgCtl, u8 twiceAntennaReduction,
499 u8 twiceMaxRegulatoryPower, u8 powerLimit);
500 u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
501};
502
503#define ar5416_get_ntxchains(_txchainmask) \
504 (((_txchainmask >> 2) & 1) + \
505 ((_txchainmask >> 1) & 1) + (_txchainmask & 1))
506
507int ath9k_hw_eeprom_attach(struct ath_hw *ah);
508
509#endif /* EEPROM_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
new file mode 100644
index 000000000000..24299e65fdcf
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -0,0 +1,3861 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <linux/io.h>
18#include <asm/unaligned.h>
19
20#include "ath9k.h"
21#include "initvals.h"
22
23static int btcoex_enable;
24module_param(btcoex_enable, bool, 0);
25MODULE_PARM_DESC(btcoex_enable, "Enable Bluetooth coexistence support");
26
27#define ATH9K_CLOCK_RATE_CCK 22
28#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40
29#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44
30
31static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
32static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan,
33 enum ath9k_ht_macmode macmode);
34static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
35 struct ar5416_eeprom_def *pEepData,
36 u32 reg, u32 value);
37static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan);
38static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan);
39
40/********************/
41/* Helper Functions */
42/********************/
43
44static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks)
45{
46 struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
47
48 if (!ah->curchan) /* should really check for CCK instead */
49 return clks / ATH9K_CLOCK_RATE_CCK;
50 if (conf->channel->band == IEEE80211_BAND_2GHZ)
51 return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM;
52
53 return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM;
54}
55
56static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks)
57{
58 struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
59
60 if (conf_is_ht40(conf))
61 return ath9k_hw_mac_usec(ah, clks) / 2;
62 else
63 return ath9k_hw_mac_usec(ah, clks);
64}
65
66static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs)
67{
68 struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
69
70 if (!ah->curchan) /* should really check for CCK instead */
71 return usecs *ATH9K_CLOCK_RATE_CCK;
72 if (conf->channel->band == IEEE80211_BAND_2GHZ)
73 return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM;
74 return usecs *ATH9K_CLOCK_RATE_5GHZ_OFDM;
75}
76
77static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
78{
79 struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
80
81 if (conf_is_ht40(conf))
82 return ath9k_hw_mac_clks(ah, usecs) * 2;
83 else
84 return ath9k_hw_mac_clks(ah, usecs);
85}
86
87bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
88{
89 int i;
90
91 BUG_ON(timeout < AH_TIME_QUANTUM);
92
93 for (i = 0; i < (timeout / AH_TIME_QUANTUM); i++) {
94 if ((REG_READ(ah, reg) & mask) == val)
95 return true;
96
97 udelay(AH_TIME_QUANTUM);
98 }
99
100 DPRINTF(ah->ah_sc, ATH_DBG_ANY,
101 "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
102 timeout, reg, REG_READ(ah, reg), mask, val);
103
104 return false;
105}
106
107u32 ath9k_hw_reverse_bits(u32 val, u32 n)
108{
109 u32 retval;
110 int i;
111
112 for (i = 0, retval = 0; i < n; i++) {
113 retval = (retval << 1) | (val & 1);
114 val >>= 1;
115 }
116 return retval;
117}
118
119bool ath9k_get_channel_edges(struct ath_hw *ah,
120 u16 flags, u16 *low,
121 u16 *high)
122{
123 struct ath9k_hw_capabilities *pCap = &ah->caps;
124
125 if (flags & CHANNEL_5GHZ) {
126 *low = pCap->low_5ghz_chan;
127 *high = pCap->high_5ghz_chan;
128 return true;
129 }
130 if ((flags & CHANNEL_2GHZ)) {
131 *low = pCap->low_2ghz_chan;
132 *high = pCap->high_2ghz_chan;
133 return true;
134 }
135 return false;
136}
137
138u16 ath9k_hw_computetxtime(struct ath_hw *ah,
139 struct ath_rate_table *rates,
140 u32 frameLen, u16 rateix,
141 bool shortPreamble)
142{
143 u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
144 u32 kbps;
145
146 kbps = rates->info[rateix].ratekbps;
147
148 if (kbps == 0)
149 return 0;
150
151 switch (rates->info[rateix].phy) {
152 case WLAN_RC_PHY_CCK:
153 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
154 if (shortPreamble && rates->info[rateix].short_preamble)
155 phyTime >>= 1;
156 numBits = frameLen << 3;
157 txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps);
158 break;
159 case WLAN_RC_PHY_OFDM:
160 if (ah->curchan && IS_CHAN_QUARTER_RATE(ah->curchan)) {
161 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
162 numBits = OFDM_PLCP_BITS + (frameLen << 3);
163 numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
164 txTime = OFDM_SIFS_TIME_QUARTER
165 + OFDM_PREAMBLE_TIME_QUARTER
166 + (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
167 } else if (ah->curchan &&
168 IS_CHAN_HALF_RATE(ah->curchan)) {
169 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
170 numBits = OFDM_PLCP_BITS + (frameLen << 3);
171 numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
172 txTime = OFDM_SIFS_TIME_HALF +
173 OFDM_PREAMBLE_TIME_HALF
174 + (numSymbols * OFDM_SYMBOL_TIME_HALF);
175 } else {
176 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
177 numBits = OFDM_PLCP_BITS + (frameLen << 3);
178 numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
179 txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
180 + (numSymbols * OFDM_SYMBOL_TIME);
181 }
182 break;
183 default:
184 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
185 "Unknown phy %u (rate ix %u)\n",
186 rates->info[rateix].phy, rateix);
187 txTime = 0;
188 break;
189 }
190
191 return txTime;
192}
193
194void ath9k_hw_get_channel_centers(struct ath_hw *ah,
195 struct ath9k_channel *chan,
196 struct chan_centers *centers)
197{
198 int8_t extoff;
199
200 if (!IS_CHAN_HT40(chan)) {
201 centers->ctl_center = centers->ext_center =
202 centers->synth_center = chan->channel;
203 return;
204 }
205
206 if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
207 (chan->chanmode == CHANNEL_G_HT40PLUS)) {
208 centers->synth_center =
209 chan->channel + HT40_CHANNEL_CENTER_SHIFT;
210 extoff = 1;
211 } else {
212 centers->synth_center =
213 chan->channel - HT40_CHANNEL_CENTER_SHIFT;
214 extoff = -1;
215 }
216
217 centers->ctl_center =
218 centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT);
219 centers->ext_center =
220 centers->synth_center + (extoff *
221 ((ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_20) ?
222 HT40_CHANNEL_CENTER_SHIFT : 15));
223}
224
225/******************/
226/* Chip Revisions */
227/******************/
228
229static void ath9k_hw_read_revisions(struct ath_hw *ah)
230{
231 u32 val;
232
233 val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
234
235 if (val == 0xFF) {
236 val = REG_READ(ah, AR_SREV);
237 ah->hw_version.macVersion =
238 (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
239 ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
240 ah->is_pciexpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
241 } else {
242 if (!AR_SREV_9100(ah))
243 ah->hw_version.macVersion = MS(val, AR_SREV_VERSION);
244
245 ah->hw_version.macRev = val & AR_SREV_REVISION;
246
247 if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)
248 ah->is_pciexpress = true;
249 }
250}
251
252static int ath9k_hw_get_radiorev(struct ath_hw *ah)
253{
254 u32 val;
255 int i;
256
257 REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
258
259 for (i = 0; i < 8; i++)
260 REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
261 val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
262 val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
263
264 return ath9k_hw_reverse_bits(val, 8);
265}
266
267/************************************/
268/* HW Attach, Detach, Init Routines */
269/************************************/
270
271static void ath9k_hw_disablepcie(struct ath_hw *ah)
272{
273 if (AR_SREV_9100(ah))
274 return;
275
276 REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
277 REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
278 REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
279 REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824);
280 REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579);
281 REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000);
282 REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
283 REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
284 REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
285
286 REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
287}
288
289static bool ath9k_hw_chip_test(struct ath_hw *ah)
290{
291 u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) };
292 u32 regHold[2];
293 u32 patternData[4] = { 0x55555555,
294 0xaaaaaaaa,
295 0x66666666,
296 0x99999999 };
297 int i, j;
298
299 for (i = 0; i < 2; i++) {
300 u32 addr = regAddr[i];
301 u32 wrData, rdData;
302
303 regHold[i] = REG_READ(ah, addr);
304 for (j = 0; j < 0x100; j++) {
305 wrData = (j << 16) | j;
306 REG_WRITE(ah, addr, wrData);
307 rdData = REG_READ(ah, addr);
308 if (rdData != wrData) {
309 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
310 "address test failed "
311 "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
312 addr, wrData, rdData);
313 return false;
314 }
315 }
316 for (j = 0; j < 4; j++) {
317 wrData = patternData[j];
318 REG_WRITE(ah, addr, wrData);
319 rdData = REG_READ(ah, addr);
320 if (wrData != rdData) {
321 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
322 "address test failed "
323 "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
324 addr, wrData, rdData);
325 return false;
326 }
327 }
328 REG_WRITE(ah, regAddr[i], regHold[i]);
329 }
330 udelay(100);
331
332 return true;
333}
334
335static const char *ath9k_hw_devname(u16 devid)
336{
337 switch (devid) {
338 case AR5416_DEVID_PCI:
339 return "Atheros 5416";
340 case AR5416_DEVID_PCIE:
341 return "Atheros 5418";
342 case AR9160_DEVID_PCI:
343 return "Atheros 9160";
344 case AR5416_AR9100_DEVID:
345 return "Atheros 9100";
346 case AR9280_DEVID_PCI:
347 case AR9280_DEVID_PCIE:
348 return "Atheros 9280";
349 case AR9285_DEVID_PCIE:
350 return "Atheros 9285";
351 }
352
353 return NULL;
354}
355
356static void ath9k_hw_set_defaults(struct ath_hw *ah)
357{
358 int i;
359
360 ah->config.dma_beacon_response_time = 2;
361 ah->config.sw_beacon_response_time = 10;
362 ah->config.additional_swba_backoff = 0;
363 ah->config.ack_6mb = 0x0;
364 ah->config.cwm_ignore_extcca = 0;
365 ah->config.pcie_powersave_enable = 0;
366 ah->config.pcie_clock_req = 0;
367 ah->config.pcie_waen = 0;
368 ah->config.analog_shiftreg = 1;
369 ah->config.ht_enable = 1;
370 ah->config.ofdm_trig_low = 200;
371 ah->config.ofdm_trig_high = 500;
372 ah->config.cck_trig_high = 200;
373 ah->config.cck_trig_low = 100;
374 ah->config.enable_ani = 1;
375 ah->config.diversity_control = 0;
376 ah->config.antenna_switch_swap = 0;
377
378 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
379 ah->config.spurchans[i][0] = AR_NO_SPUR;
380 ah->config.spurchans[i][1] = AR_NO_SPUR;
381 }
382
383 ah->config.intr_mitigation = true;
384
385 /*
386 * We need this for PCI devices only (Cardbus, PCI, miniPCI)
387 * _and_ if on non-uniprocessor systems (Multiprocessor/HT).
388 * This means we use it for all AR5416 devices, and the few
389 * minor PCI AR9280 devices out there.
390 *
391 * Serialization is required because these devices do not handle
392 * well the case of two concurrent reads/writes due to the latency
393 * involved. During one read/write another read/write can be issued
394 * on another CPU while the previous read/write may still be working
395 * on our hardware, if we hit this case the hardware poops in a loop.
396 * We prevent this by serializing reads and writes.
397 *
398 * This issue is not present on PCI-Express devices or pre-AR5416
399 * devices (legacy, 802.11abg).
400 */
401 if (num_possible_cpus() > 1)
402 ah->config.serialize_regmode = SER_REG_MODE_AUTO;
403}
404
405static struct ath_hw *ath9k_hw_newstate(u16 devid, struct ath_softc *sc,
406 int *status)
407{
408 struct ath_hw *ah;
409
410 ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
411 if (ah == NULL) {
412 DPRINTF(sc, ATH_DBG_FATAL,
413 "Cannot allocate memory for state block\n");
414 *status = -ENOMEM;
415 return NULL;
416 }
417
418 ah->ah_sc = sc;
419 ah->hw_version.magic = AR5416_MAGIC;
420 ah->regulatory.country_code = CTRY_DEFAULT;
421 ah->hw_version.devid = devid;
422 ah->hw_version.subvendorid = 0;
423
424 ah->ah_flags = 0;
425 if ((devid == AR5416_AR9100_DEVID))
426 ah->hw_version.macVersion = AR_SREV_VERSION_9100;
427 if (!AR_SREV_9100(ah))
428 ah->ah_flags = AH_USE_EEPROM;
429
430 ah->regulatory.power_limit = MAX_RATE_POWER;
431 ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX;
432 ah->atim_window = 0;
433 ah->diversity_control = ah->config.diversity_control;
434 ah->antenna_switch_swap =
435 ah->config.antenna_switch_swap;
436 ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
437 ah->beacon_interval = 100;
438 ah->enable_32kHz_clock = DONT_USE_32KHZ;
439 ah->slottime = (u32) -1;
440 ah->acktimeout = (u32) -1;
441 ah->ctstimeout = (u32) -1;
442 ah->globaltxtimeout = (u32) -1;
443
444 ah->gbeacon_rate = 0;
445
446 return ah;
447}
448
449static int ath9k_hw_rfattach(struct ath_hw *ah)
450{
451 bool rfStatus = false;
452 int ecode = 0;
453
454 rfStatus = ath9k_hw_init_rf(ah, &ecode);
455 if (!rfStatus) {
456 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
457 "RF setup failed, status: %u\n", ecode);
458 return ecode;
459 }
460
461 return 0;
462}
463
464static int ath9k_hw_rf_claim(struct ath_hw *ah)
465{
466 u32 val;
467
468 REG_WRITE(ah, AR_PHY(0), 0x00000007);
469
470 val = ath9k_hw_get_radiorev(ah);
471 switch (val & AR_RADIO_SREV_MAJOR) {
472 case 0:
473 val = AR_RAD5133_SREV_MAJOR;
474 break;
475 case AR_RAD5133_SREV_MAJOR:
476 case AR_RAD5122_SREV_MAJOR:
477 case AR_RAD2133_SREV_MAJOR:
478 case AR_RAD2122_SREV_MAJOR:
479 break;
480 default:
481 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
482 "Radio Chip Rev 0x%02X not supported\n",
483 val & AR_RADIO_SREV_MAJOR);
484 return -EOPNOTSUPP;
485 }
486
487 ah->hw_version.analog5GhzRev = val;
488
489 return 0;
490}
491
492static int ath9k_hw_init_macaddr(struct ath_hw *ah)
493{
494 u32 sum;
495 int i;
496 u16 eeval;
497
498 sum = 0;
499 for (i = 0; i < 3; i++) {
500 eeval = ah->eep_ops->get_eeprom(ah, AR_EEPROM_MAC(i));
501 sum += eeval;
502 ah->macaddr[2 * i] = eeval >> 8;
503 ah->macaddr[2 * i + 1] = eeval & 0xff;
504 }
505 if (sum == 0 || sum == 0xffff * 3)
506 return -EADDRNOTAVAIL;
507
508 return 0;
509}
510
511static void ath9k_hw_init_rxgain_ini(struct ath_hw *ah)
512{
513 u32 rxgain_type;
514
515 if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_17) {
516 rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
517
518 if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
519 INIT_INI_ARRAY(&ah->iniModesRxGain,
520 ar9280Modes_backoff_13db_rxgain_9280_2,
521 ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6);
522 else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
523 INIT_INI_ARRAY(&ah->iniModesRxGain,
524 ar9280Modes_backoff_23db_rxgain_9280_2,
525 ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6);
526 else
527 INIT_INI_ARRAY(&ah->iniModesRxGain,
528 ar9280Modes_original_rxgain_9280_2,
529 ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
530 } else {
531 INIT_INI_ARRAY(&ah->iniModesRxGain,
532 ar9280Modes_original_rxgain_9280_2,
533 ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
534 }
535}
536
537static void ath9k_hw_init_txgain_ini(struct ath_hw *ah)
538{
539 u32 txgain_type;
540
541 if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_19) {
542 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
543
544 if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
545 INIT_INI_ARRAY(&ah->iniModesTxGain,
546 ar9280Modes_high_power_tx_gain_9280_2,
547 ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6);
548 else
549 INIT_INI_ARRAY(&ah->iniModesTxGain,
550 ar9280Modes_original_tx_gain_9280_2,
551 ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
552 } else {
553 INIT_INI_ARRAY(&ah->iniModesTxGain,
554 ar9280Modes_original_tx_gain_9280_2,
555 ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
556 }
557}
558
559static int ath9k_hw_post_attach(struct ath_hw *ah)
560{
561 int ecode;
562
563 if (!ath9k_hw_chip_test(ah))
564 return -ENODEV;
565
566 ecode = ath9k_hw_rf_claim(ah);
567 if (ecode != 0)
568 return ecode;
569
570 ecode = ath9k_hw_eeprom_attach(ah);
571 if (ecode != 0)
572 return ecode;
573
574 DPRINTF(ah->ah_sc, ATH_DBG_CONFIG, "Eeprom VER: %d, REV: %d\n",
575 ah->eep_ops->get_eeprom_ver(ah), ah->eep_ops->get_eeprom_rev(ah));
576
577 ecode = ath9k_hw_rfattach(ah);
578 if (ecode != 0)
579 return ecode;
580
581 if (!AR_SREV_9100(ah)) {
582 ath9k_hw_ani_setup(ah);
583 ath9k_hw_ani_attach(ah);
584 }
585
586 return 0;
587}
588
589static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
590 int *status)
591{
592 struct ath_hw *ah;
593 int ecode;
594 u32 i, j;
595
596 ah = ath9k_hw_newstate(devid, sc, status);
597 if (ah == NULL)
598 return NULL;
599
600 ath9k_hw_set_defaults(ah);
601
602 if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
603 DPRINTF(sc, ATH_DBG_FATAL, "Couldn't reset chip\n");
604 ecode = -EIO;
605 goto bad;
606 }
607
608 if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
609 DPRINTF(sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n");
610 ecode = -EIO;
611 goto bad;
612 }
613
614 if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
615 if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
616 (AR_SREV_9280(ah) && !ah->is_pciexpress)) {
617 ah->config.serialize_regmode =
618 SER_REG_MODE_ON;
619 } else {
620 ah->config.serialize_regmode =
621 SER_REG_MODE_OFF;
622 }
623 }
624
625 DPRINTF(sc, ATH_DBG_RESET, "serialize_regmode is %d\n",
626 ah->config.serialize_regmode);
627
628 if ((ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCI) &&
629 (ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) &&
630 (ah->hw_version.macVersion != AR_SREV_VERSION_9160) &&
631 (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && (!AR_SREV_9285(ah))) {
632 DPRINTF(sc, ATH_DBG_FATAL,
633 "Mac Chip Rev 0x%02x.%x is not supported by "
634 "this driver\n", ah->hw_version.macVersion,
635 ah->hw_version.macRev);
636 ecode = -EOPNOTSUPP;
637 goto bad;
638 }
639
640 if (AR_SREV_9100(ah)) {
641 ah->iq_caldata.calData = &iq_cal_multi_sample;
642 ah->supp_cals = IQ_MISMATCH_CAL;
643 ah->is_pciexpress = false;
644 }
645 ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
646
647 if (AR_SREV_9160_10_OR_LATER(ah)) {
648 if (AR_SREV_9280_10_OR_LATER(ah)) {
649 ah->iq_caldata.calData = &iq_cal_single_sample;
650 ah->adcgain_caldata.calData =
651 &adc_gain_cal_single_sample;
652 ah->adcdc_caldata.calData =
653 &adc_dc_cal_single_sample;
654 ah->adcdc_calinitdata.calData =
655 &adc_init_dc_cal;
656 } else {
657 ah->iq_caldata.calData = &iq_cal_multi_sample;
658 ah->adcgain_caldata.calData =
659 &adc_gain_cal_multi_sample;
660 ah->adcdc_caldata.calData =
661 &adc_dc_cal_multi_sample;
662 ah->adcdc_calinitdata.calData =
663 &adc_init_dc_cal;
664 }
665 ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
666 }
667
668 ah->ani_function = ATH9K_ANI_ALL;
669 if (AR_SREV_9280_10_OR_LATER(ah))
670 ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
671
672 if (AR_SREV_9285_12_OR_LATER(ah)) {
673
674 INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
675 ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
676 INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
677 ARRAY_SIZE(ar9285Common_9285_1_2), 2);
678
679 if (ah->config.pcie_clock_req) {
680 INIT_INI_ARRAY(&ah->iniPcieSerdes,
681 ar9285PciePhy_clkreq_off_L1_9285_1_2,
682 ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2);
683 } else {
684 INIT_INI_ARRAY(&ah->iniPcieSerdes,
685 ar9285PciePhy_clkreq_always_on_L1_9285_1_2,
686 ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2),
687 2);
688 }
689 } else if (AR_SREV_9285_10_OR_LATER(ah)) {
690 INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285,
691 ARRAY_SIZE(ar9285Modes_9285), 6);
692 INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285,
693 ARRAY_SIZE(ar9285Common_9285), 2);
694
695 if (ah->config.pcie_clock_req) {
696 INIT_INI_ARRAY(&ah->iniPcieSerdes,
697 ar9285PciePhy_clkreq_off_L1_9285,
698 ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2);
699 } else {
700 INIT_INI_ARRAY(&ah->iniPcieSerdes,
701 ar9285PciePhy_clkreq_always_on_L1_9285,
702 ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2);
703 }
704 } else if (AR_SREV_9280_20_OR_LATER(ah)) {
705 INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
706 ARRAY_SIZE(ar9280Modes_9280_2), 6);
707 INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
708 ARRAY_SIZE(ar9280Common_9280_2), 2);
709
710 if (ah->config.pcie_clock_req) {
711 INIT_INI_ARRAY(&ah->iniPcieSerdes,
712 ar9280PciePhy_clkreq_off_L1_9280,
713 ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280),2);
714 } else {
715 INIT_INI_ARRAY(&ah->iniPcieSerdes,
716 ar9280PciePhy_clkreq_always_on_L1_9280,
717 ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2);
718 }
719 INIT_INI_ARRAY(&ah->iniModesAdditional,
720 ar9280Modes_fast_clock_9280_2,
721 ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
722 } else if (AR_SREV_9280_10_OR_LATER(ah)) {
723 INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280,
724 ARRAY_SIZE(ar9280Modes_9280), 6);
725 INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280,
726 ARRAY_SIZE(ar9280Common_9280), 2);
727 } else if (AR_SREV_9160_10_OR_LATER(ah)) {
728 INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
729 ARRAY_SIZE(ar5416Modes_9160), 6);
730 INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
731 ARRAY_SIZE(ar5416Common_9160), 2);
732 INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160,
733 ARRAY_SIZE(ar5416Bank0_9160), 2);
734 INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160,
735 ARRAY_SIZE(ar5416BB_RfGain_9160), 3);
736 INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160,
737 ARRAY_SIZE(ar5416Bank1_9160), 2);
738 INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160,
739 ARRAY_SIZE(ar5416Bank2_9160), 2);
740 INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160,
741 ARRAY_SIZE(ar5416Bank3_9160), 3);
742 INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160,
743 ARRAY_SIZE(ar5416Bank6_9160), 3);
744 INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160,
745 ARRAY_SIZE(ar5416Bank6TPC_9160), 3);
746 INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160,
747 ARRAY_SIZE(ar5416Bank7_9160), 2);
748 if (AR_SREV_9160_11(ah)) {
749 INIT_INI_ARRAY(&ah->iniAddac,
750 ar5416Addac_91601_1,
751 ARRAY_SIZE(ar5416Addac_91601_1), 2);
752 } else {
753 INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160,
754 ARRAY_SIZE(ar5416Addac_9160), 2);
755 }
756 } else if (AR_SREV_9100_OR_LATER(ah)) {
757 INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
758 ARRAY_SIZE(ar5416Modes_9100), 6);
759 INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
760 ARRAY_SIZE(ar5416Common_9100), 2);
761 INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100,
762 ARRAY_SIZE(ar5416Bank0_9100), 2);
763 INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100,
764 ARRAY_SIZE(ar5416BB_RfGain_9100), 3);
765 INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100,
766 ARRAY_SIZE(ar5416Bank1_9100), 2);
767 INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100,
768 ARRAY_SIZE(ar5416Bank2_9100), 2);
769 INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100,
770 ARRAY_SIZE(ar5416Bank3_9100), 3);
771 INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100,
772 ARRAY_SIZE(ar5416Bank6_9100), 3);
773 INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100,
774 ARRAY_SIZE(ar5416Bank6TPC_9100), 3);
775 INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100,
776 ARRAY_SIZE(ar5416Bank7_9100), 2);
777 INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100,
778 ARRAY_SIZE(ar5416Addac_9100), 2);
779 } else {
780 INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
781 ARRAY_SIZE(ar5416Modes), 6);
782 INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
783 ARRAY_SIZE(ar5416Common), 2);
784 INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
785 ARRAY_SIZE(ar5416Bank0), 2);
786 INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain,
787 ARRAY_SIZE(ar5416BB_RfGain), 3);
788 INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1,
789 ARRAY_SIZE(ar5416Bank1), 2);
790 INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2,
791 ARRAY_SIZE(ar5416Bank2), 2);
792 INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3,
793 ARRAY_SIZE(ar5416Bank3), 3);
794 INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6,
795 ARRAY_SIZE(ar5416Bank6), 3);
796 INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC,
797 ARRAY_SIZE(ar5416Bank6TPC), 3);
798 INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7,
799 ARRAY_SIZE(ar5416Bank7), 2);
800 INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
801 ARRAY_SIZE(ar5416Addac), 2);
802 }
803
804 if (ah->is_pciexpress)
805 ath9k_hw_configpcipowersave(ah, 0);
806 else
807 ath9k_hw_disablepcie(ah);
808
809 ecode = ath9k_hw_post_attach(ah);
810 if (ecode != 0)
811 goto bad;
812
813 if (AR_SREV_9285_12_OR_LATER(ah)) {
814 u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
815
816 /* txgain table */
817 if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
818 INIT_INI_ARRAY(&ah->iniModesTxGain,
819 ar9285Modes_high_power_tx_gain_9285_1_2,
820 ARRAY_SIZE(ar9285Modes_high_power_tx_gain_9285_1_2), 6);
821 } else {
822 INIT_INI_ARRAY(&ah->iniModesTxGain,
823 ar9285Modes_original_tx_gain_9285_1_2,
824 ARRAY_SIZE(ar9285Modes_original_tx_gain_9285_1_2), 6);
825 }
826
827 }
828
829 /* rxgain table */
830 if (AR_SREV_9280_20(ah))
831 ath9k_hw_init_rxgain_ini(ah);
832
833 /* txgain table */
834 if (AR_SREV_9280_20(ah))
835 ath9k_hw_init_txgain_ini(ah);
836
837 ath9k_hw_fill_cap_info(ah);
838
839 if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
840 test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) {
841
842 /* EEPROM Fixup */
843 for (i = 0; i < ah->iniModes.ia_rows; i++) {
844 u32 reg = INI_RA(&ah->iniModes, i, 0);
845
846 for (j = 1; j < ah->iniModes.ia_columns; j++) {
847 u32 val = INI_RA(&ah->iniModes, i, j);
848
849 INI_RA(&ah->iniModes, i, j) =
850 ath9k_hw_ini_fixup(ah,
851 &ah->eeprom.def,
852 reg, val);
853 }
854 }
855 }
856
857 ecode = ath9k_hw_init_macaddr(ah);
858 if (ecode != 0) {
859 DPRINTF(sc, ATH_DBG_FATAL,
860 "Failed to initialize MAC address\n");
861 goto bad;
862 }
863
864 if (AR_SREV_9285(ah))
865 ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S);
866 else
867 ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
868
869 ath9k_init_nfcal_hist_buffer(ah);
870
871 return ah;
872bad:
873 if (ah)
874 ath9k_hw_detach(ah);
875 if (status)
876 *status = ecode;
877
878 return NULL;
879}
880
881static void ath9k_hw_init_bb(struct ath_hw *ah,
882 struct ath9k_channel *chan)
883{
884 u32 synthDelay;
885
886 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
887 if (IS_CHAN_B(chan))
888 synthDelay = (4 * synthDelay) / 22;
889 else
890 synthDelay /= 10;
891
892 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
893
894 udelay(synthDelay + BASE_ACTIVATE_DELAY);
895}
896
897static void ath9k_hw_init_qos(struct ath_hw *ah)
898{
899 REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
900 REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
901
902 REG_WRITE(ah, AR_QOS_NO_ACK,
903 SM(2, AR_QOS_NO_ACK_TWO_BIT) |
904 SM(5, AR_QOS_NO_ACK_BIT_OFF) |
905 SM(0, AR_QOS_NO_ACK_BYTE_OFF));
906
907 REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
908 REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
909 REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
910 REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
911 REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
912}
913
914static void ath9k_hw_init_pll(struct ath_hw *ah,
915 struct ath9k_channel *chan)
916{
917 u32 pll;
918
919 if (AR_SREV_9100(ah)) {
920 if (chan && IS_CHAN_5GHZ(chan))
921 pll = 0x1450;
922 else
923 pll = 0x1458;
924 } else {
925 if (AR_SREV_9280_10_OR_LATER(ah)) {
926 pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
927
928 if (chan && IS_CHAN_HALF_RATE(chan))
929 pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
930 else if (chan && IS_CHAN_QUARTER_RATE(chan))
931 pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
932
933 if (chan && IS_CHAN_5GHZ(chan)) {
934 pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
935
936
937 if (AR_SREV_9280_20(ah)) {
938 if (((chan->channel % 20) == 0)
939 || ((chan->channel % 10) == 0))
940 pll = 0x2850;
941 else
942 pll = 0x142c;
943 }
944 } else {
945 pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
946 }
947
948 } else if (AR_SREV_9160_10_OR_LATER(ah)) {
949
950 pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
951
952 if (chan && IS_CHAN_HALF_RATE(chan))
953 pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
954 else if (chan && IS_CHAN_QUARTER_RATE(chan))
955 pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
956
957 if (chan && IS_CHAN_5GHZ(chan))
958 pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
959 else
960 pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
961 } else {
962 pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
963
964 if (chan && IS_CHAN_HALF_RATE(chan))
965 pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
966 else if (chan && IS_CHAN_QUARTER_RATE(chan))
967 pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
968
969 if (chan && IS_CHAN_5GHZ(chan))
970 pll |= SM(0xa, AR_RTC_PLL_DIV);
971 else
972 pll |= SM(0xb, AR_RTC_PLL_DIV);
973 }
974 }
975 REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
976
977 udelay(RTC_PLL_SETTLE_DELAY);
978
979 REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
980}
981
982static void ath9k_hw_init_chain_masks(struct ath_hw *ah)
983{
984 int rx_chainmask, tx_chainmask;
985
986 rx_chainmask = ah->rxchainmask;
987 tx_chainmask = ah->txchainmask;
988
989 switch (rx_chainmask) {
990 case 0x5:
991 REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
992 AR_PHY_SWAP_ALT_CHAIN);
993 case 0x3:
994 if (((ah)->hw_version.macVersion <= AR_SREV_VERSION_9160)) {
995 REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
996 REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);
997 break;
998 }
999 case 0x1:
1000 case 0x2:
1001 case 0x7:
1002 REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
1003 REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
1004 break;
1005 default:
1006 break;
1007 }
1008
1009 REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
1010 if (tx_chainmask == 0x5) {
1011 REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
1012 AR_PHY_SWAP_ALT_CHAIN);
1013 }
1014 if (AR_SREV_9100(ah))
1015 REG_WRITE(ah, AR_PHY_ANALOG_SWAP,
1016 REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001);
1017}
1018
1019static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
1020 enum nl80211_iftype opmode)
1021{
1022 ah->mask_reg = AR_IMR_TXERR |
1023 AR_IMR_TXURN |
1024 AR_IMR_RXERR |
1025 AR_IMR_RXORN |
1026 AR_IMR_BCNMISC;
1027
1028 if (ah->config.intr_mitigation)
1029 ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
1030 else
1031 ah->mask_reg |= AR_IMR_RXOK;
1032
1033 ah->mask_reg |= AR_IMR_TXOK;
1034
1035 if (opmode == NL80211_IFTYPE_AP)
1036 ah->mask_reg |= AR_IMR_MIB;
1037
1038 REG_WRITE(ah, AR_IMR, ah->mask_reg);
1039 REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT);
1040
1041 if (!AR_SREV_9100(ah)) {
1042 REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
1043 REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
1044 REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);
1045 }
1046}
1047
1048static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
1049{
1050 if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
1051 DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad ack timeout %u\n", us);
1052 ah->acktimeout = (u32) -1;
1053 return false;
1054 } else {
1055 REG_RMW_FIELD(ah, AR_TIME_OUT,
1056 AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us));
1057 ah->acktimeout = us;
1058 return true;
1059 }
1060}
1061
1062static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
1063{
1064 if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
1065 DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad cts timeout %u\n", us);
1066 ah->ctstimeout = (u32) -1;
1067 return false;
1068 } else {
1069 REG_RMW_FIELD(ah, AR_TIME_OUT,
1070 AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us));
1071 ah->ctstimeout = us;
1072 return true;
1073 }
1074}
1075
1076static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
1077{
1078 if (tu > 0xFFFF) {
1079 DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
1080 "bad global tx timeout %u\n", tu);
1081 ah->globaltxtimeout = (u32) -1;
1082 return false;
1083 } else {
1084 REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
1085 ah->globaltxtimeout = tu;
1086 return true;
1087 }
1088}
1089
1090static void ath9k_hw_init_user_settings(struct ath_hw *ah)
1091{
1092 DPRINTF(ah->ah_sc, ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
1093 ah->misc_mode);
1094
1095 if (ah->misc_mode != 0)
1096 REG_WRITE(ah, AR_PCU_MISC,
1097 REG_READ(ah, AR_PCU_MISC) | ah->misc_mode);
1098 if (ah->slottime != (u32) -1)
1099 ath9k_hw_setslottime(ah, ah->slottime);
1100 if (ah->acktimeout != (u32) -1)
1101 ath9k_hw_set_ack_timeout(ah, ah->acktimeout);
1102 if (ah->ctstimeout != (u32) -1)
1103 ath9k_hw_set_cts_timeout(ah, ah->ctstimeout);
1104 if (ah->globaltxtimeout != (u32) -1)
1105 ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
1106}
1107
1108const char *ath9k_hw_probe(u16 vendorid, u16 devid)
1109{
1110 return vendorid == ATHEROS_VENDOR_ID ?
1111 ath9k_hw_devname(devid) : NULL;
1112}
1113
1114void ath9k_hw_detach(struct ath_hw *ah)
1115{
1116 if (!AR_SREV_9100(ah))
1117 ath9k_hw_ani_detach(ah);
1118
1119 ath9k_hw_rfdetach(ah);
1120 ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
1121 kfree(ah);
1122}
1123
1124struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error)
1125{
1126 struct ath_hw *ah = NULL;
1127
1128 switch (devid) {
1129 case AR5416_DEVID_PCI:
1130 case AR5416_DEVID_PCIE:
1131 case AR5416_AR9100_DEVID:
1132 case AR9160_DEVID_PCI:
1133 case AR9280_DEVID_PCI:
1134 case AR9280_DEVID_PCIE:
1135 case AR9285_DEVID_PCIE:
1136 ah = ath9k_hw_do_attach(devid, sc, error);
1137 break;
1138 default:
1139 *error = -ENXIO;
1140 break;
1141 }
1142
1143 return ah;
1144}
1145
1146/*******/
1147/* INI */
1148/*******/
1149
1150static void ath9k_hw_override_ini(struct ath_hw *ah,
1151 struct ath9k_channel *chan)
1152{
1153 /*
1154 * Set the RX_ABORT and RX_DIS and clear if off only after
1155 * RXE is set for MAC. This prevents frames with corrupted
1156 * descriptor status.
1157 */
1158 REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
1159
1160
1161 if (!AR_SREV_5416_20_OR_LATER(ah) ||
1162 AR_SREV_9280_10_OR_LATER(ah))
1163 return;
1164
1165 REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
1166}
1167
1168static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah,
1169 struct ar5416_eeprom_def *pEepData,
1170 u32 reg, u32 value)
1171{
1172 struct base_eep_header *pBase = &(pEepData->baseEepHeader);
1173
1174 switch (ah->hw_version.devid) {
1175 case AR9280_DEVID_PCI:
1176 if (reg == 0x7894) {
1177 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1178 "ini VAL: %x EEPROM: %x\n", value,
1179 (pBase->version & 0xff));
1180
1181 if ((pBase->version & 0xff) > 0x0a) {
1182 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1183 "PWDCLKIND: %d\n",
1184 pBase->pwdclkind);
1185 value &= ~AR_AN_TOP2_PWDCLKIND;
1186 value |= AR_AN_TOP2_PWDCLKIND &
1187 (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S);
1188 } else {
1189 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1190 "PWDCLKIND Earlier Rev\n");
1191 }
1192
1193 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1194 "final ini VAL: %x\n", value);
1195 }
1196 break;
1197 }
1198
1199 return value;
1200}
1201
1202static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
1203 struct ar5416_eeprom_def *pEepData,
1204 u32 reg, u32 value)
1205{
1206 if (ah->eep_map == EEP_MAP_4KBITS)
1207 return value;
1208 else
1209 return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value);
1210}
1211
1212static void ath9k_olc_init(struct ath_hw *ah)
1213{
1214 u32 i;
1215
1216 for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++)
1217 ah->originalGain[i] =
1218 MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4),
1219 AR_PHY_TX_GAIN);
1220 ah->PDADCdelta = 0;
1221}
1222
1223static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg,
1224 struct ath9k_channel *chan)
1225{
1226 u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band);
1227
1228 if (IS_CHAN_B(chan))
1229 ctl |= CTL_11B;
1230 else if (IS_CHAN_G(chan))
1231 ctl |= CTL_11G;
1232 else
1233 ctl |= CTL_11A;
1234
1235 return ctl;
1236}
1237
1238static int ath9k_hw_process_ini(struct ath_hw *ah,
1239 struct ath9k_channel *chan,
1240 enum ath9k_ht_macmode macmode)
1241{
1242 int i, regWrites = 0;
1243 struct ieee80211_channel *channel = chan->chan;
1244 u32 modesIndex, freqIndex;
1245 int status;
1246
1247 switch (chan->chanmode) {
1248 case CHANNEL_A:
1249 case CHANNEL_A_HT20:
1250 modesIndex = 1;
1251 freqIndex = 1;
1252 break;
1253 case CHANNEL_A_HT40PLUS:
1254 case CHANNEL_A_HT40MINUS:
1255 modesIndex = 2;
1256 freqIndex = 1;
1257 break;
1258 case CHANNEL_G:
1259 case CHANNEL_G_HT20:
1260 case CHANNEL_B:
1261 modesIndex = 4;
1262 freqIndex = 2;
1263 break;
1264 case CHANNEL_G_HT40PLUS:
1265 case CHANNEL_G_HT40MINUS:
1266 modesIndex = 3;
1267 freqIndex = 2;
1268 break;
1269
1270 default:
1271 return -EINVAL;
1272 }
1273
1274 REG_WRITE(ah, AR_PHY(0), 0x00000007);
1275 REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
1276 ah->eep_ops->set_addac(ah, chan);
1277
1278 if (AR_SREV_5416_22_OR_LATER(ah)) {
1279 REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
1280 } else {
1281 struct ar5416IniArray temp;
1282 u32 addacSize =
1283 sizeof(u32) * ah->iniAddac.ia_rows *
1284 ah->iniAddac.ia_columns;
1285
1286 memcpy(ah->addac5416_21,
1287 ah->iniAddac.ia_array, addacSize);
1288
1289 (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0;
1290
1291 temp.ia_array = ah->addac5416_21;
1292 temp.ia_columns = ah->iniAddac.ia_columns;
1293 temp.ia_rows = ah->iniAddac.ia_rows;
1294 REG_WRITE_ARRAY(&temp, 1, regWrites);
1295 }
1296
1297 REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
1298
1299 for (i = 0; i < ah->iniModes.ia_rows; i++) {
1300 u32 reg = INI_RA(&ah->iniModes, i, 0);
1301 u32 val = INI_RA(&ah->iniModes, i, modesIndex);
1302
1303 REG_WRITE(ah, reg, val);
1304
1305 if (reg >= 0x7800 && reg < 0x78a0
1306 && ah->config.analog_shiftreg) {
1307 udelay(100);
1308 }
1309
1310 DO_DELAY(regWrites);
1311 }
1312
1313 if (AR_SREV_9280(ah))
1314 REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);
1315
1316 if (AR_SREV_9280(ah) || (AR_SREV_9285(ah) &&
1317 AR_SREV_9285_12_OR_LATER(ah)))
1318 REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
1319
1320 for (i = 0; i < ah->iniCommon.ia_rows; i++) {
1321 u32 reg = INI_RA(&ah->iniCommon, i, 0);
1322 u32 val = INI_RA(&ah->iniCommon, i, 1);
1323
1324 REG_WRITE(ah, reg, val);
1325
1326 if (reg >= 0x7800 && reg < 0x78a0
1327 && ah->config.analog_shiftreg) {
1328 udelay(100);
1329 }
1330
1331 DO_DELAY(regWrites);
1332 }
1333
1334 ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites);
1335
1336 if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) {
1337 REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex,
1338 regWrites);
1339 }
1340
1341 ath9k_hw_override_ini(ah, chan);
1342 ath9k_hw_set_regs(ah, chan, macmode);
1343 ath9k_hw_init_chain_masks(ah);
1344
1345 if (OLC_FOR_AR9280_20_LATER)
1346 ath9k_olc_init(ah);
1347
1348 status = ah->eep_ops->set_txpower(ah, chan,
1349 ath9k_regd_get_ctl(&ah->regulatory, chan),
1350 channel->max_antenna_gain * 2,
1351 channel->max_power * 2,
1352 min((u32) MAX_RATE_POWER,
1353 (u32) ah->regulatory.power_limit));
1354 if (status != 0) {
1355 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
1356 "Error initializing transmit power\n");
1357 return -EIO;
1358 }
1359
1360 if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
1361 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
1362 "ar5416SetRfRegs failed\n");
1363 return -EIO;
1364 }
1365
1366 return 0;
1367}
1368
1369/****************************************/
1370/* Reset and Channel Switching Routines */
1371/****************************************/
1372
1373static void ath9k_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan)
1374{
1375 u32 rfMode = 0;
1376
1377 if (chan == NULL)
1378 return;
1379
1380 rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
1381 ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
1382
1383 if (!AR_SREV_9280_10_OR_LATER(ah))
1384 rfMode |= (IS_CHAN_5GHZ(chan)) ?
1385 AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
1386
1387 if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan))
1388 rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
1389
1390 REG_WRITE(ah, AR_PHY_MODE, rfMode);
1391}
1392
1393static void ath9k_hw_mark_phy_inactive(struct ath_hw *ah)
1394{
1395 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
1396}
1397
1398static inline void ath9k_hw_set_dma(struct ath_hw *ah)
1399{
1400 u32 regval;
1401
1402 regval = REG_READ(ah, AR_AHB_MODE);
1403 REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
1404
1405 regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
1406 REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
1407
1408 REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level);
1409
1410 regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK;
1411 REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B);
1412
1413 REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
1414
1415 if (AR_SREV_9285(ah)) {
1416 REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
1417 AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
1418 } else {
1419 REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
1420 AR_PCU_TXBUF_CTRL_USABLE_SIZE);
1421 }
1422}
1423
1424static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)
1425{
1426 u32 val;
1427
1428 val = REG_READ(ah, AR_STA_ID1);
1429 val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC);
1430 switch (opmode) {
1431 case NL80211_IFTYPE_AP:
1432 REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP
1433 | AR_STA_ID1_KSRCH_MODE);
1434 REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
1435 break;
1436 case NL80211_IFTYPE_ADHOC:
1437 case NL80211_IFTYPE_MESH_POINT:
1438 REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC
1439 | AR_STA_ID1_KSRCH_MODE);
1440 REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
1441 break;
1442 case NL80211_IFTYPE_STATION:
1443 case NL80211_IFTYPE_MONITOR:
1444 REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
1445 break;
1446 }
1447}
1448
1449static inline void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah,
1450 u32 coef_scaled,
1451 u32 *coef_mantissa,
1452 u32 *coef_exponent)
1453{
1454 u32 coef_exp, coef_man;
1455
1456 for (coef_exp = 31; coef_exp > 0; coef_exp--)
1457 if ((coef_scaled >> coef_exp) & 0x1)
1458 break;
1459
1460 coef_exp = 14 - (coef_exp - COEF_SCALE_S);
1461
1462 coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1));
1463
1464 *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp);
1465 *coef_exponent = coef_exp - 16;
1466}
1467
1468static void ath9k_hw_set_delta_slope(struct ath_hw *ah,
1469 struct ath9k_channel *chan)
1470{
1471 u32 coef_scaled, ds_coef_exp, ds_coef_man;
1472 u32 clockMhzScaled = 0x64000000;
1473 struct chan_centers centers;
1474
1475 if (IS_CHAN_HALF_RATE(chan))
1476 clockMhzScaled = clockMhzScaled >> 1;
1477 else if (IS_CHAN_QUARTER_RATE(chan))
1478 clockMhzScaled = clockMhzScaled >> 2;
1479
1480 ath9k_hw_get_channel_centers(ah, chan, &centers);
1481 coef_scaled = clockMhzScaled / centers.synth_center;
1482
1483 ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
1484 &ds_coef_exp);
1485
1486 REG_RMW_FIELD(ah, AR_PHY_TIMING3,
1487 AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
1488 REG_RMW_FIELD(ah, AR_PHY_TIMING3,
1489 AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
1490
1491 coef_scaled = (9 * coef_scaled) / 10;
1492
1493 ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
1494 &ds_coef_exp);
1495
1496 REG_RMW_FIELD(ah, AR_PHY_HALFGI,
1497 AR_PHY_HALFGI_DSC_MAN, ds_coef_man);
1498 REG_RMW_FIELD(ah, AR_PHY_HALFGI,
1499 AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);
1500}
1501
1502static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
1503{
1504 u32 rst_flags;
1505 u32 tmpReg;
1506
1507 if (AR_SREV_9100(ah)) {
1508 u32 val = REG_READ(ah, AR_RTC_DERIVED_CLK);
1509 val &= ~AR_RTC_DERIVED_CLK_PERIOD;
1510 val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD);
1511 REG_WRITE(ah, AR_RTC_DERIVED_CLK, val);
1512 (void)REG_READ(ah, AR_RTC_DERIVED_CLK);
1513 }
1514
1515 REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
1516 AR_RTC_FORCE_WAKE_ON_INT);
1517
1518 if (AR_SREV_9100(ah)) {
1519 rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD |
1520 AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
1521 } else {
1522 tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
1523 if (tmpReg &
1524 (AR_INTR_SYNC_LOCAL_TIMEOUT |
1525 AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
1526 REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
1527 REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
1528 } else {
1529 REG_WRITE(ah, AR_RC, AR_RC_AHB);
1530 }
1531
1532 rst_flags = AR_RTC_RC_MAC_WARM;
1533 if (type == ATH9K_RESET_COLD)
1534 rst_flags |= AR_RTC_RC_MAC_COLD;
1535 }
1536
1537 REG_WRITE(ah, AR_RTC_RC, rst_flags);
1538 udelay(50);
1539
1540 REG_WRITE(ah, AR_RTC_RC, 0);
1541 if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) {
1542 DPRINTF(ah->ah_sc, ATH_DBG_RESET,
1543 "RTC stuck in MAC reset\n");
1544 return false;
1545 }
1546
1547 if (!AR_SREV_9100(ah))
1548 REG_WRITE(ah, AR_RC, 0);
1549
1550 ath9k_hw_init_pll(ah, NULL);
1551
1552 if (AR_SREV_9100(ah))
1553 udelay(50);
1554
1555 return true;
1556}
1557
1558static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
1559{
1560 REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
1561 AR_RTC_FORCE_WAKE_ON_INT);
1562
1563 REG_WRITE(ah, AR_RTC_RESET, 0);
1564 udelay(2);
1565 REG_WRITE(ah, AR_RTC_RESET, 1);
1566
1567 if (!ath9k_hw_wait(ah,
1568 AR_RTC_STATUS,
1569 AR_RTC_STATUS_M,
1570 AR_RTC_STATUS_ON,
1571 AH_WAIT_TIMEOUT)) {
1572 DPRINTF(ah->ah_sc, ATH_DBG_RESET, "RTC not waking up\n");
1573 return false;
1574 }
1575
1576 ath9k_hw_read_revisions(ah);
1577
1578 return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
1579}
1580
1581static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
1582{
1583 REG_WRITE(ah, AR_RTC_FORCE_WAKE,
1584 AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
1585
1586 switch (type) {
1587 case ATH9K_RESET_POWER_ON:
1588 return ath9k_hw_set_reset_power_on(ah);
1589 break;
1590 case ATH9K_RESET_WARM:
1591 case ATH9K_RESET_COLD:
1592 return ath9k_hw_set_reset(ah, type);
1593 break;
1594 default:
1595 return false;
1596 }
1597}
1598
1599static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan,
1600 enum ath9k_ht_macmode macmode)
1601{
1602 u32 phymode;
1603 u32 enableDacFifo = 0;
1604
1605 if (AR_SREV_9285_10_OR_LATER(ah))
1606 enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &
1607 AR_PHY_FC_ENABLE_DAC_FIFO);
1608
1609 phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
1610 | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo;
1611
1612 if (IS_CHAN_HT40(chan)) {
1613 phymode |= AR_PHY_FC_DYN2040_EN;
1614
1615 if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
1616 (chan->chanmode == CHANNEL_G_HT40PLUS))
1617 phymode |= AR_PHY_FC_DYN2040_PRI_CH;
1618
1619 if (ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_25)
1620 phymode |= AR_PHY_FC_DYN2040_EXT_CH;
1621 }
1622 REG_WRITE(ah, AR_PHY_TURBO, phymode);
1623
1624 ath9k_hw_set11nmac2040(ah, macmode);
1625
1626 REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
1627 REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
1628}
1629
1630static bool ath9k_hw_chip_reset(struct ath_hw *ah,
1631 struct ath9k_channel *chan)
1632{
1633 if (OLC_FOR_AR9280_20_LATER) {
1634 if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
1635 return false;
1636 } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
1637 return false;
1638
1639 if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
1640 return false;
1641
1642 ah->chip_fullsleep = false;
1643 ath9k_hw_init_pll(ah, chan);
1644 ath9k_hw_set_rfmode(ah, chan);
1645
1646 return true;
1647}
1648
1649static bool ath9k_hw_channel_change(struct ath_hw *ah,
1650 struct ath9k_channel *chan,
1651 enum ath9k_ht_macmode macmode)
1652{
1653 struct ieee80211_channel *channel = chan->chan;
1654 u32 synthDelay, qnum;
1655
1656 for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
1657 if (ath9k_hw_numtxpending(ah, qnum)) {
1658 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
1659 "Transmit frames pending on queue %d\n", qnum);
1660 return false;
1661 }
1662 }
1663
1664 REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
1665 if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
1666 AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) {
1667 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
1668 "Could not kill baseband RX\n");
1669 return false;
1670 }
1671
1672 ath9k_hw_set_regs(ah, chan, macmode);
1673
1674 if (AR_SREV_9280_10_OR_LATER(ah)) {
1675 if (!(ath9k_hw_ar9280_set_channel(ah, chan))) {
1676 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
1677 "Failed to set channel\n");
1678 return false;
1679 }
1680 } else {
1681 if (!(ath9k_hw_set_channel(ah, chan))) {
1682 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
1683 "Failed to set channel\n");
1684 return false;
1685 }
1686 }
1687
1688 if (ah->eep_ops->set_txpower(ah, chan,
1689 ath9k_regd_get_ctl(&ah->regulatory, chan),
1690 channel->max_antenna_gain * 2,
1691 channel->max_power * 2,
1692 min((u32) MAX_RATE_POWER,
1693 (u32) ah->regulatory.power_limit)) != 0) {
1694 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1695 "Error initializing transmit power\n");
1696 return false;
1697 }
1698
1699 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
1700 if (IS_CHAN_B(chan))
1701 synthDelay = (4 * synthDelay) / 22;
1702 else
1703 synthDelay /= 10;
1704
1705 udelay(synthDelay + BASE_ACTIVATE_DELAY);
1706
1707 REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
1708
1709 if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
1710 ath9k_hw_set_delta_slope(ah, chan);
1711
1712 if (AR_SREV_9280_10_OR_LATER(ah))
1713 ath9k_hw_9280_spur_mitigate(ah, chan);
1714 else
1715 ath9k_hw_spur_mitigate(ah, chan);
1716
1717 if (!chan->oneTimeCalsDone)
1718 chan->oneTimeCalsDone = true;
1719
1720 return true;
1721}
1722
1723static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan)
1724{
1725 int bb_spur = AR_NO_SPUR;
1726 int freq;
1727 int bin, cur_bin;
1728 int bb_spur_off, spur_subchannel_sd;
1729 int spur_freq_sd;
1730 int spur_delta_phase;
1731 int denominator;
1732 int upper, lower, cur_vit_mask;
1733 int tmp, newVal;
1734 int i;
1735 int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
1736 AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
1737 };
1738 int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
1739 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
1740 };
1741 int inc[4] = { 0, 100, 0, 0 };
1742 struct chan_centers centers;
1743
1744 int8_t mask_m[123];
1745 int8_t mask_p[123];
1746 int8_t mask_amt;
1747 int tmp_mask;
1748 int cur_bb_spur;
1749 bool is2GHz = IS_CHAN_2GHZ(chan);
1750
1751 memset(&mask_m, 0, sizeof(int8_t) * 123);
1752 memset(&mask_p, 0, sizeof(int8_t) * 123);
1753
1754 ath9k_hw_get_channel_centers(ah, chan, &centers);
1755 freq = centers.synth_center;
1756
1757 ah->config.spurmode = SPUR_ENABLE_EEPROM;
1758 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
1759 cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
1760
1761 if (is2GHz)
1762 cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
1763 else
1764 cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
1765
1766 if (AR_NO_SPUR == cur_bb_spur)
1767 break;
1768 cur_bb_spur = cur_bb_spur - freq;
1769
1770 if (IS_CHAN_HT40(chan)) {
1771 if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
1772 (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
1773 bb_spur = cur_bb_spur;
1774 break;
1775 }
1776 } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
1777 (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
1778 bb_spur = cur_bb_spur;
1779 break;
1780 }
1781 }
1782
1783 if (AR_NO_SPUR == bb_spur) {
1784 REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
1785 AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
1786 return;
1787 } else {
1788 REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
1789 AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
1790 }
1791
1792 bin = bb_spur * 320;
1793
1794 tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
1795
1796 newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
1797 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
1798 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
1799 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
1800 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal);
1801
1802 newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
1803 AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
1804 AR_PHY_SPUR_REG_MASK_RATE_SELECT |
1805 AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
1806 SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
1807 REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
1808
1809 if (IS_CHAN_HT40(chan)) {
1810 if (bb_spur < 0) {
1811 spur_subchannel_sd = 1;
1812 bb_spur_off = bb_spur + 10;
1813 } else {
1814 spur_subchannel_sd = 0;
1815 bb_spur_off = bb_spur - 10;
1816 }
1817 } else {
1818 spur_subchannel_sd = 0;
1819 bb_spur_off = bb_spur;
1820 }
1821
1822 if (IS_CHAN_HT40(chan))
1823 spur_delta_phase =
1824 ((bb_spur * 262144) /
1825 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
1826 else
1827 spur_delta_phase =
1828 ((bb_spur * 524288) /
1829 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
1830
1831 denominator = IS_CHAN_2GHZ(chan) ? 44 : 40;
1832 spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
1833
1834 newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
1835 SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
1836 SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
1837 REG_WRITE(ah, AR_PHY_TIMING11, newVal);
1838
1839 newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
1840 REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
1841
1842 cur_bin = -6000;
1843 upper = bin + 100;
1844 lower = bin - 100;
1845
1846 for (i = 0; i < 4; i++) {
1847 int pilot_mask = 0;
1848 int chan_mask = 0;
1849 int bp = 0;
1850 for (bp = 0; bp < 30; bp++) {
1851 if ((cur_bin > lower) && (cur_bin < upper)) {
1852 pilot_mask = pilot_mask | 0x1 << bp;
1853 chan_mask = chan_mask | 0x1 << bp;
1854 }
1855 cur_bin += 100;
1856 }
1857 cur_bin += inc[i];
1858 REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
1859 REG_WRITE(ah, chan_mask_reg[i], chan_mask);
1860 }
1861
1862 cur_vit_mask = 6100;
1863 upper = bin + 120;
1864 lower = bin - 120;
1865
1866 for (i = 0; i < 123; i++) {
1867 if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
1868
1869 /* workaround for gcc bug #37014 */
1870 volatile int tmp_v = abs(cur_vit_mask - bin);
1871
1872 if (tmp_v < 75)
1873 mask_amt = 1;
1874 else
1875 mask_amt = 0;
1876 if (cur_vit_mask < 0)
1877 mask_m[abs(cur_vit_mask / 100)] = mask_amt;
1878 else
1879 mask_p[cur_vit_mask / 100] = mask_amt;
1880 }
1881 cur_vit_mask -= 100;
1882 }
1883
1884 tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
1885 | (mask_m[48] << 26) | (mask_m[49] << 24)
1886 | (mask_m[50] << 22) | (mask_m[51] << 20)
1887 | (mask_m[52] << 18) | (mask_m[53] << 16)
1888 | (mask_m[54] << 14) | (mask_m[55] << 12)
1889 | (mask_m[56] << 10) | (mask_m[57] << 8)
1890 | (mask_m[58] << 6) | (mask_m[59] << 4)
1891 | (mask_m[60] << 2) | (mask_m[61] << 0);
1892 REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
1893 REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
1894
1895 tmp_mask = (mask_m[31] << 28)
1896 | (mask_m[32] << 26) | (mask_m[33] << 24)
1897 | (mask_m[34] << 22) | (mask_m[35] << 20)
1898 | (mask_m[36] << 18) | (mask_m[37] << 16)
1899 | (mask_m[48] << 14) | (mask_m[39] << 12)
1900 | (mask_m[40] << 10) | (mask_m[41] << 8)
1901 | (mask_m[42] << 6) | (mask_m[43] << 4)
1902 | (mask_m[44] << 2) | (mask_m[45] << 0);
1903 REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
1904 REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
1905
1906 tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
1907 | (mask_m[18] << 26) | (mask_m[18] << 24)
1908 | (mask_m[20] << 22) | (mask_m[20] << 20)
1909 | (mask_m[22] << 18) | (mask_m[22] << 16)
1910 | (mask_m[24] << 14) | (mask_m[24] << 12)
1911 | (mask_m[25] << 10) | (mask_m[26] << 8)
1912 | (mask_m[27] << 6) | (mask_m[28] << 4)
1913 | (mask_m[29] << 2) | (mask_m[30] << 0);
1914 REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
1915 REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
1916
1917 tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
1918 | (mask_m[2] << 26) | (mask_m[3] << 24)
1919 | (mask_m[4] << 22) | (mask_m[5] << 20)
1920 | (mask_m[6] << 18) | (mask_m[7] << 16)
1921 | (mask_m[8] << 14) | (mask_m[9] << 12)
1922 | (mask_m[10] << 10) | (mask_m[11] << 8)
1923 | (mask_m[12] << 6) | (mask_m[13] << 4)
1924 | (mask_m[14] << 2) | (mask_m[15] << 0);
1925 REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
1926 REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
1927
1928 tmp_mask = (mask_p[15] << 28)
1929 | (mask_p[14] << 26) | (mask_p[13] << 24)
1930 | (mask_p[12] << 22) | (mask_p[11] << 20)
1931 | (mask_p[10] << 18) | (mask_p[9] << 16)
1932 | (mask_p[8] << 14) | (mask_p[7] << 12)
1933 | (mask_p[6] << 10) | (mask_p[5] << 8)
1934 | (mask_p[4] << 6) | (mask_p[3] << 4)
1935 | (mask_p[2] << 2) | (mask_p[1] << 0);
1936 REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
1937 REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
1938
1939 tmp_mask = (mask_p[30] << 28)
1940 | (mask_p[29] << 26) | (mask_p[28] << 24)
1941 | (mask_p[27] << 22) | (mask_p[26] << 20)
1942 | (mask_p[25] << 18) | (mask_p[24] << 16)
1943 | (mask_p[23] << 14) | (mask_p[22] << 12)
1944 | (mask_p[21] << 10) | (mask_p[20] << 8)
1945 | (mask_p[19] << 6) | (mask_p[18] << 4)
1946 | (mask_p[17] << 2) | (mask_p[16] << 0);
1947 REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
1948 REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
1949
1950 tmp_mask = (mask_p[45] << 28)
1951 | (mask_p[44] << 26) | (mask_p[43] << 24)
1952 | (mask_p[42] << 22) | (mask_p[41] << 20)
1953 | (mask_p[40] << 18) | (mask_p[39] << 16)
1954 | (mask_p[38] << 14) | (mask_p[37] << 12)
1955 | (mask_p[36] << 10) | (mask_p[35] << 8)
1956 | (mask_p[34] << 6) | (mask_p[33] << 4)
1957 | (mask_p[32] << 2) | (mask_p[31] << 0);
1958 REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
1959 REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
1960
1961 tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
1962 | (mask_p[59] << 26) | (mask_p[58] << 24)
1963 | (mask_p[57] << 22) | (mask_p[56] << 20)
1964 | (mask_p[55] << 18) | (mask_p[54] << 16)
1965 | (mask_p[53] << 14) | (mask_p[52] << 12)
1966 | (mask_p[51] << 10) | (mask_p[50] << 8)
1967 | (mask_p[49] << 6) | (mask_p[48] << 4)
1968 | (mask_p[47] << 2) | (mask_p[46] << 0);
1969 REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
1970 REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
1971}
1972
1973static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan)
1974{
1975 int bb_spur = AR_NO_SPUR;
1976 int bin, cur_bin;
1977 int spur_freq_sd;
1978 int spur_delta_phase;
1979 int denominator;
1980 int upper, lower, cur_vit_mask;
1981 int tmp, new;
1982 int i;
1983 int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
1984 AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
1985 };
1986 int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
1987 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
1988 };
1989 int inc[4] = { 0, 100, 0, 0 };
1990
1991 int8_t mask_m[123];
1992 int8_t mask_p[123];
1993 int8_t mask_amt;
1994 int tmp_mask;
1995 int cur_bb_spur;
1996 bool is2GHz = IS_CHAN_2GHZ(chan);
1997
1998 memset(&mask_m, 0, sizeof(int8_t) * 123);
1999 memset(&mask_p, 0, sizeof(int8_t) * 123);
2000
2001 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
2002 cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
2003 if (AR_NO_SPUR == cur_bb_spur)
2004 break;
2005 cur_bb_spur = cur_bb_spur - (chan->channel * 10);
2006 if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
2007 bb_spur = cur_bb_spur;
2008 break;
2009 }
2010 }
2011
2012 if (AR_NO_SPUR == bb_spur)
2013 return;
2014
2015 bin = bb_spur * 32;
2016
2017 tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
2018 new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
2019 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
2020 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
2021 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
2022
2023 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new);
2024
2025 new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
2026 AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
2027 AR_PHY_SPUR_REG_MASK_RATE_SELECT |
2028 AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
2029 SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
2030 REG_WRITE(ah, AR_PHY_SPUR_REG, new);
2031
2032 spur_delta_phase = ((bb_spur * 524288) / 100) &
2033 AR_PHY_TIMING11_SPUR_DELTA_PHASE;
2034
2035 denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;
2036 spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
2037
2038 new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
2039 SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
2040 SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
2041 REG_WRITE(ah, AR_PHY_TIMING11, new);
2042
2043 cur_bin = -6000;
2044 upper = bin + 100;
2045 lower = bin - 100;
2046
2047 for (i = 0; i < 4; i++) {
2048 int pilot_mask = 0;
2049 int chan_mask = 0;
2050 int bp = 0;
2051 for (bp = 0; bp < 30; bp++) {
2052 if ((cur_bin > lower) && (cur_bin < upper)) {
2053 pilot_mask = pilot_mask | 0x1 << bp;
2054 chan_mask = chan_mask | 0x1 << bp;
2055 }
2056 cur_bin += 100;
2057 }
2058 cur_bin += inc[i];
2059 REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
2060 REG_WRITE(ah, chan_mask_reg[i], chan_mask);
2061 }
2062
2063 cur_vit_mask = 6100;
2064 upper = bin + 120;
2065 lower = bin - 120;
2066
2067 for (i = 0; i < 123; i++) {
2068 if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
2069
2070 /* workaround for gcc bug #37014 */
2071 volatile int tmp_v = abs(cur_vit_mask - bin);
2072
2073 if (tmp_v < 75)
2074 mask_amt = 1;
2075 else
2076 mask_amt = 0;
2077 if (cur_vit_mask < 0)
2078 mask_m[abs(cur_vit_mask / 100)] = mask_amt;
2079 else
2080 mask_p[cur_vit_mask / 100] = mask_amt;
2081 }
2082 cur_vit_mask -= 100;
2083 }
2084
2085 tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
2086 | (mask_m[48] << 26) | (mask_m[49] << 24)
2087 | (mask_m[50] << 22) | (mask_m[51] << 20)
2088 | (mask_m[52] << 18) | (mask_m[53] << 16)
2089 | (mask_m[54] << 14) | (mask_m[55] << 12)
2090 | (mask_m[56] << 10) | (mask_m[57] << 8)
2091 | (mask_m[58] << 6) | (mask_m[59] << 4)
2092 | (mask_m[60] << 2) | (mask_m[61] << 0);
2093 REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
2094 REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
2095
2096 tmp_mask = (mask_m[31] << 28)
2097 | (mask_m[32] << 26) | (mask_m[33] << 24)
2098 | (mask_m[34] << 22) | (mask_m[35] << 20)
2099 | (mask_m[36] << 18) | (mask_m[37] << 16)
2100 | (mask_m[48] << 14) | (mask_m[39] << 12)
2101 | (mask_m[40] << 10) | (mask_m[41] << 8)
2102 | (mask_m[42] << 6) | (mask_m[43] << 4)
2103 | (mask_m[44] << 2) | (mask_m[45] << 0);
2104 REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
2105 REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
2106
2107 tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
2108 | (mask_m[18] << 26) | (mask_m[18] << 24)
2109 | (mask_m[20] << 22) | (mask_m[20] << 20)
2110 | (mask_m[22] << 18) | (mask_m[22] << 16)
2111 | (mask_m[24] << 14) | (mask_m[24] << 12)
2112 | (mask_m[25] << 10) | (mask_m[26] << 8)
2113 | (mask_m[27] << 6) | (mask_m[28] << 4)
2114 | (mask_m[29] << 2) | (mask_m[30] << 0);
2115 REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
2116 REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
2117
2118 tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
2119 | (mask_m[2] << 26) | (mask_m[3] << 24)
2120 | (mask_m[4] << 22) | (mask_m[5] << 20)
2121 | (mask_m[6] << 18) | (mask_m[7] << 16)
2122 | (mask_m[8] << 14) | (mask_m[9] << 12)
2123 | (mask_m[10] << 10) | (mask_m[11] << 8)
2124 | (mask_m[12] << 6) | (mask_m[13] << 4)
2125 | (mask_m[14] << 2) | (mask_m[15] << 0);
2126 REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
2127 REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
2128
2129 tmp_mask = (mask_p[15] << 28)
2130 | (mask_p[14] << 26) | (mask_p[13] << 24)
2131 | (mask_p[12] << 22) | (mask_p[11] << 20)
2132 | (mask_p[10] << 18) | (mask_p[9] << 16)
2133 | (mask_p[8] << 14) | (mask_p[7] << 12)
2134 | (mask_p[6] << 10) | (mask_p[5] << 8)
2135 | (mask_p[4] << 6) | (mask_p[3] << 4)
2136 | (mask_p[2] << 2) | (mask_p[1] << 0);
2137 REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
2138 REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
2139
2140 tmp_mask = (mask_p[30] << 28)
2141 | (mask_p[29] << 26) | (mask_p[28] << 24)
2142 | (mask_p[27] << 22) | (mask_p[26] << 20)
2143 | (mask_p[25] << 18) | (mask_p[24] << 16)
2144 | (mask_p[23] << 14) | (mask_p[22] << 12)
2145 | (mask_p[21] << 10) | (mask_p[20] << 8)
2146 | (mask_p[19] << 6) | (mask_p[18] << 4)
2147 | (mask_p[17] << 2) | (mask_p[16] << 0);
2148 REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
2149 REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
2150
2151 tmp_mask = (mask_p[45] << 28)
2152 | (mask_p[44] << 26) | (mask_p[43] << 24)
2153 | (mask_p[42] << 22) | (mask_p[41] << 20)
2154 | (mask_p[40] << 18) | (mask_p[39] << 16)
2155 | (mask_p[38] << 14) | (mask_p[37] << 12)
2156 | (mask_p[36] << 10) | (mask_p[35] << 8)
2157 | (mask_p[34] << 6) | (mask_p[33] << 4)
2158 | (mask_p[32] << 2) | (mask_p[31] << 0);
2159 REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
2160 REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
2161
2162 tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
2163 | (mask_p[59] << 26) | (mask_p[58] << 24)
2164 | (mask_p[57] << 22) | (mask_p[56] << 20)
2165 | (mask_p[55] << 18) | (mask_p[54] << 16)
2166 | (mask_p[53] << 14) | (mask_p[52] << 12)
2167 | (mask_p[51] << 10) | (mask_p[50] << 8)
2168 | (mask_p[49] << 6) | (mask_p[48] << 4)
2169 | (mask_p[47] << 2) | (mask_p[46] << 0);
2170 REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
2171 REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
2172}
2173
2174int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
2175 bool bChannelChange)
2176{
2177 u32 saveLedState;
2178 struct ath_softc *sc = ah->ah_sc;
2179 struct ath9k_channel *curchan = ah->curchan;
2180 u32 saveDefAntenna;
2181 u32 macStaId1;
2182 int i, rx_chainmask, r;
2183
2184 ah->extprotspacing = sc->ht_extprotspacing;
2185 ah->txchainmask = sc->tx_chainmask;
2186 ah->rxchainmask = sc->rx_chainmask;
2187
2188 if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
2189 return -EIO;
2190
2191 if (curchan)
2192 ath9k_hw_getnf(ah, curchan);
2193
2194 if (bChannelChange &&
2195 (ah->chip_fullsleep != true) &&
2196 (ah->curchan != NULL) &&
2197 (chan->channel != ah->curchan->channel) &&
2198 ((chan->channelFlags & CHANNEL_ALL) ==
2199 (ah->curchan->channelFlags & CHANNEL_ALL)) &&
2200 (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) &&
2201 !IS_CHAN_A_5MHZ_SPACED(ah->curchan)))) {
2202
2203 if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) {
2204 ath9k_hw_loadnf(ah, ah->curchan);
2205 ath9k_hw_start_nfcal(ah);
2206 return 0;
2207 }
2208 }
2209
2210 saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA);
2211 if (saveDefAntenna == 0)
2212 saveDefAntenna = 1;
2213
2214 macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
2215
2216 saveLedState = REG_READ(ah, AR_CFG_LED) &
2217 (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
2218 AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW);
2219
2220 ath9k_hw_mark_phy_inactive(ah);
2221
2222 if (!ath9k_hw_chip_reset(ah, chan)) {
2223 DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n");
2224 return -EINVAL;
2225 }
2226
2227 if (AR_SREV_9280_10_OR_LATER(ah))
2228 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
2229
2230 r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width);
2231 if (r)
2232 return r;
2233
2234 /* Setup MFP options for CCMP */
2235 if (AR_SREV_9280_20_OR_LATER(ah)) {
2236 /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
2237 * frames when constructing CCMP AAD. */
2238 REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT,
2239 0xc7ff);
2240 ah->sw_mgmt_crypto = false;
2241 } else if (AR_SREV_9160_10_OR_LATER(ah)) {
2242 /* Disable hardware crypto for management frames */
2243 REG_CLR_BIT(ah, AR_PCU_MISC_MODE2,
2244 AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
2245 REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
2246 AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
2247 ah->sw_mgmt_crypto = true;
2248 } else
2249 ah->sw_mgmt_crypto = true;
2250
2251 if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
2252 ath9k_hw_set_delta_slope(ah, chan);
2253
2254 if (AR_SREV_9280_10_OR_LATER(ah))
2255 ath9k_hw_9280_spur_mitigate(ah, chan);
2256 else
2257 ath9k_hw_spur_mitigate(ah, chan);
2258
2259 ah->eep_ops->set_board_values(ah, chan);
2260
2261 ath9k_hw_decrease_chain_power(ah, chan);
2262
2263 REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(ah->macaddr));
2264 REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(ah->macaddr + 4)
2265 | macStaId1
2266 | AR_STA_ID1_RTS_USE_DEF
2267 | (ah->config.
2268 ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
2269 | ah->sta_id1_defaults);
2270 ath9k_hw_set_operating_mode(ah, ah->opmode);
2271
2272 REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask));
2273 REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4));
2274
2275 REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
2276
2277 REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid));
2278 REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) |
2279 ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S));
2280
2281 REG_WRITE(ah, AR_ISR, ~0);
2282
2283 REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
2284
2285 if (AR_SREV_9280_10_OR_LATER(ah)) {
2286 if (!(ath9k_hw_ar9280_set_channel(ah, chan)))
2287 return -EIO;
2288 } else {
2289 if (!(ath9k_hw_set_channel(ah, chan)))
2290 return -EIO;
2291 }
2292
2293 for (i = 0; i < AR_NUM_DCU; i++)
2294 REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
2295
2296 ah->intr_txqs = 0;
2297 for (i = 0; i < ah->caps.total_queues; i++)
2298 ath9k_hw_resettxqueue(ah, i);
2299
2300 ath9k_hw_init_interrupt_masks(ah, ah->opmode);
2301 ath9k_hw_init_qos(ah);
2302
2303#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
2304 if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
2305 ath9k_enable_rfkill(ah);
2306#endif
2307 ath9k_hw_init_user_settings(ah);
2308
2309 REG_WRITE(ah, AR_STA_ID1,
2310 REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM);
2311
2312 ath9k_hw_set_dma(ah);
2313
2314 REG_WRITE(ah, AR_OBS, 8);
2315
2316 if (ah->config.intr_mitigation) {
2317 REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
2318 REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
2319 }
2320
2321 ath9k_hw_init_bb(ah, chan);
2322
2323 if (!ath9k_hw_init_cal(ah, chan))
2324 return -EIO;;
2325
2326 rx_chainmask = ah->rxchainmask;
2327 if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) {
2328 REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
2329 REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
2330 }
2331
2332 REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
2333
2334 if (AR_SREV_9100(ah)) {
2335 u32 mask;
2336 mask = REG_READ(ah, AR_CFG);
2337 if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
2338 DPRINTF(ah->ah_sc, ATH_DBG_RESET,
2339 "CFG Byte Swap Set 0x%x\n", mask);
2340 } else {
2341 mask =
2342 INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
2343 REG_WRITE(ah, AR_CFG, mask);
2344 DPRINTF(ah->ah_sc, ATH_DBG_RESET,
2345 "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG));
2346 }
2347 } else {
2348#ifdef __BIG_ENDIAN
2349 REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
2350#endif
2351 }
2352
2353 return 0;
2354}
2355
2356/************************/
2357/* Key Cache Management */
2358/************************/
2359
2360bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry)
2361{
2362 u32 keyType;
2363
2364 if (entry >= ah->caps.keycache_size) {
2365 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
2366 "keychache entry %u out of range\n", entry);
2367 return false;
2368 }
2369
2370 keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
2371
2372 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
2373 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
2374 REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
2375 REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
2376 REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
2377 REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
2378 REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
2379 REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
2380
2381 if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
2382 u16 micentry = entry + 64;
2383
2384 REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
2385 REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
2386 REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
2387 REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
2388
2389 }
2390
2391 if (ah->curchan == NULL)
2392 return true;
2393
2394 return true;
2395}
2396
2397bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
2398{
2399 u32 macHi, macLo;
2400
2401 if (entry >= ah->caps.keycache_size) {
2402 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
2403 "keychache entry %u out of range\n", entry);
2404 return false;
2405 }
2406
2407 if (mac != NULL) {
2408 macHi = (mac[5] << 8) | mac[4];
2409 macLo = (mac[3] << 24) |
2410 (mac[2] << 16) |
2411 (mac[1] << 8) |
2412 mac[0];
2413 macLo >>= 1;
2414 macLo |= (macHi & 1) << 31;
2415 macHi >>= 1;
2416 } else {
2417 macLo = macHi = 0;
2418 }
2419 REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
2420 REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID);
2421
2422 return true;
2423}
2424
2425bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
2426 const struct ath9k_keyval *k,
2427 const u8 *mac)
2428{
2429 const struct ath9k_hw_capabilities *pCap = &ah->caps;
2430 u32 key0, key1, key2, key3, key4;
2431 u32 keyType;
2432
2433 if (entry >= pCap->keycache_size) {
2434 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
2435 "keycache entry %u out of range\n", entry);
2436 return false;
2437 }
2438
2439 switch (k->kv_type) {
2440 case ATH9K_CIPHER_AES_OCB:
2441 keyType = AR_KEYTABLE_TYPE_AES;
2442 break;
2443 case ATH9K_CIPHER_AES_CCM:
2444 if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) {
2445 DPRINTF(ah->ah_sc, ATH_DBG_ANY,
2446 "AES-CCM not supported by mac rev 0x%x\n",
2447 ah->hw_version.macRev);
2448 return false;
2449 }
2450 keyType = AR_KEYTABLE_TYPE_CCM;
2451 break;
2452 case ATH9K_CIPHER_TKIP:
2453 keyType = AR_KEYTABLE_TYPE_TKIP;
2454 if (ATH9K_IS_MIC_ENABLED(ah)
2455 && entry + 64 >= pCap->keycache_size) {
2456 DPRINTF(ah->ah_sc, ATH_DBG_ANY,
2457 "entry %u inappropriate for TKIP\n", entry);
2458 return false;
2459 }
2460 break;
2461 case ATH9K_CIPHER_WEP:
2462 if (k->kv_len < LEN_WEP40) {
2463 DPRINTF(ah->ah_sc, ATH_DBG_ANY,
2464 "WEP key length %u too small\n", k->kv_len);
2465 return false;
2466 }
2467 if (k->kv_len <= LEN_WEP40)
2468 keyType = AR_KEYTABLE_TYPE_40;
2469 else if (k->kv_len <= LEN_WEP104)
2470 keyType = AR_KEYTABLE_TYPE_104;
2471 else
2472 keyType = AR_KEYTABLE_TYPE_128;
2473 break;
2474 case ATH9K_CIPHER_CLR:
2475 keyType = AR_KEYTABLE_TYPE_CLR;
2476 break;
2477 default:
2478 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
2479 "cipher %u not supported\n", k->kv_type);
2480 return false;
2481 }
2482
2483 key0 = get_unaligned_le32(k->kv_val + 0);
2484 key1 = get_unaligned_le16(k->kv_val + 4);
2485 key2 = get_unaligned_le32(k->kv_val + 6);
2486 key3 = get_unaligned_le16(k->kv_val + 10);
2487 key4 = get_unaligned_le32(k->kv_val + 12);
2488 if (k->kv_len <= LEN_WEP104)
2489 key4 &= 0xff;
2490
2491 /*
2492 * Note: Key cache registers access special memory area that requires
2493 * two 32-bit writes to actually update the values in the internal
2494 * memory. Consequently, the exact order and pairs used here must be
2495 * maintained.
2496 */
2497
2498 if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
2499 u16 micentry = entry + 64;
2500
2501 /*
2502 * Write inverted key[47:0] first to avoid Michael MIC errors
2503 * on frames that could be sent or received at the same time.
2504 * The correct key will be written in the end once everything
2505 * else is ready.
2506 */
2507 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
2508 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
2509
2510 /* Write key[95:48] */
2511 REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
2512 REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
2513
2514 /* Write key[127:96] and key type */
2515 REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
2516 REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
2517
2518 /* Write MAC address for the entry */
2519 (void) ath9k_hw_keysetmac(ah, entry, mac);
2520
2521 if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) {
2522 /*
2523 * TKIP uses two key cache entries:
2524 * Michael MIC TX/RX keys in the same key cache entry
2525 * (idx = main index + 64):
2526 * key0 [31:0] = RX key [31:0]
2527 * key1 [15:0] = TX key [31:16]
2528 * key1 [31:16] = reserved
2529 * key2 [31:0] = RX key [63:32]
2530 * key3 [15:0] = TX key [15:0]
2531 * key3 [31:16] = reserved
2532 * key4 [31:0] = TX key [63:32]
2533 */
2534 u32 mic0, mic1, mic2, mic3, mic4;
2535
2536 mic0 = get_unaligned_le32(k->kv_mic + 0);
2537 mic2 = get_unaligned_le32(k->kv_mic + 4);
2538 mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
2539 mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
2540 mic4 = get_unaligned_le32(k->kv_txmic + 4);
2541
2542 /* Write RX[31:0] and TX[31:16] */
2543 REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
2544 REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
2545
2546 /* Write RX[63:32] and TX[15:0] */
2547 REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
2548 REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
2549
2550 /* Write TX[63:32] and keyType(reserved) */
2551 REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
2552 REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
2553 AR_KEYTABLE_TYPE_CLR);
2554
2555 } else {
2556 /*
2557 * TKIP uses four key cache entries (two for group
2558 * keys):
2559 * Michael MIC TX/RX keys are in different key cache
2560 * entries (idx = main index + 64 for TX and
2561 * main index + 32 + 96 for RX):
2562 * key0 [31:0] = TX/RX MIC key [31:0]
2563 * key1 [31:0] = reserved
2564 * key2 [31:0] = TX/RX MIC key [63:32]
2565 * key3 [31:0] = reserved
2566 * key4 [31:0] = reserved
2567 *
2568 * Upper layer code will call this function separately
2569 * for TX and RX keys when these registers offsets are
2570 * used.
2571 */
2572 u32 mic0, mic2;
2573
2574 mic0 = get_unaligned_le32(k->kv_mic + 0);
2575 mic2 = get_unaligned_le32(k->kv_mic + 4);
2576
2577 /* Write MIC key[31:0] */
2578 REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
2579 REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
2580
2581 /* Write MIC key[63:32] */
2582 REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
2583 REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
2584
2585 /* Write TX[63:32] and keyType(reserved) */
2586 REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
2587 REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
2588 AR_KEYTABLE_TYPE_CLR);
2589 }
2590
2591 /* MAC address registers are reserved for the MIC entry */
2592 REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
2593 REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
2594
2595 /*
2596 * Write the correct (un-inverted) key[47:0] last to enable
2597 * TKIP now that all other registers are set with correct
2598 * values.
2599 */
2600 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
2601 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
2602 } else {
2603 /* Write key[47:0] */
2604 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
2605 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
2606
2607 /* Write key[95:48] */
2608 REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
2609 REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
2610
2611 /* Write key[127:96] and key type */
2612 REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
2613 REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
2614
2615 /* Write MAC address for the entry */
2616 (void) ath9k_hw_keysetmac(ah, entry, mac);
2617 }
2618
2619 return true;
2620}
2621
2622bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry)
2623{
2624 if (entry < ah->caps.keycache_size) {
2625 u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry));
2626 if (val & AR_KEYTABLE_VALID)
2627 return true;
2628 }
2629 return false;
2630}
2631
2632/******************************/
2633/* Power Management (Chipset) */
2634/******************************/
2635
2636static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
2637{
2638 REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
2639 if (setChip) {
2640 REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
2641 AR_RTC_FORCE_WAKE_EN);
2642 if (!AR_SREV_9100(ah))
2643 REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
2644
2645 REG_CLR_BIT(ah, (AR_RTC_RESET),
2646 AR_RTC_RESET_EN);
2647 }
2648}
2649
2650static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
2651{
2652 REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
2653 if (setChip) {
2654 struct ath9k_hw_capabilities *pCap = &ah->caps;
2655
2656 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
2657 REG_WRITE(ah, AR_RTC_FORCE_WAKE,
2658 AR_RTC_FORCE_WAKE_ON_INT);
2659 } else {
2660 REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
2661 AR_RTC_FORCE_WAKE_EN);
2662 }
2663 }
2664}
2665
2666static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
2667{
2668 u32 val;
2669 int i;
2670
2671 if (setChip) {
2672 if ((REG_READ(ah, AR_RTC_STATUS) &
2673 AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
2674 if (ath9k_hw_set_reset_reg(ah,
2675 ATH9K_RESET_POWER_ON) != true) {
2676 return false;
2677 }
2678 }
2679 if (AR_SREV_9100(ah))
2680 REG_SET_BIT(ah, AR_RTC_RESET,
2681 AR_RTC_RESET_EN);
2682
2683 REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
2684 AR_RTC_FORCE_WAKE_EN);
2685 udelay(50);
2686
2687 for (i = POWER_UP_TIME / 50; i > 0; i--) {
2688 val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
2689 if (val == AR_RTC_STATUS_ON)
2690 break;
2691 udelay(50);
2692 REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
2693 AR_RTC_FORCE_WAKE_EN);
2694 }
2695 if (i == 0) {
2696 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
2697 "Failed to wakeup in %uus\n", POWER_UP_TIME / 20);
2698 return false;
2699 }
2700 }
2701
2702 REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
2703
2704 return true;
2705}
2706
2707bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
2708{
2709 int status = true, setChip = true;
2710 static const char *modes[] = {
2711 "AWAKE",
2712 "FULL-SLEEP",
2713 "NETWORK SLEEP",
2714 "UNDEFINED"
2715 };
2716
2717 DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s -> %s\n",
2718 modes[ah->power_mode], modes[mode]);
2719
2720 switch (mode) {
2721 case ATH9K_PM_AWAKE:
2722 status = ath9k_hw_set_power_awake(ah, setChip);
2723 break;
2724 case ATH9K_PM_FULL_SLEEP:
2725 ath9k_set_power_sleep(ah, setChip);
2726 ah->chip_fullsleep = true;
2727 break;
2728 case ATH9K_PM_NETWORK_SLEEP:
2729 ath9k_set_power_network_sleep(ah, setChip);
2730 break;
2731 default:
2732 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
2733 "Unknown power mode %u\n", mode);
2734 return false;
2735 }
2736 ah->power_mode = mode;
2737
2738 return status;
2739}
2740
2741/*
2742 * Helper for ASPM support.
2743 *
2744 * Disable PLL when in L0s as well as receiver clock when in L1.
2745 * This power saving option must be enabled through the SerDes.
2746 *
2747 * Programming the SerDes must go through the same 288 bit serial shift
2748 * register as the other analog registers. Hence the 9 writes.
2749 */
2750void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore)
2751{
2752 u8 i;
2753
2754 if (ah->is_pciexpress != true)
2755 return;
2756
2757 /* Do not touch SerDes registers */
2758 if (ah->config.pcie_powersave_enable == 2)
2759 return;
2760
2761 /* Nothing to do on restore for 11N */
2762 if (restore)
2763 return;
2764
2765 if (AR_SREV_9280_20_OR_LATER(ah)) {
2766 /*
2767 * AR9280 2.0 or later chips use SerDes values from the
2768 * initvals.h initialized depending on chipset during
2769 * ath9k_hw_do_attach()
2770 */
2771 for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
2772 REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
2773 INI_RA(&ah->iniPcieSerdes, i, 1));
2774 }
2775 } else if (AR_SREV_9280(ah) &&
2776 (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) {
2777 REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
2778 REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
2779
2780 /* RX shut off when elecidle is asserted */
2781 REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
2782 REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
2783 REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
2784
2785 /* Shut off CLKREQ active in L1 */
2786 if (ah->config.pcie_clock_req)
2787 REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
2788 else
2789 REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
2790
2791 REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
2792 REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
2793 REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
2794
2795 /* Load the new settings */
2796 REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
2797
2798 } else {
2799 REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
2800 REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
2801
2802 /* RX shut off when elecidle is asserted */
2803 REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
2804 REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
2805 REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
2806
2807 /*
2808 * Ignore ah->ah_config.pcie_clock_req setting for
2809 * pre-AR9280 11n
2810 */
2811 REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
2812
2813 REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
2814 REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
2815 REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
2816
2817 /* Load the new settings */
2818 REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
2819 }
2820
2821 udelay(1000);
2822
2823 /* set bit 19 to allow forcing of pcie core into L1 state */
2824 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
2825
2826 /* Several PCIe massages to ensure proper behaviour */
2827 if (ah->config.pcie_waen) {
2828 REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
2829 } else {
2830 if (AR_SREV_9285(ah))
2831 REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
2832 /*
2833 * On AR9280 chips bit 22 of 0x4004 needs to be set to
2834 * otherwise card may disappear.
2835 */
2836 else if (AR_SREV_9280(ah))
2837 REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT);
2838 else
2839 REG_WRITE(ah, AR_WA, AR_WA_DEFAULT);
2840 }
2841}
2842
2843/**********************/
2844/* Interrupt Handling */
2845/**********************/
2846
2847bool ath9k_hw_intrpend(struct ath_hw *ah)
2848{
2849 u32 host_isr;
2850
2851 if (AR_SREV_9100(ah))
2852 return true;
2853
2854 host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
2855 if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS))
2856 return true;
2857
2858 host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE);
2859 if ((host_isr & AR_INTR_SYNC_DEFAULT)
2860 && (host_isr != AR_INTR_SPURIOUS))
2861 return true;
2862
2863 return false;
2864}
2865
2866bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
2867{
2868 u32 isr = 0;
2869 u32 mask2 = 0;
2870 struct ath9k_hw_capabilities *pCap = &ah->caps;
2871 u32 sync_cause = 0;
2872 bool fatal_int = false;
2873
2874 if (!AR_SREV_9100(ah)) {
2875 if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
2876 if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
2877 == AR_RTC_STATUS_ON) {
2878 isr = REG_READ(ah, AR_ISR);
2879 }
2880 }
2881
2882 sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) &
2883 AR_INTR_SYNC_DEFAULT;
2884
2885 *masked = 0;
2886
2887 if (!isr && !sync_cause)
2888 return false;
2889 } else {
2890 *masked = 0;
2891 isr = REG_READ(ah, AR_ISR);
2892 }
2893
2894 if (isr) {
2895 if (isr & AR_ISR_BCNMISC) {
2896 u32 isr2;
2897 isr2 = REG_READ(ah, AR_ISR_S2);
2898 if (isr2 & AR_ISR_S2_TIM)
2899 mask2 |= ATH9K_INT_TIM;
2900 if (isr2 & AR_ISR_S2_DTIM)
2901 mask2 |= ATH9K_INT_DTIM;
2902 if (isr2 & AR_ISR_S2_DTIMSYNC)
2903 mask2 |= ATH9K_INT_DTIMSYNC;
2904 if (isr2 & (AR_ISR_S2_CABEND))
2905 mask2 |= ATH9K_INT_CABEND;
2906 if (isr2 & AR_ISR_S2_GTT)
2907 mask2 |= ATH9K_INT_GTT;
2908 if (isr2 & AR_ISR_S2_CST)
2909 mask2 |= ATH9K_INT_CST;
2910 if (isr2 & AR_ISR_S2_TSFOOR)
2911 mask2 |= ATH9K_INT_TSFOOR;
2912 }
2913
2914 isr = REG_READ(ah, AR_ISR_RAC);
2915 if (isr == 0xffffffff) {
2916 *masked = 0;
2917 return false;
2918 }
2919
2920 *masked = isr & ATH9K_INT_COMMON;
2921
2922 if (ah->config.intr_mitigation) {
2923 if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
2924 *masked |= ATH9K_INT_RX;
2925 }
2926
2927 if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
2928 *masked |= ATH9K_INT_RX;
2929 if (isr &
2930 (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
2931 AR_ISR_TXEOL)) {
2932 u32 s0_s, s1_s;
2933
2934 *masked |= ATH9K_INT_TX;
2935
2936 s0_s = REG_READ(ah, AR_ISR_S0_S);
2937 ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
2938 ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
2939
2940 s1_s = REG_READ(ah, AR_ISR_S1_S);
2941 ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
2942 ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
2943 }
2944
2945 if (isr & AR_ISR_RXORN) {
2946 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
2947 "receive FIFO overrun interrupt\n");
2948 }
2949
2950 if (!AR_SREV_9100(ah)) {
2951 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
2952 u32 isr5 = REG_READ(ah, AR_ISR_S5_S);
2953 if (isr5 & AR_ISR_S5_TIM_TIMER)
2954 *masked |= ATH9K_INT_TIM_TIMER;
2955 }
2956 }
2957
2958 *masked |= mask2;
2959 }
2960
2961 if (AR_SREV_9100(ah))
2962 return true;
2963
2964 if (sync_cause) {
2965 fatal_int =
2966 (sync_cause &
2967 (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
2968 ? true : false;
2969
2970 if (fatal_int) {
2971 if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
2972 DPRINTF(ah->ah_sc, ATH_DBG_ANY,
2973 "received PCI FATAL interrupt\n");
2974 }
2975 if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
2976 DPRINTF(ah->ah_sc, ATH_DBG_ANY,
2977 "received PCI PERR interrupt\n");
2978 }
2979 }
2980 if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
2981 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
2982 "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
2983 REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
2984 REG_WRITE(ah, AR_RC, 0);
2985 *masked |= ATH9K_INT_FATAL;
2986 }
2987 if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
2988 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
2989 "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
2990 }
2991
2992 REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
2993 (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
2994 }
2995
2996 return true;
2997}
2998
2999enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah)
3000{
3001 return ah->mask_reg;
3002}
3003
3004enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
3005{
3006 u32 omask = ah->mask_reg;
3007 u32 mask, mask2;
3008 struct ath9k_hw_capabilities *pCap = &ah->caps;
3009
3010 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
3011
3012 if (omask & ATH9K_INT_GLOBAL) {
3013 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "disable IER\n");
3014 REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
3015 (void) REG_READ(ah, AR_IER);
3016 if (!AR_SREV_9100(ah)) {
3017 REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
3018 (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
3019
3020 REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
3021 (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
3022 }
3023 }
3024
3025 mask = ints & ATH9K_INT_COMMON;
3026 mask2 = 0;
3027
3028 if (ints & ATH9K_INT_TX) {
3029 if (ah->txok_interrupt_mask)
3030 mask |= AR_IMR_TXOK;
3031 if (ah->txdesc_interrupt_mask)
3032 mask |= AR_IMR_TXDESC;
3033 if (ah->txerr_interrupt_mask)
3034 mask |= AR_IMR_TXERR;
3035 if (ah->txeol_interrupt_mask)
3036 mask |= AR_IMR_TXEOL;
3037 }
3038 if (ints & ATH9K_INT_RX) {
3039 mask |= AR_IMR_RXERR;
3040 if (ah->config.intr_mitigation)
3041 mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
3042 else
3043 mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
3044 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
3045 mask |= AR_IMR_GENTMR;
3046 }
3047
3048 if (ints & (ATH9K_INT_BMISC)) {
3049 mask |= AR_IMR_BCNMISC;
3050 if (ints & ATH9K_INT_TIM)
3051 mask2 |= AR_IMR_S2_TIM;
3052 if (ints & ATH9K_INT_DTIM)
3053 mask2 |= AR_IMR_S2_DTIM;
3054 if (ints & ATH9K_INT_DTIMSYNC)
3055 mask2 |= AR_IMR_S2_DTIMSYNC;
3056 if (ints & ATH9K_INT_CABEND)
3057 mask2 |= AR_IMR_S2_CABEND;
3058 if (ints & ATH9K_INT_TSFOOR)
3059 mask2 |= AR_IMR_S2_TSFOOR;
3060 }
3061
3062 if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
3063 mask |= AR_IMR_BCNMISC;
3064 if (ints & ATH9K_INT_GTT)
3065 mask2 |= AR_IMR_S2_GTT;
3066 if (ints & ATH9K_INT_CST)
3067 mask2 |= AR_IMR_S2_CST;
3068 }
3069
3070 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
3071 REG_WRITE(ah, AR_IMR, mask);
3072 mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM |
3073 AR_IMR_S2_DTIM |
3074 AR_IMR_S2_DTIMSYNC |
3075 AR_IMR_S2_CABEND |
3076 AR_IMR_S2_CABTO |
3077 AR_IMR_S2_TSFOOR |
3078 AR_IMR_S2_GTT | AR_IMR_S2_CST);
3079 REG_WRITE(ah, AR_IMR_S2, mask | mask2);
3080 ah->mask_reg = ints;
3081
3082 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
3083 if (ints & ATH9K_INT_TIM_TIMER)
3084 REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
3085 else
3086 REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
3087 }
3088
3089 if (ints & ATH9K_INT_GLOBAL) {
3090 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "enable IER\n");
3091 REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
3092 if (!AR_SREV_9100(ah)) {
3093 REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
3094 AR_INTR_MAC_IRQ);
3095 REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
3096
3097
3098 REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
3099 AR_INTR_SYNC_DEFAULT);
3100 REG_WRITE(ah, AR_INTR_SYNC_MASK,
3101 AR_INTR_SYNC_DEFAULT);
3102 }
3103 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
3104 REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
3105 }
3106
3107 return omask;
3108}
3109
3110/*******************/
3111/* Beacon Handling */
3112/*******************/
3113
3114void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
3115{
3116 int flags = 0;
3117
3118 ah->beacon_interval = beacon_period;
3119
3120 switch (ah->opmode) {
3121 case NL80211_IFTYPE_STATION:
3122 case NL80211_IFTYPE_MONITOR:
3123 REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
3124 REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
3125 REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
3126 flags |= AR_TBTT_TIMER_EN;
3127 break;
3128 case NL80211_IFTYPE_ADHOC:
3129 case NL80211_IFTYPE_MESH_POINT:
3130 REG_SET_BIT(ah, AR_TXCFG,
3131 AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
3132 REG_WRITE(ah, AR_NEXT_NDP_TIMER,
3133 TU_TO_USEC(next_beacon +
3134 (ah->atim_window ? ah->
3135 atim_window : 1)));
3136 flags |= AR_NDP_TIMER_EN;
3137 case NL80211_IFTYPE_AP:
3138 REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
3139 REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT,
3140 TU_TO_USEC(next_beacon -
3141 ah->config.
3142 dma_beacon_response_time));
3143 REG_WRITE(ah, AR_NEXT_SWBA,
3144 TU_TO_USEC(next_beacon -
3145 ah->config.
3146 sw_beacon_response_time));
3147 flags |=
3148 AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
3149 break;
3150 default:
3151 DPRINTF(ah->ah_sc, ATH_DBG_BEACON,
3152 "%s: unsupported opmode: %d\n",
3153 __func__, ah->opmode);
3154 return;
3155 break;
3156 }
3157
3158 REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period));
3159 REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period));
3160 REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period));
3161 REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period));
3162
3163 beacon_period &= ~ATH9K_BEACON_ENA;
3164 if (beacon_period & ATH9K_BEACON_RESET_TSF) {
3165 beacon_period &= ~ATH9K_BEACON_RESET_TSF;
3166 ath9k_hw_reset_tsf(ah);
3167 }
3168
3169 REG_SET_BIT(ah, AR_TIMER_MODE, flags);
3170}
3171
3172void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
3173 const struct ath9k_beacon_state *bs)
3174{
3175 u32 nextTbtt, beaconintval, dtimperiod, beacontimeout;
3176 struct ath9k_hw_capabilities *pCap = &ah->caps;
3177
3178 REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
3179
3180 REG_WRITE(ah, AR_BEACON_PERIOD,
3181 TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
3182 REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
3183 TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
3184
3185 REG_RMW_FIELD(ah, AR_RSSI_THR,
3186 AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
3187
3188 beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD;
3189
3190 if (bs->bs_sleepduration > beaconintval)
3191 beaconintval = bs->bs_sleepduration;
3192
3193 dtimperiod = bs->bs_dtimperiod;
3194 if (bs->bs_sleepduration > dtimperiod)
3195 dtimperiod = bs->bs_sleepduration;
3196
3197 if (beaconintval == dtimperiod)
3198 nextTbtt = bs->bs_nextdtim;
3199 else
3200 nextTbtt = bs->bs_nexttbtt;
3201
3202 DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim);
3203 DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt);
3204 DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "beacon period %d\n", beaconintval);
3205 DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod);
3206
3207 REG_WRITE(ah, AR_NEXT_DTIM,
3208 TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
3209 REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
3210
3211 REG_WRITE(ah, AR_SLEEP1,
3212 SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT)
3213 | AR_SLEEP1_ASSUME_DTIM);
3214
3215 if (pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)
3216 beacontimeout = (BEACON_TIMEOUT_VAL << 3);
3217 else
3218 beacontimeout = MIN_BEACON_TIMEOUT_VAL;
3219
3220 REG_WRITE(ah, AR_SLEEP2,
3221 SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
3222
3223 REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
3224 REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
3225
3226 REG_SET_BIT(ah, AR_TIMER_MODE,
3227 AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN |
3228 AR_DTIM_TIMER_EN);
3229
3230 /* TSF Out of Range Threshold */
3231 REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold);
3232}
3233
3234/*******************/
3235/* HW Capabilities */
3236/*******************/
3237
3238void ath9k_hw_fill_cap_info(struct ath_hw *ah)
3239{
3240 struct ath9k_hw_capabilities *pCap = &ah->caps;
3241 u16 capField = 0, eeval;
3242
3243 eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
3244 ah->regulatory.current_rd = eeval;
3245
3246 eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
3247 if (AR_SREV_9285_10_OR_LATER(ah))
3248 eeval |= AR9285_RDEXT_DEFAULT;
3249 ah->regulatory.current_rd_ext = eeval;
3250
3251 capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP);
3252
3253 if (ah->opmode != NL80211_IFTYPE_AP &&
3254 ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) {
3255 if (ah->regulatory.current_rd == 0x64 ||
3256 ah->regulatory.current_rd == 0x65)
3257 ah->regulatory.current_rd += 5;
3258 else if (ah->regulatory.current_rd == 0x41)
3259 ah->regulatory.current_rd = 0x43;
3260 DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
3261 "regdomain mapped to 0x%x\n", ah->regulatory.current_rd);
3262 }
3263
3264 eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
3265 bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX);
3266
3267 if (eeval & AR5416_OPFLAGS_11A) {
3268 set_bit(ATH9K_MODE_11A, pCap->wireless_modes);
3269 if (ah->config.ht_enable) {
3270 if (!(eeval & AR5416_OPFLAGS_N_5G_HT20))
3271 set_bit(ATH9K_MODE_11NA_HT20,
3272 pCap->wireless_modes);
3273 if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) {
3274 set_bit(ATH9K_MODE_11NA_HT40PLUS,
3275 pCap->wireless_modes);
3276 set_bit(ATH9K_MODE_11NA_HT40MINUS,
3277 pCap->wireless_modes);
3278 }
3279 }
3280 }
3281
3282 if (eeval & AR5416_OPFLAGS_11G) {
3283 set_bit(ATH9K_MODE_11B, pCap->wireless_modes);
3284 set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
3285 if (ah->config.ht_enable) {
3286 if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
3287 set_bit(ATH9K_MODE_11NG_HT20,
3288 pCap->wireless_modes);
3289 if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) {
3290 set_bit(ATH9K_MODE_11NG_HT40PLUS,
3291 pCap->wireless_modes);
3292 set_bit(ATH9K_MODE_11NG_HT40MINUS,
3293 pCap->wireless_modes);
3294 }
3295 }
3296 }
3297
3298 pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
3299 if ((ah->hw_version.devid == AR5416_DEVID_PCI) &&
3300 !(eeval & AR5416_OPFLAGS_11A))
3301 pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7;
3302 else
3303 pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
3304
3305 if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0)))
3306 ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
3307
3308 pCap->low_2ghz_chan = 2312;
3309 pCap->high_2ghz_chan = 2732;
3310
3311 pCap->low_5ghz_chan = 4920;
3312 pCap->high_5ghz_chan = 6100;
3313
3314 pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP;
3315 pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP;
3316 pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM;
3317
3318 pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP;
3319 pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP;
3320 pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM;
3321
3322 if (ah->config.ht_enable)
3323 pCap->hw_caps |= ATH9K_HW_CAP_HT;
3324 else
3325 pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
3326
3327 pCap->hw_caps |= ATH9K_HW_CAP_GTT;
3328 pCap->hw_caps |= ATH9K_HW_CAP_VEOL;
3329 pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK;
3330 pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH;
3331
3332 if (capField & AR_EEPROM_EEPCAP_MAXQCU)
3333 pCap->total_queues =
3334 MS(capField, AR_EEPROM_EEPCAP_MAXQCU);
3335 else
3336 pCap->total_queues = ATH9K_NUM_TX_QUEUES;
3337
3338 if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES)
3339 pCap->keycache_size =
3340 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES);
3341 else
3342 pCap->keycache_size = AR_KEYTABLE_SIZE;
3343
3344 pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
3345 pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
3346
3347 if (AR_SREV_9285_10_OR_LATER(ah))
3348 pCap->num_gpio_pins = AR9285_NUM_GPIO;
3349 else if (AR_SREV_9280_10_OR_LATER(ah))
3350 pCap->num_gpio_pins = AR928X_NUM_GPIO;
3351 else
3352 pCap->num_gpio_pins = AR_NUM_GPIO;
3353
3354 if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) {
3355 pCap->hw_caps |= ATH9K_HW_CAP_CST;
3356 pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
3357 } else {
3358 pCap->rts_aggr_limit = (8 * 1024);
3359 }
3360
3361 pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM;
3362
3363#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
3364 ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT);
3365 if (ah->rfsilent & EEP_RFSILENT_ENABLED) {
3366 ah->rfkill_gpio =
3367 MS(ah->rfsilent, EEP_RFSILENT_GPIO_SEL);
3368 ah->rfkill_polarity =
3369 MS(ah->rfsilent, EEP_RFSILENT_POLARITY);
3370
3371 pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
3372 }
3373#endif
3374
3375 if ((ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) ||
3376 (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) ||
3377 (ah->hw_version.macVersion == AR_SREV_VERSION_9160) ||
3378 (ah->hw_version.macVersion == AR_SREV_VERSION_9100) ||
3379 (ah->hw_version.macVersion == AR_SREV_VERSION_9280))
3380 pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
3381 else
3382 pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
3383
3384 if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
3385 pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
3386 else
3387 pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
3388
3389 if (ah->regulatory.current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) {
3390 pCap->reg_cap =
3391 AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
3392 AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
3393 AR_EEPROM_EEREGCAP_EN_KK_U2 |
3394 AR_EEPROM_EEREGCAP_EN_KK_MIDBAND;
3395 } else {
3396 pCap->reg_cap =
3397 AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
3398 AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN;
3399 }
3400
3401 pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND;
3402
3403 pCap->num_antcfg_5ghz =
3404 ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ);
3405 pCap->num_antcfg_2ghz =
3406 ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
3407
3408 if (AR_SREV_9280_10_OR_LATER(ah) && btcoex_enable) {
3409 pCap->hw_caps |= ATH9K_HW_CAP_BT_COEX;
3410 ah->btactive_gpio = 6;
3411 ah->wlanactive_gpio = 5;
3412 }
3413}
3414
3415bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
3416 u32 capability, u32 *result)
3417{
3418 switch (type) {
3419 case ATH9K_CAP_CIPHER:
3420 switch (capability) {
3421 case ATH9K_CIPHER_AES_CCM:
3422 case ATH9K_CIPHER_AES_OCB:
3423 case ATH9K_CIPHER_TKIP:
3424 case ATH9K_CIPHER_WEP:
3425 case ATH9K_CIPHER_MIC:
3426 case ATH9K_CIPHER_CLR:
3427 return true;
3428 default:
3429 return false;
3430 }
3431 case ATH9K_CAP_TKIP_MIC:
3432 switch (capability) {
3433 case 0:
3434 return true;
3435 case 1:
3436 return (ah->sta_id1_defaults &
3437 AR_STA_ID1_CRPT_MIC_ENABLE) ? true :
3438 false;
3439 }
3440 case ATH9K_CAP_TKIP_SPLIT:
3441 return (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ?
3442 false : true;
3443 case ATH9K_CAP_DIVERSITY:
3444 return (REG_READ(ah, AR_PHY_CCK_DETECT) &
3445 AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ?
3446 true : false;
3447 case ATH9K_CAP_MCAST_KEYSRCH:
3448 switch (capability) {
3449 case 0:
3450 return true;
3451 case 1:
3452 if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) {
3453 return false;
3454 } else {
3455 return (ah->sta_id1_defaults &
3456 AR_STA_ID1_MCAST_KSRCH) ? true :
3457 false;
3458 }
3459 }
3460 return false;
3461 case ATH9K_CAP_TXPOW:
3462 switch (capability) {
3463 case 0:
3464 return 0;
3465 case 1:
3466 *result = ah->regulatory.power_limit;
3467 return 0;
3468 case 2:
3469 *result = ah->regulatory.max_power_level;
3470 return 0;
3471 case 3:
3472 *result = ah->regulatory.tp_scale;
3473 return 0;
3474 }
3475 return false;
3476 case ATH9K_CAP_DS:
3477 return (AR_SREV_9280_20_OR_LATER(ah) &&
3478 (ah->eep_ops->get_eeprom(ah, EEP_RC_CHAIN_MASK) == 1))
3479 ? false : true;
3480 default:
3481 return false;
3482 }
3483}
3484
3485bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,
3486 u32 capability, u32 setting, int *status)
3487{
3488 u32 v;
3489
3490 switch (type) {
3491 case ATH9K_CAP_TKIP_MIC:
3492 if (setting)
3493 ah->sta_id1_defaults |=
3494 AR_STA_ID1_CRPT_MIC_ENABLE;
3495 else
3496 ah->sta_id1_defaults &=
3497 ~AR_STA_ID1_CRPT_MIC_ENABLE;
3498 return true;
3499 case ATH9K_CAP_DIVERSITY:
3500 v = REG_READ(ah, AR_PHY_CCK_DETECT);
3501 if (setting)
3502 v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
3503 else
3504 v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
3505 REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
3506 return true;
3507 case ATH9K_CAP_MCAST_KEYSRCH:
3508 if (setting)
3509 ah->sta_id1_defaults |= AR_STA_ID1_MCAST_KSRCH;
3510 else
3511 ah->sta_id1_defaults &= ~AR_STA_ID1_MCAST_KSRCH;
3512 return true;
3513 default:
3514 return false;
3515 }
3516}
3517
3518/****************************/
3519/* GPIO / RFKILL / Antennae */
3520/****************************/
3521
3522static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah,
3523 u32 gpio, u32 type)
3524{
3525 int addr;
3526 u32 gpio_shift, tmp;
3527
3528 if (gpio > 11)
3529 addr = AR_GPIO_OUTPUT_MUX3;
3530 else if (gpio > 5)
3531 addr = AR_GPIO_OUTPUT_MUX2;
3532 else
3533 addr = AR_GPIO_OUTPUT_MUX1;
3534
3535 gpio_shift = (gpio % 6) * 5;
3536
3537 if (AR_SREV_9280_20_OR_LATER(ah)
3538 || (addr != AR_GPIO_OUTPUT_MUX1)) {
3539 REG_RMW(ah, addr, (type << gpio_shift),
3540 (0x1f << gpio_shift));
3541 } else {
3542 tmp = REG_READ(ah, addr);
3543 tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);
3544 tmp &= ~(0x1f << gpio_shift);
3545 tmp |= (type << gpio_shift);
3546 REG_WRITE(ah, addr, tmp);
3547 }
3548}
3549
3550void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio)
3551{
3552 u32 gpio_shift;
3553
3554 ASSERT(gpio < ah->caps.num_gpio_pins);
3555
3556 gpio_shift = gpio << 1;
3557
3558 REG_RMW(ah,
3559 AR_GPIO_OE_OUT,
3560 (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
3561 (AR_GPIO_OE_OUT_DRV << gpio_shift));
3562}
3563
3564u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
3565{
3566#define MS_REG_READ(x, y) \
3567 (MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & (AR_GPIO_BIT(y)))
3568
3569 if (gpio >= ah->caps.num_gpio_pins)
3570 return 0xffffffff;
3571
3572 if (AR_SREV_9285_10_OR_LATER(ah))
3573 return MS_REG_READ(AR9285, gpio) != 0;
3574 else if (AR_SREV_9280_10_OR_LATER(ah))
3575 return MS_REG_READ(AR928X, gpio) != 0;
3576 else
3577 return MS_REG_READ(AR, gpio) != 0;
3578}
3579
3580void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
3581 u32 ah_signal_type)
3582{
3583 u32 gpio_shift;
3584
3585 ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
3586
3587 gpio_shift = 2 * gpio;
3588
3589 REG_RMW(ah,
3590 AR_GPIO_OE_OUT,
3591 (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
3592 (AR_GPIO_OE_OUT_DRV << gpio_shift));
3593}
3594
3595void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
3596{
3597 REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
3598 AR_GPIO_BIT(gpio));
3599}
3600
3601#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
3602void ath9k_enable_rfkill(struct ath_hw *ah)
3603{
3604 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
3605 AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
3606
3607 REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
3608 AR_GPIO_INPUT_MUX2_RFSILENT);
3609
3610 ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio);
3611 REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
3612}
3613#endif
3614
3615u32 ath9k_hw_getdefantenna(struct ath_hw *ah)
3616{
3617 return REG_READ(ah, AR_DEF_ANTENNA) & 0x7;
3618}
3619
3620void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna)
3621{
3622 REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
3623}
3624
3625bool ath9k_hw_setantennaswitch(struct ath_hw *ah,
3626 enum ath9k_ant_setting settings,
3627 struct ath9k_channel *chan,
3628 u8 *tx_chainmask,
3629 u8 *rx_chainmask,
3630 u8 *antenna_cfgd)
3631{
3632 static u8 tx_chainmask_cfg, rx_chainmask_cfg;
3633
3634 if (AR_SREV_9280(ah)) {
3635 if (!tx_chainmask_cfg) {
3636
3637 tx_chainmask_cfg = *tx_chainmask;
3638 rx_chainmask_cfg = *rx_chainmask;
3639 }
3640
3641 switch (settings) {
3642 case ATH9K_ANT_FIXED_A:
3643 *tx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
3644 *rx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
3645 *antenna_cfgd = true;
3646 break;
3647 case ATH9K_ANT_FIXED_B:
3648 if (ah->caps.tx_chainmask >
3649 ATH9K_ANTENNA1_CHAINMASK) {
3650 *tx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
3651 }
3652 *rx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
3653 *antenna_cfgd = true;
3654 break;
3655 case ATH9K_ANT_VARIABLE:
3656 *tx_chainmask = tx_chainmask_cfg;
3657 *rx_chainmask = rx_chainmask_cfg;
3658 *antenna_cfgd = true;
3659 break;
3660 default:
3661 break;
3662 }
3663 } else {
3664 ah->diversity_control = settings;
3665 }
3666
3667 return true;
3668}
3669
3670/*********************/
3671/* General Operation */
3672/*********************/
3673
3674u32 ath9k_hw_getrxfilter(struct ath_hw *ah)
3675{
3676 u32 bits = REG_READ(ah, AR_RX_FILTER);
3677 u32 phybits = REG_READ(ah, AR_PHY_ERR);
3678
3679 if (phybits & AR_PHY_ERR_RADAR)
3680 bits |= ATH9K_RX_FILTER_PHYRADAR;
3681 if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING))
3682 bits |= ATH9K_RX_FILTER_PHYERR;
3683
3684 return bits;
3685}
3686
3687void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
3688{
3689 u32 phybits;
3690
3691 REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff) | AR_RX_COMPR_BAR);
3692 phybits = 0;
3693 if (bits & ATH9K_RX_FILTER_PHYRADAR)
3694 phybits |= AR_PHY_ERR_RADAR;
3695 if (bits & ATH9K_RX_FILTER_PHYERR)
3696 phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
3697 REG_WRITE(ah, AR_PHY_ERR, phybits);
3698
3699 if (phybits)
3700 REG_WRITE(ah, AR_RXCFG,
3701 REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
3702 else
3703 REG_WRITE(ah, AR_RXCFG,
3704 REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
3705}
3706
3707bool ath9k_hw_phy_disable(struct ath_hw *ah)
3708{
3709 return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM);
3710}
3711
3712bool ath9k_hw_disable(struct ath_hw *ah)
3713{
3714 if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
3715 return false;
3716
3717 return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD);
3718}
3719
3720bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
3721{
3722 struct ath9k_channel *chan = ah->curchan;
3723 struct ieee80211_channel *channel = chan->chan;
3724
3725 ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER);
3726
3727 if (ah->eep_ops->set_txpower(ah, chan,
3728 ath9k_regd_get_ctl(&ah->regulatory, chan),
3729 channel->max_antenna_gain * 2,
3730 channel->max_power * 2,
3731 min((u32) MAX_RATE_POWER,
3732 (u32) ah->regulatory.power_limit)) != 0)
3733 return false;
3734
3735 return true;
3736}
3737
3738void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac)
3739{
3740 memcpy(ah->macaddr, mac, ETH_ALEN);
3741}
3742
3743void ath9k_hw_setopmode(struct ath_hw *ah)
3744{
3745 ath9k_hw_set_operating_mode(ah, ah->opmode);
3746}
3747
3748void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1)
3749{
3750 REG_WRITE(ah, AR_MCAST_FIL0, filter0);
3751 REG_WRITE(ah, AR_MCAST_FIL1, filter1);
3752}
3753
3754void ath9k_hw_setbssidmask(struct ath_softc *sc)
3755{
3756 REG_WRITE(sc->sc_ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask));
3757 REG_WRITE(sc->sc_ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4));
3758}
3759
3760void ath9k_hw_write_associd(struct ath_softc *sc)
3761{
3762 REG_WRITE(sc->sc_ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid));
3763 REG_WRITE(sc->sc_ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) |
3764 ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S));
3765}
3766
3767u64 ath9k_hw_gettsf64(struct ath_hw *ah)
3768{
3769 u64 tsf;
3770
3771 tsf = REG_READ(ah, AR_TSF_U32);
3772 tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32);
3773
3774 return tsf;
3775}
3776
3777void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64)
3778{
3779 REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
3780 REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
3781}
3782
3783void ath9k_hw_reset_tsf(struct ath_hw *ah)
3784{
3785 int count;
3786
3787 count = 0;
3788 while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) {
3789 count++;
3790 if (count > 10) {
3791 DPRINTF(ah->ah_sc, ATH_DBG_RESET,
3792 "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n");
3793 break;
3794 }
3795 udelay(10);
3796 }
3797 REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
3798}
3799
3800bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting)
3801{
3802 if (setting)
3803 ah->misc_mode |= AR_PCU_TX_ADD_TSF;
3804 else
3805 ah->misc_mode &= ~AR_PCU_TX_ADD_TSF;
3806
3807 return true;
3808}
3809
3810bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
3811{
3812 if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
3813 DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad slot time %u\n", us);
3814 ah->slottime = (u32) -1;
3815 return false;
3816 } else {
3817 REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us));
3818 ah->slottime = us;
3819 return true;
3820 }
3821}
3822
3823void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode)
3824{
3825 u32 macmode;
3826
3827 if (mode == ATH9K_HT_MACMODE_2040 &&
3828 !ah->config.cwm_ignore_extcca)
3829 macmode = AR_2040_JOINED_RX_CLEAR;
3830 else
3831 macmode = 0;
3832
3833 REG_WRITE(ah, AR_2040_MODE, macmode);
3834}
3835
3836/***************************/
3837/* Bluetooth Coexistence */
3838/***************************/
3839
3840void ath9k_hw_btcoex_enable(struct ath_hw *ah)
3841{
3842 /* connect bt_active to baseband */
3843 REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
3844 (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
3845 AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));
3846
3847 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
3848 AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
3849
3850 /* Set input mux for bt_active to gpio pin */
3851 REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
3852 AR_GPIO_INPUT_MUX1_BT_ACTIVE,
3853 ah->btactive_gpio);
3854
3855 /* Configure the desired gpio port for input */
3856 ath9k_hw_cfg_gpio_input(ah, ah->btactive_gpio);
3857
3858 /* Configure the desired GPIO port for TX_FRAME output */
3859 ath9k_hw_cfg_output(ah, ah->wlanactive_gpio,
3860 AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
3861}
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
new file mode 100644
index 000000000000..5c4127e6c1c6
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -0,0 +1,631 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef HW_H
18#define HW_H
19
20#include <linux/if_ether.h>
21#include <linux/delay.h>
22#include <linux/io.h>
23
24#include "mac.h"
25#include "ani.h"
26#include "eeprom.h"
27#include "calib.h"
28#include "reg.h"
29#include "phy.h"
30
31#include "../regd.h"
32
33#define ATHEROS_VENDOR_ID 0x168c
34#define AR5416_DEVID_PCI 0x0023
35#define AR5416_DEVID_PCIE 0x0024
36#define AR9160_DEVID_PCI 0x0027
37#define AR9280_DEVID_PCI 0x0029
38#define AR9280_DEVID_PCIE 0x002a
39#define AR9285_DEVID_PCIE 0x002b
40#define AR5416_AR9100_DEVID 0x000b
41#define AR_SUBVENDOR_ID_NOG 0x0e11
42#define AR_SUBVENDOR_ID_NEW_A 0x7065
43#define AR5416_MAGIC 0x19641014
44
45/* Register read/write primitives */
46#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val))
47#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg))
48
49#define SM(_v, _f) (((_v) << _f##_S) & _f)
50#define MS(_v, _f) (((_v) & _f) >> _f##_S)
51#define REG_RMW(_a, _r, _set, _clr) \
52 REG_WRITE(_a, _r, (REG_READ(_a, _r) & ~(_clr)) | (_set))
53#define REG_RMW_FIELD(_a, _r, _f, _v) \
54 REG_WRITE(_a, _r, \
55 (REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f))
56#define REG_SET_BIT(_a, _r, _f) \
57 REG_WRITE(_a, _r, REG_READ(_a, _r) | _f)
58#define REG_CLR_BIT(_a, _r, _f) \
59 REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f)
60
61#define DO_DELAY(x) do { \
62 if ((++(x) % 64) == 0) \
63 udelay(1); \
64 } while (0)
65
66#define REG_WRITE_ARRAY(iniarray, column, regWr) do { \
67 int r; \
68 for (r = 0; r < ((iniarray)->ia_rows); r++) { \
69 REG_WRITE(ah, INI_RA((iniarray), (r), 0), \
70 INI_RA((iniarray), r, (column))); \
71 DO_DELAY(regWr); \
72 } \
73 } while (0)
74
75#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0
76#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
77#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2
78#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3
79#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5
80#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6
81
82#define AR_GPIOD_MASK 0x00001FFF
83#define AR_GPIO_BIT(_gpio) (1 << (_gpio))
84
85#define BASE_ACTIVATE_DELAY 100
86#define RTC_PLL_SETTLE_DELAY 1000
87#define COEF_SCALE_S 24
88#define HT40_CHANNEL_CENTER_SHIFT 10
89
90#define ATH9K_ANTENNA0_CHAINMASK 0x1
91#define ATH9K_ANTENNA1_CHAINMASK 0x2
92
93#define ATH9K_NUM_DMA_DEBUG_REGS 8
94#define ATH9K_NUM_QUEUES 10
95
96#define MAX_RATE_POWER 63
97#define AH_WAIT_TIMEOUT 100000 /* (us) */
98#define AH_TIME_QUANTUM 10
99#define AR_KEYTABLE_SIZE 128
100#define POWER_UP_TIME 200000
101#define SPUR_RSSI_THRESH 40
102
103#define CAB_TIMEOUT_VAL 10
104#define BEACON_TIMEOUT_VAL 10
105#define MIN_BEACON_TIMEOUT_VAL 1
106#define SLEEP_SLOP 3
107
108#define INIT_CONFIG_STATUS 0x00000000
109#define INIT_RSSI_THR 0x00000700
110#define INIT_BCON_CNTRL_REG 0x00000000
111
112#define TU_TO_USEC(_tu) ((_tu) << 10)
113
114enum wireless_mode {
115 ATH9K_MODE_11A = 0,
116 ATH9K_MODE_11B = 2,
117 ATH9K_MODE_11G = 3,
118 ATH9K_MODE_11NA_HT20 = 6,
119 ATH9K_MODE_11NG_HT20 = 7,
120 ATH9K_MODE_11NA_HT40PLUS = 8,
121 ATH9K_MODE_11NA_HT40MINUS = 9,
122 ATH9K_MODE_11NG_HT40PLUS = 10,
123 ATH9K_MODE_11NG_HT40MINUS = 11,
124 ATH9K_MODE_MAX
125};
126
127enum ath9k_hw_caps {
128 ATH9K_HW_CAP_MIC_AESCCM = BIT(0),
129 ATH9K_HW_CAP_MIC_CKIP = BIT(1),
130 ATH9K_HW_CAP_MIC_TKIP = BIT(2),
131 ATH9K_HW_CAP_CIPHER_AESCCM = BIT(3),
132 ATH9K_HW_CAP_CIPHER_CKIP = BIT(4),
133 ATH9K_HW_CAP_CIPHER_TKIP = BIT(5),
134 ATH9K_HW_CAP_VEOL = BIT(6),
135 ATH9K_HW_CAP_BSSIDMASK = BIT(7),
136 ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(8),
137 ATH9K_HW_CAP_HT = BIT(9),
138 ATH9K_HW_CAP_GTT = BIT(10),
139 ATH9K_HW_CAP_FASTCC = BIT(11),
140 ATH9K_HW_CAP_RFSILENT = BIT(12),
141 ATH9K_HW_CAP_CST = BIT(13),
142 ATH9K_HW_CAP_ENHANCEDPM = BIT(14),
143 ATH9K_HW_CAP_AUTOSLEEP = BIT(15),
144 ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16),
145 ATH9K_HW_CAP_BT_COEX = BIT(17)
146};
147
148enum ath9k_capability_type {
149 ATH9K_CAP_CIPHER = 0,
150 ATH9K_CAP_TKIP_MIC,
151 ATH9K_CAP_TKIP_SPLIT,
152 ATH9K_CAP_DIVERSITY,
153 ATH9K_CAP_TXPOW,
154 ATH9K_CAP_MCAST_KEYSRCH,
155 ATH9K_CAP_DS
156};
157
158struct ath9k_hw_capabilities {
159 u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
160 DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */
161 u16 total_queues;
162 u16 keycache_size;
163 u16 low_5ghz_chan, high_5ghz_chan;
164 u16 low_2ghz_chan, high_2ghz_chan;
165 u16 rts_aggr_limit;
166 u8 tx_chainmask;
167 u8 rx_chainmask;
168 u16 tx_triglevel_max;
169 u16 reg_cap;
170 u8 num_gpio_pins;
171 u8 num_antcfg_2ghz;
172 u8 num_antcfg_5ghz;
173};
174
175struct ath9k_ops_config {
176 int dma_beacon_response_time;
177 int sw_beacon_response_time;
178 int additional_swba_backoff;
179 int ack_6mb;
180 int cwm_ignore_extcca;
181 u8 pcie_powersave_enable;
182 u8 pcie_clock_req;
183 u32 pcie_waen;
184 u8 analog_shiftreg;
185 u8 ht_enable;
186 u32 ofdm_trig_low;
187 u32 ofdm_trig_high;
188 u32 cck_trig_high;
189 u32 cck_trig_low;
190 u32 enable_ani;
191 u16 diversity_control;
192 u16 antenna_switch_swap;
193 int serialize_regmode;
194 bool intr_mitigation;
195#define SPUR_DISABLE 0
196#define SPUR_ENABLE_IOCTL 1
197#define SPUR_ENABLE_EEPROM 2
198#define AR_EEPROM_MODAL_SPURS 5
199#define AR_SPUR_5413_1 1640
200#define AR_SPUR_5413_2 1200
201#define AR_NO_SPUR 0x8000
202#define AR_BASE_FREQ_2GHZ 2300
203#define AR_BASE_FREQ_5GHZ 4900
204#define AR_SPUR_FEEQ_BOUND_HT40 19
205#define AR_SPUR_FEEQ_BOUND_HT20 10
206 int spurmode;
207 u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
208};
209
210enum ath9k_int {
211 ATH9K_INT_RX = 0x00000001,
212 ATH9K_INT_RXDESC = 0x00000002,
213 ATH9K_INT_RXNOFRM = 0x00000008,
214 ATH9K_INT_RXEOL = 0x00000010,
215 ATH9K_INT_RXORN = 0x00000020,
216 ATH9K_INT_TX = 0x00000040,
217 ATH9K_INT_TXDESC = 0x00000080,
218 ATH9K_INT_TIM_TIMER = 0x00000100,
219 ATH9K_INT_TXURN = 0x00000800,
220 ATH9K_INT_MIB = 0x00001000,
221 ATH9K_INT_RXPHY = 0x00004000,
222 ATH9K_INT_RXKCM = 0x00008000,
223 ATH9K_INT_SWBA = 0x00010000,
224 ATH9K_INT_BMISS = 0x00040000,
225 ATH9K_INT_BNR = 0x00100000,
226 ATH9K_INT_TIM = 0x00200000,
227 ATH9K_INT_DTIM = 0x00400000,
228 ATH9K_INT_DTIMSYNC = 0x00800000,
229 ATH9K_INT_GPIO = 0x01000000,
230 ATH9K_INT_CABEND = 0x02000000,
231 ATH9K_INT_TSFOOR = 0x04000000,
232 ATH9K_INT_CST = 0x10000000,
233 ATH9K_INT_GTT = 0x20000000,
234 ATH9K_INT_FATAL = 0x40000000,
235 ATH9K_INT_GLOBAL = 0x80000000,
236 ATH9K_INT_BMISC = ATH9K_INT_TIM |
237 ATH9K_INT_DTIM |
238 ATH9K_INT_DTIMSYNC |
239 ATH9K_INT_TSFOOR |
240 ATH9K_INT_CABEND,
241 ATH9K_INT_COMMON = ATH9K_INT_RXNOFRM |
242 ATH9K_INT_RXDESC |
243 ATH9K_INT_RXEOL |
244 ATH9K_INT_RXORN |
245 ATH9K_INT_TXURN |
246 ATH9K_INT_TXDESC |
247 ATH9K_INT_MIB |
248 ATH9K_INT_RXPHY |
249 ATH9K_INT_RXKCM |
250 ATH9K_INT_SWBA |
251 ATH9K_INT_BMISS |
252 ATH9K_INT_GPIO,
253 ATH9K_INT_NOCARD = 0xffffffff
254};
255
256#define CHANNEL_CW_INT 0x00002
257#define CHANNEL_CCK 0x00020
258#define CHANNEL_OFDM 0x00040
259#define CHANNEL_2GHZ 0x00080
260#define CHANNEL_5GHZ 0x00100
261#define CHANNEL_PASSIVE 0x00200
262#define CHANNEL_DYN 0x00400
263#define CHANNEL_HALF 0x04000
264#define CHANNEL_QUARTER 0x08000
265#define CHANNEL_HT20 0x10000
266#define CHANNEL_HT40PLUS 0x20000
267#define CHANNEL_HT40MINUS 0x40000
268
269#define CHANNEL_INTERFERENCE 0x01
270#define CHANNEL_DFS 0x02
271#define CHANNEL_4MS_LIMIT 0x04
272#define CHANNEL_DFS_CLEAR 0x08
273#define CHANNEL_DISALLOW_ADHOC 0x10
274#define CHANNEL_PER_11D_ADHOC 0x20
275
276#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM)
277#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK)
278#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM)
279#define CHANNEL_G_HT20 (CHANNEL_2GHZ|CHANNEL_HT20)
280#define CHANNEL_A_HT20 (CHANNEL_5GHZ|CHANNEL_HT20)
281#define CHANNEL_G_HT40PLUS (CHANNEL_2GHZ|CHANNEL_HT40PLUS)
282#define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS)
283#define CHANNEL_A_HT40PLUS (CHANNEL_5GHZ|CHANNEL_HT40PLUS)
284#define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS)
285#define CHANNEL_ALL \
286 (CHANNEL_OFDM| \
287 CHANNEL_CCK| \
288 CHANNEL_2GHZ | \
289 CHANNEL_5GHZ | \
290 CHANNEL_HT20 | \
291 CHANNEL_HT40PLUS | \
292 CHANNEL_HT40MINUS)
293
294struct ath9k_channel {
295 struct ieee80211_channel *chan;
296 u16 channel;
297 u32 channelFlags;
298 u32 chanmode;
299 int32_t CalValid;
300 bool oneTimeCalsDone;
301 int8_t iCoff;
302 int8_t qCoff;
303 int16_t rawNoiseFloor;
304};
305
306#define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \
307 (((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \
308 (((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \
309 (((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS))
310#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
311 (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \
312 (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \
313 (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS))
314#define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0)
315#define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0)
316#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
317#define IS_CHAN_PASSIVE(_c) (((_c)->channelFlags & CHANNEL_PASSIVE) != 0)
318#define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0)
319#define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
320#define IS_CHAN_A_5MHZ_SPACED(_c) \
321 ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \
322 (((_c)->channel % 20) != 0) && \
323 (((_c)->channel % 10) != 0))
324
325/* These macros check chanmode and not channelFlags */
326#define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B)
327#define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \
328 ((_c)->chanmode == CHANNEL_G_HT20))
329#define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \
330 ((_c)->chanmode == CHANNEL_A_HT40MINUS) || \
331 ((_c)->chanmode == CHANNEL_G_HT40PLUS) || \
332 ((_c)->chanmode == CHANNEL_G_HT40MINUS))
333#define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c)))
334
335enum ath9k_power_mode {
336 ATH9K_PM_AWAKE = 0,
337 ATH9K_PM_FULL_SLEEP,
338 ATH9K_PM_NETWORK_SLEEP,
339 ATH9K_PM_UNDEFINED
340};
341
342enum ath9k_ant_setting {
343 ATH9K_ANT_VARIABLE = 0,
344 ATH9K_ANT_FIXED_A,
345 ATH9K_ANT_FIXED_B
346};
347
348enum ath9k_tp_scale {
349 ATH9K_TP_SCALE_MAX = 0,
350 ATH9K_TP_SCALE_50,
351 ATH9K_TP_SCALE_25,
352 ATH9K_TP_SCALE_12,
353 ATH9K_TP_SCALE_MIN
354};
355
356enum ser_reg_mode {
357 SER_REG_MODE_OFF = 0,
358 SER_REG_MODE_ON = 1,
359 SER_REG_MODE_AUTO = 2,
360};
361
362struct ath9k_beacon_state {
363 u32 bs_nexttbtt;
364 u32 bs_nextdtim;
365 u32 bs_intval;
366#define ATH9K_BEACON_PERIOD 0x0000ffff
367#define ATH9K_BEACON_ENA 0x00800000
368#define ATH9K_BEACON_RESET_TSF 0x01000000
369#define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */
370 u32 bs_dtimperiod;
371 u16 bs_cfpperiod;
372 u16 bs_cfpmaxduration;
373 u32 bs_cfpnext;
374 u16 bs_timoffset;
375 u16 bs_bmissthreshold;
376 u32 bs_sleepduration;
377 u32 bs_tsfoor_threshold;
378};
379
380struct chan_centers {
381 u16 synth_center;
382 u16 ctl_center;
383 u16 ext_center;
384};
385
386enum {
387 ATH9K_RESET_POWER_ON,
388 ATH9K_RESET_WARM,
389 ATH9K_RESET_COLD,
390};
391
392struct ath9k_hw_version {
393 u32 magic;
394 u16 devid;
395 u16 subvendorid;
396 u32 macVersion;
397 u16 macRev;
398 u16 phyRev;
399 u16 analog5GhzRev;
400 u16 analog2GhzRev;
401};
402
403struct ath_hw {
404 struct ath_softc *ah_sc;
405 struct ath9k_hw_version hw_version;
406 struct ath9k_ops_config config;
407 struct ath9k_hw_capabilities caps;
408 struct ath_regulatory regulatory;
409 struct ath9k_channel channels[38];
410 struct ath9k_channel *curchan;
411
412 union {
413 struct ar5416_eeprom_def def;
414 struct ar5416_eeprom_4k map4k;
415 } eeprom;
416 const struct eeprom_ops *eep_ops;
417 enum ath9k_eep_map eep_map;
418
419 bool sw_mgmt_crypto;
420 bool is_pciexpress;
421 u8 macaddr[ETH_ALEN];
422 u16 tx_trig_level;
423 u16 rfsilent;
424 u32 rfkill_gpio;
425 u32 rfkill_polarity;
426 u32 btactive_gpio;
427 u32 wlanactive_gpio;
428 u32 ah_flags;
429
430 enum nl80211_iftype opmode;
431 enum ath9k_power_mode power_mode;
432 enum ath9k_power_mode restore_mode;
433
434 struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
435 struct ar5416Stats stats;
436 struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
437
438 int16_t curchan_rad_index;
439 u32 mask_reg;
440 u32 txok_interrupt_mask;
441 u32 txerr_interrupt_mask;
442 u32 txdesc_interrupt_mask;
443 u32 txeol_interrupt_mask;
444 u32 txurn_interrupt_mask;
445 bool chip_fullsleep;
446 u32 atim_window;
447 u16 antenna_switch_swap;
448 enum ath9k_ant_setting diversity_control;
449
450 /* Calibration */
451 enum hal_cal_types supp_cals;
452 struct hal_cal_list iq_caldata;
453 struct hal_cal_list adcgain_caldata;
454 struct hal_cal_list adcdc_calinitdata;
455 struct hal_cal_list adcdc_caldata;
456 struct hal_cal_list *cal_list;
457 struct hal_cal_list *cal_list_last;
458 struct hal_cal_list *cal_list_curr;
459#define totalPowerMeasI meas0.unsign
460#define totalPowerMeasQ meas1.unsign
461#define totalIqCorrMeas meas2.sign
462#define totalAdcIOddPhase meas0.unsign
463#define totalAdcIEvenPhase meas1.unsign
464#define totalAdcQOddPhase meas2.unsign
465#define totalAdcQEvenPhase meas3.unsign
466#define totalAdcDcOffsetIOddPhase meas0.sign
467#define totalAdcDcOffsetIEvenPhase meas1.sign
468#define totalAdcDcOffsetQOddPhase meas2.sign
469#define totalAdcDcOffsetQEvenPhase meas3.sign
470 union {
471 u32 unsign[AR5416_MAX_CHAINS];
472 int32_t sign[AR5416_MAX_CHAINS];
473 } meas0;
474 union {
475 u32 unsign[AR5416_MAX_CHAINS];
476 int32_t sign[AR5416_MAX_CHAINS];
477 } meas1;
478 union {
479 u32 unsign[AR5416_MAX_CHAINS];
480 int32_t sign[AR5416_MAX_CHAINS];
481 } meas2;
482 union {
483 u32 unsign[AR5416_MAX_CHAINS];
484 int32_t sign[AR5416_MAX_CHAINS];
485 } meas3;
486 u16 cal_samples;
487
488 u32 sta_id1_defaults;
489 u32 misc_mode;
490 enum {
491 AUTO_32KHZ,
492 USE_32KHZ,
493 DONT_USE_32KHZ,
494 } enable_32kHz_clock;
495
496 /* RF */
497 u32 *analogBank0Data;
498 u32 *analogBank1Data;
499 u32 *analogBank2Data;
500 u32 *analogBank3Data;
501 u32 *analogBank6Data;
502 u32 *analogBank6TPCData;
503 u32 *analogBank7Data;
504 u32 *addac5416_21;
505 u32 *bank6Temp;
506
507 int16_t txpower_indexoffset;
508 u32 beacon_interval;
509 u32 slottime;
510 u32 acktimeout;
511 u32 ctstimeout;
512 u32 globaltxtimeout;
513 u8 gbeacon_rate;
514
515 /* ANI */
516 u32 proc_phyerr;
517 bool has_hw_phycounters;
518 u32 aniperiod;
519 struct ar5416AniState *curani;
520 struct ar5416AniState ani[255];
521 int totalSizeDesired[5];
522 int coarse_high[5];
523 int coarse_low[5];
524 int firpwr[5];
525 enum ath9k_ani_cmd ani_function;
526
527 u32 intr_txqs;
528 enum ath9k_ht_extprotspacing extprotspacing;
529 u8 txchainmask;
530 u8 rxchainmask;
531
532 u32 originalGain[22];
533 int initPDADC;
534 int PDADCdelta;
535
536 struct ar5416IniArray iniModes;
537 struct ar5416IniArray iniCommon;
538 struct ar5416IniArray iniBank0;
539 struct ar5416IniArray iniBB_RfGain;
540 struct ar5416IniArray iniBank1;
541 struct ar5416IniArray iniBank2;
542 struct ar5416IniArray iniBank3;
543 struct ar5416IniArray iniBank6;
544 struct ar5416IniArray iniBank6TPC;
545 struct ar5416IniArray iniBank7;
546 struct ar5416IniArray iniAddac;
547 struct ar5416IniArray iniPcieSerdes;
548 struct ar5416IniArray iniModesAdditional;
549 struct ar5416IniArray iniModesRxGain;
550 struct ar5416IniArray iniModesTxGain;
551};
552
553/* Attach, Detach, Reset */
554const char *ath9k_hw_probe(u16 vendorid, u16 devid);
555void ath9k_hw_detach(struct ath_hw *ah);
556struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error);
557void ath9k_hw_rfdetach(struct ath_hw *ah);
558int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
559 bool bChannelChange);
560void ath9k_hw_fill_cap_info(struct ath_hw *ah);
561bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
562 u32 capability, u32 *result);
563bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,
564 u32 capability, u32 setting, int *status);
565
566/* Key Cache Management */
567bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry);
568bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac);
569bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
570 const struct ath9k_keyval *k,
571 const u8 *mac);
572bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry);
573
574/* GPIO / RFKILL / Antennae */
575void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio);
576u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio);
577void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
578 u32 ah_signal_type);
579void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
580#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
581void ath9k_enable_rfkill(struct ath_hw *ah);
582#endif
583u32 ath9k_hw_getdefantenna(struct ath_hw *ah);
584void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
585bool ath9k_hw_setantennaswitch(struct ath_hw *ah,
586 enum ath9k_ant_setting settings,
587 struct ath9k_channel *chan,
588 u8 *tx_chainmask, u8 *rx_chainmask,
589 u8 *antenna_cfgd);
590
591/* General Operation */
592bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
593u32 ath9k_hw_reverse_bits(u32 val, u32 n);
594bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high);
595u16 ath9k_hw_computetxtime(struct ath_hw *ah, struct ath_rate_table *rates,
596 u32 frameLen, u16 rateix, bool shortPreamble);
597void ath9k_hw_get_channel_centers(struct ath_hw *ah,
598 struct ath9k_channel *chan,
599 struct chan_centers *centers);
600u32 ath9k_hw_getrxfilter(struct ath_hw *ah);
601void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
602bool ath9k_hw_phy_disable(struct ath_hw *ah);
603bool ath9k_hw_disable(struct ath_hw *ah);
604bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit);
605void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac);
606void ath9k_hw_setopmode(struct ath_hw *ah);
607void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
608void ath9k_hw_setbssidmask(struct ath_softc *sc);
609void ath9k_hw_write_associd(struct ath_softc *sc);
610u64 ath9k_hw_gettsf64(struct ath_hw *ah);
611void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
612void ath9k_hw_reset_tsf(struct ath_hw *ah);
613bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
614bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us);
615void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode);
616void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
617void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
618 const struct ath9k_beacon_state *bs);
619bool ath9k_hw_setpower(struct ath_hw *ah,
620 enum ath9k_power_mode mode);
621void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore);
622
623/* Interrupt Handling */
624bool ath9k_hw_intrpend(struct ath_hw *ah);
625bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked);
626enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah);
627enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
628
629void ath9k_hw_btcoex_enable(struct ath_hw *ah);
630
631#endif
diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h
new file mode 100644
index 000000000000..e2f0a34b79a1
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/initvals.h
@@ -0,0 +1,4848 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17static const u32 ar5416Modes[][6] = {
18 { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
19 { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
20 { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
21 { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
22 { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
23 { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
24 { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
25 { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
26 { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
27 { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
28 { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
29 { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
30 { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 },
31 { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
32 { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
33 { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
34 { 0x00009850, 0x6c48b4e0, 0x6c48b4e0, 0x6c48b0de, 0x6c48b0de, 0x6c48b0de },
35 { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
36 { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e },
37 { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 },
38 { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
39 { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 },
40 { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
41 { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
42 { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 },
43 { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b },
44 { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 },
45 { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
46 { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
47 { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
48 { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 },
49 { 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 },
50 { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
51 { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
52 { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c },
53 { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
54 { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
55 { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
56 { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
57 { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 },
58 { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
59 { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
60 { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
61 { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
62 { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
63 { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
64 { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
65 { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
66 { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
67 { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
68 { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
69 { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
70 { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
71 { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
72 { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
73 { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
74 { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
75 { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
76 { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
77 { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
78 { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
79};
80
81static const u32 ar5416Common[][2] = {
82 { 0x0000000c, 0x00000000 },
83 { 0x00000030, 0x00020015 },
84 { 0x00000034, 0x00000005 },
85 { 0x00000040, 0x00000000 },
86 { 0x00000044, 0x00000008 },
87 { 0x00000048, 0x00000008 },
88 { 0x0000004c, 0x00000010 },
89 { 0x00000050, 0x00000000 },
90 { 0x00000054, 0x0000001f },
91 { 0x00000800, 0x00000000 },
92 { 0x00000804, 0x00000000 },
93 { 0x00000808, 0x00000000 },
94 { 0x0000080c, 0x00000000 },
95 { 0x00000810, 0x00000000 },
96 { 0x00000814, 0x00000000 },
97 { 0x00000818, 0x00000000 },
98 { 0x0000081c, 0x00000000 },
99 { 0x00000820, 0x00000000 },
100 { 0x00000824, 0x00000000 },
101 { 0x00001040, 0x002ffc0f },
102 { 0x00001044, 0x002ffc0f },
103 { 0x00001048, 0x002ffc0f },
104 { 0x0000104c, 0x002ffc0f },
105 { 0x00001050, 0x002ffc0f },
106 { 0x00001054, 0x002ffc0f },
107 { 0x00001058, 0x002ffc0f },
108 { 0x0000105c, 0x002ffc0f },
109 { 0x00001060, 0x002ffc0f },
110 { 0x00001064, 0x002ffc0f },
111 { 0x00001230, 0x00000000 },
112 { 0x00001270, 0x00000000 },
113 { 0x00001038, 0x00000000 },
114 { 0x00001078, 0x00000000 },
115 { 0x000010b8, 0x00000000 },
116 { 0x000010f8, 0x00000000 },
117 { 0x00001138, 0x00000000 },
118 { 0x00001178, 0x00000000 },
119 { 0x000011b8, 0x00000000 },
120 { 0x000011f8, 0x00000000 },
121 { 0x00001238, 0x00000000 },
122 { 0x00001278, 0x00000000 },
123 { 0x000012b8, 0x00000000 },
124 { 0x000012f8, 0x00000000 },
125 { 0x00001338, 0x00000000 },
126 { 0x00001378, 0x00000000 },
127 { 0x000013b8, 0x00000000 },
128 { 0x000013f8, 0x00000000 },
129 { 0x00001438, 0x00000000 },
130 { 0x00001478, 0x00000000 },
131 { 0x000014b8, 0x00000000 },
132 { 0x000014f8, 0x00000000 },
133 { 0x00001538, 0x00000000 },
134 { 0x00001578, 0x00000000 },
135 { 0x000015b8, 0x00000000 },
136 { 0x000015f8, 0x00000000 },
137 { 0x00001638, 0x00000000 },
138 { 0x00001678, 0x00000000 },
139 { 0x000016b8, 0x00000000 },
140 { 0x000016f8, 0x00000000 },
141 { 0x00001738, 0x00000000 },
142 { 0x00001778, 0x00000000 },
143 { 0x000017b8, 0x00000000 },
144 { 0x000017f8, 0x00000000 },
145 { 0x0000103c, 0x00000000 },
146 { 0x0000107c, 0x00000000 },
147 { 0x000010bc, 0x00000000 },
148 { 0x000010fc, 0x00000000 },
149 { 0x0000113c, 0x00000000 },
150 { 0x0000117c, 0x00000000 },
151 { 0x000011bc, 0x00000000 },
152 { 0x000011fc, 0x00000000 },
153 { 0x0000123c, 0x00000000 },
154 { 0x0000127c, 0x00000000 },
155 { 0x000012bc, 0x00000000 },
156 { 0x000012fc, 0x00000000 },
157 { 0x0000133c, 0x00000000 },
158 { 0x0000137c, 0x00000000 },
159 { 0x000013bc, 0x00000000 },
160 { 0x000013fc, 0x00000000 },
161 { 0x0000143c, 0x00000000 },
162 { 0x0000147c, 0x00000000 },
163 { 0x00004030, 0x00000002 },
164 { 0x0000403c, 0x00000002 },
165 { 0x00007010, 0x00000000 },
166 { 0x00007038, 0x000004c2 },
167 { 0x00008004, 0x00000000 },
168 { 0x00008008, 0x00000000 },
169 { 0x0000800c, 0x00000000 },
170 { 0x00008018, 0x00000700 },
171 { 0x00008020, 0x00000000 },
172 { 0x00008038, 0x00000000 },
173 { 0x0000803c, 0x00000000 },
174 { 0x00008048, 0x40000000 },
175 { 0x00008054, 0x00000000 },
176 { 0x00008058, 0x00000000 },
177 { 0x0000805c, 0x000fc78f },
178 { 0x00008060, 0x0000000f },
179 { 0x00008064, 0x00000000 },
180 { 0x000080c0, 0x2a82301a },
181 { 0x000080c4, 0x05dc01e0 },
182 { 0x000080c8, 0x1f402710 },
183 { 0x000080cc, 0x01f40000 },
184 { 0x000080d0, 0x00001e00 },
185 { 0x000080d4, 0x00000000 },
186 { 0x000080d8, 0x00400000 },
187 { 0x000080e0, 0xffffffff },
188 { 0x000080e4, 0x0000ffff },
189 { 0x000080e8, 0x003f3f3f },
190 { 0x000080ec, 0x00000000 },
191 { 0x000080f0, 0x00000000 },
192 { 0x000080f4, 0x00000000 },
193 { 0x000080f8, 0x00000000 },
194 { 0x000080fc, 0x00020000 },
195 { 0x00008100, 0x00020000 },
196 { 0x00008104, 0x00000001 },
197 { 0x00008108, 0x00000052 },
198 { 0x0000810c, 0x00000000 },
199 { 0x00008110, 0x00000168 },
200 { 0x00008118, 0x000100aa },
201 { 0x0000811c, 0x00003210 },
202 { 0x00008120, 0x08f04800 },
203 { 0x00008124, 0x00000000 },
204 { 0x00008128, 0x00000000 },
205 { 0x0000812c, 0x00000000 },
206 { 0x00008130, 0x00000000 },
207 { 0x00008134, 0x00000000 },
208 { 0x00008138, 0x00000000 },
209 { 0x0000813c, 0x00000000 },
210 { 0x00008144, 0xffffffff },
211 { 0x00008168, 0x00000000 },
212 { 0x0000816c, 0x00000000 },
213 { 0x00008170, 0x32143320 },
214 { 0x00008174, 0xfaa4fa50 },
215 { 0x00008178, 0x00000100 },
216 { 0x0000817c, 0x00000000 },
217 { 0x000081c4, 0x00000000 },
218 { 0x000081d0, 0x00003210 },
219 { 0x000081ec, 0x00000000 },
220 { 0x000081f0, 0x00000000 },
221 { 0x000081f4, 0x00000000 },
222 { 0x000081f8, 0x00000000 },
223 { 0x000081fc, 0x00000000 },
224 { 0x00008200, 0x00000000 },
225 { 0x00008204, 0x00000000 },
226 { 0x00008208, 0x00000000 },
227 { 0x0000820c, 0x00000000 },
228 { 0x00008210, 0x00000000 },
229 { 0x00008214, 0x00000000 },
230 { 0x00008218, 0x00000000 },
231 { 0x0000821c, 0x00000000 },
232 { 0x00008220, 0x00000000 },
233 { 0x00008224, 0x00000000 },
234 { 0x00008228, 0x00000000 },
235 { 0x0000822c, 0x00000000 },
236 { 0x00008230, 0x00000000 },
237 { 0x00008234, 0x00000000 },
238 { 0x00008238, 0x00000000 },
239 { 0x0000823c, 0x00000000 },
240 { 0x00008240, 0x00100000 },
241 { 0x00008244, 0x0010f400 },
242 { 0x00008248, 0x00000100 },
243 { 0x0000824c, 0x0001e800 },
244 { 0x00008250, 0x00000000 },
245 { 0x00008254, 0x00000000 },
246 { 0x00008258, 0x00000000 },
247 { 0x0000825c, 0x400000ff },
248 { 0x00008260, 0x00080922 },
249 { 0x00008270, 0x00000000 },
250 { 0x00008274, 0x40000000 },
251 { 0x00008278, 0x003e4180 },
252 { 0x0000827c, 0x00000000 },
253 { 0x00008284, 0x0000002c },
254 { 0x00008288, 0x0000002c },
255 { 0x0000828c, 0x00000000 },
256 { 0x00008294, 0x00000000 },
257 { 0x00008298, 0x00000000 },
258 { 0x00008300, 0x00000000 },
259 { 0x00008304, 0x00000000 },
260 { 0x00008308, 0x00000000 },
261 { 0x0000830c, 0x00000000 },
262 { 0x00008310, 0x00000000 },
263 { 0x00008314, 0x00000000 },
264 { 0x00008318, 0x00000000 },
265 { 0x00008328, 0x00000000 },
266 { 0x0000832c, 0x00000007 },
267 { 0x00008330, 0x00000302 },
268 { 0x00008334, 0x00000e00 },
269 { 0x00008338, 0x00070000 },
270 { 0x0000833c, 0x00000000 },
271 { 0x00008340, 0x000107ff },
272 { 0x00009808, 0x00000000 },
273 { 0x0000980c, 0xad848e19 },
274 { 0x00009810, 0x7d14e000 },
275 { 0x00009814, 0x9c0a9f6b },
276 { 0x0000981c, 0x00000000 },
277 { 0x0000982c, 0x0000a000 },
278 { 0x00009830, 0x00000000 },
279 { 0x0000983c, 0x00200400 },
280 { 0x00009840, 0x206a002e },
281 { 0x0000984c, 0x1284233c },
282 { 0x00009854, 0x00000859 },
283 { 0x00009900, 0x00000000 },
284 { 0x00009904, 0x00000000 },
285 { 0x00009908, 0x00000000 },
286 { 0x0000990c, 0x00000000 },
287 { 0x0000991c, 0x10000fff },
288 { 0x00009920, 0x05100000 },
289 { 0x0000a920, 0x05100000 },
290 { 0x0000b920, 0x05100000 },
291 { 0x00009928, 0x00000001 },
292 { 0x0000992c, 0x00000004 },
293 { 0x00009934, 0x1e1f2022 },
294 { 0x00009938, 0x0a0b0c0d },
295 { 0x0000993c, 0x00000000 },
296 { 0x00009948, 0x9280b212 },
297 { 0x0000994c, 0x00020028 },
298 { 0x00009954, 0x5d50e188 },
299 { 0x00009958, 0x00081fff },
300 { 0x0000c95c, 0x004b6a8e },
301 { 0x0000c968, 0x000003ce },
302 { 0x00009970, 0x190fb515 },
303 { 0x00009974, 0x00000000 },
304 { 0x00009978, 0x00000001 },
305 { 0x0000997c, 0x00000000 },
306 { 0x00009980, 0x00000000 },
307 { 0x00009984, 0x00000000 },
308 { 0x00009988, 0x00000000 },
309 { 0x0000998c, 0x00000000 },
310 { 0x00009990, 0x00000000 },
311 { 0x00009994, 0x00000000 },
312 { 0x00009998, 0x00000000 },
313 { 0x0000999c, 0x00000000 },
314 { 0x000099a0, 0x00000000 },
315 { 0x000099a4, 0x00000001 },
316 { 0x000099a8, 0x001fff00 },
317 { 0x000099ac, 0x00000000 },
318 { 0x000099b0, 0x03051000 },
319 { 0x000099dc, 0x00000000 },
320 { 0x000099e0, 0x00000200 },
321 { 0x000099e4, 0xaaaaaaaa },
322 { 0x000099e8, 0x3c466478 },
323 { 0x000099ec, 0x000000aa },
324 { 0x000099fc, 0x00001042 },
325 { 0x00009b00, 0x00000000 },
326 { 0x00009b04, 0x00000001 },
327 { 0x00009b08, 0x00000002 },
328 { 0x00009b0c, 0x00000003 },
329 { 0x00009b10, 0x00000004 },
330 { 0x00009b14, 0x00000005 },
331 { 0x00009b18, 0x00000008 },
332 { 0x00009b1c, 0x00000009 },
333 { 0x00009b20, 0x0000000a },
334 { 0x00009b24, 0x0000000b },
335 { 0x00009b28, 0x0000000c },
336 { 0x00009b2c, 0x0000000d },
337 { 0x00009b30, 0x00000010 },
338 { 0x00009b34, 0x00000011 },
339 { 0x00009b38, 0x00000012 },
340 { 0x00009b3c, 0x00000013 },
341 { 0x00009b40, 0x00000014 },
342 { 0x00009b44, 0x00000015 },
343 { 0x00009b48, 0x00000018 },
344 { 0x00009b4c, 0x00000019 },
345 { 0x00009b50, 0x0000001a },
346 { 0x00009b54, 0x0000001b },
347 { 0x00009b58, 0x0000001c },
348 { 0x00009b5c, 0x0000001d },
349 { 0x00009b60, 0x00000020 },
350 { 0x00009b64, 0x00000021 },
351 { 0x00009b68, 0x00000022 },
352 { 0x00009b6c, 0x00000023 },
353 { 0x00009b70, 0x00000024 },
354 { 0x00009b74, 0x00000025 },
355 { 0x00009b78, 0x00000028 },
356 { 0x00009b7c, 0x00000029 },
357 { 0x00009b80, 0x0000002a },
358 { 0x00009b84, 0x0000002b },
359 { 0x00009b88, 0x0000002c },
360 { 0x00009b8c, 0x0000002d },
361 { 0x00009b90, 0x00000030 },
362 { 0x00009b94, 0x00000031 },
363 { 0x00009b98, 0x00000032 },
364 { 0x00009b9c, 0x00000033 },
365 { 0x00009ba0, 0x00000034 },
366 { 0x00009ba4, 0x00000035 },
367 { 0x00009ba8, 0x00000035 },
368 { 0x00009bac, 0x00000035 },
369 { 0x00009bb0, 0x00000035 },
370 { 0x00009bb4, 0x00000035 },
371 { 0x00009bb8, 0x00000035 },
372 { 0x00009bbc, 0x00000035 },
373 { 0x00009bc0, 0x00000035 },
374 { 0x00009bc4, 0x00000035 },
375 { 0x00009bc8, 0x00000035 },
376 { 0x00009bcc, 0x00000035 },
377 { 0x00009bd0, 0x00000035 },
378 { 0x00009bd4, 0x00000035 },
379 { 0x00009bd8, 0x00000035 },
380 { 0x00009bdc, 0x00000035 },
381 { 0x00009be0, 0x00000035 },
382 { 0x00009be4, 0x00000035 },
383 { 0x00009be8, 0x00000035 },
384 { 0x00009bec, 0x00000035 },
385 { 0x00009bf0, 0x00000035 },
386 { 0x00009bf4, 0x00000035 },
387 { 0x00009bf8, 0x00000010 },
388 { 0x00009bfc, 0x0000001a },
389 { 0x0000a210, 0x40806333 },
390 { 0x0000a214, 0x00106c10 },
391 { 0x0000a218, 0x009c4060 },
392 { 0x0000a220, 0x018830c6 },
393 { 0x0000a224, 0x00000400 },
394 { 0x0000a228, 0x00000bb5 },
395 { 0x0000a22c, 0x00000011 },
396 { 0x0000a234, 0x20202020 },
397 { 0x0000a238, 0x20202020 },
398 { 0x0000a23c, 0x13c889af },
399 { 0x0000a240, 0x38490a20 },
400 { 0x0000a244, 0x00007bb6 },
401 { 0x0000a248, 0x0fff3ffc },
402 { 0x0000a24c, 0x00000001 },
403 { 0x0000a250, 0x0000a000 },
404 { 0x0000a254, 0x00000000 },
405 { 0x0000a258, 0x0cc75380 },
406 { 0x0000a25c, 0x0f0f0f01 },
407 { 0x0000a260, 0xdfa91f01 },
408 { 0x0000a268, 0x00000000 },
409 { 0x0000a26c, 0x0ebae9c6 },
410 { 0x0000b26c, 0x0ebae9c6 },
411 { 0x0000c26c, 0x0ebae9c6 },
412 { 0x0000d270, 0x00820820 },
413 { 0x0000a278, 0x1ce739ce },
414 { 0x0000a27c, 0x051701ce },
415 { 0x0000a338, 0x00000000 },
416 { 0x0000a33c, 0x00000000 },
417 { 0x0000a340, 0x00000000 },
418 { 0x0000a344, 0x00000000 },
419 { 0x0000a348, 0x3fffffff },
420 { 0x0000a34c, 0x3fffffff },
421 { 0x0000a350, 0x3fffffff },
422 { 0x0000a354, 0x0003ffff },
423 { 0x0000a358, 0x79a8aa1f },
424 { 0x0000d35c, 0x07ffffef },
425 { 0x0000d360, 0x0fffffe7 },
426 { 0x0000d364, 0x17ffffe5 },
427 { 0x0000d368, 0x1fffffe4 },
428 { 0x0000d36c, 0x37ffffe3 },
429 { 0x0000d370, 0x3fffffe3 },
430 { 0x0000d374, 0x57ffffe3 },
431 { 0x0000d378, 0x5fffffe2 },
432 { 0x0000d37c, 0x7fffffe2 },
433 { 0x0000d380, 0x7f3c7bba },
434 { 0x0000d384, 0xf3307ff0 },
435 { 0x0000a388, 0x08000000 },
436 { 0x0000a38c, 0x20202020 },
437 { 0x0000a390, 0x20202020 },
438 { 0x0000a394, 0x1ce739ce },
439 { 0x0000a398, 0x000001ce },
440 { 0x0000a39c, 0x00000001 },
441 { 0x0000a3a0, 0x00000000 },
442 { 0x0000a3a4, 0x00000000 },
443 { 0x0000a3a8, 0x00000000 },
444 { 0x0000a3ac, 0x00000000 },
445 { 0x0000a3b0, 0x00000000 },
446 { 0x0000a3b4, 0x00000000 },
447 { 0x0000a3b8, 0x00000000 },
448 { 0x0000a3bc, 0x00000000 },
449 { 0x0000a3c0, 0x00000000 },
450 { 0x0000a3c4, 0x00000000 },
451 { 0x0000a3c8, 0x00000246 },
452 { 0x0000a3cc, 0x20202020 },
453 { 0x0000a3d0, 0x20202020 },
454 { 0x0000a3d4, 0x20202020 },
455 { 0x0000a3dc, 0x1ce739ce },
456 { 0x0000a3e0, 0x000001ce },
457};
458
459static const u32 ar5416Bank0[][2] = {
460 { 0x000098b0, 0x1e5795e5 },
461 { 0x000098e0, 0x02008020 },
462};
463
464static const u32 ar5416BB_RfGain[][3] = {
465 { 0x00009a00, 0x00000000, 0x00000000 },
466 { 0x00009a04, 0x00000040, 0x00000040 },
467 { 0x00009a08, 0x00000080, 0x00000080 },
468 { 0x00009a0c, 0x000001a1, 0x00000141 },
469 { 0x00009a10, 0x000001e1, 0x00000181 },
470 { 0x00009a14, 0x00000021, 0x000001c1 },
471 { 0x00009a18, 0x00000061, 0x00000001 },
472 { 0x00009a1c, 0x00000168, 0x00000041 },
473 { 0x00009a20, 0x000001a8, 0x000001a8 },
474 { 0x00009a24, 0x000001e8, 0x000001e8 },
475 { 0x00009a28, 0x00000028, 0x00000028 },
476 { 0x00009a2c, 0x00000068, 0x00000068 },
477 { 0x00009a30, 0x00000189, 0x000000a8 },
478 { 0x00009a34, 0x000001c9, 0x00000169 },
479 { 0x00009a38, 0x00000009, 0x000001a9 },
480 { 0x00009a3c, 0x00000049, 0x000001e9 },
481 { 0x00009a40, 0x00000089, 0x00000029 },
482 { 0x00009a44, 0x00000170, 0x00000069 },
483 { 0x00009a48, 0x000001b0, 0x00000190 },
484 { 0x00009a4c, 0x000001f0, 0x000001d0 },
485 { 0x00009a50, 0x00000030, 0x00000010 },
486 { 0x00009a54, 0x00000070, 0x00000050 },
487 { 0x00009a58, 0x00000191, 0x00000090 },
488 { 0x00009a5c, 0x000001d1, 0x00000151 },
489 { 0x00009a60, 0x00000011, 0x00000191 },
490 { 0x00009a64, 0x00000051, 0x000001d1 },
491 { 0x00009a68, 0x00000091, 0x00000011 },
492 { 0x00009a6c, 0x000001b8, 0x00000051 },
493 { 0x00009a70, 0x000001f8, 0x00000198 },
494 { 0x00009a74, 0x00000038, 0x000001d8 },
495 { 0x00009a78, 0x00000078, 0x00000018 },
496 { 0x00009a7c, 0x00000199, 0x00000058 },
497 { 0x00009a80, 0x000001d9, 0x00000098 },
498 { 0x00009a84, 0x00000019, 0x00000159 },
499 { 0x00009a88, 0x00000059, 0x00000199 },
500 { 0x00009a8c, 0x00000099, 0x000001d9 },
501 { 0x00009a90, 0x000000d9, 0x00000019 },
502 { 0x00009a94, 0x000000f9, 0x00000059 },
503 { 0x00009a98, 0x000000f9, 0x00000099 },
504 { 0x00009a9c, 0x000000f9, 0x000000d9 },
505 { 0x00009aa0, 0x000000f9, 0x000000f9 },
506 { 0x00009aa4, 0x000000f9, 0x000000f9 },
507 { 0x00009aa8, 0x000000f9, 0x000000f9 },
508 { 0x00009aac, 0x000000f9, 0x000000f9 },
509 { 0x00009ab0, 0x000000f9, 0x000000f9 },
510 { 0x00009ab4, 0x000000f9, 0x000000f9 },
511 { 0x00009ab8, 0x000000f9, 0x000000f9 },
512 { 0x00009abc, 0x000000f9, 0x000000f9 },
513 { 0x00009ac0, 0x000000f9, 0x000000f9 },
514 { 0x00009ac4, 0x000000f9, 0x000000f9 },
515 { 0x00009ac8, 0x000000f9, 0x000000f9 },
516 { 0x00009acc, 0x000000f9, 0x000000f9 },
517 { 0x00009ad0, 0x000000f9, 0x000000f9 },
518 { 0x00009ad4, 0x000000f9, 0x000000f9 },
519 { 0x00009ad8, 0x000000f9, 0x000000f9 },
520 { 0x00009adc, 0x000000f9, 0x000000f9 },
521 { 0x00009ae0, 0x000000f9, 0x000000f9 },
522 { 0x00009ae4, 0x000000f9, 0x000000f9 },
523 { 0x00009ae8, 0x000000f9, 0x000000f9 },
524 { 0x00009aec, 0x000000f9, 0x000000f9 },
525 { 0x00009af0, 0x000000f9, 0x000000f9 },
526 { 0x00009af4, 0x000000f9, 0x000000f9 },
527 { 0x00009af8, 0x000000f9, 0x000000f9 },
528 { 0x00009afc, 0x000000f9, 0x000000f9 },
529};
530
531static const u32 ar5416Bank1[][2] = {
532 { 0x000098b0, 0x02108421 },
533 { 0x000098ec, 0x00000008 },
534};
535
536static const u32 ar5416Bank2[][2] = {
537 { 0x000098b0, 0x0e73ff17 },
538 { 0x000098e0, 0x00000420 },
539};
540
541static const u32 ar5416Bank3[][3] = {
542 { 0x000098f0, 0x01400018, 0x01c00018 },
543};
544
545static const u32 ar5416Bank6[][3] = {
546
547 { 0x0000989c, 0x00000000, 0x00000000 },
548 { 0x0000989c, 0x00000000, 0x00000000 },
549 { 0x0000989c, 0x00000000, 0x00000000 },
550 { 0x0000989c, 0x00e00000, 0x00e00000 },
551 { 0x0000989c, 0x005e0000, 0x005e0000 },
552 { 0x0000989c, 0x00120000, 0x00120000 },
553 { 0x0000989c, 0x00620000, 0x00620000 },
554 { 0x0000989c, 0x00020000, 0x00020000 },
555 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
556 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
557 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
558 { 0x0000989c, 0x40ff0000, 0x40ff0000 },
559 { 0x0000989c, 0x005f0000, 0x005f0000 },
560 { 0x0000989c, 0x00870000, 0x00870000 },
561 { 0x0000989c, 0x00f90000, 0x00f90000 },
562 { 0x0000989c, 0x007b0000, 0x007b0000 },
563 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
564 { 0x0000989c, 0x00f50000, 0x00f50000 },
565 { 0x0000989c, 0x00dc0000, 0x00dc0000 },
566 { 0x0000989c, 0x00110000, 0x00110000 },
567 { 0x0000989c, 0x006100a8, 0x006100a8 },
568 { 0x0000989c, 0x004210a2, 0x004210a2 },
569 { 0x0000989c, 0x0014008f, 0x0014008f },
570 { 0x0000989c, 0x00c40003, 0x00c40003 },
571 { 0x0000989c, 0x003000f2, 0x003000f2 },
572 { 0x0000989c, 0x00440016, 0x00440016 },
573 { 0x0000989c, 0x00410040, 0x00410040 },
574 { 0x0000989c, 0x0001805e, 0x0001805e },
575 { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
576 { 0x0000989c, 0x000000f1, 0x000000f1 },
577 { 0x0000989c, 0x00002081, 0x00002081 },
578 { 0x0000989c, 0x000000d4, 0x000000d4 },
579 { 0x000098d0, 0x0000000f, 0x0010000f },
580};
581
582static const u32 ar5416Bank6TPC[][3] = {
583 { 0x0000989c, 0x00000000, 0x00000000 },
584 { 0x0000989c, 0x00000000, 0x00000000 },
585 { 0x0000989c, 0x00000000, 0x00000000 },
586 { 0x0000989c, 0x00e00000, 0x00e00000 },
587 { 0x0000989c, 0x005e0000, 0x005e0000 },
588 { 0x0000989c, 0x00120000, 0x00120000 },
589 { 0x0000989c, 0x00620000, 0x00620000 },
590 { 0x0000989c, 0x00020000, 0x00020000 },
591 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
592 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
593 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
594 { 0x0000989c, 0x40ff0000, 0x40ff0000 },
595 { 0x0000989c, 0x005f0000, 0x005f0000 },
596 { 0x0000989c, 0x00870000, 0x00870000 },
597 { 0x0000989c, 0x00f90000, 0x00f90000 },
598 { 0x0000989c, 0x007b0000, 0x007b0000 },
599 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
600 { 0x0000989c, 0x00f50000, 0x00f50000 },
601 { 0x0000989c, 0x00dc0000, 0x00dc0000 },
602 { 0x0000989c, 0x00110000, 0x00110000 },
603 { 0x0000989c, 0x006100a8, 0x006100a8 },
604 { 0x0000989c, 0x00423022, 0x00423022 },
605 { 0x0000989c, 0x201400df, 0x201400df },
606 { 0x0000989c, 0x00c40002, 0x00c40002 },
607 { 0x0000989c, 0x003000f2, 0x003000f2 },
608 { 0x0000989c, 0x00440016, 0x00440016 },
609 { 0x0000989c, 0x00410040, 0x00410040 },
610 { 0x0000989c, 0x0001805e, 0x0001805e },
611 { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
612 { 0x0000989c, 0x000000e1, 0x000000e1 },
613 { 0x0000989c, 0x00007081, 0x00007081 },
614 { 0x0000989c, 0x000000d4, 0x000000d4 },
615 { 0x000098d0, 0x0000000f, 0x0010000f },
616};
617
618static const u32 ar5416Bank7[][2] = {
619 { 0x0000989c, 0x00000500 },
620 { 0x0000989c, 0x00000800 },
621 { 0x000098cc, 0x0000000e },
622};
623
624static const u32 ar5416Addac[][2] = {
625 {0x0000989c, 0x00000000 },
626 {0x0000989c, 0x00000003 },
627 {0x0000989c, 0x00000000 },
628 {0x0000989c, 0x0000000c },
629 {0x0000989c, 0x00000000 },
630 {0x0000989c, 0x00000030 },
631 {0x0000989c, 0x00000000 },
632 {0x0000989c, 0x00000000 },
633 {0x0000989c, 0x00000000 },
634 {0x0000989c, 0x00000000 },
635 {0x0000989c, 0x00000000 },
636 {0x0000989c, 0x00000000 },
637 {0x0000989c, 0x00000000 },
638 {0x0000989c, 0x00000000 },
639 {0x0000989c, 0x00000000 },
640 {0x0000989c, 0x00000000 },
641 {0x0000989c, 0x00000000 },
642 {0x0000989c, 0x00000000 },
643 {0x0000989c, 0x00000060 },
644 {0x0000989c, 0x00000000 },
645 {0x0000989c, 0x00000000 },
646 {0x0000989c, 0x00000000 },
647 {0x0000989c, 0x00000000 },
648 {0x0000989c, 0x00000000 },
649 {0x0000989c, 0x00000000 },
650 {0x0000989c, 0x00000000 },
651 {0x0000989c, 0x00000000 },
652 {0x0000989c, 0x00000000 },
653 {0x0000989c, 0x00000000 },
654 {0x0000989c, 0x00000000 },
655 {0x0000989c, 0x00000000 },
656 {0x0000989c, 0x00000058 },
657 {0x0000989c, 0x00000000 },
658 {0x0000989c, 0x00000000 },
659 {0x0000989c, 0x00000000 },
660 {0x0000989c, 0x00000000 },
661 {0x000098cc, 0x00000000 },
662};
663
664static const u32 ar5416Modes_9100[][6] = {
665 { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
666 { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
667 { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
668 { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
669 { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
670 { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
671 { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
672 { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
673 { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
674 { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
675 { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
676 { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
677 { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
678 { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
679 { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
680 { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
681 { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 },
682 { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec86d2e, 0x7ec84d2e, 0x7ec82d2e },
683 { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
684 { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
685 { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
686 { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 },
687 { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
688 { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
689 { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
690 { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a11, 0xd00a8a0d, 0xd00a8a0d },
691 { 0x00009940, 0x00754604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204 },
692 { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 },
693 { 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e },
694 { 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff },
695#ifdef TB243
696 { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
697 { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
698 { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
699 { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 },
700#else
701 { 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 },
702 { 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 },
703 { 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 },
704 { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 },
705#endif
706 { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00 },
707 { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
708 { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
709 { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
710 { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
711 { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
712 { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
713 { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
714 { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 },
715 { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
716 { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
717 { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
718 { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
719 { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
720 { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
721 { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
722 { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
723 { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
724 { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
725 { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
726 { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
727 { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
728 { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
729 { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
730 { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
731 { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
732 { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
733 { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
734 { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
735 { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
736};
737
738static const u32 ar5416Common_9100[][2] = {
739 { 0x0000000c, 0x00000000 },
740 { 0x00000030, 0x00020015 },
741 { 0x00000034, 0x00000005 },
742 { 0x00000040, 0x00000000 },
743 { 0x00000044, 0x00000008 },
744 { 0x00000048, 0x00000008 },
745 { 0x0000004c, 0x00000010 },
746 { 0x00000050, 0x00000000 },
747 { 0x00000054, 0x0000001f },
748 { 0x00000800, 0x00000000 },
749 { 0x00000804, 0x00000000 },
750 { 0x00000808, 0x00000000 },
751 { 0x0000080c, 0x00000000 },
752 { 0x00000810, 0x00000000 },
753 { 0x00000814, 0x00000000 },
754 { 0x00000818, 0x00000000 },
755 { 0x0000081c, 0x00000000 },
756 { 0x00000820, 0x00000000 },
757 { 0x00000824, 0x00000000 },
758 { 0x00001040, 0x002ffc0f },
759 { 0x00001044, 0x002ffc0f },
760 { 0x00001048, 0x002ffc0f },
761 { 0x0000104c, 0x002ffc0f },
762 { 0x00001050, 0x002ffc0f },
763 { 0x00001054, 0x002ffc0f },
764 { 0x00001058, 0x002ffc0f },
765 { 0x0000105c, 0x002ffc0f },
766 { 0x00001060, 0x002ffc0f },
767 { 0x00001064, 0x002ffc0f },
768 { 0x00001230, 0x00000000 },
769 { 0x00001270, 0x00000000 },
770 { 0x00001038, 0x00000000 },
771 { 0x00001078, 0x00000000 },
772 { 0x000010b8, 0x00000000 },
773 { 0x000010f8, 0x00000000 },
774 { 0x00001138, 0x00000000 },
775 { 0x00001178, 0x00000000 },
776 { 0x000011b8, 0x00000000 },
777 { 0x000011f8, 0x00000000 },
778 { 0x00001238, 0x00000000 },
779 { 0x00001278, 0x00000000 },
780 { 0x000012b8, 0x00000000 },
781 { 0x000012f8, 0x00000000 },
782 { 0x00001338, 0x00000000 },
783 { 0x00001378, 0x00000000 },
784 { 0x000013b8, 0x00000000 },
785 { 0x000013f8, 0x00000000 },
786 { 0x00001438, 0x00000000 },
787 { 0x00001478, 0x00000000 },
788 { 0x000014b8, 0x00000000 },
789 { 0x000014f8, 0x00000000 },
790 { 0x00001538, 0x00000000 },
791 { 0x00001578, 0x00000000 },
792 { 0x000015b8, 0x00000000 },
793 { 0x000015f8, 0x00000000 },
794 { 0x00001638, 0x00000000 },
795 { 0x00001678, 0x00000000 },
796 { 0x000016b8, 0x00000000 },
797 { 0x000016f8, 0x00000000 },
798 { 0x00001738, 0x00000000 },
799 { 0x00001778, 0x00000000 },
800 { 0x000017b8, 0x00000000 },
801 { 0x000017f8, 0x00000000 },
802 { 0x0000103c, 0x00000000 },
803 { 0x0000107c, 0x00000000 },
804 { 0x000010bc, 0x00000000 },
805 { 0x000010fc, 0x00000000 },
806 { 0x0000113c, 0x00000000 },
807 { 0x0000117c, 0x00000000 },
808 { 0x000011bc, 0x00000000 },
809 { 0x000011fc, 0x00000000 },
810 { 0x0000123c, 0x00000000 },
811 { 0x0000127c, 0x00000000 },
812 { 0x000012bc, 0x00000000 },
813 { 0x000012fc, 0x00000000 },
814 { 0x0000133c, 0x00000000 },
815 { 0x0000137c, 0x00000000 },
816 { 0x000013bc, 0x00000000 },
817 { 0x000013fc, 0x00000000 },
818 { 0x0000143c, 0x00000000 },
819 { 0x0000147c, 0x00000000 },
820 { 0x00020010, 0x00000003 },
821 { 0x00020038, 0x000004c2 },
822 { 0x00008004, 0x00000000 },
823 { 0x00008008, 0x00000000 },
824 { 0x0000800c, 0x00000000 },
825 { 0x00008018, 0x00000700 },
826 { 0x00008020, 0x00000000 },
827 { 0x00008038, 0x00000000 },
828 { 0x0000803c, 0x00000000 },
829 { 0x00008048, 0x40000000 },
830 { 0x00008054, 0x00004000 },
831 { 0x00008058, 0x00000000 },
832 { 0x0000805c, 0x000fc78f },
833 { 0x00008060, 0x0000000f },
834 { 0x00008064, 0x00000000 },
835 { 0x000080c0, 0x2a82301a },
836 { 0x000080c4, 0x05dc01e0 },
837 { 0x000080c8, 0x1f402710 },
838 { 0x000080cc, 0x01f40000 },
839 { 0x000080d0, 0x00001e00 },
840 { 0x000080d4, 0x00000000 },
841 { 0x000080d8, 0x00400000 },
842 { 0x000080e0, 0xffffffff },
843 { 0x000080e4, 0x0000ffff },
844 { 0x000080e8, 0x003f3f3f },
845 { 0x000080ec, 0x00000000 },
846 { 0x000080f0, 0x00000000 },
847 { 0x000080f4, 0x00000000 },
848 { 0x000080f8, 0x00000000 },
849 { 0x000080fc, 0x00020000 },
850 { 0x00008100, 0x00020000 },
851 { 0x00008104, 0x00000001 },
852 { 0x00008108, 0x00000052 },
853 { 0x0000810c, 0x00000000 },
854 { 0x00008110, 0x00000168 },
855 { 0x00008118, 0x000100aa },
856 { 0x0000811c, 0x00003210 },
857 { 0x00008120, 0x08f04800 },
858 { 0x00008124, 0x00000000 },
859 { 0x00008128, 0x00000000 },
860 { 0x0000812c, 0x00000000 },
861 { 0x00008130, 0x00000000 },
862 { 0x00008134, 0x00000000 },
863 { 0x00008138, 0x00000000 },
864 { 0x0000813c, 0x00000000 },
865 { 0x00008144, 0x00000000 },
866 { 0x00008168, 0x00000000 },
867 { 0x0000816c, 0x00000000 },
868 { 0x00008170, 0x32143320 },
869 { 0x00008174, 0xfaa4fa50 },
870 { 0x00008178, 0x00000100 },
871 { 0x0000817c, 0x00000000 },
872 { 0x000081c4, 0x00000000 },
873 { 0x000081d0, 0x00003210 },
874 { 0x000081ec, 0x00000000 },
875 { 0x000081f0, 0x00000000 },
876 { 0x000081f4, 0x00000000 },
877 { 0x000081f8, 0x00000000 },
878 { 0x000081fc, 0x00000000 },
879 { 0x00008200, 0x00000000 },
880 { 0x00008204, 0x00000000 },
881 { 0x00008208, 0x00000000 },
882 { 0x0000820c, 0x00000000 },
883 { 0x00008210, 0x00000000 },
884 { 0x00008214, 0x00000000 },
885 { 0x00008218, 0x00000000 },
886 { 0x0000821c, 0x00000000 },
887 { 0x00008220, 0x00000000 },
888 { 0x00008224, 0x00000000 },
889 { 0x00008228, 0x00000000 },
890 { 0x0000822c, 0x00000000 },
891 { 0x00008230, 0x00000000 },
892 { 0x00008234, 0x00000000 },
893 { 0x00008238, 0x00000000 },
894 { 0x0000823c, 0x00000000 },
895 { 0x00008240, 0x00100000 },
896 { 0x00008244, 0x0010f400 },
897 { 0x00008248, 0x00000100 },
898 { 0x0000824c, 0x0001e800 },
899 { 0x00008250, 0x00000000 },
900 { 0x00008254, 0x00000000 },
901 { 0x00008258, 0x00000000 },
902 { 0x0000825c, 0x400000ff },
903 { 0x00008260, 0x00080922 },
904 { 0x00008270, 0x00000000 },
905 { 0x00008274, 0x40000000 },
906 { 0x00008278, 0x003e4180 },
907 { 0x0000827c, 0x00000000 },
908 { 0x00008284, 0x0000002c },
909 { 0x00008288, 0x0000002c },
910 { 0x0000828c, 0x00000000 },
911 { 0x00008294, 0x00000000 },
912 { 0x00008298, 0x00000000 },
913 { 0x00008300, 0x00000000 },
914 { 0x00008304, 0x00000000 },
915 { 0x00008308, 0x00000000 },
916 { 0x0000830c, 0x00000000 },
917 { 0x00008310, 0x00000000 },
918 { 0x00008314, 0x00000000 },
919 { 0x00008318, 0x00000000 },
920 { 0x00008328, 0x00000000 },
921 { 0x0000832c, 0x00000007 },
922 { 0x00008330, 0x00000302 },
923 { 0x00008334, 0x00000e00 },
924 { 0x00008338, 0x00000000 },
925 { 0x0000833c, 0x00000000 },
926 { 0x00008340, 0x000107ff },
927 { 0x00009808, 0x00000000 },
928 { 0x0000980c, 0xad848e19 },
929 { 0x00009810, 0x7d14e000 },
930 { 0x00009814, 0x9c0a9f6b },
931 { 0x0000981c, 0x00000000 },
932 { 0x0000982c, 0x0000a000 },
933 { 0x00009830, 0x00000000 },
934 { 0x0000983c, 0x00200400 },
935 { 0x00009840, 0x206a01ae },
936 { 0x0000984c, 0x1284233c },
937 { 0x00009854, 0x00000859 },
938 { 0x00009900, 0x00000000 },
939 { 0x00009904, 0x00000000 },
940 { 0x00009908, 0x00000000 },
941 { 0x0000990c, 0x00000000 },
942 { 0x0000991c, 0x10000fff },
943 { 0x00009920, 0x05100000 },
944 { 0x0000a920, 0x05100000 },
945 { 0x0000b920, 0x05100000 },
946 { 0x00009928, 0x00000001 },
947 { 0x0000992c, 0x00000004 },
948 { 0x00009934, 0x1e1f2022 },
949 { 0x00009938, 0x0a0b0c0d },
950 { 0x0000993c, 0x00000000 },
951 { 0x00009948, 0x9280b212 },
952 { 0x0000994c, 0x00020028 },
953 { 0x0000c95c, 0x004b6a8e },
954 { 0x0000c968, 0x000003ce },
955 { 0x00009970, 0x190fb515 },
956 { 0x00009974, 0x00000000 },
957 { 0x00009978, 0x00000001 },
958 { 0x0000997c, 0x00000000 },
959 { 0x00009980, 0x00000000 },
960 { 0x00009984, 0x00000000 },
961 { 0x00009988, 0x00000000 },
962 { 0x0000998c, 0x00000000 },
963 { 0x00009990, 0x00000000 },
964 { 0x00009994, 0x00000000 },
965 { 0x00009998, 0x00000000 },
966 { 0x0000999c, 0x00000000 },
967 { 0x000099a0, 0x00000000 },
968 { 0x000099a4, 0x00000001 },
969 { 0x000099a8, 0x201fff00 },
970 { 0x000099ac, 0x006f0000 },
971 { 0x000099b0, 0x03051000 },
972 { 0x000099dc, 0x00000000 },
973 { 0x000099e0, 0x00000200 },
974 { 0x000099e4, 0xaaaaaaaa },
975 { 0x000099e8, 0x3c466478 },
976 { 0x000099ec, 0x0cc80caa },
977 { 0x000099fc, 0x00001042 },
978 { 0x00009b00, 0x00000000 },
979 { 0x00009b04, 0x00000001 },
980 { 0x00009b08, 0x00000002 },
981 { 0x00009b0c, 0x00000003 },
982 { 0x00009b10, 0x00000004 },
983 { 0x00009b14, 0x00000005 },
984 { 0x00009b18, 0x00000008 },
985 { 0x00009b1c, 0x00000009 },
986 { 0x00009b20, 0x0000000a },
987 { 0x00009b24, 0x0000000b },
988 { 0x00009b28, 0x0000000c },
989 { 0x00009b2c, 0x0000000d },
990 { 0x00009b30, 0x00000010 },
991 { 0x00009b34, 0x00000011 },
992 { 0x00009b38, 0x00000012 },
993 { 0x00009b3c, 0x00000013 },
994 { 0x00009b40, 0x00000014 },
995 { 0x00009b44, 0x00000015 },
996 { 0x00009b48, 0x00000018 },
997 { 0x00009b4c, 0x00000019 },
998 { 0x00009b50, 0x0000001a },
999 { 0x00009b54, 0x0000001b },
1000 { 0x00009b58, 0x0000001c },
1001 { 0x00009b5c, 0x0000001d },
1002 { 0x00009b60, 0x00000020 },
1003 { 0x00009b64, 0x00000021 },
1004 { 0x00009b68, 0x00000022 },
1005 { 0x00009b6c, 0x00000023 },
1006 { 0x00009b70, 0x00000024 },
1007 { 0x00009b74, 0x00000025 },
1008 { 0x00009b78, 0x00000028 },
1009 { 0x00009b7c, 0x00000029 },
1010 { 0x00009b80, 0x0000002a },
1011 { 0x00009b84, 0x0000002b },
1012 { 0x00009b88, 0x0000002c },
1013 { 0x00009b8c, 0x0000002d },
1014 { 0x00009b90, 0x00000030 },
1015 { 0x00009b94, 0x00000031 },
1016 { 0x00009b98, 0x00000032 },
1017 { 0x00009b9c, 0x00000033 },
1018 { 0x00009ba0, 0x00000034 },
1019 { 0x00009ba4, 0x00000035 },
1020 { 0x00009ba8, 0x00000035 },
1021 { 0x00009bac, 0x00000035 },
1022 { 0x00009bb0, 0x00000035 },
1023 { 0x00009bb4, 0x00000035 },
1024 { 0x00009bb8, 0x00000035 },
1025 { 0x00009bbc, 0x00000035 },
1026 { 0x00009bc0, 0x00000035 },
1027 { 0x00009bc4, 0x00000035 },
1028 { 0x00009bc8, 0x00000035 },
1029 { 0x00009bcc, 0x00000035 },
1030 { 0x00009bd0, 0x00000035 },
1031 { 0x00009bd4, 0x00000035 },
1032 { 0x00009bd8, 0x00000035 },
1033 { 0x00009bdc, 0x00000035 },
1034 { 0x00009be0, 0x00000035 },
1035 { 0x00009be4, 0x00000035 },
1036 { 0x00009be8, 0x00000035 },
1037 { 0x00009bec, 0x00000035 },
1038 { 0x00009bf0, 0x00000035 },
1039 { 0x00009bf4, 0x00000035 },
1040 { 0x00009bf8, 0x00000010 },
1041 { 0x00009bfc, 0x0000001a },
1042 { 0x0000a210, 0x40806333 },
1043 { 0x0000a214, 0x00106c10 },
1044 { 0x0000a218, 0x009c4060 },
1045 { 0x0000a220, 0x018830c6 },
1046 { 0x0000a224, 0x00000400 },
1047 { 0x0000a228, 0x001a0bb5 },
1048 { 0x0000a22c, 0x00000000 },
1049 { 0x0000a234, 0x20202020 },
1050 { 0x0000a238, 0x20202020 },
1051 { 0x0000a23c, 0x13c889ae },
1052 { 0x0000a240, 0x38490a20 },
1053 { 0x0000a244, 0x00007bb6 },
1054 { 0x0000a248, 0x0fff3ffc },
1055 { 0x0000a24c, 0x00000001 },
1056 { 0x0000a250, 0x0000a000 },
1057 { 0x0000a254, 0x00000000 },
1058 { 0x0000a258, 0x0cc75380 },
1059 { 0x0000a25c, 0x0f0f0f01 },
1060 { 0x0000a260, 0xdfa91f01 },
1061 { 0x0000a268, 0x00000001 },
1062 { 0x0000a26c, 0x0ebae9c6 },
1063 { 0x0000b26c, 0x0ebae9c6 },
1064 { 0x0000c26c, 0x0ebae9c6 },
1065 { 0x0000d270, 0x00820820 },
1066 { 0x0000a278, 0x1ce739ce },
1067 { 0x0000a27c, 0x050701ce },
1068 { 0x0000a338, 0x00000000 },
1069 { 0x0000a33c, 0x00000000 },
1070 { 0x0000a340, 0x00000000 },
1071 { 0x0000a344, 0x00000000 },
1072 { 0x0000a348, 0x3fffffff },
1073 { 0x0000a34c, 0x3fffffff },
1074 { 0x0000a350, 0x3fffffff },
1075 { 0x0000a354, 0x0003ffff },
1076 { 0x0000a358, 0x79a8aa33 },
1077 { 0x0000d35c, 0x07ffffef },
1078 { 0x0000d360, 0x0fffffe7 },
1079 { 0x0000d364, 0x17ffffe5 },
1080 { 0x0000d368, 0x1fffffe4 },
1081 { 0x0000d36c, 0x37ffffe3 },
1082 { 0x0000d370, 0x3fffffe3 },
1083 { 0x0000d374, 0x57ffffe3 },
1084 { 0x0000d378, 0x5fffffe2 },
1085 { 0x0000d37c, 0x7fffffe2 },
1086 { 0x0000d380, 0x7f3c7bba },
1087 { 0x0000d384, 0xf3307ff0 },
1088 { 0x0000a388, 0x0c000000 },
1089 { 0x0000a38c, 0x20202020 },
1090 { 0x0000a390, 0x20202020 },
1091 { 0x0000a394, 0x1ce739ce },
1092 { 0x0000a398, 0x000001ce },
1093 { 0x0000a39c, 0x00000001 },
1094 { 0x0000a3a0, 0x00000000 },
1095 { 0x0000a3a4, 0x00000000 },
1096 { 0x0000a3a8, 0x00000000 },
1097 { 0x0000a3ac, 0x00000000 },
1098 { 0x0000a3b0, 0x00000000 },
1099 { 0x0000a3b4, 0x00000000 },
1100 { 0x0000a3b8, 0x00000000 },
1101 { 0x0000a3bc, 0x00000000 },
1102 { 0x0000a3c0, 0x00000000 },
1103 { 0x0000a3c4, 0x00000000 },
1104 { 0x0000a3c8, 0x00000246 },
1105 { 0x0000a3cc, 0x20202020 },
1106 { 0x0000a3d0, 0x20202020 },
1107 { 0x0000a3d4, 0x20202020 },
1108 { 0x0000a3dc, 0x1ce739ce },
1109 { 0x0000a3e0, 0x000001ce },
1110};
1111
1112static const u32 ar5416Bank0_9100[][2] = {
1113 { 0x000098b0, 0x1e5795e5 },
1114 { 0x000098e0, 0x02008020 },
1115};
1116
1117static const u32 ar5416BB_RfGain_9100[][3] = {
1118 { 0x00009a00, 0x00000000, 0x00000000 },
1119 { 0x00009a04, 0x00000040, 0x00000040 },
1120 { 0x00009a08, 0x00000080, 0x00000080 },
1121 { 0x00009a0c, 0x000001a1, 0x00000141 },
1122 { 0x00009a10, 0x000001e1, 0x00000181 },
1123 { 0x00009a14, 0x00000021, 0x000001c1 },
1124 { 0x00009a18, 0x00000061, 0x00000001 },
1125 { 0x00009a1c, 0x00000168, 0x00000041 },
1126 { 0x00009a20, 0x000001a8, 0x000001a8 },
1127 { 0x00009a24, 0x000001e8, 0x000001e8 },
1128 { 0x00009a28, 0x00000028, 0x00000028 },
1129 { 0x00009a2c, 0x00000068, 0x00000068 },
1130 { 0x00009a30, 0x00000189, 0x000000a8 },
1131 { 0x00009a34, 0x000001c9, 0x00000169 },
1132 { 0x00009a38, 0x00000009, 0x000001a9 },
1133 { 0x00009a3c, 0x00000049, 0x000001e9 },
1134 { 0x00009a40, 0x00000089, 0x00000029 },
1135 { 0x00009a44, 0x00000170, 0x00000069 },
1136 { 0x00009a48, 0x000001b0, 0x00000190 },
1137 { 0x00009a4c, 0x000001f0, 0x000001d0 },
1138 { 0x00009a50, 0x00000030, 0x00000010 },
1139 { 0x00009a54, 0x00000070, 0x00000050 },
1140 { 0x00009a58, 0x00000191, 0x00000090 },
1141 { 0x00009a5c, 0x000001d1, 0x00000151 },
1142 { 0x00009a60, 0x00000011, 0x00000191 },
1143 { 0x00009a64, 0x00000051, 0x000001d1 },
1144 { 0x00009a68, 0x00000091, 0x00000011 },
1145 { 0x00009a6c, 0x000001b8, 0x00000051 },
1146 { 0x00009a70, 0x000001f8, 0x00000198 },
1147 { 0x00009a74, 0x00000038, 0x000001d8 },
1148 { 0x00009a78, 0x00000078, 0x00000018 },
1149 { 0x00009a7c, 0x00000199, 0x00000058 },
1150 { 0x00009a80, 0x000001d9, 0x00000098 },
1151 { 0x00009a84, 0x00000019, 0x00000159 },
1152 { 0x00009a88, 0x00000059, 0x00000199 },
1153 { 0x00009a8c, 0x00000099, 0x000001d9 },
1154 { 0x00009a90, 0x000000d9, 0x00000019 },
1155 { 0x00009a94, 0x000000f9, 0x00000059 },
1156 { 0x00009a98, 0x000000f9, 0x00000099 },
1157 { 0x00009a9c, 0x000000f9, 0x000000d9 },
1158 { 0x00009aa0, 0x000000f9, 0x000000f9 },
1159 { 0x00009aa4, 0x000000f9, 0x000000f9 },
1160 { 0x00009aa8, 0x000000f9, 0x000000f9 },
1161 { 0x00009aac, 0x000000f9, 0x000000f9 },
1162 { 0x00009ab0, 0x000000f9, 0x000000f9 },
1163 { 0x00009ab4, 0x000000f9, 0x000000f9 },
1164 { 0x00009ab8, 0x000000f9, 0x000000f9 },
1165 { 0x00009abc, 0x000000f9, 0x000000f9 },
1166 { 0x00009ac0, 0x000000f9, 0x000000f9 },
1167 { 0x00009ac4, 0x000000f9, 0x000000f9 },
1168 { 0x00009ac8, 0x000000f9, 0x000000f9 },
1169 { 0x00009acc, 0x000000f9, 0x000000f9 },
1170 { 0x00009ad0, 0x000000f9, 0x000000f9 },
1171 { 0x00009ad4, 0x000000f9, 0x000000f9 },
1172 { 0x00009ad8, 0x000000f9, 0x000000f9 },
1173 { 0x00009adc, 0x000000f9, 0x000000f9 },
1174 { 0x00009ae0, 0x000000f9, 0x000000f9 },
1175 { 0x00009ae4, 0x000000f9, 0x000000f9 },
1176 { 0x00009ae8, 0x000000f9, 0x000000f9 },
1177 { 0x00009aec, 0x000000f9, 0x000000f9 },
1178 { 0x00009af0, 0x000000f9, 0x000000f9 },
1179 { 0x00009af4, 0x000000f9, 0x000000f9 },
1180 { 0x00009af8, 0x000000f9, 0x000000f9 },
1181 { 0x00009afc, 0x000000f9, 0x000000f9 },
1182};
1183
1184static const u32 ar5416Bank1_9100[][2] = {
1185 { 0x000098b0, 0x02108421},
1186 { 0x000098ec, 0x00000008},
1187};
1188
1189static const u32 ar5416Bank2_9100[][2] = {
1190 { 0x000098b0, 0x0e73ff17},
1191 { 0x000098e0, 0x00000420},
1192};
1193
1194static const u32 ar5416Bank3_9100[][3] = {
1195 { 0x000098f0, 0x01400018, 0x01c00018 },
1196};
1197
1198static const u32 ar5416Bank6_9100[][3] = {
1199
1200 { 0x0000989c, 0x00000000, 0x00000000 },
1201 { 0x0000989c, 0x00000000, 0x00000000 },
1202 { 0x0000989c, 0x00000000, 0x00000000 },
1203 { 0x0000989c, 0x00e00000, 0x00e00000 },
1204 { 0x0000989c, 0x005e0000, 0x005e0000 },
1205 { 0x0000989c, 0x00120000, 0x00120000 },
1206 { 0x0000989c, 0x00620000, 0x00620000 },
1207 { 0x0000989c, 0x00020000, 0x00020000 },
1208 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1209 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1210 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1211 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1212 { 0x0000989c, 0x005f0000, 0x005f0000 },
1213 { 0x0000989c, 0x00870000, 0x00870000 },
1214 { 0x0000989c, 0x00f90000, 0x00f90000 },
1215 { 0x0000989c, 0x007b0000, 0x007b0000 },
1216 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1217 { 0x0000989c, 0x00f50000, 0x00f50000 },
1218 { 0x0000989c, 0x00dc0000, 0x00dc0000 },
1219 { 0x0000989c, 0x00110000, 0x00110000 },
1220 { 0x0000989c, 0x006100a8, 0x006100a8 },
1221 { 0x0000989c, 0x004210a2, 0x004210a2 },
1222 { 0x0000989c, 0x0014000f, 0x0014000f },
1223 { 0x0000989c, 0x00c40002, 0x00c40002 },
1224 { 0x0000989c, 0x003000f2, 0x003000f2 },
1225 { 0x0000989c, 0x00440016, 0x00440016 },
1226 { 0x0000989c, 0x00410040, 0x00410040 },
1227 { 0x0000989c, 0x000180d6, 0x000180d6 },
1228 { 0x0000989c, 0x0000c0aa, 0x0000c0aa },
1229 { 0x0000989c, 0x000000b1, 0x000000b1 },
1230 { 0x0000989c, 0x00002000, 0x00002000 },
1231 { 0x0000989c, 0x000000d4, 0x000000d4 },
1232 { 0x000098d0, 0x0000000f, 0x0010000f },
1233};
1234
1235
1236static const u32 ar5416Bank6TPC_9100[][3] = {
1237
1238 { 0x0000989c, 0x00000000, 0x00000000 },
1239 { 0x0000989c, 0x00000000, 0x00000000 },
1240 { 0x0000989c, 0x00000000, 0x00000000 },
1241 { 0x0000989c, 0x00e00000, 0x00e00000 },
1242 { 0x0000989c, 0x005e0000, 0x005e0000 },
1243 { 0x0000989c, 0x00120000, 0x00120000 },
1244 { 0x0000989c, 0x00620000, 0x00620000 },
1245 { 0x0000989c, 0x00020000, 0x00020000 },
1246 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1247 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1248 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1249 { 0x0000989c, 0x40ff0000, 0x40ff0000 },
1250 { 0x0000989c, 0x005f0000, 0x005f0000 },
1251 { 0x0000989c, 0x00870000, 0x00870000 },
1252 { 0x0000989c, 0x00f90000, 0x00f90000 },
1253 { 0x0000989c, 0x007b0000, 0x007b0000 },
1254 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1255 { 0x0000989c, 0x00f50000, 0x00f50000 },
1256 { 0x0000989c, 0x00dc0000, 0x00dc0000 },
1257 { 0x0000989c, 0x00110000, 0x00110000 },
1258 { 0x0000989c, 0x006100a8, 0x006100a8 },
1259 { 0x0000989c, 0x00423022, 0x00423022 },
1260 { 0x0000989c, 0x2014008f, 0x2014008f },
1261 { 0x0000989c, 0x00c40002, 0x00c40002 },
1262 { 0x0000989c, 0x003000f2, 0x003000f2 },
1263 { 0x0000989c, 0x00440016, 0x00440016 },
1264 { 0x0000989c, 0x00410040, 0x00410040 },
1265 { 0x0000989c, 0x0001805e, 0x0001805e },
1266 { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
1267 { 0x0000989c, 0x000000e1, 0x000000e1 },
1268 { 0x0000989c, 0x00007080, 0x00007080 },
1269 { 0x0000989c, 0x000000d4, 0x000000d4 },
1270 { 0x000098d0, 0x0000000f, 0x0010000f },
1271};
1272
1273static const u32 ar5416Bank7_9100[][2] = {
1274 { 0x0000989c, 0x00000500 },
1275 { 0x0000989c, 0x00000800 },
1276 { 0x000098cc, 0x0000000e },
1277};
1278
1279static const u32 ar5416Addac_9100[][2] = {
1280 {0x0000989c, 0x00000000 },
1281 {0x0000989c, 0x00000000 },
1282 {0x0000989c, 0x00000000 },
1283 {0x0000989c, 0x00000000 },
1284 {0x0000989c, 0x00000000 },
1285 {0x0000989c, 0x00000000 },
1286 {0x0000989c, 0x00000000 },
1287 {0x0000989c, 0x00000010 },
1288 {0x0000989c, 0x00000000 },
1289 {0x0000989c, 0x00000000 },
1290 {0x0000989c, 0x00000000 },
1291 {0x0000989c, 0x00000000 },
1292 {0x0000989c, 0x00000000 },
1293 {0x0000989c, 0x00000000 },
1294 {0x0000989c, 0x00000000 },
1295 {0x0000989c, 0x00000000 },
1296 {0x0000989c, 0x00000000 },
1297 {0x0000989c, 0x00000000 },
1298 {0x0000989c, 0x00000000 },
1299 {0x0000989c, 0x00000000 },
1300 {0x0000989c, 0x00000000 },
1301 {0x0000989c, 0x000000c0 },
1302 {0x0000989c, 0x00000015 },
1303 {0x0000989c, 0x00000000 },
1304 {0x0000989c, 0x00000000 },
1305 {0x0000989c, 0x00000000 },
1306 {0x0000989c, 0x00000000 },
1307 {0x0000989c, 0x00000000 },
1308 {0x0000989c, 0x00000000 },
1309 {0x0000989c, 0x00000000 },
1310 {0x0000989c, 0x00000000 },
1311 {0x000098cc, 0x00000000 },
1312};
1313
1314static const u32 ar5416Modes_9160[][6] = {
1315 { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
1316 { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
1317 { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
1318 { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
1319 { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
1320 { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
1321 { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
1322 { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
1323 { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
1324 { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
1325 { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
1326 { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
1327 { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
1328 { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
1329 { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
1330 { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
1331 { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 },
1332 { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
1333 { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e },
1334 { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
1335 { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
1336 { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 },
1337 { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
1338 { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
1339 { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
1340 { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
1341 { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 },
1342 { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
1343 { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
1344 { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
1345 { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 },
1346 { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce },
1347 { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 },
1348 { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
1349 { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
1350 { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
1351 { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
1352 { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
1353 { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
1354 { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
1355 { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 },
1356 { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
1357 { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
1358 { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
1359 { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
1360 { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
1361 { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
1362 { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
1363 { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
1364 { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
1365 { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
1366 { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
1367 { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
1368 { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
1369 { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
1370 { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
1371 { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
1372 { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
1373 { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
1374 { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
1375 { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
1376 { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
1377};
1378
1379static const u32 ar5416Common_9160[][2] = {
1380 { 0x0000000c, 0x00000000 },
1381 { 0x00000030, 0x00020015 },
1382 { 0x00000034, 0x00000005 },
1383 { 0x00000040, 0x00000000 },
1384 { 0x00000044, 0x00000008 },
1385 { 0x00000048, 0x00000008 },
1386 { 0x0000004c, 0x00000010 },
1387 { 0x00000050, 0x00000000 },
1388 { 0x00000054, 0x0000001f },
1389 { 0x00000800, 0x00000000 },
1390 { 0x00000804, 0x00000000 },
1391 { 0x00000808, 0x00000000 },
1392 { 0x0000080c, 0x00000000 },
1393 { 0x00000810, 0x00000000 },
1394 { 0x00000814, 0x00000000 },
1395 { 0x00000818, 0x00000000 },
1396 { 0x0000081c, 0x00000000 },
1397 { 0x00000820, 0x00000000 },
1398 { 0x00000824, 0x00000000 },
1399 { 0x00001040, 0x002ffc0f },
1400 { 0x00001044, 0x002ffc0f },
1401 { 0x00001048, 0x002ffc0f },
1402 { 0x0000104c, 0x002ffc0f },
1403 { 0x00001050, 0x002ffc0f },
1404 { 0x00001054, 0x002ffc0f },
1405 { 0x00001058, 0x002ffc0f },
1406 { 0x0000105c, 0x002ffc0f },
1407 { 0x00001060, 0x002ffc0f },
1408 { 0x00001064, 0x002ffc0f },
1409 { 0x00001230, 0x00000000 },
1410 { 0x00001270, 0x00000000 },
1411 { 0x00001038, 0x00000000 },
1412 { 0x00001078, 0x00000000 },
1413 { 0x000010b8, 0x00000000 },
1414 { 0x000010f8, 0x00000000 },
1415 { 0x00001138, 0x00000000 },
1416 { 0x00001178, 0x00000000 },
1417 { 0x000011b8, 0x00000000 },
1418 { 0x000011f8, 0x00000000 },
1419 { 0x00001238, 0x00000000 },
1420 { 0x00001278, 0x00000000 },
1421 { 0x000012b8, 0x00000000 },
1422 { 0x000012f8, 0x00000000 },
1423 { 0x00001338, 0x00000000 },
1424 { 0x00001378, 0x00000000 },
1425 { 0x000013b8, 0x00000000 },
1426 { 0x000013f8, 0x00000000 },
1427 { 0x00001438, 0x00000000 },
1428 { 0x00001478, 0x00000000 },
1429 { 0x000014b8, 0x00000000 },
1430 { 0x000014f8, 0x00000000 },
1431 { 0x00001538, 0x00000000 },
1432 { 0x00001578, 0x00000000 },
1433 { 0x000015b8, 0x00000000 },
1434 { 0x000015f8, 0x00000000 },
1435 { 0x00001638, 0x00000000 },
1436 { 0x00001678, 0x00000000 },
1437 { 0x000016b8, 0x00000000 },
1438 { 0x000016f8, 0x00000000 },
1439 { 0x00001738, 0x00000000 },
1440 { 0x00001778, 0x00000000 },
1441 { 0x000017b8, 0x00000000 },
1442 { 0x000017f8, 0x00000000 },
1443 { 0x0000103c, 0x00000000 },
1444 { 0x0000107c, 0x00000000 },
1445 { 0x000010bc, 0x00000000 },
1446 { 0x000010fc, 0x00000000 },
1447 { 0x0000113c, 0x00000000 },
1448 { 0x0000117c, 0x00000000 },
1449 { 0x000011bc, 0x00000000 },
1450 { 0x000011fc, 0x00000000 },
1451 { 0x0000123c, 0x00000000 },
1452 { 0x0000127c, 0x00000000 },
1453 { 0x000012bc, 0x00000000 },
1454 { 0x000012fc, 0x00000000 },
1455 { 0x0000133c, 0x00000000 },
1456 { 0x0000137c, 0x00000000 },
1457 { 0x000013bc, 0x00000000 },
1458 { 0x000013fc, 0x00000000 },
1459 { 0x0000143c, 0x00000000 },
1460 { 0x0000147c, 0x00000000 },
1461 { 0x00004030, 0x00000002 },
1462 { 0x0000403c, 0x00000002 },
1463 { 0x00007010, 0x00000020 },
1464 { 0x00007038, 0x000004c2 },
1465 { 0x00008004, 0x00000000 },
1466 { 0x00008008, 0x00000000 },
1467 { 0x0000800c, 0x00000000 },
1468 { 0x00008018, 0x00000700 },
1469 { 0x00008020, 0x00000000 },
1470 { 0x00008038, 0x00000000 },
1471 { 0x0000803c, 0x00000000 },
1472 { 0x00008048, 0x40000000 },
1473 { 0x00008054, 0x00000000 },
1474 { 0x00008058, 0x00000000 },
1475 { 0x0000805c, 0x000fc78f },
1476 { 0x00008060, 0x0000000f },
1477 { 0x00008064, 0x00000000 },
1478 { 0x000080c0, 0x2a82301a },
1479 { 0x000080c4, 0x05dc01e0 },
1480 { 0x000080c8, 0x1f402710 },
1481 { 0x000080cc, 0x01f40000 },
1482 { 0x000080d0, 0x00001e00 },
1483 { 0x000080d4, 0x00000000 },
1484 { 0x000080d8, 0x00400000 },
1485 { 0x000080e0, 0xffffffff },
1486 { 0x000080e4, 0x0000ffff },
1487 { 0x000080e8, 0x003f3f3f },
1488 { 0x000080ec, 0x00000000 },
1489 { 0x000080f0, 0x00000000 },
1490 { 0x000080f4, 0x00000000 },
1491 { 0x000080f8, 0x00000000 },
1492 { 0x000080fc, 0x00020000 },
1493 { 0x00008100, 0x00020000 },
1494 { 0x00008104, 0x00000001 },
1495 { 0x00008108, 0x00000052 },
1496 { 0x0000810c, 0x00000000 },
1497 { 0x00008110, 0x00000168 },
1498 { 0x00008118, 0x000100aa },
1499 { 0x0000811c, 0x00003210 },
1500 { 0x00008120, 0x08f04800 },
1501 { 0x00008124, 0x00000000 },
1502 { 0x00008128, 0x00000000 },
1503 { 0x0000812c, 0x00000000 },
1504 { 0x00008130, 0x00000000 },
1505 { 0x00008134, 0x00000000 },
1506 { 0x00008138, 0x00000000 },
1507 { 0x0000813c, 0x00000000 },
1508 { 0x00008144, 0xffffffff },
1509 { 0x00008168, 0x00000000 },
1510 { 0x0000816c, 0x00000000 },
1511 { 0x00008170, 0x32143320 },
1512 { 0x00008174, 0xfaa4fa50 },
1513 { 0x00008178, 0x00000100 },
1514 { 0x0000817c, 0x00000000 },
1515 { 0x000081c4, 0x00000000 },
1516 { 0x000081d0, 0x00003210 },
1517 { 0x000081ec, 0x00000000 },
1518 { 0x000081f0, 0x00000000 },
1519 { 0x000081f4, 0x00000000 },
1520 { 0x000081f8, 0x00000000 },
1521 { 0x000081fc, 0x00000000 },
1522 { 0x00008200, 0x00000000 },
1523 { 0x00008204, 0x00000000 },
1524 { 0x00008208, 0x00000000 },
1525 { 0x0000820c, 0x00000000 },
1526 { 0x00008210, 0x00000000 },
1527 { 0x00008214, 0x00000000 },
1528 { 0x00008218, 0x00000000 },
1529 { 0x0000821c, 0x00000000 },
1530 { 0x00008220, 0x00000000 },
1531 { 0x00008224, 0x00000000 },
1532 { 0x00008228, 0x00000000 },
1533 { 0x0000822c, 0x00000000 },
1534 { 0x00008230, 0x00000000 },
1535 { 0x00008234, 0x00000000 },
1536 { 0x00008238, 0x00000000 },
1537 { 0x0000823c, 0x00000000 },
1538 { 0x00008240, 0x00100000 },
1539 { 0x00008244, 0x0010f400 },
1540 { 0x00008248, 0x00000100 },
1541 { 0x0000824c, 0x0001e800 },
1542 { 0x00008250, 0x00000000 },
1543 { 0x00008254, 0x00000000 },
1544 { 0x00008258, 0x00000000 },
1545 { 0x0000825c, 0x400000ff },
1546 { 0x00008260, 0x00080922 },
1547 { 0x00008270, 0x00000000 },
1548 { 0x00008274, 0x40000000 },
1549 { 0x00008278, 0x003e4180 },
1550 { 0x0000827c, 0x00000000 },
1551 { 0x00008284, 0x0000002c },
1552 { 0x00008288, 0x0000002c },
1553 { 0x0000828c, 0x00000000 },
1554 { 0x00008294, 0x00000000 },
1555 { 0x00008298, 0x00000000 },
1556 { 0x00008300, 0x00000000 },
1557 { 0x00008304, 0x00000000 },
1558 { 0x00008308, 0x00000000 },
1559 { 0x0000830c, 0x00000000 },
1560 { 0x00008310, 0x00000000 },
1561 { 0x00008314, 0x00000000 },
1562 { 0x00008318, 0x00000000 },
1563 { 0x00008328, 0x00000000 },
1564 { 0x0000832c, 0x00000007 },
1565 { 0x00008330, 0x00000302 },
1566 { 0x00008334, 0x00000e00 },
1567 { 0x00008338, 0x00ff0000 },
1568 { 0x0000833c, 0x00000000 },
1569 { 0x00008340, 0x000107ff },
1570 { 0x00009808, 0x00000000 },
1571 { 0x0000980c, 0xad848e19 },
1572 { 0x00009810, 0x7d14e000 },
1573 { 0x00009814, 0x9c0a9f6b },
1574 { 0x0000981c, 0x00000000 },
1575 { 0x0000982c, 0x0000a000 },
1576 { 0x00009830, 0x00000000 },
1577 { 0x0000983c, 0x00200400 },
1578 { 0x00009840, 0x206a01ae },
1579 { 0x0000984c, 0x1284233c },
1580 { 0x00009854, 0x00000859 },
1581 { 0x00009900, 0x00000000 },
1582 { 0x00009904, 0x00000000 },
1583 { 0x00009908, 0x00000000 },
1584 { 0x0000990c, 0x00000000 },
1585 { 0x0000991c, 0x10000fff },
1586 { 0x00009920, 0x05100000 },
1587 { 0x0000a920, 0x05100000 },
1588 { 0x0000b920, 0x05100000 },
1589 { 0x00009928, 0x00000001 },
1590 { 0x0000992c, 0x00000004 },
1591 { 0x00009934, 0x1e1f2022 },
1592 { 0x00009938, 0x0a0b0c0d },
1593 { 0x0000993c, 0x00000000 },
1594 { 0x00009948, 0x9280b212 },
1595 { 0x0000994c, 0x00020028 },
1596 { 0x00009954, 0x5f3ca3de },
1597 { 0x00009958, 0x2108ecff },
1598 { 0x00009940, 0x00750604 },
1599 { 0x0000c95c, 0x004b6a8e },
1600 { 0x00009970, 0x190fb515 },
1601 { 0x00009974, 0x00000000 },
1602 { 0x00009978, 0x00000001 },
1603 { 0x0000997c, 0x00000000 },
1604 { 0x00009980, 0x00000000 },
1605 { 0x00009984, 0x00000000 },
1606 { 0x00009988, 0x00000000 },
1607 { 0x0000998c, 0x00000000 },
1608 { 0x00009990, 0x00000000 },
1609 { 0x00009994, 0x00000000 },
1610 { 0x00009998, 0x00000000 },
1611 { 0x0000999c, 0x00000000 },
1612 { 0x000099a0, 0x00000000 },
1613 { 0x000099a4, 0x00000001 },
1614 { 0x000099a8, 0x201fff00 },
1615 { 0x000099ac, 0x006f0000 },
1616 { 0x000099b0, 0x03051000 },
1617 { 0x000099dc, 0x00000000 },
1618 { 0x000099e0, 0x00000200 },
1619 { 0x000099e4, 0xaaaaaaaa },
1620 { 0x000099e8, 0x3c466478 },
1621 { 0x000099ec, 0x0cc80caa },
1622 { 0x000099fc, 0x00001042 },
1623 { 0x00009b00, 0x00000000 },
1624 { 0x00009b04, 0x00000001 },
1625 { 0x00009b08, 0x00000002 },
1626 { 0x00009b0c, 0x00000003 },
1627 { 0x00009b10, 0x00000004 },
1628 { 0x00009b14, 0x00000005 },
1629 { 0x00009b18, 0x00000008 },
1630 { 0x00009b1c, 0x00000009 },
1631 { 0x00009b20, 0x0000000a },
1632 { 0x00009b24, 0x0000000b },
1633 { 0x00009b28, 0x0000000c },
1634 { 0x00009b2c, 0x0000000d },
1635 { 0x00009b30, 0x00000010 },
1636 { 0x00009b34, 0x00000011 },
1637 { 0x00009b38, 0x00000012 },
1638 { 0x00009b3c, 0x00000013 },
1639 { 0x00009b40, 0x00000014 },
1640 { 0x00009b44, 0x00000015 },
1641 { 0x00009b48, 0x00000018 },
1642 { 0x00009b4c, 0x00000019 },
1643 { 0x00009b50, 0x0000001a },
1644 { 0x00009b54, 0x0000001b },
1645 { 0x00009b58, 0x0000001c },
1646 { 0x00009b5c, 0x0000001d },
1647 { 0x00009b60, 0x00000020 },
1648 { 0x00009b64, 0x00000021 },
1649 { 0x00009b68, 0x00000022 },
1650 { 0x00009b6c, 0x00000023 },
1651 { 0x00009b70, 0x00000024 },
1652 { 0x00009b74, 0x00000025 },
1653 { 0x00009b78, 0x00000028 },
1654 { 0x00009b7c, 0x00000029 },
1655 { 0x00009b80, 0x0000002a },
1656 { 0x00009b84, 0x0000002b },
1657 { 0x00009b88, 0x0000002c },
1658 { 0x00009b8c, 0x0000002d },
1659 { 0x00009b90, 0x00000030 },
1660 { 0x00009b94, 0x00000031 },
1661 { 0x00009b98, 0x00000032 },
1662 { 0x00009b9c, 0x00000033 },
1663 { 0x00009ba0, 0x00000034 },
1664 { 0x00009ba4, 0x00000035 },
1665 { 0x00009ba8, 0x00000035 },
1666 { 0x00009bac, 0x00000035 },
1667 { 0x00009bb0, 0x00000035 },
1668 { 0x00009bb4, 0x00000035 },
1669 { 0x00009bb8, 0x00000035 },
1670 { 0x00009bbc, 0x00000035 },
1671 { 0x00009bc0, 0x00000035 },
1672 { 0x00009bc4, 0x00000035 },
1673 { 0x00009bc8, 0x00000035 },
1674 { 0x00009bcc, 0x00000035 },
1675 { 0x00009bd0, 0x00000035 },
1676 { 0x00009bd4, 0x00000035 },
1677 { 0x00009bd8, 0x00000035 },
1678 { 0x00009bdc, 0x00000035 },
1679 { 0x00009be0, 0x00000035 },
1680 { 0x00009be4, 0x00000035 },
1681 { 0x00009be8, 0x00000035 },
1682 { 0x00009bec, 0x00000035 },
1683 { 0x00009bf0, 0x00000035 },
1684 { 0x00009bf4, 0x00000035 },
1685 { 0x00009bf8, 0x00000010 },
1686 { 0x00009bfc, 0x0000001a },
1687 { 0x0000a210, 0x40806333 },
1688 { 0x0000a214, 0x00106c10 },
1689 { 0x0000a218, 0x009c4060 },
1690 { 0x0000a220, 0x018830c6 },
1691 { 0x0000a224, 0x00000400 },
1692 { 0x0000a228, 0x001a0bb5 },
1693 { 0x0000a22c, 0x00000000 },
1694 { 0x0000a234, 0x20202020 },
1695 { 0x0000a238, 0x20202020 },
1696 { 0x0000a23c, 0x13c889af },
1697 { 0x0000a240, 0x38490a20 },
1698 { 0x0000a244, 0x00007bb6 },
1699 { 0x0000a248, 0x0fff3ffc },
1700 { 0x0000a24c, 0x00000001 },
1701 { 0x0000a250, 0x0000e000 },
1702 { 0x0000a254, 0x00000000 },
1703 { 0x0000a258, 0x0cc75380 },
1704 { 0x0000a25c, 0x0f0f0f01 },
1705 { 0x0000a260, 0xdfa91f01 },
1706 { 0x0000a268, 0x00000001 },
1707 { 0x0000a26c, 0x0ebae9c6 },
1708 { 0x0000b26c, 0x0ebae9c6 },
1709 { 0x0000c26c, 0x0ebae9c6 },
1710 { 0x0000d270, 0x00820820 },
1711 { 0x0000a278, 0x1ce739ce },
1712 { 0x0000a27c, 0x050701ce },
1713 { 0x0000a338, 0x00000000 },
1714 { 0x0000a33c, 0x00000000 },
1715 { 0x0000a340, 0x00000000 },
1716 { 0x0000a344, 0x00000000 },
1717 { 0x0000a348, 0x3fffffff },
1718 { 0x0000a34c, 0x3fffffff },
1719 { 0x0000a350, 0x3fffffff },
1720 { 0x0000a354, 0x0003ffff },
1721 { 0x0000a358, 0x79bfaa03 },
1722 { 0x0000d35c, 0x07ffffef },
1723 { 0x0000d360, 0x0fffffe7 },
1724 { 0x0000d364, 0x17ffffe5 },
1725 { 0x0000d368, 0x1fffffe4 },
1726 { 0x0000d36c, 0x37ffffe3 },
1727 { 0x0000d370, 0x3fffffe3 },
1728 { 0x0000d374, 0x57ffffe3 },
1729 { 0x0000d378, 0x5fffffe2 },
1730 { 0x0000d37c, 0x7fffffe2 },
1731 { 0x0000d380, 0x7f3c7bba },
1732 { 0x0000d384, 0xf3307ff0 },
1733 { 0x0000a388, 0x0c000000 },
1734 { 0x0000a38c, 0x20202020 },
1735 { 0x0000a390, 0x20202020 },
1736 { 0x0000a394, 0x1ce739ce },
1737 { 0x0000a398, 0x000001ce },
1738 { 0x0000a39c, 0x00000001 },
1739 { 0x0000a3a0, 0x00000000 },
1740 { 0x0000a3a4, 0x00000000 },
1741 { 0x0000a3a8, 0x00000000 },
1742 { 0x0000a3ac, 0x00000000 },
1743 { 0x0000a3b0, 0x00000000 },
1744 { 0x0000a3b4, 0x00000000 },
1745 { 0x0000a3b8, 0x00000000 },
1746 { 0x0000a3bc, 0x00000000 },
1747 { 0x0000a3c0, 0x00000000 },
1748 { 0x0000a3c4, 0x00000000 },
1749 { 0x0000a3c8, 0x00000246 },
1750 { 0x0000a3cc, 0x20202020 },
1751 { 0x0000a3d0, 0x20202020 },
1752 { 0x0000a3d4, 0x20202020 },
1753 { 0x0000a3dc, 0x1ce739ce },
1754 { 0x0000a3e0, 0x000001ce },
1755};
1756
1757static const u32 ar5416Bank0_9160[][2] = {
1758 { 0x000098b0, 0x1e5795e5 },
1759 { 0x000098e0, 0x02008020 },
1760};
1761
1762static const u32 ar5416BB_RfGain_9160[][3] = {
1763 { 0x00009a00, 0x00000000, 0x00000000 },
1764 { 0x00009a04, 0x00000040, 0x00000040 },
1765 { 0x00009a08, 0x00000080, 0x00000080 },
1766 { 0x00009a0c, 0x000001a1, 0x00000141 },
1767 { 0x00009a10, 0x000001e1, 0x00000181 },
1768 { 0x00009a14, 0x00000021, 0x000001c1 },
1769 { 0x00009a18, 0x00000061, 0x00000001 },
1770 { 0x00009a1c, 0x00000168, 0x00000041 },
1771 { 0x00009a20, 0x000001a8, 0x000001a8 },
1772 { 0x00009a24, 0x000001e8, 0x000001e8 },
1773 { 0x00009a28, 0x00000028, 0x00000028 },
1774 { 0x00009a2c, 0x00000068, 0x00000068 },
1775 { 0x00009a30, 0x00000189, 0x000000a8 },
1776 { 0x00009a34, 0x000001c9, 0x00000169 },
1777 { 0x00009a38, 0x00000009, 0x000001a9 },
1778 { 0x00009a3c, 0x00000049, 0x000001e9 },
1779 { 0x00009a40, 0x00000089, 0x00000029 },
1780 { 0x00009a44, 0x00000170, 0x00000069 },
1781 { 0x00009a48, 0x000001b0, 0x00000190 },
1782 { 0x00009a4c, 0x000001f0, 0x000001d0 },
1783 { 0x00009a50, 0x00000030, 0x00000010 },
1784 { 0x00009a54, 0x00000070, 0x00000050 },
1785 { 0x00009a58, 0x00000191, 0x00000090 },
1786 { 0x00009a5c, 0x000001d1, 0x00000151 },
1787 { 0x00009a60, 0x00000011, 0x00000191 },
1788 { 0x00009a64, 0x00000051, 0x000001d1 },
1789 { 0x00009a68, 0x00000091, 0x00000011 },
1790 { 0x00009a6c, 0x000001b8, 0x00000051 },
1791 { 0x00009a70, 0x000001f8, 0x00000198 },
1792 { 0x00009a74, 0x00000038, 0x000001d8 },
1793 { 0x00009a78, 0x00000078, 0x00000018 },
1794 { 0x00009a7c, 0x00000199, 0x00000058 },
1795 { 0x00009a80, 0x000001d9, 0x00000098 },
1796 { 0x00009a84, 0x00000019, 0x00000159 },
1797 { 0x00009a88, 0x00000059, 0x00000199 },
1798 { 0x00009a8c, 0x00000099, 0x000001d9 },
1799 { 0x00009a90, 0x000000d9, 0x00000019 },
1800 { 0x00009a94, 0x000000f9, 0x00000059 },
1801 { 0x00009a98, 0x000000f9, 0x00000099 },
1802 { 0x00009a9c, 0x000000f9, 0x000000d9 },
1803 { 0x00009aa0, 0x000000f9, 0x000000f9 },
1804 { 0x00009aa4, 0x000000f9, 0x000000f9 },
1805 { 0x00009aa8, 0x000000f9, 0x000000f9 },
1806 { 0x00009aac, 0x000000f9, 0x000000f9 },
1807 { 0x00009ab0, 0x000000f9, 0x000000f9 },
1808 { 0x00009ab4, 0x000000f9, 0x000000f9 },
1809 { 0x00009ab8, 0x000000f9, 0x000000f9 },
1810 { 0x00009abc, 0x000000f9, 0x000000f9 },
1811 { 0x00009ac0, 0x000000f9, 0x000000f9 },
1812 { 0x00009ac4, 0x000000f9, 0x000000f9 },
1813 { 0x00009ac8, 0x000000f9, 0x000000f9 },
1814 { 0x00009acc, 0x000000f9, 0x000000f9 },
1815 { 0x00009ad0, 0x000000f9, 0x000000f9 },
1816 { 0x00009ad4, 0x000000f9, 0x000000f9 },
1817 { 0x00009ad8, 0x000000f9, 0x000000f9 },
1818 { 0x00009adc, 0x000000f9, 0x000000f9 },
1819 { 0x00009ae0, 0x000000f9, 0x000000f9 },
1820 { 0x00009ae4, 0x000000f9, 0x000000f9 },
1821 { 0x00009ae8, 0x000000f9, 0x000000f9 },
1822 { 0x00009aec, 0x000000f9, 0x000000f9 },
1823 { 0x00009af0, 0x000000f9, 0x000000f9 },
1824 { 0x00009af4, 0x000000f9, 0x000000f9 },
1825 { 0x00009af8, 0x000000f9, 0x000000f9 },
1826 { 0x00009afc, 0x000000f9, 0x000000f9 },
1827};
1828
1829static const u32 ar5416Bank1_9160[][2] = {
1830 { 0x000098b0, 0x02108421 },
1831 { 0x000098ec, 0x00000008 },
1832};
1833
1834static const u32 ar5416Bank2_9160[][2] = {
1835 { 0x000098b0, 0x0e73ff17 },
1836 { 0x000098e0, 0x00000420 },
1837};
1838
1839static const u32 ar5416Bank3_9160[][3] = {
1840 { 0x000098f0, 0x01400018, 0x01c00018 },
1841};
1842
1843static const u32 ar5416Bank6_9160[][3] = {
1844 { 0x0000989c, 0x00000000, 0x00000000 },
1845 { 0x0000989c, 0x00000000, 0x00000000 },
1846 { 0x0000989c, 0x00000000, 0x00000000 },
1847 { 0x0000989c, 0x00e00000, 0x00e00000 },
1848 { 0x0000989c, 0x005e0000, 0x005e0000 },
1849 { 0x0000989c, 0x00120000, 0x00120000 },
1850 { 0x0000989c, 0x00620000, 0x00620000 },
1851 { 0x0000989c, 0x00020000, 0x00020000 },
1852 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1853 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1854 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1855 { 0x0000989c, 0x40ff0000, 0x40ff0000 },
1856 { 0x0000989c, 0x005f0000, 0x005f0000 },
1857 { 0x0000989c, 0x00870000, 0x00870000 },
1858 { 0x0000989c, 0x00f90000, 0x00f90000 },
1859 { 0x0000989c, 0x007b0000, 0x007b0000 },
1860 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1861 { 0x0000989c, 0x00f50000, 0x00f50000 },
1862 { 0x0000989c, 0x00dc0000, 0x00dc0000 },
1863 { 0x0000989c, 0x00110000, 0x00110000 },
1864 { 0x0000989c, 0x006100a8, 0x006100a8 },
1865 { 0x0000989c, 0x004210a2, 0x004210a2 },
1866 { 0x0000989c, 0x0014008f, 0x0014008f },
1867 { 0x0000989c, 0x00c40003, 0x00c40003 },
1868 { 0x0000989c, 0x003000f2, 0x003000f2 },
1869 { 0x0000989c, 0x00440016, 0x00440016 },
1870 { 0x0000989c, 0x00410040, 0x00410040 },
1871 { 0x0000989c, 0x0001805e, 0x0001805e },
1872 { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
1873 { 0x0000989c, 0x000000f1, 0x000000f1 },
1874 { 0x0000989c, 0x00002081, 0x00002081 },
1875 { 0x0000989c, 0x000000d4, 0x000000d4 },
1876 { 0x000098d0, 0x0000000f, 0x0010000f },
1877};
1878
1879static const u32 ar5416Bank6TPC_9160[][3] = {
1880 { 0x0000989c, 0x00000000, 0x00000000 },
1881 { 0x0000989c, 0x00000000, 0x00000000 },
1882 { 0x0000989c, 0x00000000, 0x00000000 },
1883 { 0x0000989c, 0x00e00000, 0x00e00000 },
1884 { 0x0000989c, 0x005e0000, 0x005e0000 },
1885 { 0x0000989c, 0x00120000, 0x00120000 },
1886 { 0x0000989c, 0x00620000, 0x00620000 },
1887 { 0x0000989c, 0x00020000, 0x00020000 },
1888 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1889 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1890 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1891 { 0x0000989c, 0x40ff0000, 0x40ff0000 },
1892 { 0x0000989c, 0x005f0000, 0x005f0000 },
1893 { 0x0000989c, 0x00870000, 0x00870000 },
1894 { 0x0000989c, 0x00f90000, 0x00f90000 },
1895 { 0x0000989c, 0x007b0000, 0x007b0000 },
1896 { 0x0000989c, 0x00ff0000, 0x00ff0000 },
1897 { 0x0000989c, 0x00f50000, 0x00f50000 },
1898 { 0x0000989c, 0x00dc0000, 0x00dc0000 },
1899 { 0x0000989c, 0x00110000, 0x00110000 },
1900 { 0x0000989c, 0x006100a8, 0x006100a8 },
1901 { 0x0000989c, 0x00423022, 0x00423022 },
1902 { 0x0000989c, 0x2014008f, 0x2014008f },
1903 { 0x0000989c, 0x00c40002, 0x00c40002 },
1904 { 0x0000989c, 0x003000f2, 0x003000f2 },
1905 { 0x0000989c, 0x00440016, 0x00440016 },
1906 { 0x0000989c, 0x00410040, 0x00410040 },
1907 { 0x0000989c, 0x0001805e, 0x0001805e },
1908 { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
1909 { 0x0000989c, 0x000000e1, 0x000000e1 },
1910 { 0x0000989c, 0x00007080, 0x00007080 },
1911 { 0x0000989c, 0x000000d4, 0x000000d4 },
1912 { 0x000098d0, 0x0000000f, 0x0010000f },
1913};
1914
1915static const u32 ar5416Bank7_9160[][2] = {
1916 { 0x0000989c, 0x00000500 },
1917 { 0x0000989c, 0x00000800 },
1918 { 0x000098cc, 0x0000000e },
1919};
1920
1921static u32 ar5416Addac_9160[][2] = {
1922 {0x0000989c, 0x00000000 },
1923 {0x0000989c, 0x00000000 },
1924 {0x0000989c, 0x00000000 },
1925 {0x0000989c, 0x00000000 },
1926 {0x0000989c, 0x00000000 },
1927 {0x0000989c, 0x00000000 },
1928 {0x0000989c, 0x000000c0 },
1929 {0x0000989c, 0x00000018 },
1930 {0x0000989c, 0x00000004 },
1931 {0x0000989c, 0x00000000 },
1932 {0x0000989c, 0x00000000 },
1933 {0x0000989c, 0x00000000 },
1934 {0x0000989c, 0x00000000 },
1935 {0x0000989c, 0x00000000 },
1936 {0x0000989c, 0x00000000 },
1937 {0x0000989c, 0x00000000 },
1938 {0x0000989c, 0x00000000 },
1939 {0x0000989c, 0x00000000 },
1940 {0x0000989c, 0x00000000 },
1941 {0x0000989c, 0x00000000 },
1942 {0x0000989c, 0x00000000 },
1943 {0x0000989c, 0x000000c0 },
1944 {0x0000989c, 0x00000019 },
1945 {0x0000989c, 0x00000004 },
1946 {0x0000989c, 0x00000000 },
1947 {0x0000989c, 0x00000000 },
1948 {0x0000989c, 0x00000000 },
1949 {0x0000989c, 0x00000004 },
1950 {0x0000989c, 0x00000003 },
1951 {0x0000989c, 0x00000008 },
1952 {0x0000989c, 0x00000000 },
1953 {0x000098cc, 0x00000000 },
1954};
1955
1956static u32 ar5416Addac_91601_1[][2] = {
1957 {0x0000989c, 0x00000000 },
1958 {0x0000989c, 0x00000000 },
1959 {0x0000989c, 0x00000000 },
1960 {0x0000989c, 0x00000000 },
1961 {0x0000989c, 0x00000000 },
1962 {0x0000989c, 0x00000000 },
1963 {0x0000989c, 0x000000c0 },
1964 {0x0000989c, 0x00000018 },
1965 {0x0000989c, 0x00000004 },
1966 {0x0000989c, 0x00000000 },
1967 {0x0000989c, 0x00000000 },
1968 {0x0000989c, 0x00000000 },
1969 {0x0000989c, 0x00000000 },
1970 {0x0000989c, 0x00000000 },
1971 {0x0000989c, 0x00000000 },
1972 {0x0000989c, 0x00000000 },
1973 {0x0000989c, 0x00000000 },
1974 {0x0000989c, 0x00000000 },
1975 {0x0000989c, 0x00000000 },
1976 {0x0000989c, 0x00000000 },
1977 {0x0000989c, 0x00000000 },
1978 {0x0000989c, 0x000000c0 },
1979 {0x0000989c, 0x00000019 },
1980 {0x0000989c, 0x00000004 },
1981 {0x0000989c, 0x00000000 },
1982 {0x0000989c, 0x00000000 },
1983 {0x0000989c, 0x00000000 },
1984 {0x0000989c, 0x00000000 },
1985 {0x0000989c, 0x00000000 },
1986 {0x0000989c, 0x00000000 },
1987 {0x0000989c, 0x00000000 },
1988 {0x000098cc, 0x00000000 },
1989};
1990
1991/* XXX 9280 1 */
1992static const u32 ar9280Modes_9280[][6] = {
1993 { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
1994 { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
1995 { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
1996 { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
1997 { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 },
1998 { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
1999 { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
2000 { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
2001 { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
2002 { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
2003 { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
2004 { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
2005 { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 },
2006 { 0x00009848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 },
2007 { 0x0000a848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 },
2008 { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
2009 { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
2010 { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
2011 { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d20, 0x00049d20, 0x00049d18 },
2012 { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
2013 { 0x00009868, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190 },
2014 { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
2015 { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
2016 { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
2017 { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
2018 { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 },
2019 { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
2020 { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
2021 { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 },
2022 { 0x0000c9b8, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a },
2023 { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
2024 { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
2025 { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
2026 { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c },
2027 { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
2028 { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
2029 { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
2030 { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
2031 { 0x00009a00, 0x00008184, 0x00008184, 0x00000214, 0x00000214, 0x00000214 },
2032 { 0x00009a04, 0x00008188, 0x00008188, 0x00000218, 0x00000218, 0x00000218 },
2033 { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000224, 0x00000224, 0x00000224 },
2034 { 0x00009a0c, 0x00008190, 0x00008190, 0x00000228, 0x00000228, 0x00000228 },
2035 { 0x00009a10, 0x00008194, 0x00008194, 0x0000022c, 0x0000022c, 0x0000022c },
2036 { 0x00009a14, 0x00008200, 0x00008200, 0x00000230, 0x00000230, 0x00000230 },
2037 { 0x00009a18, 0x00008204, 0x00008204, 0x000002a4, 0x000002a4, 0x000002a4 },
2038 { 0x00009a1c, 0x00008208, 0x00008208, 0x000002a8, 0x000002a8, 0x000002a8 },
2039 { 0x00009a20, 0x0000820c, 0x0000820c, 0x000002ac, 0x000002ac, 0x000002ac },
2040 { 0x00009a24, 0x00008210, 0x00008210, 0x000002b0, 0x000002b0, 0x000002b0 },
2041 { 0x00009a28, 0x00008214, 0x00008214, 0x000002b4, 0x000002b4, 0x000002b4 },
2042 { 0x00009a2c, 0x00008280, 0x00008280, 0x000002b8, 0x000002b8, 0x000002b8 },
2043 { 0x00009a30, 0x00008284, 0x00008284, 0x00000390, 0x00000390, 0x00000390 },
2044 { 0x00009a34, 0x00008288, 0x00008288, 0x00000394, 0x00000394, 0x00000394 },
2045 { 0x00009a38, 0x0000828c, 0x0000828c, 0x00000398, 0x00000398, 0x00000398 },
2046 { 0x00009a3c, 0x00008290, 0x00008290, 0x00000334, 0x00000334, 0x00000334 },
2047 { 0x00009a40, 0x00008300, 0x00008300, 0x00000338, 0x00000338, 0x00000338 },
2048 { 0x00009a44, 0x00008304, 0x00008304, 0x000003ac, 0x000003ac, 0x000003ac },
2049 { 0x00009a48, 0x00008308, 0x00008308, 0x000003b0, 0x000003b0, 0x000003b0 },
2050 { 0x00009a4c, 0x0000830c, 0x0000830c, 0x000003b4, 0x000003b4, 0x000003b4 },
2051 { 0x00009a50, 0x00008310, 0x00008310, 0x000003b8, 0x000003b8, 0x000003b8 },
2052 { 0x00009a54, 0x00008314, 0x00008314, 0x000003a5, 0x000003a5, 0x000003a5 },
2053 { 0x00009a58, 0x00008380, 0x00008380, 0x000003a9, 0x000003a9, 0x000003a9 },
2054 { 0x00009a5c, 0x00008384, 0x00008384, 0x000003ad, 0x000003ad, 0x000003ad },
2055 { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
2056 { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
2057 { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
2058 { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
2059 { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
2060 { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
2061 { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
2062 { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
2063 { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
2064 { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
2065 { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
2066 { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
2067 { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
2068 { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
2069 { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
2070 { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
2071 { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
2072 { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
2073 { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
2074 { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
2075 { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
2076 { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
2077 { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
2078 { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
2079 { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
2080 { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
2081 { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
2082 { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
2083 { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
2084 { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
2085 { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
2086 { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
2087 { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
2088 { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
2089 { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c },
2090 { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 },
2091 { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 },
2092 { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 },
2093 { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 },
2094 { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 },
2095 { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 },
2096 { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 },
2097 { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 },
2098 { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 },
2099 { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 },
2100 { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 },
2101 { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 },
2102 { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c },
2103 { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 },
2104 { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 },
2105 { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 },
2106 { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 },
2107 { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 },
2108 { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 },
2109 { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 },
2110 { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 },
2111 { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad },
2112 { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 },
2113 { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 },
2114 { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 },
2115 { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 },
2116 { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 },
2117 { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 },
2118 { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 },
2119 { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 },
2120 { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 },
2121 { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca },
2122 { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce },
2123 { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 },
2124 { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 },
2125 { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 },
2126 { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 },
2127 { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb },
2128 { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf },
2129 { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 },
2130 { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db },
2131 { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db },
2132 { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db },
2133 { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2134 { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2135 { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2136 { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2137 { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2138 { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2139 { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2140 { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2141 { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2142 { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2143 { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2144 { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2145 { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2146 { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2147 { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2148 { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2149 { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2150 { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2151 { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2152 { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2153 { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2154 { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2155 { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2156 { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2157 { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2158 { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
2159 { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 },
2160 { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 },
2161 { 0x0000a20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 },
2162 { 0x0000b20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 },
2163 { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
2164 { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
2165 { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
2166 { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
2167 { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 },
2168 { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 },
2169 { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b },
2170 { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 },
2171 { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 },
2172 { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a },
2173 { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 },
2174 { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
2175 { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b },
2176 { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 },
2177 { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 },
2178 { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a },
2179 { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 },
2180 { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b },
2181 { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 },
2182 { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 },
2183 { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a },
2184 { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 },
2185 { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a },
2186 { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 },
2187 { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 },
2188 { 0x0000784c, 0x0e4f048c, 0x0e4f048c, 0x0e4d048c, 0x0e4d048c, 0x0e4d048c },
2189 { 0x00007854, 0x12031828, 0x12031828, 0x12035828, 0x12035828, 0x12035828 },
2190 { 0x00007870, 0x807ec400, 0x807ec400, 0x807ec000, 0x807ec000, 0x807ec000 },
2191 { 0x0000788c, 0x00010000, 0x00010000, 0x00110000, 0x00110000, 0x00110000 },
2192};
2193
2194static const u32 ar9280Common_9280[][2] = {
2195 { 0x0000000c, 0x00000000 },
2196 { 0x00000030, 0x00020015 },
2197 { 0x00000034, 0x00000005 },
2198 { 0x00000040, 0x00000000 },
2199 { 0x00000044, 0x00000008 },
2200 { 0x00000048, 0x00000008 },
2201 { 0x0000004c, 0x00000010 },
2202 { 0x00000050, 0x00000000 },
2203 { 0x00000054, 0x0000001f },
2204 { 0x00000800, 0x00000000 },
2205 { 0x00000804, 0x00000000 },
2206 { 0x00000808, 0x00000000 },
2207 { 0x0000080c, 0x00000000 },
2208 { 0x00000810, 0x00000000 },
2209 { 0x00000814, 0x00000000 },
2210 { 0x00000818, 0x00000000 },
2211 { 0x0000081c, 0x00000000 },
2212 { 0x00000820, 0x00000000 },
2213 { 0x00000824, 0x00000000 },
2214 { 0x00001040, 0x002ffc0f },
2215 { 0x00001044, 0x002ffc0f },
2216 { 0x00001048, 0x002ffc0f },
2217 { 0x0000104c, 0x002ffc0f },
2218 { 0x00001050, 0x002ffc0f },
2219 { 0x00001054, 0x002ffc0f },
2220 { 0x00001058, 0x002ffc0f },
2221 { 0x0000105c, 0x002ffc0f },
2222 { 0x00001060, 0x002ffc0f },
2223 { 0x00001064, 0x002ffc0f },
2224 { 0x00001230, 0x00000000 },
2225 { 0x00001270, 0x00000000 },
2226 { 0x00001038, 0x00000000 },
2227 { 0x00001078, 0x00000000 },
2228 { 0x000010b8, 0x00000000 },
2229 { 0x000010f8, 0x00000000 },
2230 { 0x00001138, 0x00000000 },
2231 { 0x00001178, 0x00000000 },
2232 { 0x000011b8, 0x00000000 },
2233 { 0x000011f8, 0x00000000 },
2234 { 0x00001238, 0x00000000 },
2235 { 0x00001278, 0x00000000 },
2236 { 0x000012b8, 0x00000000 },
2237 { 0x000012f8, 0x00000000 },
2238 { 0x00001338, 0x00000000 },
2239 { 0x00001378, 0x00000000 },
2240 { 0x000013b8, 0x00000000 },
2241 { 0x000013f8, 0x00000000 },
2242 { 0x00001438, 0x00000000 },
2243 { 0x00001478, 0x00000000 },
2244 { 0x000014b8, 0x00000000 },
2245 { 0x000014f8, 0x00000000 },
2246 { 0x00001538, 0x00000000 },
2247 { 0x00001578, 0x00000000 },
2248 { 0x000015b8, 0x00000000 },
2249 { 0x000015f8, 0x00000000 },
2250 { 0x00001638, 0x00000000 },
2251 { 0x00001678, 0x00000000 },
2252 { 0x000016b8, 0x00000000 },
2253 { 0x000016f8, 0x00000000 },
2254 { 0x00001738, 0x00000000 },
2255 { 0x00001778, 0x00000000 },
2256 { 0x000017b8, 0x00000000 },
2257 { 0x000017f8, 0x00000000 },
2258 { 0x0000103c, 0x00000000 },
2259 { 0x0000107c, 0x00000000 },
2260 { 0x000010bc, 0x00000000 },
2261 { 0x000010fc, 0x00000000 },
2262 { 0x0000113c, 0x00000000 },
2263 { 0x0000117c, 0x00000000 },
2264 { 0x000011bc, 0x00000000 },
2265 { 0x000011fc, 0x00000000 },
2266 { 0x0000123c, 0x00000000 },
2267 { 0x0000127c, 0x00000000 },
2268 { 0x000012bc, 0x00000000 },
2269 { 0x000012fc, 0x00000000 },
2270 { 0x0000133c, 0x00000000 },
2271 { 0x0000137c, 0x00000000 },
2272 { 0x000013bc, 0x00000000 },
2273 { 0x000013fc, 0x00000000 },
2274 { 0x0000143c, 0x00000000 },
2275 { 0x0000147c, 0x00000000 },
2276 { 0x00004030, 0x00000002 },
2277 { 0x0000403c, 0x00000002 },
2278 { 0x00004024, 0x0000001f },
2279 { 0x00007010, 0x00000033 },
2280 { 0x00007038, 0x000004c2 },
2281 { 0x00008004, 0x00000000 },
2282 { 0x00008008, 0x00000000 },
2283 { 0x0000800c, 0x00000000 },
2284 { 0x00008018, 0x00000700 },
2285 { 0x00008020, 0x00000000 },
2286 { 0x00008038, 0x00000000 },
2287 { 0x0000803c, 0x00000000 },
2288 { 0x00008048, 0x40000000 },
2289 { 0x00008054, 0x00000000 },
2290 { 0x00008058, 0x00000000 },
2291 { 0x0000805c, 0x000fc78f },
2292 { 0x00008060, 0x0000000f },
2293 { 0x00008064, 0x00000000 },
2294 { 0x00008070, 0x00000000 },
2295 { 0x000080c0, 0x2a82301a },
2296 { 0x000080c4, 0x05dc01e0 },
2297 { 0x000080c8, 0x1f402710 },
2298 { 0x000080cc, 0x01f40000 },
2299 { 0x000080d0, 0x00001e00 },
2300 { 0x000080d4, 0x00000000 },
2301 { 0x000080d8, 0x00400000 },
2302 { 0x000080e0, 0xffffffff },
2303 { 0x000080e4, 0x0000ffff },
2304 { 0x000080e8, 0x003f3f3f },
2305 { 0x000080ec, 0x00000000 },
2306 { 0x000080f0, 0x00000000 },
2307 { 0x000080f4, 0x00000000 },
2308 { 0x000080f8, 0x00000000 },
2309 { 0x000080fc, 0x00020000 },
2310 { 0x00008100, 0x00020000 },
2311 { 0x00008104, 0x00000001 },
2312 { 0x00008108, 0x00000052 },
2313 { 0x0000810c, 0x00000000 },
2314 { 0x00008110, 0x00000168 },
2315 { 0x00008118, 0x000100aa },
2316 { 0x0000811c, 0x00003210 },
2317 { 0x00008120, 0x08f04800 },
2318 { 0x00008124, 0x00000000 },
2319 { 0x00008128, 0x00000000 },
2320 { 0x0000812c, 0x00000000 },
2321 { 0x00008130, 0x00000000 },
2322 { 0x00008134, 0x00000000 },
2323 { 0x00008138, 0x00000000 },
2324 { 0x0000813c, 0x00000000 },
2325 { 0x00008144, 0x00000000 },
2326 { 0x00008168, 0x00000000 },
2327 { 0x0000816c, 0x00000000 },
2328 { 0x00008170, 0x32143320 },
2329 { 0x00008174, 0xfaa4fa50 },
2330 { 0x00008178, 0x00000100 },
2331 { 0x0000817c, 0x00000000 },
2332 { 0x000081c4, 0x00000000 },
2333 { 0x000081d0, 0x00003210 },
2334 { 0x000081ec, 0x00000000 },
2335 { 0x000081f0, 0x00000000 },
2336 { 0x000081f4, 0x00000000 },
2337 { 0x000081f8, 0x00000000 },
2338 { 0x000081fc, 0x00000000 },
2339 { 0x00008200, 0x00000000 },
2340 { 0x00008204, 0x00000000 },
2341 { 0x00008208, 0x00000000 },
2342 { 0x0000820c, 0x00000000 },
2343 { 0x00008210, 0x00000000 },
2344 { 0x00008214, 0x00000000 },
2345 { 0x00008218, 0x00000000 },
2346 { 0x0000821c, 0x00000000 },
2347 { 0x00008220, 0x00000000 },
2348 { 0x00008224, 0x00000000 },
2349 { 0x00008228, 0x00000000 },
2350 { 0x0000822c, 0x00000000 },
2351 { 0x00008230, 0x00000000 },
2352 { 0x00008234, 0x00000000 },
2353 { 0x00008238, 0x00000000 },
2354 { 0x0000823c, 0x00000000 },
2355 { 0x00008240, 0x00100000 },
2356 { 0x00008244, 0x0010f400 },
2357 { 0x00008248, 0x00000100 },
2358 { 0x0000824c, 0x0001e800 },
2359 { 0x00008250, 0x00000000 },
2360 { 0x00008254, 0x00000000 },
2361 { 0x00008258, 0x00000000 },
2362 { 0x0000825c, 0x400000ff },
2363 { 0x00008260, 0x00080922 },
2364 { 0x00008270, 0x00000000 },
2365 { 0x00008274, 0x40000000 },
2366 { 0x00008278, 0x003e4180 },
2367 { 0x0000827c, 0x00000000 },
2368 { 0x00008284, 0x0000002c },
2369 { 0x00008288, 0x0000002c },
2370 { 0x0000828c, 0x00000000 },
2371 { 0x00008294, 0x00000000 },
2372 { 0x00008298, 0x00000000 },
2373 { 0x00008300, 0x00000000 },
2374 { 0x00008304, 0x00000000 },
2375 { 0x00008308, 0x00000000 },
2376 { 0x0000830c, 0x00000000 },
2377 { 0x00008310, 0x00000000 },
2378 { 0x00008314, 0x00000000 },
2379 { 0x00008318, 0x00000000 },
2380 { 0x00008328, 0x00000000 },
2381 { 0x0000832c, 0x00000007 },
2382 { 0x00008330, 0x00000302 },
2383 { 0x00008334, 0x00000e00 },
2384 { 0x00008338, 0x00000000 },
2385 { 0x0000833c, 0x00000000 },
2386 { 0x00008340, 0x000107ff },
2387 { 0x00008344, 0x00000000 },
2388 { 0x00009808, 0x00000000 },
2389 { 0x0000980c, 0xaf268e30 },
2390 { 0x00009810, 0xfd14e000 },
2391 { 0x00009814, 0x9c0a9f6b },
2392 { 0x0000981c, 0x00000000 },
2393 { 0x0000982c, 0x0000a000 },
2394 { 0x00009830, 0x00000000 },
2395 { 0x0000983c, 0x00200400 },
2396 { 0x00009840, 0x206a01ae },
2397 { 0x0000984c, 0x0040233c },
2398 { 0x0000a84c, 0x0040233c },
2399 { 0x00009854, 0x00000044 },
2400 { 0x00009900, 0x00000000 },
2401 { 0x00009904, 0x00000000 },
2402 { 0x00009908, 0x00000000 },
2403 { 0x0000990c, 0x00000000 },
2404 { 0x0000991c, 0x10000fff },
2405 { 0x00009920, 0x04900000 },
2406 { 0x0000a920, 0x04900000 },
2407 { 0x00009928, 0x00000001 },
2408 { 0x0000992c, 0x00000004 },
2409 { 0x00009934, 0x1e1f2022 },
2410 { 0x00009938, 0x0a0b0c0d },
2411 { 0x0000993c, 0x00000000 },
2412 { 0x00009948, 0x9280c00a },
2413 { 0x0000994c, 0x00020028 },
2414 { 0x00009954, 0xe250a51e },
2415 { 0x00009958, 0x3388ffff },
2416 { 0x00009940, 0x00781204 },
2417 { 0x0000c95c, 0x004b6a8e },
2418 { 0x0000c968, 0x000003ce },
2419 { 0x00009970, 0x190fb514 },
2420 { 0x00009974, 0x00000000 },
2421 { 0x00009978, 0x00000001 },
2422 { 0x0000997c, 0x00000000 },
2423 { 0x00009980, 0x00000000 },
2424 { 0x00009984, 0x00000000 },
2425 { 0x00009988, 0x00000000 },
2426 { 0x0000998c, 0x00000000 },
2427 { 0x00009990, 0x00000000 },
2428 { 0x00009994, 0x00000000 },
2429 { 0x00009998, 0x00000000 },
2430 { 0x0000999c, 0x00000000 },
2431 { 0x000099a0, 0x00000000 },
2432 { 0x000099a4, 0x00000001 },
2433 { 0x000099a8, 0x201fff00 },
2434 { 0x000099ac, 0x006f00c4 },
2435 { 0x000099b0, 0x03051000 },
2436 { 0x000099b4, 0x00000820 },
2437 { 0x000099dc, 0x00000000 },
2438 { 0x000099e0, 0x00000000 },
2439 { 0x000099e4, 0xaaaaaaaa },
2440 { 0x000099e8, 0x3c466478 },
2441 { 0x000099ec, 0x0cc80caa },
2442 { 0x000099fc, 0x00001042 },
2443 { 0x0000a210, 0x4080a333 },
2444 { 0x0000a214, 0x40206c10 },
2445 { 0x0000a218, 0x009c4060 },
2446 { 0x0000a220, 0x01834061 },
2447 { 0x0000a224, 0x00000400 },
2448 { 0x0000a228, 0x000003b5 },
2449 { 0x0000a22c, 0x23277200 },
2450 { 0x0000a234, 0x20202020 },
2451 { 0x0000a238, 0x20202020 },
2452 { 0x0000a23c, 0x13c889af },
2453 { 0x0000a240, 0x38490a20 },
2454 { 0x0000a244, 0x00007bb6 },
2455 { 0x0000a248, 0x0fff3ffc },
2456 { 0x0000a24c, 0x00000001 },
2457 { 0x0000a250, 0x001da000 },
2458 { 0x0000a254, 0x00000000 },
2459 { 0x0000a258, 0x0cdbd380 },
2460 { 0x0000a25c, 0x0f0f0f01 },
2461 { 0x0000a260, 0xdfa91f01 },
2462 { 0x0000a268, 0x00000000 },
2463 { 0x0000a26c, 0x0ebae9c6 },
2464 { 0x0000b26c, 0x0ebae9c6 },
2465 { 0x0000d270, 0x00820820 },
2466 { 0x0000a278, 0x1ce739ce },
2467 { 0x0000a27c, 0x050701ce },
2468 { 0x0000a358, 0x7999aa0f },
2469 { 0x0000d35c, 0x07ffffef },
2470 { 0x0000d360, 0x0fffffe7 },
2471 { 0x0000d364, 0x17ffffe5 },
2472 { 0x0000d368, 0x1fffffe4 },
2473 { 0x0000d36c, 0x37ffffe3 },
2474 { 0x0000d370, 0x3fffffe3 },
2475 { 0x0000d374, 0x57ffffe3 },
2476 { 0x0000d378, 0x5fffffe2 },
2477 { 0x0000d37c, 0x7fffffe2 },
2478 { 0x0000d380, 0x7f3c7bba },
2479 { 0x0000d384, 0xf3307ff0 },
2480 { 0x0000a388, 0x0c000000 },
2481 { 0x0000a38c, 0x20202020 },
2482 { 0x0000a390, 0x20202020 },
2483 { 0x0000a394, 0x1ce739ce },
2484 { 0x0000a398, 0x000001ce },
2485 { 0x0000a39c, 0x00000001 },
2486 { 0x0000a3a0, 0x00000000 },
2487 { 0x0000a3a4, 0x00000000 },
2488 { 0x0000a3a8, 0x00000000 },
2489 { 0x0000a3ac, 0x00000000 },
2490 { 0x0000a3b0, 0x00000000 },
2491 { 0x0000a3b4, 0x00000000 },
2492 { 0x0000a3b8, 0x00000000 },
2493 { 0x0000a3bc, 0x00000000 },
2494 { 0x0000a3c0, 0x00000000 },
2495 { 0x0000a3c4, 0x00000000 },
2496 { 0x0000a3c8, 0x00000246 },
2497 { 0x0000a3cc, 0x20202020 },
2498 { 0x0000a3d0, 0x20202020 },
2499 { 0x0000a3d4, 0x20202020 },
2500 { 0x0000a3dc, 0x1ce739ce },
2501 { 0x0000a3e0, 0x000001ce },
2502 { 0x0000a3e4, 0x00000000 },
2503 { 0x0000a3e8, 0x18c43433 },
2504 { 0x0000a3ec, 0x00f38081 },
2505 { 0x00007800, 0x00040000 },
2506 { 0x00007804, 0xdb005012 },
2507 { 0x00007808, 0x04924914 },
2508 { 0x0000780c, 0x21084210 },
2509 { 0x00007810, 0x6d801300 },
2510 { 0x00007814, 0x0019beff },
2511 { 0x00007818, 0x07e40000 },
2512 { 0x0000781c, 0x00492000 },
2513 { 0x00007820, 0x92492480 },
2514 { 0x00007824, 0x00040000 },
2515 { 0x00007828, 0xdb005012 },
2516 { 0x0000782c, 0x04924914 },
2517 { 0x00007830, 0x21084210 },
2518 { 0x00007834, 0x6d801300 },
2519 { 0x00007838, 0x0019beff },
2520 { 0x0000783c, 0x07e40000 },
2521 { 0x00007840, 0x00492000 },
2522 { 0x00007844, 0x92492480 },
2523 { 0x00007848, 0x00120000 },
2524 { 0x00007850, 0x54214514 },
2525 { 0x00007858, 0x92592692 },
2526 { 0x00007860, 0x52802000 },
2527 { 0x00007864, 0x0a8e370e },
2528 { 0x00007868, 0xc0102850 },
2529 { 0x0000786c, 0x812d4000 },
2530 { 0x00007874, 0x001b6db0 },
2531 { 0x00007878, 0x00376b63 },
2532 { 0x0000787c, 0x06db6db6 },
2533 { 0x00007880, 0x006d8000 },
2534 { 0x00007884, 0xffeffffe },
2535 { 0x00007888, 0xffeffffe },
2536 { 0x00007890, 0x00060aeb },
2537 { 0x00007894, 0x5a108000 },
2538 { 0x00007898, 0x2a850160 },
2539};
2540
2541/* XXX 9280 2 */
2542static const u32 ar9280Modes_9280_2[][6] = {
2543 { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
2544 { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
2545 { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
2546 { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
2547 { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
2548 { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
2549 { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 },
2550 { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a },
2551 { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
2552 { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
2553 { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
2554 { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
2555 { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
2556 { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
2557 { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
2558 { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e },
2559 { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
2560 { 0x00009850, 0x6c4000e2, 0x6c4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 },
2561 { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
2562 { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x3139605e, 0x31395d5e, 0x31395d5e },
2563 { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
2564 { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
2565 { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
2566 { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
2567 { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
2568 { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
2569 { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
2570 { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 },
2571 { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
2572 { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
2573 { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 },
2574 { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c },
2575 { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 },
2576 { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
2577 { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
2578 { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
2579 { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
2580 { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
2581 { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
2582 { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
2583 { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 },
2584 { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
2585 { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
2586 { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
2587 { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
2588 { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 },
2589 { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
2590 { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
2591 { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 },
2592};
2593
2594static const u32 ar9280Common_9280_2[][2] = {
2595 { 0x0000000c, 0x00000000 },
2596 { 0x00000030, 0x00020015 },
2597 { 0x00000034, 0x00000005 },
2598 { 0x00000040, 0x00000000 },
2599 { 0x00000044, 0x00000008 },
2600 { 0x00000048, 0x00000008 },
2601 { 0x0000004c, 0x00000010 },
2602 { 0x00000050, 0x00000000 },
2603 { 0x00000054, 0x0000001f },
2604 { 0x00000800, 0x00000000 },
2605 { 0x00000804, 0x00000000 },
2606 { 0x00000808, 0x00000000 },
2607 { 0x0000080c, 0x00000000 },
2608 { 0x00000810, 0x00000000 },
2609 { 0x00000814, 0x00000000 },
2610 { 0x00000818, 0x00000000 },
2611 { 0x0000081c, 0x00000000 },
2612 { 0x00000820, 0x00000000 },
2613 { 0x00000824, 0x00000000 },
2614 { 0x00001040, 0x002ffc0f },
2615 { 0x00001044, 0x002ffc0f },
2616 { 0x00001048, 0x002ffc0f },
2617 { 0x0000104c, 0x002ffc0f },
2618 { 0x00001050, 0x002ffc0f },
2619 { 0x00001054, 0x002ffc0f },
2620 { 0x00001058, 0x002ffc0f },
2621 { 0x0000105c, 0x002ffc0f },
2622 { 0x00001060, 0x002ffc0f },
2623 { 0x00001064, 0x002ffc0f },
2624 { 0x00001230, 0x00000000 },
2625 { 0x00001270, 0x00000000 },
2626 { 0x00001038, 0x00000000 },
2627 { 0x00001078, 0x00000000 },
2628 { 0x000010b8, 0x00000000 },
2629 { 0x000010f8, 0x00000000 },
2630 { 0x00001138, 0x00000000 },
2631 { 0x00001178, 0x00000000 },
2632 { 0x000011b8, 0x00000000 },
2633 { 0x000011f8, 0x00000000 },
2634 { 0x00001238, 0x00000000 },
2635 { 0x00001278, 0x00000000 },
2636 { 0x000012b8, 0x00000000 },
2637 { 0x000012f8, 0x00000000 },
2638 { 0x00001338, 0x00000000 },
2639 { 0x00001378, 0x00000000 },
2640 { 0x000013b8, 0x00000000 },
2641 { 0x000013f8, 0x00000000 },
2642 { 0x00001438, 0x00000000 },
2643 { 0x00001478, 0x00000000 },
2644 { 0x000014b8, 0x00000000 },
2645 { 0x000014f8, 0x00000000 },
2646 { 0x00001538, 0x00000000 },
2647 { 0x00001578, 0x00000000 },
2648 { 0x000015b8, 0x00000000 },
2649 { 0x000015f8, 0x00000000 },
2650 { 0x00001638, 0x00000000 },
2651 { 0x00001678, 0x00000000 },
2652 { 0x000016b8, 0x00000000 },
2653 { 0x000016f8, 0x00000000 },
2654 { 0x00001738, 0x00000000 },
2655 { 0x00001778, 0x00000000 },
2656 { 0x000017b8, 0x00000000 },
2657 { 0x000017f8, 0x00000000 },
2658 { 0x0000103c, 0x00000000 },
2659 { 0x0000107c, 0x00000000 },
2660 { 0x000010bc, 0x00000000 },
2661 { 0x000010fc, 0x00000000 },
2662 { 0x0000113c, 0x00000000 },
2663 { 0x0000117c, 0x00000000 },
2664 { 0x000011bc, 0x00000000 },
2665 { 0x000011fc, 0x00000000 },
2666 { 0x0000123c, 0x00000000 },
2667 { 0x0000127c, 0x00000000 },
2668 { 0x000012bc, 0x00000000 },
2669 { 0x000012fc, 0x00000000 },
2670 { 0x0000133c, 0x00000000 },
2671 { 0x0000137c, 0x00000000 },
2672 { 0x000013bc, 0x00000000 },
2673 { 0x000013fc, 0x00000000 },
2674 { 0x0000143c, 0x00000000 },
2675 { 0x0000147c, 0x00000000 },
2676 { 0x00004030, 0x00000002 },
2677 { 0x0000403c, 0x00000002 },
2678 { 0x00004024, 0x0000001f },
2679 { 0x00004060, 0x00000000 },
2680 { 0x00004064, 0x00000000 },
2681 { 0x00007010, 0x00000033 },
2682 { 0x00007034, 0x00000002 },
2683 { 0x00007038, 0x000004c2 },
2684 { 0x00008004, 0x00000000 },
2685 { 0x00008008, 0x00000000 },
2686 { 0x0000800c, 0x00000000 },
2687 { 0x00008018, 0x00000700 },
2688 { 0x00008020, 0x00000000 },
2689 { 0x00008038, 0x00000000 },
2690 { 0x0000803c, 0x00000000 },
2691 { 0x00008048, 0x40000000 },
2692 { 0x00008054, 0x00000000 },
2693 { 0x00008058, 0x00000000 },
2694 { 0x0000805c, 0x000fc78f },
2695 { 0x00008060, 0x0000000f },
2696 { 0x00008064, 0x00000000 },
2697 { 0x00008070, 0x00000000 },
2698 { 0x000080c0, 0x2a80001a },
2699 { 0x000080c4, 0x05dc01e0 },
2700 { 0x000080c8, 0x1f402710 },
2701 { 0x000080cc, 0x01f40000 },
2702 { 0x000080d0, 0x00001e00 },
2703 { 0x000080d4, 0x00000000 },
2704 { 0x000080d8, 0x00400000 },
2705 { 0x000080e0, 0xffffffff },
2706 { 0x000080e4, 0x0000ffff },
2707 { 0x000080e8, 0x003f3f3f },
2708 { 0x000080ec, 0x00000000 },
2709 { 0x000080f0, 0x00000000 },
2710 { 0x000080f4, 0x00000000 },
2711 { 0x000080f8, 0x00000000 },
2712 { 0x000080fc, 0x00020000 },
2713 { 0x00008100, 0x00020000 },
2714 { 0x00008104, 0x00000001 },
2715 { 0x00008108, 0x00000052 },
2716 { 0x0000810c, 0x00000000 },
2717 { 0x00008110, 0x00000168 },
2718 { 0x00008118, 0x000100aa },
2719 { 0x0000811c, 0x00003210 },
2720 { 0x00008124, 0x00000000 },
2721 { 0x00008128, 0x00000000 },
2722 { 0x0000812c, 0x00000000 },
2723 { 0x00008130, 0x00000000 },
2724 { 0x00008134, 0x00000000 },
2725 { 0x00008138, 0x00000000 },
2726 { 0x0000813c, 0x00000000 },
2727 { 0x00008144, 0xffffffff },
2728 { 0x00008168, 0x00000000 },
2729 { 0x0000816c, 0x00000000 },
2730 { 0x00008170, 0x32143320 },
2731 { 0x00008174, 0xfaa4fa50 },
2732 { 0x00008178, 0x00000100 },
2733 { 0x0000817c, 0x00000000 },
2734 { 0x000081c0, 0x00000000 },
2735 { 0x000081ec, 0x00000000 },
2736 { 0x000081f0, 0x00000000 },
2737 { 0x000081f4, 0x00000000 },
2738 { 0x000081f8, 0x00000000 },
2739 { 0x000081fc, 0x00000000 },
2740 { 0x00008200, 0x00000000 },
2741 { 0x00008204, 0x00000000 },
2742 { 0x00008208, 0x00000000 },
2743 { 0x0000820c, 0x00000000 },
2744 { 0x00008210, 0x00000000 },
2745 { 0x00008214, 0x00000000 },
2746 { 0x00008218, 0x00000000 },
2747 { 0x0000821c, 0x00000000 },
2748 { 0x00008220, 0x00000000 },
2749 { 0x00008224, 0x00000000 },
2750 { 0x00008228, 0x00000000 },
2751 { 0x0000822c, 0x00000000 },
2752 { 0x00008230, 0x00000000 },
2753 { 0x00008234, 0x00000000 },
2754 { 0x00008238, 0x00000000 },
2755 { 0x0000823c, 0x00000000 },
2756 { 0x00008240, 0x00100000 },
2757 { 0x00008244, 0x0010f400 },
2758 { 0x00008248, 0x00000100 },
2759 { 0x0000824c, 0x0001e800 },
2760 { 0x00008250, 0x00000000 },
2761 { 0x00008254, 0x00000000 },
2762 { 0x00008258, 0x00000000 },
2763 { 0x0000825c, 0x400000ff },
2764 { 0x00008260, 0x00080922 },
2765 { 0x00008264, 0xa8a00010 },
2766 { 0x00008270, 0x00000000 },
2767 { 0x00008274, 0x40000000 },
2768 { 0x00008278, 0x003e4180 },
2769 { 0x0000827c, 0x00000000 },
2770 { 0x00008284, 0x0000002c },
2771 { 0x00008288, 0x0000002c },
2772 { 0x0000828c, 0x00000000 },
2773 { 0x00008294, 0x00000000 },
2774 { 0x00008298, 0x00000000 },
2775 { 0x0000829c, 0x00000000 },
2776 { 0x00008300, 0x00000040 },
2777 { 0x00008314, 0x00000000 },
2778 { 0x00008328, 0x00000000 },
2779 { 0x0000832c, 0x00000007 },
2780 { 0x00008330, 0x00000302 },
2781 { 0x00008334, 0x00000e00 },
2782 { 0x00008338, 0x00ff0000 },
2783 { 0x0000833c, 0x00000000 },
2784 { 0x00008340, 0x000107ff },
2785 { 0x00008344, 0x00581043 },
2786 { 0x00009808, 0x00000000 },
2787 { 0x0000980c, 0xafa68e30 },
2788 { 0x00009810, 0xfd14e000 },
2789 { 0x00009814, 0x9c0a9f6b },
2790 { 0x0000981c, 0x00000000 },
2791 { 0x0000982c, 0x0000a000 },
2792 { 0x00009830, 0x00000000 },
2793 { 0x0000983c, 0x00200400 },
2794 { 0x0000984c, 0x0040233c },
2795 { 0x0000a84c, 0x0040233c },
2796 { 0x00009854, 0x00000044 },
2797 { 0x00009900, 0x00000000 },
2798 { 0x00009904, 0x00000000 },
2799 { 0x00009908, 0x00000000 },
2800 { 0x0000990c, 0x00000000 },
2801 { 0x00009910, 0x01002310 },
2802 { 0x0000991c, 0x10000fff },
2803 { 0x00009920, 0x04900000 },
2804 { 0x0000a920, 0x04900000 },
2805 { 0x00009928, 0x00000001 },
2806 { 0x0000992c, 0x00000004 },
2807 { 0x00009934, 0x1e1f2022 },
2808 { 0x00009938, 0x0a0b0c0d },
2809 { 0x0000993c, 0x00000000 },
2810 { 0x00009948, 0x9280c00a },
2811 { 0x0000994c, 0x00020028 },
2812 { 0x00009954, 0x5f3ca3de },
2813 { 0x00009958, 0x2108ecff },
2814 { 0x00009940, 0x14750604 },
2815 { 0x0000c95c, 0x004b6a8e },
2816 { 0x0000c968, 0x000003ce },
2817 { 0x00009970, 0x190fb515 },
2818 { 0x00009974, 0x00000000 },
2819 { 0x00009978, 0x00000001 },
2820 { 0x0000997c, 0x00000000 },
2821 { 0x00009980, 0x00000000 },
2822 { 0x00009984, 0x00000000 },
2823 { 0x00009988, 0x00000000 },
2824 { 0x0000998c, 0x00000000 },
2825 { 0x00009990, 0x00000000 },
2826 { 0x00009994, 0x00000000 },
2827 { 0x00009998, 0x00000000 },
2828 { 0x0000999c, 0x00000000 },
2829 { 0x000099a0, 0x00000000 },
2830 { 0x000099a4, 0x00000001 },
2831 { 0x000099a8, 0x201fff00 },
2832 { 0x000099ac, 0x006f0000 },
2833 { 0x000099b0, 0x03051000 },
2834 { 0x000099b4, 0x00000820 },
2835 { 0x000099dc, 0x00000000 },
2836 { 0x000099e0, 0x00000000 },
2837 { 0x000099e4, 0xaaaaaaaa },
2838 { 0x000099e8, 0x3c466478 },
2839 { 0x000099ec, 0x0cc80caa },
2840 { 0x000099f0, 0x00000000 },
2841 { 0x000099fc, 0x00001042 },
2842 { 0x0000a208, 0x803e4788 },
2843 { 0x0000a210, 0x4080a333 },
2844 { 0x0000a214, 0x40206c10 },
2845 { 0x0000a218, 0x009c4060 },
2846 { 0x0000a220, 0x01834061 },
2847 { 0x0000a224, 0x00000400 },
2848 { 0x0000a228, 0x000003b5 },
2849 { 0x0000a22c, 0x233f7180 },
2850 { 0x0000a234, 0x20202020 },
2851 { 0x0000a238, 0x20202020 },
2852 { 0x0000a23c, 0x13c88000 },
2853 { 0x0000a240, 0x38490a20 },
2854 { 0x0000a244, 0x00007bb6 },
2855 { 0x0000a248, 0x0fff3ffc },
2856 { 0x0000a24c, 0x00000000 },
2857 { 0x0000a254, 0x00000000 },
2858 { 0x0000a258, 0x0cdbd380 },
2859 { 0x0000a25c, 0x0f0f0f01 },
2860 { 0x0000a260, 0xdfa91f01 },
2861 { 0x0000a268, 0x00000000 },
2862 { 0x0000a26c, 0x0ebae9c6 },
2863 { 0x0000b26c, 0x0ebae9c6 },
2864 { 0x0000d270, 0x00820820 },
2865 { 0x0000a278, 0x1ce739ce },
2866 { 0x0000d35c, 0x07ffffef },
2867 { 0x0000d360, 0x0fffffe7 },
2868 { 0x0000d364, 0x17ffffe5 },
2869 { 0x0000d368, 0x1fffffe4 },
2870 { 0x0000d36c, 0x37ffffe3 },
2871 { 0x0000d370, 0x3fffffe3 },
2872 { 0x0000d374, 0x57ffffe3 },
2873 { 0x0000d378, 0x5fffffe2 },
2874 { 0x0000d37c, 0x7fffffe2 },
2875 { 0x0000d380, 0x7f3c7bba },
2876 { 0x0000d384, 0xf3307ff0 },
2877 { 0x0000a388, 0x0c000000 },
2878 { 0x0000a38c, 0x20202020 },
2879 { 0x0000a390, 0x20202020 },
2880 { 0x0000a394, 0x1ce739ce },
2881 { 0x0000a398, 0x000001ce },
2882 { 0x0000a39c, 0x00000001 },
2883 { 0x0000a3a0, 0x00000000 },
2884 { 0x0000a3a4, 0x00000000 },
2885 { 0x0000a3a8, 0x00000000 },
2886 { 0x0000a3ac, 0x00000000 },
2887 { 0x0000a3b0, 0x00000000 },
2888 { 0x0000a3b4, 0x00000000 },
2889 { 0x0000a3b8, 0x00000000 },
2890 { 0x0000a3bc, 0x00000000 },
2891 { 0x0000a3c0, 0x00000000 },
2892 { 0x0000a3c4, 0x00000000 },
2893 { 0x0000a3c8, 0x00000246 },
2894 { 0x0000a3cc, 0x20202020 },
2895 { 0x0000a3d0, 0x20202020 },
2896 { 0x0000a3d4, 0x20202020 },
2897 { 0x0000a3dc, 0x1ce739ce },
2898 { 0x0000a3e0, 0x000001ce },
2899 { 0x0000a3e4, 0x00000000 },
2900 { 0x0000a3e8, 0x18c43433 },
2901 { 0x0000a3ec, 0x00f70081 },
2902 { 0x00007800, 0x00040000 },
2903 { 0x00007804, 0xdb005012 },
2904 { 0x00007808, 0x04924914 },
2905 { 0x0000780c, 0x21084210 },
2906 { 0x00007810, 0x6d801300 },
2907 { 0x00007818, 0x07e41000 },
2908 { 0x00007824, 0x00040000 },
2909 { 0x00007828, 0xdb005012 },
2910 { 0x0000782c, 0x04924914 },
2911 { 0x00007830, 0x21084210 },
2912 { 0x00007834, 0x6d801300 },
2913 { 0x0000783c, 0x07e40000 },
2914 { 0x00007848, 0x00100000 },
2915 { 0x0000784c, 0x773f0567 },
2916 { 0x00007850, 0x54214514 },
2917 { 0x00007854, 0x12035828 },
2918 { 0x00007858, 0x9259269a },
2919 { 0x00007860, 0x52802000 },
2920 { 0x00007864, 0x0a8e370e },
2921 { 0x00007868, 0xc0102850 },
2922 { 0x0000786c, 0x812d4000 },
2923 { 0x00007870, 0x807ec400 },
2924 { 0x00007874, 0x001b6db0 },
2925 { 0x00007878, 0x00376b63 },
2926 { 0x0000787c, 0x06db6db6 },
2927 { 0x00007880, 0x006d8000 },
2928 { 0x00007884, 0xffeffffe },
2929 { 0x00007888, 0xffeffffe },
2930 { 0x0000788c, 0x00010000 },
2931 { 0x00007890, 0x02060aeb },
2932 { 0x00007898, 0x2a850160 },
2933};
2934
2935static const u32 ar9280Modes_fast_clock_9280_2[][3] = {
2936 { 0x00001030, 0x00000268, 0x000004d0 },
2937 { 0x00001070, 0x0000018c, 0x00000318 },
2938 { 0x000010b0, 0x00000fd0, 0x00001fa0 },
2939 { 0x00008014, 0x044c044c, 0x08980898 },
2940 { 0x0000801c, 0x148ec02b, 0x148ec057 },
2941 { 0x00008318, 0x000044c0, 0x00008980 },
2942 { 0x00009820, 0x02020200, 0x02020200 },
2943 { 0x00009824, 0x00000f0f, 0x00000f0f },
2944 { 0x00009828, 0x0b020001, 0x0b020001 },
2945 { 0x00009834, 0x00000f0f, 0x00000f0f },
2946 { 0x00009844, 0x03721821, 0x03721821 },
2947 { 0x00009914, 0x00000898, 0x00001130 },
2948 { 0x00009918, 0x0000000b, 0x00000016 },
2949};
2950
2951static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = {
2952 { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
2953 { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
2954 { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
2955 { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
2956 { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
2957 { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
2958 { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
2959 { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
2960 { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
2961 { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
2962 { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
2963 { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
2964 { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
2965 { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
2966 { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
2967 { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
2968 { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
2969 { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
2970 { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
2971 { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
2972 { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
2973 { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
2974 { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
2975 { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
2976 { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
2977 { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
2978 { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
2979 { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
2980 { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
2981 { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
2982 { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
2983 { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
2984 { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
2985 { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
2986 { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
2987 { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
2988 { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
2989 { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
2990 { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
2991 { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
2992 { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
2993 { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
2994 { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
2995 { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
2996 { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
2997 { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
2998 { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
2999 { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
3000 { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10 },
3001 { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b14, 0x00008b14, 0x00008b14 },
3002 { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b01, 0x00008b01, 0x00008b01 },
3003 { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b05, 0x00008b05, 0x00008b05 },
3004 { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b09, 0x00008b09, 0x00008b09 },
3005 { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b0d, 0x00008b0d, 0x00008b0d },
3006 { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b11, 0x00008b11, 0x00008b11 },
3007 { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b15, 0x00008b15, 0x00008b15 },
3008 { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008b02, 0x00008b02, 0x00008b02 },
3009 { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008b06, 0x00008b06, 0x00008b06 },
3010 { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008b0a, 0x00008b0a, 0x00008b0a },
3011 { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008b0e, 0x00008b0e, 0x00008b0e },
3012 { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008b12, 0x00008b12, 0x00008b12 },
3013 { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008b16, 0x00008b16, 0x00008b16 },
3014 { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008b03, 0x00008b03, 0x00008b03 },
3015 { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008b07, 0x00008b07, 0x00008b07 },
3016 { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008b0b, 0x00008b0b, 0x00008b0b },
3017 { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008b0f, 0x00008b0f, 0x00008b0f },
3018 { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008b13, 0x00008b13, 0x00008b13 },
3019 { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008b17, 0x00008b17, 0x00008b17 },
3020 { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008b23, 0x00008b23, 0x00008b23 },
3021 { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008b27, 0x00008b27, 0x00008b27 },
3022 { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008b2b, 0x00008b2b, 0x00008b2b },
3023 { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008b2f, 0x00008b2f, 0x00008b2f },
3024 { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008b33, 0x00008b33, 0x00008b33 },
3025 { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008b37, 0x00008b37, 0x00008b37 },
3026 { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008b43, 0x00008b43, 0x00008b43 },
3027 { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008b47, 0x00008b47, 0x00008b47 },
3028 { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008b4b, 0x00008b4b, 0x00008b4b },
3029 { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008b4f, 0x00008b4f, 0x00008b4f },
3030 { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008b53, 0x00008b53, 0x00008b53 },
3031 { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008b57, 0x00008b57, 0x00008b57 },
3032 { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3033 { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3034 { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3035 { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3036 { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3037 { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3038 { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3039 { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3040 { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3041 { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3042 { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3043 { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3044 { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3045 { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3046 { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3047 { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3048 { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3049 { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3050 { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3051 { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3052 { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3053 { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3054 { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3055 { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3056 { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3057 { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3058 { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3059 { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3060 { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3061 { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3062 { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3063 { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3064 { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3065 { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3066 { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3067 { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3068 { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3069 { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3070 { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3071 { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3072 { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3073 { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3074 { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3075 { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3076 { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3077 { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3078 { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3079 { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
3080 { 0x00009848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 },
3081 { 0x0000a848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 },
3082};
3083
3084static const u32 ar9280Modes_original_rxgain_9280_2[][6] = {
3085 { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
3086 { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
3087 { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
3088 { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
3089 { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
3090 { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
3091 { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
3092 { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
3093 { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
3094 { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
3095 { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
3096 { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
3097 { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
3098 { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
3099 { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
3100 { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
3101 { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
3102 { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
3103 { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
3104 { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
3105 { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
3106 { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
3107 { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
3108 { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
3109 { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
3110 { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
3111 { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
3112 { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
3113 { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
3114 { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
3115 { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
3116 { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
3117 { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
3118 { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
3119 { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
3120 { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
3121 { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
3122 { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
3123 { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
3124 { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
3125 { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
3126 { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
3127 { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
3128 { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
3129 { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
3130 { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
3131 { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
3132 { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
3133 { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
3134 { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
3135 { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
3136 { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
3137 { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
3138 { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
3139 { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
3140 { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
3141 { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
3142 { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
3143 { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c },
3144 { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 },
3145 { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 },
3146 { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 },
3147 { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 },
3148 { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 },
3149 { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 },
3150 { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 },
3151 { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 },
3152 { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 },
3153 { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 },
3154 { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 },
3155 { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 },
3156 { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c },
3157 { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 },
3158 { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 },
3159 { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 },
3160 { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 },
3161 { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 },
3162 { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 },
3163 { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 },
3164 { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 },
3165 { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad },
3166 { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 },
3167 { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 },
3168 { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 },
3169 { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 },
3170 { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 },
3171 { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 },
3172 { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 },
3173 { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 },
3174 { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 },
3175 { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca },
3176 { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce },
3177 { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 },
3178 { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 },
3179 { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 },
3180 { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 },
3181 { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb },
3182 { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf },
3183 { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 },
3184 { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db },
3185 { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db },
3186 { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db },
3187 { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3188 { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3189 { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3190 { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3191 { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3192 { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3193 { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3194 { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3195 { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3196 { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3197 { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3198 { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3199 { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3200 { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3201 { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3202 { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3203 { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3204 { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3205 { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3206 { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3207 { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3208 { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3209 { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3210 { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3211 { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3212 { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
3213 { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
3214 { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
3215};
3216
3217static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = {
3218 { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
3219 { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
3220 { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
3221 { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
3222 { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
3223 { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
3224 { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
3225 { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
3226 { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
3227 { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
3228 { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
3229 { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
3230 { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
3231 { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
3232 { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
3233 { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
3234 { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
3235 { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
3236 { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
3237 { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
3238 { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
3239 { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
3240 { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
3241 { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
3242 { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
3243 { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
3244 { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
3245 { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
3246 { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
3247 { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
3248 { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
3249 { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
3250 { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
3251 { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
3252 { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
3253 { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
3254 { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
3255 { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
3256 { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
3257 { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
3258 { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
3259 { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
3260 { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
3261 { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
3262 { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
3263 { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
3264 { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
3265 { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
3266 { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
3267 { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
3268 { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
3269 { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
3270 { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
3271 { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
3272 { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
3273 { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
3274 { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
3275 { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
3276 { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310 },
3277 { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314 },
3278 { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320 },
3279 { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324 },
3280 { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328 },
3281 { 0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c },
3282 { 0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330 },
3283 { 0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334 },
3284 { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321 },
3285 { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325 },
3286 { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329 },
3287 { 0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d },
3288 { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331 },
3289 { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335 },
3290 { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322 },
3291 { 0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326 },
3292 { 0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a },
3293 { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e },
3294 { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332 },
3295 { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336 },
3296 { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323 },
3297 { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327 },
3298 { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b },
3299 { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f },
3300 { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333 },
3301 { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337 },
3302 { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343 },
3303 { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347 },
3304 { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b },
3305 { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f },
3306 { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353 },
3307 { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357 },
3308 { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b },
3309 { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b },
3310 { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b },
3311 { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b },
3312 { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b },
3313 { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b },
3314 { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b },
3315 { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b },
3316 { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b },
3317 { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b },
3318 { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b },
3319 { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b },
3320 { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3321 { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3322 { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3323 { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3324 { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3325 { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3326 { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3327 { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3328 { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3329 { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3330 { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3331 { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3332 { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3333 { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3334 { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3335 { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3336 { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3337 { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3338 { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3339 { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3340 { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3341 { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3342 { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3343 { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3344 { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3345 { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
3346 { 0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a },
3347 { 0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a },
3348};
3349
3350static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = {
3351 { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
3352 { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 },
3353 { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 },
3354 { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010 },
3355 { 0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012 },
3356 { 0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014 },
3357 { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a },
3358 { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 },
3359 { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
3360 { 0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411 },
3361 { 0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413 },
3362 { 0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811 },
3363 { 0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813 },
3364 { 0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14 },
3365 { 0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50 },
3366 { 0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c },
3367 { 0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a },
3368 { 0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92 },
3369 { 0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 },
3370 { 0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 },
3371 { 0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 },
3372 { 0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5 },
3373 { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff },
3374 { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff },
3375 { 0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 },
3376 { 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 },
3377 { 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 },
3378 { 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 },
3379 { 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
3380 { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce },
3381};
3382
3383static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = {
3384 { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
3385 { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 },
3386 { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 },
3387 { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b },
3388 { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 },
3389 { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 },
3390 { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a },
3391 { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 },
3392 { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
3393 { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b },
3394 { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 },
3395 { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 },
3396 { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a },
3397 { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 },
3398 { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b },
3399 { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 },
3400 { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 },
3401 { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a },
3402 { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 },
3403 { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a },
3404 { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 },
3405 { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 },
3406 { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff },
3407 { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff },
3408 { 0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 },
3409 { 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 },
3410 { 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 },
3411 { 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 },
3412 { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
3413 { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce },
3414};
3415
3416static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
3417 {0x00004040, 0x9248fd00 },
3418 {0x00004040, 0x24924924 },
3419 {0x00004040, 0xa8000019 },
3420 {0x00004040, 0x13160820 },
3421 {0x00004040, 0xe5980560 },
3422 {0x00004040, 0xc01dcffc },
3423 {0x00004040, 0x1aaabe41 },
3424 {0x00004040, 0xbe105554 },
3425 {0x00004040, 0x00043007 },
3426 {0x00004044, 0x00000000 },
3427};
3428
3429static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = {
3430 {0x00004040, 0x9248fd00 },
3431 {0x00004040, 0x24924924 },
3432 {0x00004040, 0xa8000019 },
3433 {0x00004040, 0x13160820 },
3434 {0x00004040, 0xe5980560 },
3435 {0x00004040, 0xc01dcffd },
3436 {0x00004040, 0x1aaabe41 },
3437 {0x00004040, 0xbe105554 },
3438 {0x00004040, 0x00043007 },
3439 {0x00004044, 0x00000000 },
3440};
3441
3442/* AR9285 */
3443static const u_int32_t ar9285Modes_9285[][6] = {
3444 { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
3445 { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
3446 { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
3447 { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
3448 { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
3449 { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
3450 { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
3451 { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
3452 { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
3453 { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
3454 { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
3455 { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
3456 { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
3457 { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e },
3458 { 0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020, 0x037216a0 },
3459 { 0x00009848, 0x00001066, 0x00001066, 0x0000004e, 0x0000004e, 0x00001059 },
3460 { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
3461 { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
3462 { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e, 0x3139605e },
3463 { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 },
3464 { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
3465 { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
3466 { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
3467 { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
3468 { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
3469 { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d },
3470 { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1020, 0xdfbc1020, 0xdfbc1010 },
3471 { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
3472 { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
3473 { 0x000099b8, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c },
3474 { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
3475 { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
3476 { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
3477 { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
3478 { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
3479 { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
3480 { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
3481 { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
3482 { 0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 },
3483 { 0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 },
3484 { 0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 },
3485 { 0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 },
3486 { 0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 },
3487 { 0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 },
3488 { 0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 },
3489 { 0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
3490 { 0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114, 0x00000000 },
3491 { 0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 },
3492 { 0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 },
3493 { 0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 },
3494 { 0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 },
3495 { 0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 },
3496 { 0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 },
3497 { 0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 },
3498 { 0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 },
3499 { 0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 },
3500 { 0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284, 0x00000000 },
3501 { 0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288, 0x00000000 },
3502 { 0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220, 0x00000000 },
3503 { 0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 },
3504 { 0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 },
3505 { 0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304, 0x00000000 },
3506 { 0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 },
3507 { 0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 },
3508 { 0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380, 0x00000000 },
3509 { 0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384, 0x00000000 },
3510 { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
3511 { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
3512 { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
3513 { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
3514 { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
3515 { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
3516 { 0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04, 0x00000000 },
3517 { 0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 },
3518 { 0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 },
3519 { 0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c, 0x00000000 },
3520 { 0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80, 0x00000000 },
3521 { 0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84, 0x00000000 },
3522 { 0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88, 0x00000000 },
3523 { 0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c, 0x00000000 },
3524 { 0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90, 0x00000000 },
3525 { 0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80, 0x00000000 },
3526 { 0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
3527 { 0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 },
3528 { 0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c, 0x00000000 },
3529 { 0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90, 0x00000000 },
3530 { 0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c, 0x00000000 },
3531 { 0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310, 0x00000000 },
3532 { 0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 },
3533 { 0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 },
3534 { 0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324, 0x00000000 },
3535 { 0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704, 0x00000000 },
3536 { 0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4, 0x00000000 },
3537 { 0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8, 0x00000000 },
3538 { 0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 },
3539 { 0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 },
3540 { 0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720, 0x00000000 },
3541 { 0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724, 0x00000000 },
3542 { 0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728, 0x00000000 },
3543 { 0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c, 0x00000000 },
3544 { 0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0, 0x00000000 },
3545 { 0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4, 0x00000000 },
3546 { 0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 },
3547 { 0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 },
3548 { 0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4, 0x00000000 },
3549 { 0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 },
3550 { 0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 },
3551 { 0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 },
3552 { 0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad, 0x00000000 },
3553 { 0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 },
3554 { 0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 },
3555 { 0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9, 0x00000000 },
3556 { 0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5, 0x00000000 },
3557 { 0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 },
3558 { 0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 },
3559 { 0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5, 0x00000000 },
3560 { 0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 },
3561 { 0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 },
3562 { 0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 },
3563 { 0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 },
3564 { 0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 },
3565 { 0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 },
3566 { 0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 },
3567 { 0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7, 0x00000000 },
3568 { 0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 },
3569 { 0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf, 0x00000000 },
3570 { 0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7, 0x00000000 },
3571 { 0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3572 { 0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3573 { 0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3574 { 0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3575 { 0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3576 { 0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3577 { 0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3578 { 0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3579 { 0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3580 { 0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3581 { 0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3582 { 0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3583 { 0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3584 { 0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3585 { 0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3586 { 0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3587 { 0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3588 { 0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3589 { 0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3590 { 0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3591 { 0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3592 { 0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3593 { 0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3594 { 0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3595 { 0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3596 { 0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3597 { 0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3598 { 0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3599 { 0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3600 { 0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3601 { 0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3602 { 0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3603 { 0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3604 { 0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3605 { 0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3606 { 0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3607 { 0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3608 { 0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3609 { 0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
3610 { 0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 },
3611 { 0x0000aa04, 0x00000000, 0x00000000, 0x00068080, 0x00068080, 0x00000000 },
3612 { 0x0000aa08, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 },
3613 { 0x0000aa0c, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 },
3614 { 0x0000aa10, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 },
3615 { 0x0000aa14, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 },
3616 { 0x0000aa18, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 },
3617 { 0x0000aa1c, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 },
3618 { 0x0000aa20, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 },
3619 { 0x0000aa24, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
3620 { 0x0000aa28, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
3621 { 0x0000aa2c, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 },
3622 { 0x0000aa30, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 },
3623 { 0x0000aa34, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 },
3624 { 0x0000aa38, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 },
3625 { 0x0000aa3c, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 },
3626 { 0x0000aa40, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 },
3627 { 0x0000aa44, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 },
3628 { 0x0000aa48, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 },
3629 { 0x0000aa4c, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 },
3630 { 0x0000aa50, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac, 0x00000000 },
3631 { 0x0000aa54, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c, 0x00000000 },
3632 { 0x0000aa58, 0x00000000, 0x00000000, 0x00068224, 0x00068224, 0x00000000 },
3633 { 0x0000aa5c, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 },
3634 { 0x0000aa60, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 },
3635 { 0x0000aa64, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 },
3636 { 0x0000aa68, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 },
3637 { 0x0000aa6c, 0x00000000, 0x00000000, 0x00068310, 0x00068310, 0x00000000 },
3638 { 0x0000aa70, 0x00000000, 0x00000000, 0x00068788, 0x00068788, 0x00000000 },
3639 { 0x0000aa74, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c, 0x00000000 },
3640 { 0x0000aa78, 0x00000000, 0x00000000, 0x00068790, 0x00068790, 0x00000000 },
3641 { 0x0000aa7c, 0x00000000, 0x00000000, 0x00068794, 0x00068794, 0x00000000 },
3642 { 0x0000aa80, 0x00000000, 0x00000000, 0x00068798, 0x00068798, 0x00000000 },
3643 { 0x0000aa84, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c, 0x00000000 },
3644 { 0x0000aa88, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89, 0x00000000 },
3645 { 0x0000aa8c, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d, 0x00000000 },
3646 { 0x0000aa90, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91, 0x00000000 },
3647 { 0x0000aa94, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95, 0x00000000 },
3648 { 0x0000aa98, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99, 0x00000000 },
3649 { 0x0000aa9c, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5, 0x00000000 },
3650 { 0x0000aaa0, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9, 0x00000000 },
3651 { 0x0000aaa4, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad, 0x00000000 },
3652 { 0x0000aaa8, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c, 0x00000000 },
3653 { 0x0000aaac, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10, 0x00000000 },
3654 { 0x0000aab0, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14, 0x00000000 },
3655 { 0x0000aab4, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
3656 { 0x0000aab8, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
3657 { 0x0000aabc, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 },
3658 { 0x0000aac0, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380, 0x00000000 },
3659 { 0x0000aac4, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 },
3660 { 0x0000aac8, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 },
3661 { 0x0000aacc, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c, 0x00000000 },
3662 { 0x0000aad0, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394, 0x00000000 },
3663 { 0x0000aad4, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798, 0x00000000 },
3664 { 0x0000aad8, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c, 0x00000000 },
3665 { 0x0000aadc, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 },
3666 { 0x0000aae0, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 },
3667 { 0x0000aae4, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718, 0x00000000 },
3668 { 0x0000aae8, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705, 0x00000000 },
3669 { 0x0000aaec, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709, 0x00000000 },
3670 { 0x0000aaf0, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d, 0x00000000 },
3671 { 0x0000aaf4, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711, 0x00000000 },
3672 { 0x0000aaf8, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715, 0x00000000 },
3673 { 0x0000aafc, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719, 0x00000000 },
3674 { 0x0000ab00, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4, 0x00000000 },
3675 { 0x0000ab04, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 },
3676 { 0x0000ab08, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 },
3677 { 0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 },
3678 { 0x0000ab10, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 },
3679 { 0x0000ab14, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 },
3680 { 0x0000ab18, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc, 0x00000000 },
3681 { 0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1, 0x00000000 },
3682 { 0x0000ab20, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 },
3683 { 0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 },
3684 { 0x0000ab28, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 },
3685 { 0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 },
3686 { 0x0000ab30, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd, 0x00000000 },
3687 { 0x0000ab34, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 },
3688 { 0x0000ab38, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd, 0x00000000 },
3689 { 0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 },
3690 { 0x0000ab40, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 },
3691 { 0x0000ab44, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2, 0x00000000 },
3692 { 0x0000ab48, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 },
3693 { 0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 },
3694 { 0x0000ab50, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 },
3695 { 0x0000ab54, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 },
3696 { 0x0000ab58, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 },
3697 { 0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 },
3698 { 0x0000ab60, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 },
3699 { 0x0000ab64, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3700 { 0x0000ab68, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3701 { 0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3702 { 0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3703 { 0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3704 { 0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3705 { 0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3706 { 0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3707 { 0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3708 { 0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3709 { 0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3710 { 0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3711 { 0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3712 { 0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3713 { 0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3714 { 0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3715 { 0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3716 { 0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3717 { 0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3718 { 0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3719 { 0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3720 { 0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3721 { 0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3722 { 0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3723 { 0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3724 { 0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3725 { 0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3726 { 0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3727 { 0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3728 { 0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3729 { 0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3730 { 0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3731 { 0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3732 { 0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3733 { 0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3734 { 0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3735 { 0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3736 { 0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3737 { 0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
3738 { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 },
3739 { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000, 0x0001f000 },
3740 { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
3741 { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
3742 { 0x0000a250, 0x001ff000, 0x001ff000, 0x001ca000, 0x001ca000, 0x001da000 },
3743 { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652, 0x0a82a652 },
3744 { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
3745 { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 },
3746 { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408, 0x00000000 },
3747 { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a, 0x00000000 },
3748 { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818, 0x00000000 },
3749 { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858, 0x00000000 },
3750 { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859, 0x00000000 },
3751 { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b, 0x00000000 },
3752 { 0x0000a320, 0x00000000, 0x00000000, 0x0002c89a, 0x0002c89a, 0x00000000 },
3753 { 0x0000a324, 0x00000000, 0x00000000, 0x0002e89b, 0x0002e89b, 0x00000000 },
3754 { 0x0000a328, 0x00000000, 0x00000000, 0x0003089c, 0x0003089c, 0x00000000 },
3755 { 0x0000a32c, 0x00000000, 0x00000000, 0x0003289d, 0x0003289d, 0x00000000 },
3756 { 0x0000a330, 0x00000000, 0x00000000, 0x0003489e, 0x0003489e, 0x00000000 },
3757 { 0x0000a334, 0x00000000, 0x00000000, 0x000388de, 0x000388de, 0x00000000 },
3758 { 0x0000a338, 0x00000000, 0x00000000, 0x0003b91e, 0x0003b91e, 0x00000000 },
3759 { 0x0000a33c, 0x00000000, 0x00000000, 0x0003d95e, 0x0003d95e, 0x00000000 },
3760 { 0x0000a340, 0x00000000, 0x00000000, 0x000419df, 0x000419df, 0x00000000 },
3761 { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
3762 { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
3763};
3764
3765static const u_int32_t ar9285Common_9285[][2] = {
3766 { 0x0000000c, 0x00000000 },
3767 { 0x00000030, 0x00020045 },
3768 { 0x00000034, 0x00000005 },
3769 { 0x00000040, 0x00000000 },
3770 { 0x00000044, 0x00000008 },
3771 { 0x00000048, 0x00000008 },
3772 { 0x0000004c, 0x00000010 },
3773 { 0x00000050, 0x00000000 },
3774 { 0x00000054, 0x0000001f },
3775 { 0x00000800, 0x00000000 },
3776 { 0x00000804, 0x00000000 },
3777 { 0x00000808, 0x00000000 },
3778 { 0x0000080c, 0x00000000 },
3779 { 0x00000810, 0x00000000 },
3780 { 0x00000814, 0x00000000 },
3781 { 0x00000818, 0x00000000 },
3782 { 0x0000081c, 0x00000000 },
3783 { 0x00000820, 0x00000000 },
3784 { 0x00000824, 0x00000000 },
3785 { 0x00001040, 0x002ffc0f },
3786 { 0x00001044, 0x002ffc0f },
3787 { 0x00001048, 0x002ffc0f },
3788 { 0x0000104c, 0x002ffc0f },
3789 { 0x00001050, 0x002ffc0f },
3790 { 0x00001054, 0x002ffc0f },
3791 { 0x00001058, 0x002ffc0f },
3792 { 0x0000105c, 0x002ffc0f },
3793 { 0x00001060, 0x002ffc0f },
3794 { 0x00001064, 0x002ffc0f },
3795 { 0x00001230, 0x00000000 },
3796 { 0x00001270, 0x00000000 },
3797 { 0x00001038, 0x00000000 },
3798 { 0x00001078, 0x00000000 },
3799 { 0x000010b8, 0x00000000 },
3800 { 0x000010f8, 0x00000000 },
3801 { 0x00001138, 0x00000000 },
3802 { 0x00001178, 0x00000000 },
3803 { 0x000011b8, 0x00000000 },
3804 { 0x000011f8, 0x00000000 },
3805 { 0x00001238, 0x00000000 },
3806 { 0x00001278, 0x00000000 },
3807 { 0x000012b8, 0x00000000 },
3808 { 0x000012f8, 0x00000000 },
3809 { 0x00001338, 0x00000000 },
3810 { 0x00001378, 0x00000000 },
3811 { 0x000013b8, 0x00000000 },
3812 { 0x000013f8, 0x00000000 },
3813 { 0x00001438, 0x00000000 },
3814 { 0x00001478, 0x00000000 },
3815 { 0x000014b8, 0x00000000 },
3816 { 0x000014f8, 0x00000000 },
3817 { 0x00001538, 0x00000000 },
3818 { 0x00001578, 0x00000000 },
3819 { 0x000015b8, 0x00000000 },
3820 { 0x000015f8, 0x00000000 },
3821 { 0x00001638, 0x00000000 },
3822 { 0x00001678, 0x00000000 },
3823 { 0x000016b8, 0x00000000 },
3824 { 0x000016f8, 0x00000000 },
3825 { 0x00001738, 0x00000000 },
3826 { 0x00001778, 0x00000000 },
3827 { 0x000017b8, 0x00000000 },
3828 { 0x000017f8, 0x00000000 },
3829 { 0x0000103c, 0x00000000 },
3830 { 0x0000107c, 0x00000000 },
3831 { 0x000010bc, 0x00000000 },
3832 { 0x000010fc, 0x00000000 },
3833 { 0x0000113c, 0x00000000 },
3834 { 0x0000117c, 0x00000000 },
3835 { 0x000011bc, 0x00000000 },
3836 { 0x000011fc, 0x00000000 },
3837 { 0x0000123c, 0x00000000 },
3838 { 0x0000127c, 0x00000000 },
3839 { 0x000012bc, 0x00000000 },
3840 { 0x000012fc, 0x00000000 },
3841 { 0x0000133c, 0x00000000 },
3842 { 0x0000137c, 0x00000000 },
3843 { 0x000013bc, 0x00000000 },
3844 { 0x000013fc, 0x00000000 },
3845 { 0x0000143c, 0x00000000 },
3846 { 0x0000147c, 0x00000000 },
3847 { 0x00004030, 0x00000002 },
3848 { 0x0000403c, 0x00000002 },
3849 { 0x00004024, 0x0000001f },
3850 { 0x00004060, 0x00000000 },
3851 { 0x00004064, 0x00000000 },
3852 { 0x00007010, 0x00000031 },
3853 { 0x00007034, 0x00000002 },
3854 { 0x00007038, 0x000004c2 },
3855 { 0x00008004, 0x00000000 },
3856 { 0x00008008, 0x00000000 },
3857 { 0x0000800c, 0x00000000 },
3858 { 0x00008018, 0x00000700 },
3859 { 0x00008020, 0x00000000 },
3860 { 0x00008038, 0x00000000 },
3861 { 0x0000803c, 0x00000000 },
3862 { 0x00008048, 0x00000000 },
3863 { 0x00008054, 0x00000000 },
3864 { 0x00008058, 0x00000000 },
3865 { 0x0000805c, 0x000fc78f },
3866 { 0x00008060, 0x0000000f },
3867 { 0x00008064, 0x00000000 },
3868 { 0x00008070, 0x00000000 },
3869 { 0x000080c0, 0x2a80001a },
3870 { 0x000080c4, 0x05dc01e0 },
3871 { 0x000080c8, 0x1f402710 },
3872 { 0x000080cc, 0x01f40000 },
3873 { 0x000080d0, 0x00001e00 },
3874 { 0x000080d4, 0x00000000 },
3875 { 0x000080d8, 0x00400000 },
3876 { 0x000080e0, 0xffffffff },
3877 { 0x000080e4, 0x0000ffff },
3878 { 0x000080e8, 0x003f3f3f },
3879 { 0x000080ec, 0x00000000 },
3880 { 0x000080f0, 0x00000000 },
3881 { 0x000080f4, 0x00000000 },
3882 { 0x000080f8, 0x00000000 },
3883 { 0x000080fc, 0x00020000 },
3884 { 0x00008100, 0x00020000 },
3885 { 0x00008104, 0x00000001 },
3886 { 0x00008108, 0x00000052 },
3887 { 0x0000810c, 0x00000000 },
3888 { 0x00008110, 0x00000168 },
3889 { 0x00008118, 0x000100aa },
3890 { 0x0000811c, 0x00003210 },
3891 { 0x00008120, 0x08f04800 },
3892 { 0x00008124, 0x00000000 },
3893 { 0x00008128, 0x00000000 },
3894 { 0x0000812c, 0x00000000 },
3895 { 0x00008130, 0x00000000 },
3896 { 0x00008134, 0x00000000 },
3897 { 0x00008138, 0x00000000 },
3898 { 0x0000813c, 0x00000000 },
3899 { 0x00008144, 0x00000000 },
3900 { 0x00008168, 0x00000000 },
3901 { 0x0000816c, 0x00000000 },
3902 { 0x00008170, 0x32143320 },
3903 { 0x00008174, 0xfaa4fa50 },
3904 { 0x00008178, 0x00000100 },
3905 { 0x0000817c, 0x00000000 },
3906 { 0x000081c0, 0x00000000 },
3907 { 0x000081d0, 0x00003210 },
3908 { 0x000081ec, 0x00000000 },
3909 { 0x000081f0, 0x00000000 },
3910 { 0x000081f4, 0x00000000 },
3911 { 0x000081f8, 0x00000000 },
3912 { 0x000081fc, 0x00000000 },
3913 { 0x00008200, 0x00000000 },
3914 { 0x00008204, 0x00000000 },
3915 { 0x00008208, 0x00000000 },
3916 { 0x0000820c, 0x00000000 },
3917 { 0x00008210, 0x00000000 },
3918 { 0x00008214, 0x00000000 },
3919 { 0x00008218, 0x00000000 },
3920 { 0x0000821c, 0x00000000 },
3921 { 0x00008220, 0x00000000 },
3922 { 0x00008224, 0x00000000 },
3923 { 0x00008228, 0x00000000 },
3924 { 0x0000822c, 0x00000000 },
3925 { 0x00008230, 0x00000000 },
3926 { 0x00008234, 0x00000000 },
3927 { 0x00008238, 0x00000000 },
3928 { 0x0000823c, 0x00000000 },
3929 { 0x00008240, 0x00100000 },
3930 { 0x00008244, 0x0010f400 },
3931 { 0x00008248, 0x00000100 },
3932 { 0x0000824c, 0x0001e800 },
3933 { 0x00008250, 0x00000000 },
3934 { 0x00008254, 0x00000000 },
3935 { 0x00008258, 0x00000000 },
3936 { 0x0000825c, 0x400000ff },
3937 { 0x00008260, 0x00080922 },
3938 { 0x00008264, 0xa8a00010 },
3939 { 0x00008270, 0x00000000 },
3940 { 0x00008274, 0x40000000 },
3941 { 0x00008278, 0x003e4180 },
3942 { 0x0000827c, 0x00000000 },
3943 { 0x00008284, 0x0000002c },
3944 { 0x00008288, 0x0000002c },
3945 { 0x0000828c, 0x00000000 },
3946 { 0x00008294, 0x00000000 },
3947 { 0x00008298, 0x00000000 },
3948 { 0x0000829c, 0x00000000 },
3949 { 0x00008300, 0x00000040 },
3950 { 0x00008314, 0x00000000 },
3951 { 0x00008328, 0x00000000 },
3952 { 0x0000832c, 0x00000001 },
3953 { 0x00008330, 0x00000302 },
3954 { 0x00008334, 0x00000e00 },
3955 { 0x00008338, 0x00000000 },
3956 { 0x0000833c, 0x00000000 },
3957 { 0x00008340, 0x00010380 },
3958 { 0x00008344, 0x00581043 },
3959 { 0x00009808, 0x00000000 },
3960 { 0x0000980c, 0xafe68e30 },
3961 { 0x00009810, 0xfd14e000 },
3962 { 0x00009814, 0x9c0a9f6b },
3963 { 0x0000981c, 0x00000000 },
3964 { 0x0000982c, 0x0000a000 },
3965 { 0x00009830, 0x00000000 },
3966 { 0x0000983c, 0x00200400 },
3967 { 0x0000984c, 0x0040233c },
3968 { 0x00009854, 0x00000044 },
3969 { 0x00009900, 0x00000000 },
3970 { 0x00009904, 0x00000000 },
3971 { 0x00009908, 0x00000000 },
3972 { 0x0000990c, 0x00000000 },
3973 { 0x00009910, 0x01002310 },
3974 { 0x0000991c, 0x10000fff },
3975 { 0x00009920, 0x04900000 },
3976 { 0x00009928, 0x00000001 },
3977 { 0x0000992c, 0x00000004 },
3978 { 0x00009934, 0x1e1f2022 },
3979 { 0x00009938, 0x0a0b0c0d },
3980 { 0x0000993c, 0x00000000 },
3981 { 0x00009940, 0x14750604 },
3982 { 0x00009948, 0x9280c00a },
3983 { 0x0000994c, 0x00020028 },
3984 { 0x00009954, 0x5f3ca3de },
3985 { 0x00009958, 0x2108ecff },
3986 { 0x00009968, 0x000003ce },
3987 { 0x00009970, 0x1927b515 },
3988 { 0x00009974, 0x00000000 },
3989 { 0x00009978, 0x00000001 },
3990 { 0x0000997c, 0x00000000 },
3991 { 0x00009980, 0x00000000 },
3992 { 0x00009984, 0x00000000 },
3993 { 0x00009988, 0x00000000 },
3994 { 0x0000998c, 0x00000000 },
3995 { 0x00009990, 0x00000000 },
3996 { 0x00009994, 0x00000000 },
3997 { 0x00009998, 0x00000000 },
3998 { 0x0000999c, 0x00000000 },
3999 { 0x000099a0, 0x00000000 },
4000 { 0x000099a4, 0x00000001 },
4001 { 0x000099a8, 0x201fff00 },
4002 { 0x000099ac, 0x2def0a00 },
4003 { 0x000099b0, 0x03051000 },
4004 { 0x000099b4, 0x00000820 },
4005 { 0x000099dc, 0x00000000 },
4006 { 0x000099e0, 0x00000000 },
4007 { 0x000099e4, 0xaaaaaaaa },
4008 { 0x000099e8, 0x3c466478 },
4009 { 0x000099ec, 0x0cc80caa },
4010 { 0x000099f0, 0x00000000 },
4011 { 0x0000a208, 0x803e6788 },
4012 { 0x0000a210, 0x4080a333 },
4013 { 0x0000a214, 0x00206c10 },
4014 { 0x0000a218, 0x009c4060 },
4015 { 0x0000a220, 0x01834061 },
4016 { 0x0000a224, 0x00000400 },
4017 { 0x0000a228, 0x000003b5 },
4018 { 0x0000a22c, 0x00000000 },
4019 { 0x0000a234, 0x20202020 },
4020 { 0x0000a238, 0x20202020 },
4021 { 0x0000a244, 0x00000000 },
4022 { 0x0000a248, 0xfffffffc },
4023 { 0x0000a24c, 0x00000000 },
4024 { 0x0000a254, 0x00000000 },
4025 { 0x0000a258, 0x0ccb5380 },
4026 { 0x0000a25c, 0x15151501 },
4027 { 0x0000a260, 0xdfa90f01 },
4028 { 0x0000a268, 0x00000000 },
4029 { 0x0000a26c, 0x0ebae9e6 },
4030 { 0x0000d270, 0x0d820820 },
4031 { 0x0000a278, 0x39ce739c },
4032 { 0x0000a27c, 0x050e039c },
4033 { 0x0000d35c, 0x07ffffef },
4034 { 0x0000d360, 0x0fffffe7 },
4035 { 0x0000d364, 0x17ffffe5 },
4036 { 0x0000d368, 0x1fffffe4 },
4037 { 0x0000d36c, 0x37ffffe3 },
4038 { 0x0000d370, 0x3fffffe3 },
4039 { 0x0000d374, 0x57ffffe3 },
4040 { 0x0000d378, 0x5fffffe2 },
4041 { 0x0000d37c, 0x7fffffe2 },
4042 { 0x0000d380, 0x7f3c7bba },
4043 { 0x0000d384, 0xf3307ff0 },
4044 { 0x0000a388, 0x0c000000 },
4045 { 0x0000a38c, 0x20202020 },
4046 { 0x0000a390, 0x20202020 },
4047 { 0x0000a394, 0x39ce739c },
4048 { 0x0000a398, 0x0000039c },
4049 { 0x0000a39c, 0x00000001 },
4050 { 0x0000a3a0, 0x00000000 },
4051 { 0x0000a3a4, 0x00000000 },
4052 { 0x0000a3a8, 0x00000000 },
4053 { 0x0000a3ac, 0x00000000 },
4054 { 0x0000a3b0, 0x00000000 },
4055 { 0x0000a3b4, 0x00000000 },
4056 { 0x0000a3b8, 0x00000000 },
4057 { 0x0000a3bc, 0x00000000 },
4058 { 0x0000a3c0, 0x00000000 },
4059 { 0x0000a3c4, 0x00000000 },
4060 { 0x0000a3cc, 0x20202020 },
4061 { 0x0000a3d0, 0x20202020 },
4062 { 0x0000a3d4, 0x20202020 },
4063 { 0x0000a3dc, 0x39ce739c },
4064 { 0x0000a3e0, 0x0000039c },
4065 { 0x0000a3e4, 0x00000000 },
4066 { 0x0000a3e8, 0x18c43433 },
4067 { 0x0000a3ec, 0x00f70081 },
4068 { 0x00007800, 0x00140000 },
4069 { 0x00007804, 0x0e4548d8 },
4070 { 0x00007808, 0x54214514 },
4071 { 0x0000780c, 0x02025820 },
4072 { 0x00007810, 0x71c0d388 },
4073 { 0x00007814, 0x924934a8 },
4074 { 0x0000781c, 0x00000000 },
4075 { 0x00007820, 0x00000c04 },
4076 { 0x00007824, 0x00d86fff },
4077 { 0x00007828, 0x26d2491b },
4078 { 0x0000782c, 0x6e36d97b },
4079 { 0x00007830, 0xedb6d96c },
4080 { 0x00007834, 0x71400086 },
4081 { 0x00007838, 0xfac68800 },
4082 { 0x0000783c, 0x0001fffe },
4083 { 0x00007840, 0xffeb1a20 },
4084 { 0x00007844, 0x000c0db6 },
4085 { 0x00007848, 0x6db61b6f },
4086 { 0x0000784c, 0x6d9b66db },
4087 { 0x00007850, 0x6d8c6dba },
4088 { 0x00007854, 0x00040000 },
4089 { 0x00007858, 0xdb003012 },
4090 { 0x0000785c, 0x04924914 },
4091 { 0x00007860, 0x21084210 },
4092 { 0x00007864, 0xf7d7ffde },
4093 { 0x00007868, 0xc2034080 },
4094 { 0x0000786c, 0x48609eb4 },
4095 { 0x00007870, 0x10142c00 },
4096};
4097
4098static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285[][2] = {
4099 {0x00004040, 0x9248fd00 },
4100 {0x00004040, 0x24924924 },
4101 {0x00004040, 0xa8000019 },
4102 {0x00004040, 0x13160820 },
4103 {0x00004040, 0xe5980560 },
4104 {0x00004040, 0xc01dcffd },
4105 {0x00004040, 0x1aaabe41 },
4106 {0x00004040, 0xbe105554 },
4107 {0x00004040, 0x00043007 },
4108 {0x00004044, 0x00000000 },
4109};
4110
4111static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = {
4112 {0x00004040, 0x9248fd00 },
4113 {0x00004040, 0x24924924 },
4114 {0x00004040, 0xa8000019 },
4115 {0x00004040, 0x13160820 },
4116 {0x00004040, 0xe5980560 },
4117 {0x00004040, 0xc01dcffc },
4118 {0x00004040, 0x1aaabe41 },
4119 {0x00004040, 0xbe105554 },
4120 {0x00004040, 0x00043007 },
4121 {0x00004044, 0x00000000 },
4122};
4123
4124/* AR9285 v1_2 PCI Register Writes. Created: 03/04/09 */
4125static const u_int32_t ar9285Modes_9285_1_2[][6] = {
4126 { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
4127 { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
4128 { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
4129 { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
4130 { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
4131 { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
4132 { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
4133 { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
4134 { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
4135 { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
4136 { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
4137 { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
4138 { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
4139 { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e },
4140 { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 },
4141 { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 },
4142 { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
4143 { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
4144 { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e },
4145 { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 },
4146 { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
4147 { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
4148 { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
4149 { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
4150 { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
4151 { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d },
4152 { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 },
4153 { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
4154 { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
4155 { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c },
4156 { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
4157 { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
4158 { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
4159 { 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 },
4160 { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
4161 { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
4162 { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
4163 { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
4164 { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 },
4165 { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 },
4166 { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 },
4167 { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 },
4168 { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 },
4169 { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 },
4170 { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 },
4171 { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 },
4172 { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 },
4173 { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 },
4174 { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 },
4175 { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 },
4176 { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 },
4177 { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 },
4178 { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 },
4179 { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 },
4180 { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 },
4181 { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 },
4182 { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 },
4183 { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 },
4184 { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 },
4185 { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 },
4186 { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 },
4187 { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 },
4188 { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 },
4189 { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 },
4190 { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 },
4191 { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 },
4192 { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
4193 { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
4194 { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
4195 { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
4196 { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
4197 { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
4198 { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
4199 { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
4200 { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
4201 { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 },
4202 { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 },
4203 { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 },
4204 { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 },
4205 { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 },
4206 { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 },
4207 { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 },
4208 { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 },
4209 { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 },
4210 { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 },
4211 { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 },
4212 { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 },
4213 { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 },
4214 { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 },
4215 { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 },
4216 { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 },
4217 { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 },
4218 { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 },
4219 { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 },
4220 { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 },
4221 { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 },
4222 { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 },
4223 { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 },
4224 { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 },
4225 { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 },
4226 { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 },
4227 { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 },
4228 { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 },
4229 { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 },
4230 { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 },
4231 { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 },
4232 { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 },
4233 { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 },
4234 { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 },
4235 { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 },
4236 { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 },
4237 { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 },
4238 { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 },
4239 { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 },
4240 { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 },
4241 { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 },
4242 { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 },
4243 { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 },
4244 { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 },
4245 { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 },
4246 { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 },
4247 { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 },
4248 { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 },
4249 { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 },
4250 { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 },
4251 { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 },
4252 { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 },
4253 { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4254 { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4255 { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4256 { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4257 { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4258 { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4259 { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4260 { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4261 { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4262 { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4263 { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4264 { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4265 { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4266 { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4267 { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4268 { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4269 { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4270 { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4271 { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4272 { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4273 { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4274 { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4275 { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4276 { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4277 { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4278 { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4279 { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4280 { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4281 { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4282 { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4283 { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4284 { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4285 { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4286 { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4287 { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4288 { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4289 { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4290 { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4291 { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4292 { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 },
4293 { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 },
4294 { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 },
4295 { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 },
4296 { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 },
4297 { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 },
4298 { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 },
4299 { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 },
4300 { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 },
4301 { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 },
4302 { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 },
4303 { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 },
4304 { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 },
4305 { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 },
4306 { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 },
4307 { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 },
4308 { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 },
4309 { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 },
4310 { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 },
4311 { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 },
4312 { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 },
4313 { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 },
4314 { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 },
4315 { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 },
4316 { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 },
4317 { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 },
4318 { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 },
4319 { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 },
4320 { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
4321 { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
4322 { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
4323 { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
4324 { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
4325 { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
4326 { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
4327 { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
4328 { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
4329 { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 },
4330 { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 },
4331 { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 },
4332 { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 },
4333 { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 },
4334 { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 },
4335 { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 },
4336 { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 },
4337 { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 },
4338 { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 },
4339 { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 },
4340 { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 },
4341 { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 },
4342 { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 },
4343 { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 },
4344 { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 },
4345 { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 },
4346 { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 },
4347 { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 },
4348 { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 },
4349 { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 },
4350 { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 },
4351 { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 },
4352 { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 },
4353 { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 },
4354 { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 },
4355 { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 },
4356 { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 },
4357 { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 },
4358 { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 },
4359 { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 },
4360 { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 },
4361 { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 },
4362 { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 },
4363 { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 },
4364 { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 },
4365 { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 },
4366 { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 },
4367 { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 },
4368 { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 },
4369 { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 },
4370 { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 },
4371 { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 },
4372 { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 },
4373 { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 },
4374 { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 },
4375 { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 },
4376 { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 },
4377 { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 },
4378 { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 },
4379 { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 },
4380 { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 },
4381 { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4382 { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4383 { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4384 { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4385 { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4386 { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4387 { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4388 { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4389 { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4390 { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4391 { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4392 { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4393 { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4394 { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4395 { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4396 { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4397 { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4398 { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4399 { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4400 { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4401 { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4402 { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4403 { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4404 { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4405 { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4406 { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4407 { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4408 { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4409 { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4410 { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4411 { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4412 { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4413 { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4414 { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4415 { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4416 { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4417 { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4418 { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4419 { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
4420 { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 },
4421 { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 },
4422 { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
4423 { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
4424 { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 },
4425 { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
4426};
4427
4428static const u_int32_t ar9285Common_9285_1_2[][2] = {
4429 { 0x0000000c, 0x00000000 },
4430 { 0x00000030, 0x00020045 },
4431 { 0x00000034, 0x00000005 },
4432 { 0x00000040, 0x00000000 },
4433 { 0x00000044, 0x00000008 },
4434 { 0x00000048, 0x00000008 },
4435 { 0x0000004c, 0x00000010 },
4436 { 0x00000050, 0x00000000 },
4437 { 0x00000054, 0x0000001f },
4438 { 0x00000800, 0x00000000 },
4439 { 0x00000804, 0x00000000 },
4440 { 0x00000808, 0x00000000 },
4441 { 0x0000080c, 0x00000000 },
4442 { 0x00000810, 0x00000000 },
4443 { 0x00000814, 0x00000000 },
4444 { 0x00000818, 0x00000000 },
4445 { 0x0000081c, 0x00000000 },
4446 { 0x00000820, 0x00000000 },
4447 { 0x00000824, 0x00000000 },
4448 { 0x00001040, 0x002ffc0f },
4449 { 0x00001044, 0x002ffc0f },
4450 { 0x00001048, 0x002ffc0f },
4451 { 0x0000104c, 0x002ffc0f },
4452 { 0x00001050, 0x002ffc0f },
4453 { 0x00001054, 0x002ffc0f },
4454 { 0x00001058, 0x002ffc0f },
4455 { 0x0000105c, 0x002ffc0f },
4456 { 0x00001060, 0x002ffc0f },
4457 { 0x00001064, 0x002ffc0f },
4458 { 0x00001230, 0x00000000 },
4459 { 0x00001270, 0x00000000 },
4460 { 0x00001038, 0x00000000 },
4461 { 0x00001078, 0x00000000 },
4462 { 0x000010b8, 0x00000000 },
4463 { 0x000010f8, 0x00000000 },
4464 { 0x00001138, 0x00000000 },
4465 { 0x00001178, 0x00000000 },
4466 { 0x000011b8, 0x00000000 },
4467 { 0x000011f8, 0x00000000 },
4468 { 0x00001238, 0x00000000 },
4469 { 0x00001278, 0x00000000 },
4470 { 0x000012b8, 0x00000000 },
4471 { 0x000012f8, 0x00000000 },
4472 { 0x00001338, 0x00000000 },
4473 { 0x00001378, 0x00000000 },
4474 { 0x000013b8, 0x00000000 },
4475 { 0x000013f8, 0x00000000 },
4476 { 0x00001438, 0x00000000 },
4477 { 0x00001478, 0x00000000 },
4478 { 0x000014b8, 0x00000000 },
4479 { 0x000014f8, 0x00000000 },
4480 { 0x00001538, 0x00000000 },
4481 { 0x00001578, 0x00000000 },
4482 { 0x000015b8, 0x00000000 },
4483 { 0x000015f8, 0x00000000 },
4484 { 0x00001638, 0x00000000 },
4485 { 0x00001678, 0x00000000 },
4486 { 0x000016b8, 0x00000000 },
4487 { 0x000016f8, 0x00000000 },
4488 { 0x00001738, 0x00000000 },
4489 { 0x00001778, 0x00000000 },
4490 { 0x000017b8, 0x00000000 },
4491 { 0x000017f8, 0x00000000 },
4492 { 0x0000103c, 0x00000000 },
4493 { 0x0000107c, 0x00000000 },
4494 { 0x000010bc, 0x00000000 },
4495 { 0x000010fc, 0x00000000 },
4496 { 0x0000113c, 0x00000000 },
4497 { 0x0000117c, 0x00000000 },
4498 { 0x000011bc, 0x00000000 },
4499 { 0x000011fc, 0x00000000 },
4500 { 0x0000123c, 0x00000000 },
4501 { 0x0000127c, 0x00000000 },
4502 { 0x000012bc, 0x00000000 },
4503 { 0x000012fc, 0x00000000 },
4504 { 0x0000133c, 0x00000000 },
4505 { 0x0000137c, 0x00000000 },
4506 { 0x000013bc, 0x00000000 },
4507 { 0x000013fc, 0x00000000 },
4508 { 0x0000143c, 0x00000000 },
4509 { 0x0000147c, 0x00000000 },
4510 { 0x00004030, 0x00000002 },
4511 { 0x0000403c, 0x00000002 },
4512 { 0x00004024, 0x0000001f },
4513 { 0x00004060, 0x00000000 },
4514 { 0x00004064, 0x00000000 },
4515 { 0x00007010, 0x00000031 },
4516 { 0x00007034, 0x00000002 },
4517 { 0x00007038, 0x000004c2 },
4518 { 0x00008004, 0x00000000 },
4519 { 0x00008008, 0x00000000 },
4520 { 0x0000800c, 0x00000000 },
4521 { 0x00008018, 0x00000700 },
4522 { 0x00008020, 0x00000000 },
4523 { 0x00008038, 0x00000000 },
4524 { 0x0000803c, 0x00000000 },
4525 { 0x00008048, 0x00000000 },
4526 { 0x00008054, 0x00000000 },
4527 { 0x00008058, 0x00000000 },
4528 { 0x0000805c, 0x000fc78f },
4529 { 0x00008060, 0x0000000f },
4530 { 0x00008064, 0x00000000 },
4531 { 0x00008070, 0x00000000 },
4532 { 0x000080c0, 0x2a80001a },
4533 { 0x000080c4, 0x05dc01e0 },
4534 { 0x000080c8, 0x1f402710 },
4535 { 0x000080cc, 0x01f40000 },
4536 { 0x000080d0, 0x00001e00 },
4537 { 0x000080d4, 0x00000000 },
4538 { 0x000080d8, 0x00400000 },
4539 { 0x000080e0, 0xffffffff },
4540 { 0x000080e4, 0x0000ffff },
4541 { 0x000080e8, 0x003f3f3f },
4542 { 0x000080ec, 0x00000000 },
4543 { 0x000080f0, 0x00000000 },
4544 { 0x000080f4, 0x00000000 },
4545 { 0x000080f8, 0x00000000 },
4546 { 0x000080fc, 0x00020000 },
4547 { 0x00008100, 0x00020000 },
4548 { 0x00008104, 0x00000001 },
4549 { 0x00008108, 0x00000052 },
4550 { 0x0000810c, 0x00000000 },
4551 { 0x00008110, 0x00000168 },
4552 { 0x00008118, 0x000100aa },
4553 { 0x0000811c, 0x00003210 },
4554 { 0x00008120, 0x08f04810 },
4555 { 0x00008124, 0x00000000 },
4556 { 0x00008128, 0x00000000 },
4557 { 0x0000812c, 0x00000000 },
4558 { 0x00008130, 0x00000000 },
4559 { 0x00008134, 0x00000000 },
4560 { 0x00008138, 0x00000000 },
4561 { 0x0000813c, 0x00000000 },
4562 { 0x00008144, 0xffffffff },
4563 { 0x00008168, 0x00000000 },
4564 { 0x0000816c, 0x00000000 },
4565 { 0x00008170, 0x32143320 },
4566 { 0x00008174, 0xfaa4fa50 },
4567 { 0x00008178, 0x00000100 },
4568 { 0x0000817c, 0x00000000 },
4569 { 0x000081c0, 0x00000000 },
4570 { 0x000081d0, 0x0000320a },
4571 { 0x000081ec, 0x00000000 },
4572 { 0x000081f0, 0x00000000 },
4573 { 0x000081f4, 0x00000000 },
4574 { 0x000081f8, 0x00000000 },
4575 { 0x000081fc, 0x00000000 },
4576 { 0x00008200, 0x00000000 },
4577 { 0x00008204, 0x00000000 },
4578 { 0x00008208, 0x00000000 },
4579 { 0x0000820c, 0x00000000 },
4580 { 0x00008210, 0x00000000 },
4581 { 0x00008214, 0x00000000 },
4582 { 0x00008218, 0x00000000 },
4583 { 0x0000821c, 0x00000000 },
4584 { 0x00008220, 0x00000000 },
4585 { 0x00008224, 0x00000000 },
4586 { 0x00008228, 0x00000000 },
4587 { 0x0000822c, 0x00000000 },
4588 { 0x00008230, 0x00000000 },
4589 { 0x00008234, 0x00000000 },
4590 { 0x00008238, 0x00000000 },
4591 { 0x0000823c, 0x00000000 },
4592 { 0x00008240, 0x00100000 },
4593 { 0x00008244, 0x0010f400 },
4594 { 0x00008248, 0x00000100 },
4595 { 0x0000824c, 0x0001e800 },
4596 { 0x00008250, 0x00000000 },
4597 { 0x00008254, 0x00000000 },
4598 { 0x00008258, 0x00000000 },
4599 { 0x0000825c, 0x400000ff },
4600 { 0x00008260, 0x00080922 },
4601 { 0x00008264, 0xa8a00010 },
4602 { 0x00008270, 0x00000000 },
4603 { 0x00008274, 0x40000000 },
4604 { 0x00008278, 0x003e4180 },
4605 { 0x0000827c, 0x00000000 },
4606 { 0x00008284, 0x0000002c },
4607 { 0x00008288, 0x0000002c },
4608 { 0x0000828c, 0x00000000 },
4609 { 0x00008294, 0x00000000 },
4610 { 0x00008298, 0x00000000 },
4611 { 0x0000829c, 0x00000000 },
4612 { 0x00008300, 0x00000040 },
4613 { 0x00008314, 0x00000000 },
4614 { 0x00008328, 0x00000000 },
4615 { 0x0000832c, 0x00000001 },
4616 { 0x00008330, 0x00000302 },
4617 { 0x00008334, 0x00000e00 },
4618 { 0x00008338, 0x00ff0000 },
4619 { 0x0000833c, 0x00000000 },
4620 { 0x00008340, 0x00010380 },
4621 { 0x00008344, 0x00581043 },
4622 { 0x00009808, 0x00000000 },
4623 { 0x0000980c, 0xafe68e30 },
4624 { 0x00009810, 0xfd14e000 },
4625 { 0x00009814, 0x9c0a9f6b },
4626 { 0x0000981c, 0x00000000 },
4627 { 0x0000982c, 0x0000a000 },
4628 { 0x00009830, 0x00000000 },
4629 { 0x0000983c, 0x00200400 },
4630 { 0x0000984c, 0x0040233c },
4631 { 0x00009854, 0x00000044 },
4632 { 0x00009900, 0x00000000 },
4633 { 0x00009904, 0x00000000 },
4634 { 0x00009908, 0x00000000 },
4635 { 0x0000990c, 0x00000000 },
4636 { 0x00009910, 0x01002310 },
4637 { 0x0000991c, 0x10000fff },
4638 { 0x00009920, 0x04900000 },
4639 { 0x00009928, 0x00000001 },
4640 { 0x0000992c, 0x00000004 },
4641 { 0x00009934, 0x1e1f2022 },
4642 { 0x00009938, 0x0a0b0c0d },
4643 { 0x0000993c, 0x00000000 },
4644 { 0x00009940, 0x14750604 },
4645 { 0x00009948, 0x9280c00a },
4646 { 0x0000994c, 0x00020028 },
4647 { 0x00009954, 0x5f3ca3de },
4648 { 0x00009958, 0x2108ecff },
4649 { 0x00009968, 0x000003ce },
4650 { 0x00009970, 0x192bb515 },
4651 { 0x00009974, 0x00000000 },
4652 { 0x00009978, 0x00000001 },
4653 { 0x0000997c, 0x00000000 },
4654 { 0x00009980, 0x00000000 },
4655 { 0x00009984, 0x00000000 },
4656 { 0x00009988, 0x00000000 },
4657 { 0x0000998c, 0x00000000 },
4658 { 0x00009990, 0x00000000 },
4659 { 0x00009994, 0x00000000 },
4660 { 0x00009998, 0x00000000 },
4661 { 0x0000999c, 0x00000000 },
4662 { 0x000099a0, 0x00000000 },
4663 { 0x000099a4, 0x00000001 },
4664 { 0x000099a8, 0x201fff00 },
4665 { 0x000099ac, 0x2def0400 },
4666 { 0x000099b0, 0x03051000 },
4667 { 0x000099b4, 0x00000820 },
4668 { 0x000099dc, 0x00000000 },
4669 { 0x000099e0, 0x00000000 },
4670 { 0x000099e4, 0xaaaaaaaa },
4671 { 0x000099e8, 0x3c466478 },
4672 { 0x000099ec, 0x0cc80caa },
4673 { 0x000099f0, 0x00000000 },
4674 { 0x0000a208, 0x803e68c8 },
4675 { 0x0000a210, 0x4080a333 },
4676 { 0x0000a214, 0x00206c10 },
4677 { 0x0000a218, 0x009c4060 },
4678 { 0x0000a220, 0x01834061 },
4679 { 0x0000a224, 0x00000400 },
4680 { 0x0000a228, 0x000003b5 },
4681 { 0x0000a22c, 0x00000000 },
4682 { 0x0000a234, 0x20202020 },
4683 { 0x0000a238, 0x20202020 },
4684 { 0x0000a244, 0x00000000 },
4685 { 0x0000a248, 0xfffffffc },
4686 { 0x0000a24c, 0x00000000 },
4687 { 0x0000a254, 0x00000000 },
4688 { 0x0000a258, 0x0ccb5380 },
4689 { 0x0000a25c, 0x15151501 },
4690 { 0x0000a260, 0xdfa90f01 },
4691 { 0x0000a268, 0x00000000 },
4692 { 0x0000a26c, 0x0ebae9e6 },
4693 { 0x0000d270, 0x0d820820 },
4694 { 0x0000d35c, 0x07ffffef },
4695 { 0x0000d360, 0x0fffffe7 },
4696 { 0x0000d364, 0x17ffffe5 },
4697 { 0x0000d368, 0x1fffffe4 },
4698 { 0x0000d36c, 0x37ffffe3 },
4699 { 0x0000d370, 0x3fffffe3 },
4700 { 0x0000d374, 0x57ffffe3 },
4701 { 0x0000d378, 0x5fffffe2 },
4702 { 0x0000d37c, 0x7fffffe2 },
4703 { 0x0000d380, 0x7f3c7bba },
4704 { 0x0000d384, 0xf3307ff0 },
4705 { 0x0000a388, 0x0c000000 },
4706 { 0x0000a38c, 0x20202020 },
4707 { 0x0000a390, 0x20202020 },
4708 { 0x0000a39c, 0x00000001 },
4709 { 0x0000a3a0, 0x00000000 },
4710 { 0x0000a3a4, 0x00000000 },
4711 { 0x0000a3a8, 0x00000000 },
4712 { 0x0000a3ac, 0x00000000 },
4713 { 0x0000a3b0, 0x00000000 },
4714 { 0x0000a3b4, 0x00000000 },
4715 { 0x0000a3b8, 0x00000000 },
4716 { 0x0000a3bc, 0x00000000 },
4717 { 0x0000a3c0, 0x00000000 },
4718 { 0x0000a3c4, 0x00000000 },
4719 { 0x0000a3cc, 0x20202020 },
4720 { 0x0000a3d0, 0x20202020 },
4721 { 0x0000a3d4, 0x20202020 },
4722 { 0x0000a3e4, 0x00000000 },
4723 { 0x0000a3e8, 0x18c43433 },
4724 { 0x0000a3ec, 0x00f70081 },
4725 { 0x00007800, 0x00140000 },
4726 { 0x00007804, 0x0e4548d8 },
4727 { 0x00007808, 0x54214514 },
4728 { 0x0000780c, 0x02025820 },
4729 { 0x00007810, 0x71c0d388 },
4730 { 0x00007814, 0x924934a8 },
4731 { 0x0000781c, 0x00000000 },
4732 { 0x00007824, 0x00d86fff },
4733 { 0x00007828, 0x26d2491b },
4734 { 0x0000782c, 0x6e36d97b },
4735 { 0x00007830, 0xedb6d96e },
4736 { 0x00007834, 0x71400087 },
4737 { 0x0000783c, 0x0001fffe },
4738 { 0x00007840, 0xffeb1a20 },
4739 { 0x00007844, 0x000c0db6 },
4740 { 0x00007848, 0x6db61b6f },
4741 { 0x0000784c, 0x6d9b66db },
4742 { 0x00007850, 0x6d8c6dba },
4743 { 0x00007854, 0x00040000 },
4744 { 0x00007858, 0xdb003012 },
4745 { 0x0000785c, 0x04924914 },
4746 { 0x00007860, 0x21084210 },
4747 { 0x00007864, 0xf7d7ffde },
4748 { 0x00007868, 0xc2034080 },
4749 { 0x00007870, 0x10142c00 },
4750};
4751
4752static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = {
4753 /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
4754 { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
4755 { 0x0000a304, 0x00000000, 0x00000000, 0x00005200, 0x00005200, 0x00000000 },
4756 { 0x0000a308, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 },
4757 { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 },
4758 { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 },
4759 { 0x0000a314, 0x00000000, 0x00000000, 0x0000f440, 0x0000f440, 0x00000000 },
4760 { 0x0000a318, 0x00000000, 0x00000000, 0x00014640, 0x00014640, 0x00000000 },
4761 { 0x0000a31c, 0x00000000, 0x00000000, 0x00018680, 0x00018680, 0x00000000 },
4762 { 0x0000a320, 0x00000000, 0x00000000, 0x00019841, 0x00019841, 0x00000000 },
4763 { 0x0000a324, 0x00000000, 0x00000000, 0x0001ca40, 0x0001ca40, 0x00000000 },
4764 { 0x0000a328, 0x00000000, 0x00000000, 0x0001fa80, 0x0001fa80, 0x00000000 },
4765 { 0x0000a32c, 0x00000000, 0x00000000, 0x00023ac0, 0x00023ac0, 0x00000000 },
4766 { 0x0000a330, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 },
4767 { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 },
4768 { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 },
4769 { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 },
4770 { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
4771 { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
4772 { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
4773 { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
4774 { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
4775 { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
4776 { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 },
4777 { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe },
4778 { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 },
4779 { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a21a652, 0x0a21a652, 0x0a22a652 },
4780 { 0x0000a278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce },
4781 { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce },
4782 { 0x0000a394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce },
4783 { 0x0000a398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce },
4784 { 0x0000a3dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce },
4785 { 0x0000a3e0, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce },
4786};
4787
4788static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = {
4789 /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
4790 { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
4791 { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 },
4792 { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 },
4793 { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 },
4794 { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 },
4795 { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 },
4796 { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 },
4797 { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 },
4798 { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 },
4799 { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 },
4800 { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 },
4801 { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 },
4802 { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 },
4803 { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 },
4804 { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 },
4805 { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 },
4806 { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
4807 { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
4808 { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
4809 { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
4810 { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
4811 { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
4812 { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 },
4813 { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 },
4814 { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 },
4815 { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 },
4816 { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c },
4817 { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c },
4818 { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c },
4819 { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c },
4820 { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c },
4821 { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c },
4822};
4823
4824static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = {
4825 {0x00004040, 0x9248fd00 },
4826 {0x00004040, 0x24924924 },
4827 {0x00004040, 0xa8000019 },
4828 {0x00004040, 0x13160820 },
4829 {0x00004040, 0xe5980560 },
4830 {0x00004040, 0xc01dcffd },
4831 {0x00004040, 0x1aaabe41 },
4832 {0x00004040, 0xbe105554 },
4833 {0x00004040, 0x00043007 },
4834 {0x00004044, 0x00000000 },
4835};
4836
4837static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = {
4838 {0x00004040, 0x9248fd00 },
4839 {0x00004040, 0x24924924 },
4840 {0x00004040, 0xa8000019 },
4841 {0x00004040, 0x13160820 },
4842 {0x00004040, 0xe5980560 },
4843 {0x00004040, 0xc01dcffc },
4844 {0x00004040, 0x1aaabe41 },
4845 {0x00004040, 0xbe105554 },
4846 {0x00004040, 0x00043007 },
4847 {0x00004044, 0x00000000 },
4848};
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
new file mode 100644
index 000000000000..8ae4ec21667b
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -0,0 +1,976 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "ath9k.h"
18
19static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
20 struct ath9k_tx_queue_info *qi)
21{
22 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
23 "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
24 ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
25 ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
26 ah->txurn_interrupt_mask);
27
28 REG_WRITE(ah, AR_IMR_S0,
29 SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)
30 | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC));
31 REG_WRITE(ah, AR_IMR_S1,
32 SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR)
33 | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));
34 REG_RMW_FIELD(ah, AR_IMR_S2,
35 AR_IMR_S2_QCU_TXURN, ah->txurn_interrupt_mask);
36}
37
38u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
39{
40 return REG_READ(ah, AR_QTXDP(q));
41}
42
43bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
44{
45 REG_WRITE(ah, AR_QTXDP(q), txdp);
46
47 return true;
48}
49
50bool ath9k_hw_txstart(struct ath_hw *ah, u32 q)
51{
52 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q);
53
54 REG_WRITE(ah, AR_Q_TXE, 1 << q);
55
56 return true;
57}
58
59u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
60{
61 u32 npend;
62
63 npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
64 if (npend == 0) {
65
66 if (REG_READ(ah, AR_Q_TXE) & (1 << q))
67 npend = 1;
68 }
69
70 return npend;
71}
72
73bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
74{
75 u32 txcfg, curLevel, newLevel;
76 enum ath9k_int omask;
77
78 if (ah->tx_trig_level >= MAX_TX_FIFO_THRESHOLD)
79 return false;
80
81 omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL);
82
83 txcfg = REG_READ(ah, AR_TXCFG);
84 curLevel = MS(txcfg, AR_FTRIG);
85 newLevel = curLevel;
86 if (bIncTrigLevel) {
87 if (curLevel < MAX_TX_FIFO_THRESHOLD)
88 newLevel++;
89 } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
90 newLevel--;
91 if (newLevel != curLevel)
92 REG_WRITE(ah, AR_TXCFG,
93 (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
94
95 ath9k_hw_set_interrupts(ah, omask);
96
97 ah->tx_trig_level = newLevel;
98
99 return newLevel != curLevel;
100}
101
102bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
103{
104#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */
105#define ATH9K_TIME_QUANTUM 100 /* usec */
106
107 struct ath9k_hw_capabilities *pCap = &ah->caps;
108 struct ath9k_tx_queue_info *qi;
109 u32 tsfLow, j, wait;
110 u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
111
112 if (q >= pCap->total_queues) {
113 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, "
114 "invalid queue: %u\n", q);
115 return false;
116 }
117
118 qi = &ah->txq[q];
119 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
120 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, "
121 "inactive queue: %u\n", q);
122 return false;
123 }
124
125 REG_WRITE(ah, AR_Q_TXD, 1 << q);
126
127 for (wait = wait_time; wait != 0; wait--) {
128 if (ath9k_hw_numtxpending(ah, q) == 0)
129 break;
130 udelay(ATH9K_TIME_QUANTUM);
131 }
132
133 if (ath9k_hw_numtxpending(ah, q)) {
134 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
135 "%s: Num of pending TX Frames %d on Q %d\n",
136 __func__, ath9k_hw_numtxpending(ah, q), q);
137
138 for (j = 0; j < 2; j++) {
139 tsfLow = REG_READ(ah, AR_TSF_L32);
140 REG_WRITE(ah, AR_QUIET2,
141 SM(10, AR_QUIET2_QUIET_DUR));
142 REG_WRITE(ah, AR_QUIET_PERIOD, 100);
143 REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
144 REG_SET_BIT(ah, AR_TIMER_MODE,
145 AR_QUIET_TIMER_EN);
146
147 if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
148 break;
149
150 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
151 "TSF has moved while trying to set "
152 "quiet time TSF: 0x%08x\n", tsfLow);
153 }
154
155 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
156
157 udelay(200);
158 REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
159
160 wait = wait_time;
161 while (ath9k_hw_numtxpending(ah, q)) {
162 if ((--wait) == 0) {
163 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
164 "Failed to stop TX DMA in 100 "
165 "msec after killing last frame\n");
166 break;
167 }
168 udelay(ATH9K_TIME_QUANTUM);
169 }
170
171 REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
172 }
173
174 REG_WRITE(ah, AR_Q_TXD, 0);
175 return wait != 0;
176
177#undef ATH9K_TX_STOP_DMA_TIMEOUT
178#undef ATH9K_TIME_QUANTUM
179}
180
181bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
182 u32 segLen, bool firstSeg,
183 bool lastSeg, const struct ath_desc *ds0)
184{
185 struct ar5416_desc *ads = AR5416DESC(ds);
186
187 if (firstSeg) {
188 ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
189 } else if (lastSeg) {
190 ads->ds_ctl0 = 0;
191 ads->ds_ctl1 = segLen;
192 ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
193 ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
194 } else {
195 ads->ds_ctl0 = 0;
196 ads->ds_ctl1 = segLen | AR_TxMore;
197 ads->ds_ctl2 = 0;
198 ads->ds_ctl3 = 0;
199 }
200 ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
201 ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
202 ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
203 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
204 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
205
206 return true;
207}
208
209void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds)
210{
211 struct ar5416_desc *ads = AR5416DESC(ds);
212
213 ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
214 ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
215 ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
216 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
217 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
218}
219
220int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds)
221{
222 struct ar5416_desc *ads = AR5416DESC(ds);
223
224 if ((ads->ds_txstatus9 & AR_TxDone) == 0)
225 return -EINPROGRESS;
226
227 ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
228 ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
229 ds->ds_txstat.ts_status = 0;
230 ds->ds_txstat.ts_flags = 0;
231
232 if (ads->ds_txstatus1 & AR_ExcessiveRetries)
233 ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
234 if (ads->ds_txstatus1 & AR_Filtered)
235 ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
236 if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
237 ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
238 ath9k_hw_updatetxtriglevel(ah, true);
239 }
240 if (ads->ds_txstatus9 & AR_TxOpExceeded)
241 ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
242 if (ads->ds_txstatus1 & AR_TxTimerExpired)
243 ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
244
245 if (ads->ds_txstatus1 & AR_DescCfgErr)
246 ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
247 if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
248 ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
249 ath9k_hw_updatetxtriglevel(ah, true);
250 }
251 if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
252 ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
253 ath9k_hw_updatetxtriglevel(ah, true);
254 }
255 if (ads->ds_txstatus0 & AR_TxBaStatus) {
256 ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
257 ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
258 ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
259 }
260
261 ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
262 switch (ds->ds_txstat.ts_rateindex) {
263 case 0:
264 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
265 break;
266 case 1:
267 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
268 break;
269 case 2:
270 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
271 break;
272 case 3:
273 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
274 break;
275 }
276
277 ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
278 ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
279 ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
280 ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
281 ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
282 ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
283 ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
284 ds->ds_txstat.evm0 = ads->AR_TxEVM0;
285 ds->ds_txstat.evm1 = ads->AR_TxEVM1;
286 ds->ds_txstat.evm2 = ads->AR_TxEVM2;
287 ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
288 ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
289 ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
290 ds->ds_txstat.ts_antenna = 0;
291
292 return 0;
293}
294
295void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
296 u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
297 u32 keyIx, enum ath9k_key_type keyType, u32 flags)
298{
299 struct ar5416_desc *ads = AR5416DESC(ds);
300
301 txPower += ah->txpower_indexoffset;
302 if (txPower > 63)
303 txPower = 63;
304
305 ads->ds_ctl0 = (pktLen & AR_FrameLen)
306 | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
307 | SM(txPower, AR_XmitPower)
308 | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
309 | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
310 | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
311 | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
312
313 ads->ds_ctl1 =
314 (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
315 | SM(type, AR_FrameType)
316 | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
317 | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
318 | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
319
320 ads->ds_ctl6 = SM(keyType, AR_EncrType);
321
322 if (AR_SREV_9285(ah)) {
323 ads->ds_ctl8 = 0;
324 ads->ds_ctl9 = 0;
325 ads->ds_ctl10 = 0;
326 ads->ds_ctl11 = 0;
327 }
328}
329
330void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds,
331 struct ath_desc *lastds,
332 u32 durUpdateEn, u32 rtsctsRate,
333 u32 rtsctsDuration,
334 struct ath9k_11n_rate_series series[],
335 u32 nseries, u32 flags)
336{
337 struct ar5416_desc *ads = AR5416DESC(ds);
338 struct ar5416_desc *last_ads = AR5416DESC(lastds);
339 u32 ds_ctl0;
340
341 if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
342 ds_ctl0 = ads->ds_ctl0;
343
344 if (flags & ATH9K_TXDESC_RTSENA) {
345 ds_ctl0 &= ~AR_CTSEnable;
346 ds_ctl0 |= AR_RTSEnable;
347 } else {
348 ds_ctl0 &= ~AR_RTSEnable;
349 ds_ctl0 |= AR_CTSEnable;
350 }
351
352 ads->ds_ctl0 = ds_ctl0;
353 } else {
354 ads->ds_ctl0 =
355 (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
356 }
357
358 ads->ds_ctl2 = set11nTries(series, 0)
359 | set11nTries(series, 1)
360 | set11nTries(series, 2)
361 | set11nTries(series, 3)
362 | (durUpdateEn ? AR_DurUpdateEna : 0)
363 | SM(0, AR_BurstDur);
364
365 ads->ds_ctl3 = set11nRate(series, 0)
366 | set11nRate(series, 1)
367 | set11nRate(series, 2)
368 | set11nRate(series, 3);
369
370 ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
371 | set11nPktDurRTSCTS(series, 1);
372
373 ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
374 | set11nPktDurRTSCTS(series, 3);
375
376 ads->ds_ctl7 = set11nRateFlags(series, 0)
377 | set11nRateFlags(series, 1)
378 | set11nRateFlags(series, 2)
379 | set11nRateFlags(series, 3)
380 | SM(rtsctsRate, AR_RTSCTSRate);
381 last_ads->ds_ctl2 = ads->ds_ctl2;
382 last_ads->ds_ctl3 = ads->ds_ctl3;
383}
384
385void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
386 u32 aggrLen)
387{
388 struct ar5416_desc *ads = AR5416DESC(ds);
389
390 ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
391 ads->ds_ctl6 &= ~AR_AggrLen;
392 ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
393}
394
395void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
396 u32 numDelims)
397{
398 struct ar5416_desc *ads = AR5416DESC(ds);
399 unsigned int ctl6;
400
401 ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
402
403 ctl6 = ads->ds_ctl6;
404 ctl6 &= ~AR_PadDelim;
405 ctl6 |= SM(numDelims, AR_PadDelim);
406 ads->ds_ctl6 = ctl6;
407}
408
409void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds)
410{
411 struct ar5416_desc *ads = AR5416DESC(ds);
412
413 ads->ds_ctl1 |= AR_IsAggr;
414 ads->ds_ctl1 &= ~AR_MoreAggr;
415 ads->ds_ctl6 &= ~AR_PadDelim;
416}
417
418void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds)
419{
420 struct ar5416_desc *ads = AR5416DESC(ds);
421
422 ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
423}
424
425void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds,
426 u32 burstDuration)
427{
428 struct ar5416_desc *ads = AR5416DESC(ds);
429
430 ads->ds_ctl2 &= ~AR_BurstDur;
431 ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
432}
433
434void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds,
435 u32 vmf)
436{
437 struct ar5416_desc *ads = AR5416DESC(ds);
438
439 if (vmf)
440 ads->ds_ctl0 |= AR_VirtMoreFrag;
441 else
442 ads->ds_ctl0 &= ~AR_VirtMoreFrag;
443}
444
445void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
446{
447 *txqs &= ah->intr_txqs;
448 ah->intr_txqs &= ~(*txqs);
449}
450
451bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
452 const struct ath9k_tx_queue_info *qinfo)
453{
454 u32 cw;
455 struct ath9k_hw_capabilities *pCap = &ah->caps;
456 struct ath9k_tx_queue_info *qi;
457
458 if (q >= pCap->total_queues) {
459 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, "
460 "invalid queue: %u\n", q);
461 return false;
462 }
463
464 qi = &ah->txq[q];
465 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
466 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, "
467 "inactive queue: %u\n", q);
468 return false;
469 }
470
471 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q);
472
473 qi->tqi_ver = qinfo->tqi_ver;
474 qi->tqi_subtype = qinfo->tqi_subtype;
475 qi->tqi_qflags = qinfo->tqi_qflags;
476 qi->tqi_priority = qinfo->tqi_priority;
477 if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
478 qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
479 else
480 qi->tqi_aifs = INIT_AIFS;
481 if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
482 cw = min(qinfo->tqi_cwmin, 1024U);
483 qi->tqi_cwmin = 1;
484 while (qi->tqi_cwmin < cw)
485 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
486 } else
487 qi->tqi_cwmin = qinfo->tqi_cwmin;
488 if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
489 cw = min(qinfo->tqi_cwmax, 1024U);
490 qi->tqi_cwmax = 1;
491 while (qi->tqi_cwmax < cw)
492 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
493 } else
494 qi->tqi_cwmax = INIT_CWMAX;
495
496 if (qinfo->tqi_shretry != 0)
497 qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
498 else
499 qi->tqi_shretry = INIT_SH_RETRY;
500 if (qinfo->tqi_lgretry != 0)
501 qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
502 else
503 qi->tqi_lgretry = INIT_LG_RETRY;
504 qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
505 qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
506 qi->tqi_burstTime = qinfo->tqi_burstTime;
507 qi->tqi_readyTime = qinfo->tqi_readyTime;
508
509 switch (qinfo->tqi_subtype) {
510 case ATH9K_WME_UPSD:
511 if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
512 qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
513 break;
514 default:
515 break;
516 }
517
518 return true;
519}
520
521bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
522 struct ath9k_tx_queue_info *qinfo)
523{
524 struct ath9k_hw_capabilities *pCap = &ah->caps;
525 struct ath9k_tx_queue_info *qi;
526
527 if (q >= pCap->total_queues) {
528 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, "
529 "invalid queue: %u\n", q);
530 return false;
531 }
532
533 qi = &ah->txq[q];
534 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
535 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, "
536 "inactive queue: %u\n", q);
537 return false;
538 }
539
540 qinfo->tqi_qflags = qi->tqi_qflags;
541 qinfo->tqi_ver = qi->tqi_ver;
542 qinfo->tqi_subtype = qi->tqi_subtype;
543 qinfo->tqi_qflags = qi->tqi_qflags;
544 qinfo->tqi_priority = qi->tqi_priority;
545 qinfo->tqi_aifs = qi->tqi_aifs;
546 qinfo->tqi_cwmin = qi->tqi_cwmin;
547 qinfo->tqi_cwmax = qi->tqi_cwmax;
548 qinfo->tqi_shretry = qi->tqi_shretry;
549 qinfo->tqi_lgretry = qi->tqi_lgretry;
550 qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
551 qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
552 qinfo->tqi_burstTime = qi->tqi_burstTime;
553 qinfo->tqi_readyTime = qi->tqi_readyTime;
554
555 return true;
556}
557
558int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
559 const struct ath9k_tx_queue_info *qinfo)
560{
561 struct ath9k_tx_queue_info *qi;
562 struct ath9k_hw_capabilities *pCap = &ah->caps;
563 int q;
564
565 switch (type) {
566 case ATH9K_TX_QUEUE_BEACON:
567 q = pCap->total_queues - 1;
568 break;
569 case ATH9K_TX_QUEUE_CAB:
570 q = pCap->total_queues - 2;
571 break;
572 case ATH9K_TX_QUEUE_PSPOLL:
573 q = 1;
574 break;
575 case ATH9K_TX_QUEUE_UAPSD:
576 q = pCap->total_queues - 3;
577 break;
578 case ATH9K_TX_QUEUE_DATA:
579 for (q = 0; q < pCap->total_queues; q++)
580 if (ah->txq[q].tqi_type ==
581 ATH9K_TX_QUEUE_INACTIVE)
582 break;
583 if (q == pCap->total_queues) {
584 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
585 "No available TX queue\n");
586 return -1;
587 }
588 break;
589 default:
590 DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid TX queue type: %u\n",
591 type);
592 return -1;
593 }
594
595 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q);
596
597 qi = &ah->txq[q];
598 if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
599 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
600 "TX queue: %u already active\n", q);
601 return -1;
602 }
603 memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
604 qi->tqi_type = type;
605 if (qinfo == NULL) {
606 qi->tqi_qflags =
607 TXQ_FLAG_TXOKINT_ENABLE
608 | TXQ_FLAG_TXERRINT_ENABLE
609 | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
610 qi->tqi_aifs = INIT_AIFS;
611 qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
612 qi->tqi_cwmax = INIT_CWMAX;
613 qi->tqi_shretry = INIT_SH_RETRY;
614 qi->tqi_lgretry = INIT_LG_RETRY;
615 qi->tqi_physCompBuf = 0;
616 } else {
617 qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
618 (void) ath9k_hw_set_txq_props(ah, q, qinfo);
619 }
620
621 return q;
622}
623
624bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
625{
626 struct ath9k_hw_capabilities *pCap = &ah->caps;
627 struct ath9k_tx_queue_info *qi;
628
629 if (q >= pCap->total_queues) {
630 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, "
631 "invalid queue: %u\n", q);
632 return false;
633 }
634 qi = &ah->txq[q];
635 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
636 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, "
637 "inactive queue: %u\n", q);
638 return false;
639 }
640
641 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TX queue: %u\n", q);
642
643 qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
644 ah->txok_interrupt_mask &= ~(1 << q);
645 ah->txerr_interrupt_mask &= ~(1 << q);
646 ah->txdesc_interrupt_mask &= ~(1 << q);
647 ah->txeol_interrupt_mask &= ~(1 << q);
648 ah->txurn_interrupt_mask &= ~(1 << q);
649 ath9k_hw_set_txq_interrupts(ah, qi);
650
651 return true;
652}
653
654bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
655{
656 struct ath9k_hw_capabilities *pCap = &ah->caps;
657 struct ath9k_channel *chan = ah->curchan;
658 struct ath9k_tx_queue_info *qi;
659 u32 cwMin, chanCwMin, value;
660
661 if (q >= pCap->total_queues) {
662 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, "
663 "invalid queue: %u\n", q);
664 return false;
665 }
666
667 qi = &ah->txq[q];
668 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
669 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, "
670 "inactive queue: %u\n", q);
671 return true;
672 }
673
674 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q);
675
676 if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
677 if (chan && IS_CHAN_B(chan))
678 chanCwMin = INIT_CWMIN_11B;
679 else
680 chanCwMin = INIT_CWMIN;
681
682 for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
683 } else
684 cwMin = qi->tqi_cwmin;
685
686 REG_WRITE(ah, AR_DLCL_IFS(q),
687 SM(cwMin, AR_D_LCL_IFS_CWMIN) |
688 SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
689 SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
690
691 REG_WRITE(ah, AR_DRETRY_LIMIT(q),
692 SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
693 SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
694 SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
695
696 REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
697 REG_WRITE(ah, AR_DMISC(q),
698 AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
699
700 if (qi->tqi_cbrPeriod) {
701 REG_WRITE(ah, AR_QCBRCFG(q),
702 SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
703 SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
704 REG_WRITE(ah, AR_QMISC(q),
705 REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR |
706 (qi->tqi_cbrOverflowLimit ?
707 AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
708 }
709 if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
710 REG_WRITE(ah, AR_QRDYTIMECFG(q),
711 SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
712 AR_Q_RDYTIMECFG_EN);
713 }
714
715 REG_WRITE(ah, AR_DCHNTIME(q),
716 SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
717 (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
718
719 if (qi->tqi_burstTime
720 && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) {
721 REG_WRITE(ah, AR_QMISC(q),
722 REG_READ(ah, AR_QMISC(q)) |
723 AR_Q_MISC_RDYTIME_EXP_POLICY);
724
725 }
726
727 if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) {
728 REG_WRITE(ah, AR_DMISC(q),
729 REG_READ(ah, AR_DMISC(q)) |
730 AR_D_MISC_POST_FR_BKOFF_DIS);
731 }
732 if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
733 REG_WRITE(ah, AR_DMISC(q),
734 REG_READ(ah, AR_DMISC(q)) |
735 AR_D_MISC_FRAG_BKOFF_EN);
736 }
737 switch (qi->tqi_type) {
738 case ATH9K_TX_QUEUE_BEACON:
739 REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
740 | AR_Q_MISC_FSP_DBA_GATED
741 | AR_Q_MISC_BEACON_USE
742 | AR_Q_MISC_CBR_INCR_DIS1);
743
744 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
745 | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
746 AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
747 | AR_D_MISC_BEACON_USE
748 | AR_D_MISC_POST_FR_BKOFF_DIS);
749 break;
750 case ATH9K_TX_QUEUE_CAB:
751 REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
752 | AR_Q_MISC_FSP_DBA_GATED
753 | AR_Q_MISC_CBR_INCR_DIS1
754 | AR_Q_MISC_CBR_INCR_DIS0);
755 value = (qi->tqi_readyTime -
756 (ah->config.sw_beacon_response_time -
757 ah->config.dma_beacon_response_time) -
758 ah->config.additional_swba_backoff) * 1024;
759 REG_WRITE(ah, AR_QRDYTIMECFG(q),
760 value | AR_Q_RDYTIMECFG_EN);
761 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
762 | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
763 AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
764 break;
765 case ATH9K_TX_QUEUE_PSPOLL:
766 REG_WRITE(ah, AR_QMISC(q),
767 REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1);
768 break;
769 case ATH9K_TX_QUEUE_UAPSD:
770 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
771 AR_D_MISC_POST_FR_BKOFF_DIS);
772 break;
773 default:
774 break;
775 }
776
777 if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
778 REG_WRITE(ah, AR_DMISC(q),
779 REG_READ(ah, AR_DMISC(q)) |
780 SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
781 AR_D_MISC_ARB_LOCKOUT_CNTRL) |
782 AR_D_MISC_POST_FR_BKOFF_DIS);
783 }
784
785 if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
786 ah->txok_interrupt_mask |= 1 << q;
787 else
788 ah->txok_interrupt_mask &= ~(1 << q);
789 if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
790 ah->txerr_interrupt_mask |= 1 << q;
791 else
792 ah->txerr_interrupt_mask &= ~(1 << q);
793 if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
794 ah->txdesc_interrupt_mask |= 1 << q;
795 else
796 ah->txdesc_interrupt_mask &= ~(1 << q);
797 if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
798 ah->txeol_interrupt_mask |= 1 << q;
799 else
800 ah->txeol_interrupt_mask &= ~(1 << q);
801 if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
802 ah->txurn_interrupt_mask |= 1 << q;
803 else
804 ah->txurn_interrupt_mask &= ~(1 << q);
805 ath9k_hw_set_txq_interrupts(ah, qi);
806
807 return true;
808}
809
810int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
811 u32 pa, struct ath_desc *nds, u64 tsf)
812{
813 struct ar5416_desc ads;
814 struct ar5416_desc *adsp = AR5416DESC(ds);
815 u32 phyerr;
816
817 if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
818 return -EINPROGRESS;
819
820 ads.u.rx = adsp->u.rx;
821
822 ds->ds_rxstat.rs_status = 0;
823 ds->ds_rxstat.rs_flags = 0;
824
825 ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
826 ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
827
828 ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
829 ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00);
830 ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01);
831 ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02);
832 ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10);
833 ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11);
834 ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12);
835 if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
836 ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
837 else
838 ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID;
839
840 ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads));
841 ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
842
843 ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
844 ds->ds_rxstat.rs_moreaggr =
845 (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
846 ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
847 ds->ds_rxstat.rs_flags =
848 (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
849 ds->ds_rxstat.rs_flags |=
850 (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
851
852 if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
853 ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
854 if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
855 ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST;
856 if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
857 ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY;
858
859 if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
860 if (ads.ds_rxstatus8 & AR_CRCErr)
861 ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC;
862 else if (ads.ds_rxstatus8 & AR_PHYErr) {
863 ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY;
864 phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
865 ds->ds_rxstat.rs_phyerr = phyerr;
866 } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
867 ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT;
868 else if (ads.ds_rxstatus8 & AR_MichaelErr)
869 ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC;
870 }
871
872 return 0;
873}
874
875bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
876 u32 size, u32 flags)
877{
878 struct ar5416_desc *ads = AR5416DESC(ds);
879 struct ath9k_hw_capabilities *pCap = &ah->caps;
880
881 ads->ds_ctl1 = size & AR_BufLen;
882 if (flags & ATH9K_RXDESC_INTREQ)
883 ads->ds_ctl1 |= AR_RxIntrReq;
884
885 ads->ds_rxstatus8 &= ~AR_RxDone;
886 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
887 memset(&(ads->u), 0, sizeof(ads->u));
888
889 return true;
890}
891
892bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
893{
894 u32 reg;
895
896 if (set) {
897 REG_SET_BIT(ah, AR_DIAG_SW,
898 (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
899
900 if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE,
901 0, AH_WAIT_TIMEOUT)) {
902 REG_CLR_BIT(ah, AR_DIAG_SW,
903 (AR_DIAG_RX_DIS |
904 AR_DIAG_RX_ABORT));
905
906 reg = REG_READ(ah, AR_OBS_BUS_1);
907 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
908 "RX failed to go idle in 10 ms RXSM=0x%x\n", reg);
909
910 return false;
911 }
912 } else {
913 REG_CLR_BIT(ah, AR_DIAG_SW,
914 (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
915 }
916
917 return true;
918}
919
920void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)
921{
922 REG_WRITE(ah, AR_RXDP, rxdp);
923}
924
925void ath9k_hw_rxena(struct ath_hw *ah)
926{
927 REG_WRITE(ah, AR_CR, AR_CR_RXE);
928}
929
930void ath9k_hw_startpcureceive(struct ath_hw *ah)
931{
932 ath9k_enable_mib_counters(ah);
933
934 ath9k_ani_reset(ah);
935
936 REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
937}
938
939void ath9k_hw_stoppcurecv(struct ath_hw *ah)
940{
941 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
942
943 ath9k_hw_disable_mib_counters(ah);
944}
945
946bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
947{
948#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */
949#define AH_RX_TIME_QUANTUM 100 /* usec */
950
951 int i;
952
953 REG_WRITE(ah, AR_CR, AR_CR_RXD);
954
955 /* Wait for rx enable bit to go low */
956 for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
957 if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
958 break;
959 udelay(AH_TIME_QUANTUM);
960 }
961
962 if (i == 0) {
963 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
964 "DMA failed to stop in %d ms "
965 "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
966 AH_RX_STOP_DMA_TIMEOUT / 1000,
967 REG_READ(ah, AR_CR),
968 REG_READ(ah, AR_DIAG_SW));
969 return false;
970 } else {
971 return true;
972 }
973
974#undef AH_RX_TIME_QUANTUM
975#undef AH_RX_STOP_DMA_TIMEOUT
976}
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
new file mode 100644
index 000000000000..1176bce8b76c
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -0,0 +1,680 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef MAC_H
18#define MAC_H
19
20#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \
21 MS(ads->ds_rxstatus0, AR_RxRate) : \
22 (ads->ds_rxstatus3 >> 2) & 0xFF)
23
24#define set11nTries(_series, _index) \
25 (SM((_series)[_index].Tries, AR_XmitDataTries##_index))
26
27#define set11nRate(_series, _index) \
28 (SM((_series)[_index].Rate, AR_XmitRate##_index))
29
30#define set11nPktDurRTSCTS(_series, _index) \
31 (SM((_series)[_index].PktDuration, AR_PacketDur##_index) | \
32 ((_series)[_index].RateFlags & ATH9K_RATESERIES_RTS_CTS ? \
33 AR_RTSCTSQual##_index : 0))
34
35#define set11nRateFlags(_series, _index) \
36 (((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ? \
37 AR_2040_##_index : 0) \
38 |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \
39 AR_GI##_index : 0) \
40 |SM((_series)[_index].ChSel, AR_ChainSel##_index))
41
42#define CCK_SIFS_TIME 10
43#define CCK_PREAMBLE_BITS 144
44#define CCK_PLCP_BITS 48
45
46#define OFDM_SIFS_TIME 16
47#define OFDM_PREAMBLE_TIME 20
48#define OFDM_PLCP_BITS 22
49#define OFDM_SYMBOL_TIME 4
50
51#define OFDM_SIFS_TIME_HALF 32
52#define OFDM_PREAMBLE_TIME_HALF 40
53#define OFDM_PLCP_BITS_HALF 22
54#define OFDM_SYMBOL_TIME_HALF 8
55
56#define OFDM_SIFS_TIME_QUARTER 64
57#define OFDM_PREAMBLE_TIME_QUARTER 80
58#define OFDM_PLCP_BITS_QUARTER 22
59#define OFDM_SYMBOL_TIME_QUARTER 16
60
61#define INIT_AIFS 2
62#define INIT_CWMIN 15
63#define INIT_CWMIN_11B 31
64#define INIT_CWMAX 1023
65#define INIT_SH_RETRY 10
66#define INIT_LG_RETRY 10
67#define INIT_SSH_RETRY 32
68#define INIT_SLG_RETRY 32
69
70#define ATH9K_SLOT_TIME_6 6
71#define ATH9K_SLOT_TIME_9 9
72#define ATH9K_SLOT_TIME_20 20
73
74#define ATH9K_TXERR_XRETRY 0x01
75#define ATH9K_TXERR_FILT 0x02
76#define ATH9K_TXERR_FIFO 0x04
77#define ATH9K_TXERR_XTXOP 0x08
78#define ATH9K_TXERR_TIMER_EXPIRED 0x10
79
80#define ATH9K_TX_BA 0x01
81#define ATH9K_TX_PWRMGMT 0x02
82#define ATH9K_TX_DESC_CFG_ERR 0x04
83#define ATH9K_TX_DATA_UNDERRUN 0x08
84#define ATH9K_TX_DELIM_UNDERRUN 0x10
85#define ATH9K_TX_SW_ABORTED 0x40
86#define ATH9K_TX_SW_FILTERED 0x80
87
88#define MIN_TX_FIFO_THRESHOLD 0x1
89#define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1)
90#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD
91
92struct ath_tx_status {
93 u32 ts_tstamp;
94 u16 ts_seqnum;
95 u8 ts_status;
96 u8 ts_ratecode;
97 u8 ts_rateindex;
98 int8_t ts_rssi;
99 u8 ts_shortretry;
100 u8 ts_longretry;
101 u8 ts_virtcol;
102 u8 ts_antenna;
103 u8 ts_flags;
104 int8_t ts_rssi_ctl0;
105 int8_t ts_rssi_ctl1;
106 int8_t ts_rssi_ctl2;
107 int8_t ts_rssi_ext0;
108 int8_t ts_rssi_ext1;
109 int8_t ts_rssi_ext2;
110 u8 pad[3];
111 u32 ba_low;
112 u32 ba_high;
113 u32 evm0;
114 u32 evm1;
115 u32 evm2;
116};
117
118struct ath_rx_status {
119 u32 rs_tstamp;
120 u16 rs_datalen;
121 u8 rs_status;
122 u8 rs_phyerr;
123 int8_t rs_rssi;
124 u8 rs_keyix;
125 u8 rs_rate;
126 u8 rs_antenna;
127 u8 rs_more;
128 int8_t rs_rssi_ctl0;
129 int8_t rs_rssi_ctl1;
130 int8_t rs_rssi_ctl2;
131 int8_t rs_rssi_ext0;
132 int8_t rs_rssi_ext1;
133 int8_t rs_rssi_ext2;
134 u8 rs_isaggr;
135 u8 rs_moreaggr;
136 u8 rs_num_delims;
137 u8 rs_flags;
138 u32 evm0;
139 u32 evm1;
140 u32 evm2;
141};
142
143#define ATH9K_RXERR_CRC 0x01
144#define ATH9K_RXERR_PHY 0x02
145#define ATH9K_RXERR_FIFO 0x04
146#define ATH9K_RXERR_DECRYPT 0x08
147#define ATH9K_RXERR_MIC 0x10
148
149#define ATH9K_RX_MORE 0x01
150#define ATH9K_RX_MORE_AGGR 0x02
151#define ATH9K_RX_GI 0x04
152#define ATH9K_RX_2040 0x08
153#define ATH9K_RX_DELIM_CRC_PRE 0x10
154#define ATH9K_RX_DELIM_CRC_POST 0x20
155#define ATH9K_RX_DECRYPT_BUSY 0x40
156
157#define ATH9K_RXKEYIX_INVALID ((u8)-1)
158#define ATH9K_TXKEYIX_INVALID ((u32)-1)
159
160struct ath_desc {
161 u32 ds_link;
162 u32 ds_data;
163 u32 ds_ctl0;
164 u32 ds_ctl1;
165 u32 ds_hw[20];
166 union {
167 struct ath_tx_status tx;
168 struct ath_rx_status rx;
169 void *stats;
170 } ds_us;
171 void *ds_vdata;
172} __packed;
173
174#define ds_txstat ds_us.tx
175#define ds_rxstat ds_us.rx
176#define ds_stat ds_us.stats
177
178#define ATH9K_TXDESC_CLRDMASK 0x0001
179#define ATH9K_TXDESC_NOACK 0x0002
180#define ATH9K_TXDESC_RTSENA 0x0004
181#define ATH9K_TXDESC_CTSENA 0x0008
182/* ATH9K_TXDESC_INTREQ forces a tx interrupt to be generated for
183 * the descriptor its marked on. We take a tx interrupt to reap
184 * descriptors when the h/w hits an EOL condition or
185 * when the descriptor is specifically marked to generate
186 * an interrupt with this flag. Descriptors should be
187 * marked periodically to insure timely replenishing of the
188 * supply needed for sending frames. Defering interrupts
189 * reduces system load and potentially allows more concurrent
190 * work to be done but if done to aggressively can cause
191 * senders to backup. When the hardware queue is left too
192 * large rate control information may also be too out of
193 * date. An Alternative for this is TX interrupt mitigation
194 * but this needs more testing. */
195#define ATH9K_TXDESC_INTREQ 0x0010
196#define ATH9K_TXDESC_VEOL 0x0020
197#define ATH9K_TXDESC_EXT_ONLY 0x0040
198#define ATH9K_TXDESC_EXT_AND_CTL 0x0080
199#define ATH9K_TXDESC_VMF 0x0100
200#define ATH9K_TXDESC_FRAG_IS_ON 0x0200
201#define ATH9K_TXDESC_CAB 0x0400
202
203#define ATH9K_RXDESC_INTREQ 0x0020
204
205struct ar5416_desc {
206 u32 ds_link;
207 u32 ds_data;
208 u32 ds_ctl0;
209 u32 ds_ctl1;
210 union {
211 struct {
212 u32 ctl2;
213 u32 ctl3;
214 u32 ctl4;
215 u32 ctl5;
216 u32 ctl6;
217 u32 ctl7;
218 u32 ctl8;
219 u32 ctl9;
220 u32 ctl10;
221 u32 ctl11;
222 u32 status0;
223 u32 status1;
224 u32 status2;
225 u32 status3;
226 u32 status4;
227 u32 status5;
228 u32 status6;
229 u32 status7;
230 u32 status8;
231 u32 status9;
232 } tx;
233 struct {
234 u32 status0;
235 u32 status1;
236 u32 status2;
237 u32 status3;
238 u32 status4;
239 u32 status5;
240 u32 status6;
241 u32 status7;
242 u32 status8;
243 } rx;
244 } u;
245} __packed;
246
247#define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds))
248#define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds))
249
250#define ds_ctl2 u.tx.ctl2
251#define ds_ctl3 u.tx.ctl3
252#define ds_ctl4 u.tx.ctl4
253#define ds_ctl5 u.tx.ctl5
254#define ds_ctl6 u.tx.ctl6
255#define ds_ctl7 u.tx.ctl7
256#define ds_ctl8 u.tx.ctl8
257#define ds_ctl9 u.tx.ctl9
258#define ds_ctl10 u.tx.ctl10
259#define ds_ctl11 u.tx.ctl11
260
261#define ds_txstatus0 u.tx.status0
262#define ds_txstatus1 u.tx.status1
263#define ds_txstatus2 u.tx.status2
264#define ds_txstatus3 u.tx.status3
265#define ds_txstatus4 u.tx.status4
266#define ds_txstatus5 u.tx.status5
267#define ds_txstatus6 u.tx.status6
268#define ds_txstatus7 u.tx.status7
269#define ds_txstatus8 u.tx.status8
270#define ds_txstatus9 u.tx.status9
271
272#define ds_rxstatus0 u.rx.status0
273#define ds_rxstatus1 u.rx.status1
274#define ds_rxstatus2 u.rx.status2
275#define ds_rxstatus3 u.rx.status3
276#define ds_rxstatus4 u.rx.status4
277#define ds_rxstatus5 u.rx.status5
278#define ds_rxstatus6 u.rx.status6
279#define ds_rxstatus7 u.rx.status7
280#define ds_rxstatus8 u.rx.status8
281
282#define AR_FrameLen 0x00000fff
283#define AR_VirtMoreFrag 0x00001000
284#define AR_TxCtlRsvd00 0x0000e000
285#define AR_XmitPower 0x003f0000
286#define AR_XmitPower_S 16
287#define AR_RTSEnable 0x00400000
288#define AR_VEOL 0x00800000
289#define AR_ClrDestMask 0x01000000
290#define AR_TxCtlRsvd01 0x1e000000
291#define AR_TxIntrReq 0x20000000
292#define AR_DestIdxValid 0x40000000
293#define AR_CTSEnable 0x80000000
294
295#define AR_BufLen 0x00000fff
296#define AR_TxMore 0x00001000
297#define AR_DestIdx 0x000fe000
298#define AR_DestIdx_S 13
299#define AR_FrameType 0x00f00000
300#define AR_FrameType_S 20
301#define AR_NoAck 0x01000000
302#define AR_InsertTS 0x02000000
303#define AR_CorruptFCS 0x04000000
304#define AR_ExtOnly 0x08000000
305#define AR_ExtAndCtl 0x10000000
306#define AR_MoreAggr 0x20000000
307#define AR_IsAggr 0x40000000
308
309#define AR_BurstDur 0x00007fff
310#define AR_BurstDur_S 0
311#define AR_DurUpdateEna 0x00008000
312#define AR_XmitDataTries0 0x000f0000
313#define AR_XmitDataTries0_S 16
314#define AR_XmitDataTries1 0x00f00000
315#define AR_XmitDataTries1_S 20
316#define AR_XmitDataTries2 0x0f000000
317#define AR_XmitDataTries2_S 24
318#define AR_XmitDataTries3 0xf0000000
319#define AR_XmitDataTries3_S 28
320
321#define AR_XmitRate0 0x000000ff
322#define AR_XmitRate0_S 0
323#define AR_XmitRate1 0x0000ff00
324#define AR_XmitRate1_S 8
325#define AR_XmitRate2 0x00ff0000
326#define AR_XmitRate2_S 16
327#define AR_XmitRate3 0xff000000
328#define AR_XmitRate3_S 24
329
330#define AR_PacketDur0 0x00007fff
331#define AR_PacketDur0_S 0
332#define AR_RTSCTSQual0 0x00008000
333#define AR_PacketDur1 0x7fff0000
334#define AR_PacketDur1_S 16
335#define AR_RTSCTSQual1 0x80000000
336
337#define AR_PacketDur2 0x00007fff
338#define AR_PacketDur2_S 0
339#define AR_RTSCTSQual2 0x00008000
340#define AR_PacketDur3 0x7fff0000
341#define AR_PacketDur3_S 16
342#define AR_RTSCTSQual3 0x80000000
343
344#define AR_AggrLen 0x0000ffff
345#define AR_AggrLen_S 0
346#define AR_TxCtlRsvd60 0x00030000
347#define AR_PadDelim 0x03fc0000
348#define AR_PadDelim_S 18
349#define AR_EncrType 0x0c000000
350#define AR_EncrType_S 26
351#define AR_TxCtlRsvd61 0xf0000000
352
353#define AR_2040_0 0x00000001
354#define AR_GI0 0x00000002
355#define AR_ChainSel0 0x0000001c
356#define AR_ChainSel0_S 2
357#define AR_2040_1 0x00000020
358#define AR_GI1 0x00000040
359#define AR_ChainSel1 0x00000380
360#define AR_ChainSel1_S 7
361#define AR_2040_2 0x00000400
362#define AR_GI2 0x00000800
363#define AR_ChainSel2 0x00007000
364#define AR_ChainSel2_S 12
365#define AR_2040_3 0x00008000
366#define AR_GI3 0x00010000
367#define AR_ChainSel3 0x000e0000
368#define AR_ChainSel3_S 17
369#define AR_RTSCTSRate 0x0ff00000
370#define AR_RTSCTSRate_S 20
371#define AR_TxCtlRsvd70 0xf0000000
372
373#define AR_TxRSSIAnt00 0x000000ff
374#define AR_TxRSSIAnt00_S 0
375#define AR_TxRSSIAnt01 0x0000ff00
376#define AR_TxRSSIAnt01_S 8
377#define AR_TxRSSIAnt02 0x00ff0000
378#define AR_TxRSSIAnt02_S 16
379#define AR_TxStatusRsvd00 0x3f000000
380#define AR_TxBaStatus 0x40000000
381#define AR_TxStatusRsvd01 0x80000000
382
383#define AR_FrmXmitOK 0x00000001
384#define AR_ExcessiveRetries 0x00000002
385#define AR_FIFOUnderrun 0x00000004
386#define AR_Filtered 0x00000008
387#define AR_RTSFailCnt 0x000000f0
388#define AR_RTSFailCnt_S 4
389#define AR_DataFailCnt 0x00000f00
390#define AR_DataFailCnt_S 8
391#define AR_VirtRetryCnt 0x0000f000
392#define AR_VirtRetryCnt_S 12
393#define AR_TxDelimUnderrun 0x00010000
394#define AR_TxDataUnderrun 0x00020000
395#define AR_DescCfgErr 0x00040000
396#define AR_TxTimerExpired 0x00080000
397#define AR_TxStatusRsvd10 0xfff00000
398
399#define AR_SendTimestamp ds_txstatus2
400#define AR_BaBitmapLow ds_txstatus3
401#define AR_BaBitmapHigh ds_txstatus4
402
403#define AR_TxRSSIAnt10 0x000000ff
404#define AR_TxRSSIAnt10_S 0
405#define AR_TxRSSIAnt11 0x0000ff00
406#define AR_TxRSSIAnt11_S 8
407#define AR_TxRSSIAnt12 0x00ff0000
408#define AR_TxRSSIAnt12_S 16
409#define AR_TxRSSICombined 0xff000000
410#define AR_TxRSSICombined_S 24
411
412#define AR_TxEVM0 ds_txstatus5
413#define AR_TxEVM1 ds_txstatus6
414#define AR_TxEVM2 ds_txstatus7
415
416#define AR_TxDone 0x00000001
417#define AR_SeqNum 0x00001ffe
418#define AR_SeqNum_S 1
419#define AR_TxStatusRsvd80 0x0001e000
420#define AR_TxOpExceeded 0x00020000
421#define AR_TxStatusRsvd81 0x001c0000
422#define AR_FinalTxIdx 0x00600000
423#define AR_FinalTxIdx_S 21
424#define AR_TxStatusRsvd82 0x01800000
425#define AR_PowerMgmt 0x02000000
426#define AR_TxStatusRsvd83 0xfc000000
427
428#define AR_RxCTLRsvd00 0xffffffff
429
430#define AR_BufLen 0x00000fff
431#define AR_RxCtlRsvd00 0x00001000
432#define AR_RxIntrReq 0x00002000
433#define AR_RxCtlRsvd01 0xffffc000
434
435#define AR_RxRSSIAnt00 0x000000ff
436#define AR_RxRSSIAnt00_S 0
437#define AR_RxRSSIAnt01 0x0000ff00
438#define AR_RxRSSIAnt01_S 8
439#define AR_RxRSSIAnt02 0x00ff0000
440#define AR_RxRSSIAnt02_S 16
441#define AR_RxRate 0xff000000
442#define AR_RxRate_S 24
443#define AR_RxStatusRsvd00 0xff000000
444
445#define AR_DataLen 0x00000fff
446#define AR_RxMore 0x00001000
447#define AR_NumDelim 0x003fc000
448#define AR_NumDelim_S 14
449#define AR_RxStatusRsvd10 0xff800000
450
451#define AR_RcvTimestamp ds_rxstatus2
452
453#define AR_GI 0x00000001
454#define AR_2040 0x00000002
455#define AR_Parallel40 0x00000004
456#define AR_Parallel40_S 2
457#define AR_RxStatusRsvd30 0x000000f8
458#define AR_RxAntenna 0xffffff00
459#define AR_RxAntenna_S 8
460
461#define AR_RxRSSIAnt10 0x000000ff
462#define AR_RxRSSIAnt10_S 0
463#define AR_RxRSSIAnt11 0x0000ff00
464#define AR_RxRSSIAnt11_S 8
465#define AR_RxRSSIAnt12 0x00ff0000
466#define AR_RxRSSIAnt12_S 16
467#define AR_RxRSSICombined 0xff000000
468#define AR_RxRSSICombined_S 24
469
470#define AR_RxEVM0 ds_rxstatus4
471#define AR_RxEVM1 ds_rxstatus5
472#define AR_RxEVM2 ds_rxstatus6
473
474#define AR_RxDone 0x00000001
475#define AR_RxFrameOK 0x00000002
476#define AR_CRCErr 0x00000004
477#define AR_DecryptCRCErr 0x00000008
478#define AR_PHYErr 0x00000010
479#define AR_MichaelErr 0x00000020
480#define AR_PreDelimCRCErr 0x00000040
481#define AR_RxStatusRsvd70 0x00000080
482#define AR_RxKeyIdxValid 0x00000100
483#define AR_KeyIdx 0x0000fe00
484#define AR_KeyIdx_S 9
485#define AR_PHYErrCode 0x0000ff00
486#define AR_PHYErrCode_S 8
487#define AR_RxMoreAggr 0x00010000
488#define AR_RxAggr 0x00020000
489#define AR_PostDelimCRCErr 0x00040000
490#define AR_RxStatusRsvd71 0x3ff80000
491#define AR_DecryptBusyErr 0x40000000
492#define AR_KeyMiss 0x80000000
493
494enum ath9k_tx_queue {
495 ATH9K_TX_QUEUE_INACTIVE = 0,
496 ATH9K_TX_QUEUE_DATA,
497 ATH9K_TX_QUEUE_BEACON,
498 ATH9K_TX_QUEUE_CAB,
499 ATH9K_TX_QUEUE_UAPSD,
500 ATH9K_TX_QUEUE_PSPOLL
501};
502
503#define ATH9K_NUM_TX_QUEUES 10
504
505enum ath9k_tx_queue_subtype {
506 ATH9K_WME_AC_BK = 0,
507 ATH9K_WME_AC_BE,
508 ATH9K_WME_AC_VI,
509 ATH9K_WME_AC_VO,
510 ATH9K_WME_UPSD
511};
512
513enum ath9k_tx_queue_flags {
514 TXQ_FLAG_TXOKINT_ENABLE = 0x0001,
515 TXQ_FLAG_TXERRINT_ENABLE = 0x0001,
516 TXQ_FLAG_TXDESCINT_ENABLE = 0x0002,
517 TXQ_FLAG_TXEOLINT_ENABLE = 0x0004,
518 TXQ_FLAG_TXURNINT_ENABLE = 0x0008,
519 TXQ_FLAG_BACKOFF_DISABLE = 0x0010,
520 TXQ_FLAG_COMPRESSION_ENABLE = 0x0020,
521 TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE = 0x0040,
522 TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE = 0x0080,
523};
524
525#define ATH9K_TXQ_USEDEFAULT ((u32) -1)
526#define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001
527
528#define ATH9K_DECOMP_MASK_SIZE 128
529#define ATH9K_READY_TIME_LO_BOUND 50
530#define ATH9K_READY_TIME_HI_BOUND 96
531
532enum ath9k_pkt_type {
533 ATH9K_PKT_TYPE_NORMAL = 0,
534 ATH9K_PKT_TYPE_ATIM,
535 ATH9K_PKT_TYPE_PSPOLL,
536 ATH9K_PKT_TYPE_BEACON,
537 ATH9K_PKT_TYPE_PROBE_RESP,
538 ATH9K_PKT_TYPE_CHIRP,
539 ATH9K_PKT_TYPE_GRP_POLL,
540};
541
542struct ath9k_tx_queue_info {
543 u32 tqi_ver;
544 enum ath9k_tx_queue tqi_type;
545 enum ath9k_tx_queue_subtype tqi_subtype;
546 enum ath9k_tx_queue_flags tqi_qflags;
547 u32 tqi_priority;
548 u32 tqi_aifs;
549 u32 tqi_cwmin;
550 u32 tqi_cwmax;
551 u16 tqi_shretry;
552 u16 tqi_lgretry;
553 u32 tqi_cbrPeriod;
554 u32 tqi_cbrOverflowLimit;
555 u32 tqi_burstTime;
556 u32 tqi_readyTime;
557 u32 tqi_physCompBuf;
558 u32 tqi_intFlags;
559};
560
561enum ath9k_rx_filter {
562 ATH9K_RX_FILTER_UCAST = 0x00000001,
563 ATH9K_RX_FILTER_MCAST = 0x00000002,
564 ATH9K_RX_FILTER_BCAST = 0x00000004,
565 ATH9K_RX_FILTER_CONTROL = 0x00000008,
566 ATH9K_RX_FILTER_BEACON = 0x00000010,
567 ATH9K_RX_FILTER_PROM = 0x00000020,
568 ATH9K_RX_FILTER_PROBEREQ = 0x00000080,
569 ATH9K_RX_FILTER_PHYERR = 0x00000100,
570 ATH9K_RX_FILTER_MYBEACON = 0x00000200,
571 ATH9K_RX_FILTER_PSPOLL = 0x00004000,
572 ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
573 ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
574};
575
576#define ATH9K_RATESERIES_RTS_CTS 0x0001
577#define ATH9K_RATESERIES_2040 0x0002
578#define ATH9K_RATESERIES_HALFGI 0x0004
579
580struct ath9k_11n_rate_series {
581 u32 Tries;
582 u32 Rate;
583 u32 PktDuration;
584 u32 ChSel;
585 u32 RateFlags;
586};
587
588struct ath9k_keyval {
589 u8 kv_type;
590 u8 kv_pad;
591 u16 kv_len;
592 u8 kv_val[16]; /* TK */
593 u8 kv_mic[8]; /* Michael MIC key */
594 u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware
595 * supports both MIC keys in the same key cache entry;
596 * in that case, kv_mic is the RX key) */
597};
598
599enum ath9k_key_type {
600 ATH9K_KEY_TYPE_CLEAR,
601 ATH9K_KEY_TYPE_WEP,
602 ATH9K_KEY_TYPE_AES,
603 ATH9K_KEY_TYPE_TKIP,
604};
605
606enum ath9k_cipher {
607 ATH9K_CIPHER_WEP = 0,
608 ATH9K_CIPHER_AES_OCB = 1,
609 ATH9K_CIPHER_AES_CCM = 2,
610 ATH9K_CIPHER_CKIP = 3,
611 ATH9K_CIPHER_TKIP = 4,
612 ATH9K_CIPHER_CLR = 5,
613 ATH9K_CIPHER_MIC = 127
614};
615
616enum ath9k_ht_macmode {
617 ATH9K_HT_MACMODE_20 = 0,
618 ATH9K_HT_MACMODE_2040 = 1,
619};
620
621enum ath9k_ht_extprotspacing {
622 ATH9K_HT_EXTPROTSPACING_20 = 0,
623 ATH9K_HT_EXTPROTSPACING_25 = 1,
624};
625
626struct ath_hw;
627struct ath9k_channel;
628struct ath_rate_table;
629
630u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
631bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
632bool ath9k_hw_txstart(struct ath_hw *ah, u32 q);
633u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
634bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
635bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q);
636bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
637 u32 segLen, bool firstSeg,
638 bool lastSeg, const struct ath_desc *ds0);
639void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds);
640int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds);
641void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
642 u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
643 u32 keyIx, enum ath9k_key_type keyType, u32 flags);
644void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds,
645 struct ath_desc *lastds,
646 u32 durUpdateEn, u32 rtsctsRate,
647 u32 rtsctsDuration,
648 struct ath9k_11n_rate_series series[],
649 u32 nseries, u32 flags);
650void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
651 u32 aggrLen);
652void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
653 u32 numDelims);
654void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds);
655void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds);
656void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds,
657 u32 burstDuration);
658void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds,
659 u32 vmf);
660void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
661bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
662 const struct ath9k_tx_queue_info *qinfo);
663bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
664 struct ath9k_tx_queue_info *qinfo);
665int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
666 const struct ath9k_tx_queue_info *qinfo);
667bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q);
668bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q);
669int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
670 u32 pa, struct ath_desc *nds, u64 tsf);
671bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
672 u32 size, u32 flags);
673bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
674void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
675void ath9k_hw_rxena(struct ath_hw *ah);
676void ath9k_hw_startpcureceive(struct ath_hw *ah);
677void ath9k_hw_stoppcurecv(struct ath_hw *ah);
678bool ath9k_hw_stopdmarecv(struct ath_hw *ah);
679
680#endif /* MAC_H */
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
new file mode 100644
index 000000000000..8b6a7ea4e59b
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -0,0 +1,2890 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <linux/nl80211.h>
18#include "ath9k.h"
19
20#define ATH_PCI_VERSION "0.1"
21
22static char *dev_info = "ath9k";
23
24MODULE_AUTHOR("Atheros Communications");
25MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
26MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
27MODULE_LICENSE("Dual BSD/GPL");
28
29static int modparam_nohwcrypt;
30module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
31MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
32
33/* We use the hw_value as an index into our private channel structure */
34
35#define CHAN2G(_freq, _idx) { \
36 .center_freq = (_freq), \
37 .hw_value = (_idx), \
38 .max_power = 30, \
39}
40
41#define CHAN5G(_freq, _idx) { \
42 .band = IEEE80211_BAND_5GHZ, \
43 .center_freq = (_freq), \
44 .hw_value = (_idx), \
45 .max_power = 30, \
46}
47
48/* Some 2 GHz radios are actually tunable on 2312-2732
49 * on 5 MHz steps, we support the channels which we know
50 * we have calibration data for all cards though to make
51 * this static */
52static struct ieee80211_channel ath9k_2ghz_chantable[] = {
53 CHAN2G(2412, 0), /* Channel 1 */
54 CHAN2G(2417, 1), /* Channel 2 */
55 CHAN2G(2422, 2), /* Channel 3 */
56 CHAN2G(2427, 3), /* Channel 4 */
57 CHAN2G(2432, 4), /* Channel 5 */
58 CHAN2G(2437, 5), /* Channel 6 */
59 CHAN2G(2442, 6), /* Channel 7 */
60 CHAN2G(2447, 7), /* Channel 8 */
61 CHAN2G(2452, 8), /* Channel 9 */
62 CHAN2G(2457, 9), /* Channel 10 */
63 CHAN2G(2462, 10), /* Channel 11 */
64 CHAN2G(2467, 11), /* Channel 12 */
65 CHAN2G(2472, 12), /* Channel 13 */
66 CHAN2G(2484, 13), /* Channel 14 */
67};
68
69/* Some 5 GHz radios are actually tunable on XXXX-YYYY
70 * on 5 MHz steps, we support the channels which we know
71 * we have calibration data for all cards though to make
72 * this static */
73static struct ieee80211_channel ath9k_5ghz_chantable[] = {
74 /* _We_ call this UNII 1 */
75 CHAN5G(5180, 14), /* Channel 36 */
76 CHAN5G(5200, 15), /* Channel 40 */
77 CHAN5G(5220, 16), /* Channel 44 */
78 CHAN5G(5240, 17), /* Channel 48 */
79 /* _We_ call this UNII 2 */
80 CHAN5G(5260, 18), /* Channel 52 */
81 CHAN5G(5280, 19), /* Channel 56 */
82 CHAN5G(5300, 20), /* Channel 60 */
83 CHAN5G(5320, 21), /* Channel 64 */
84 /* _We_ call this "Middle band" */
85 CHAN5G(5500, 22), /* Channel 100 */
86 CHAN5G(5520, 23), /* Channel 104 */
87 CHAN5G(5540, 24), /* Channel 108 */
88 CHAN5G(5560, 25), /* Channel 112 */
89 CHAN5G(5580, 26), /* Channel 116 */
90 CHAN5G(5600, 27), /* Channel 120 */
91 CHAN5G(5620, 28), /* Channel 124 */
92 CHAN5G(5640, 29), /* Channel 128 */
93 CHAN5G(5660, 30), /* Channel 132 */
94 CHAN5G(5680, 31), /* Channel 136 */
95 CHAN5G(5700, 32), /* Channel 140 */
96 /* _We_ call this UNII 3 */
97 CHAN5G(5745, 33), /* Channel 149 */
98 CHAN5G(5765, 34), /* Channel 153 */
99 CHAN5G(5785, 35), /* Channel 157 */
100 CHAN5G(5805, 36), /* Channel 161 */
101 CHAN5G(5825, 37), /* Channel 165 */
102};
103
104static void ath_cache_conf_rate(struct ath_softc *sc,
105 struct ieee80211_conf *conf)
106{
107 switch (conf->channel->band) {
108 case IEEE80211_BAND_2GHZ:
109 if (conf_is_ht20(conf))
110 sc->cur_rate_table =
111 sc->hw_rate_table[ATH9K_MODE_11NG_HT20];
112 else if (conf_is_ht40_minus(conf))
113 sc->cur_rate_table =
114 sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS];
115 else if (conf_is_ht40_plus(conf))
116 sc->cur_rate_table =
117 sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS];
118 else
119 sc->cur_rate_table =
120 sc->hw_rate_table[ATH9K_MODE_11G];
121 break;
122 case IEEE80211_BAND_5GHZ:
123 if (conf_is_ht20(conf))
124 sc->cur_rate_table =
125 sc->hw_rate_table[ATH9K_MODE_11NA_HT20];
126 else if (conf_is_ht40_minus(conf))
127 sc->cur_rate_table =
128 sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS];
129 else if (conf_is_ht40_plus(conf))
130 sc->cur_rate_table =
131 sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS];
132 else
133 sc->cur_rate_table =
134 sc->hw_rate_table[ATH9K_MODE_11A];
135 break;
136 default:
137 BUG_ON(1);
138 break;
139 }
140}
141
142static void ath_update_txpow(struct ath_softc *sc)
143{
144 struct ath_hw *ah = sc->sc_ah;
145 u32 txpow;
146
147 if (sc->curtxpow != sc->config.txpowlimit) {
148 ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit);
149 /* read back in case value is clamped */
150 ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow);
151 sc->curtxpow = txpow;
152 }
153}
154
155static u8 parse_mpdudensity(u8 mpdudensity)
156{
157 /*
158 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
159 * 0 for no restriction
160 * 1 for 1/4 us
161 * 2 for 1/2 us
162 * 3 for 1 us
163 * 4 for 2 us
164 * 5 for 4 us
165 * 6 for 8 us
166 * 7 for 16 us
167 */
168 switch (mpdudensity) {
169 case 0:
170 return 0;
171 case 1:
172 case 2:
173 case 3:
174 /* Our lower layer calculations limit our precision to
175 1 microsecond */
176 return 1;
177 case 4:
178 return 2;
179 case 5:
180 return 4;
181 case 6:
182 return 8;
183 case 7:
184 return 16;
185 default:
186 return 0;
187 }
188}
189
190static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band)
191{
192 struct ath_rate_table *rate_table = NULL;
193 struct ieee80211_supported_band *sband;
194 struct ieee80211_rate *rate;
195 int i, maxrates;
196
197 switch (band) {
198 case IEEE80211_BAND_2GHZ:
199 rate_table = sc->hw_rate_table[ATH9K_MODE_11G];
200 break;
201 case IEEE80211_BAND_5GHZ:
202 rate_table = sc->hw_rate_table[ATH9K_MODE_11A];
203 break;
204 default:
205 break;
206 }
207
208 if (rate_table == NULL)
209 return;
210
211 sband = &sc->sbands[band];
212 rate = sc->rates[band];
213
214 if (rate_table->rate_cnt > ATH_RATE_MAX)
215 maxrates = ATH_RATE_MAX;
216 else
217 maxrates = rate_table->rate_cnt;
218
219 for (i = 0; i < maxrates; i++) {
220 rate[i].bitrate = rate_table->info[i].ratekbps / 100;
221 rate[i].hw_value = rate_table->info[i].ratecode;
222 if (rate_table->info[i].short_preamble) {
223 rate[i].hw_value_short = rate_table->info[i].ratecode |
224 rate_table->info[i].short_preamble;
225 rate[i].flags = IEEE80211_RATE_SHORT_PREAMBLE;
226 }
227 sband->n_bitrates++;
228
229 DPRINTF(sc, ATH_DBG_CONFIG, "Rate: %2dMbps, ratecode: %2d\n",
230 rate[i].bitrate / 10, rate[i].hw_value);
231 }
232}
233
234/*
235 * Set/change channels. If the channel is really being changed, it's done
236 * by reseting the chip. To accomplish this we must first cleanup any pending
237 * DMA, then restart stuff.
238*/
239int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
240 struct ath9k_channel *hchan)
241{
242 struct ath_hw *ah = sc->sc_ah;
243 bool fastcc = true, stopped;
244 struct ieee80211_channel *channel = hw->conf.channel;
245 int r;
246
247 if (sc->sc_flags & SC_OP_INVALID)
248 return -EIO;
249
250 ath9k_ps_wakeup(sc);
251
252 /*
253 * This is only performed if the channel settings have
254 * actually changed.
255 *
256 * To switch channels clear any pending DMA operations;
257 * wait long enough for the RX fifo to drain, reset the
258 * hardware at the new frequency, and then re-enable
259 * the relevant bits of the h/w.
260 */
261 ath9k_hw_set_interrupts(ah, 0);
262 ath_drain_all_txq(sc, false);
263 stopped = ath_stoprecv(sc);
264
265 /* XXX: do not flush receive queue here. We don't want
266 * to flush data frames already in queue because of
267 * changing channel. */
268
269 if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET))
270 fastcc = false;
271
272 DPRINTF(sc, ATH_DBG_CONFIG,
273 "(%u MHz) -> (%u MHz), chanwidth: %d\n",
274 sc->sc_ah->curchan->channel,
275 channel->center_freq, sc->tx_chan_width);
276
277 spin_lock_bh(&sc->sc_resetlock);
278
279 r = ath9k_hw_reset(ah, hchan, fastcc);
280 if (r) {
281 DPRINTF(sc, ATH_DBG_FATAL,
282 "Unable to reset channel (%u Mhz) "
283 "reset status %u\n",
284 channel->center_freq, r);
285 spin_unlock_bh(&sc->sc_resetlock);
286 return r;
287 }
288 spin_unlock_bh(&sc->sc_resetlock);
289
290 sc->sc_flags &= ~SC_OP_FULL_RESET;
291
292 if (ath_startrecv(sc) != 0) {
293 DPRINTF(sc, ATH_DBG_FATAL,
294 "Unable to restart recv logic\n");
295 return -EIO;
296 }
297
298 ath_cache_conf_rate(sc, &hw->conf);
299 ath_update_txpow(sc);
300 ath9k_hw_set_interrupts(ah, sc->imask);
301 ath9k_ps_restore(sc);
302 return 0;
303}
304
305/*
306 * This routine performs the periodic noise floor calibration function
307 * that is used to adjust and optimize the chip performance. This
308 * takes environmental changes (location, temperature) into account.
309 * When the task is complete, it reschedules itself depending on the
310 * appropriate interval that was calculated.
311 */
312static void ath_ani_calibrate(unsigned long data)
313{
314 struct ath_softc *sc = (struct ath_softc *)data;
315 struct ath_hw *ah = sc->sc_ah;
316 bool longcal = false;
317 bool shortcal = false;
318 bool aniflag = false;
319 unsigned int timestamp = jiffies_to_msecs(jiffies);
320 u32 cal_interval, short_cal_interval;
321
322 short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
323 ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
324
325 /*
326 * don't calibrate when we're scanning.
327 * we are most likely not on our home channel.
328 */
329 if (sc->sc_flags & SC_OP_SCANNING)
330 goto set_timer;
331
332 /* Long calibration runs independently of short calibration. */
333 if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
334 longcal = true;
335 DPRINTF(sc, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
336 sc->ani.longcal_timer = timestamp;
337 }
338
339 /* Short calibration applies only while caldone is false */
340 if (!sc->ani.caldone) {
341 if ((timestamp - sc->ani.shortcal_timer) >= short_cal_interval) {
342 shortcal = true;
343 DPRINTF(sc, ATH_DBG_ANI, "shortcal @%lu\n", jiffies);
344 sc->ani.shortcal_timer = timestamp;
345 sc->ani.resetcal_timer = timestamp;
346 }
347 } else {
348 if ((timestamp - sc->ani.resetcal_timer) >=
349 ATH_RESTART_CALINTERVAL) {
350 sc->ani.caldone = ath9k_hw_reset_calvalid(ah);
351 if (sc->ani.caldone)
352 sc->ani.resetcal_timer = timestamp;
353 }
354 }
355
356 /* Verify whether we must check ANI */
357 if ((timestamp - sc->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
358 aniflag = true;
359 sc->ani.checkani_timer = timestamp;
360 }
361
362 /* Skip all processing if there's nothing to do. */
363 if (longcal || shortcal || aniflag) {
364 /* Call ANI routine if necessary */
365 if (aniflag)
366 ath9k_hw_ani_monitor(ah, &sc->nodestats, ah->curchan);
367
368 /* Perform calibration if necessary */
369 if (longcal || shortcal) {
370 bool iscaldone = false;
371
372 if (ath9k_hw_calibrate(ah, ah->curchan,
373 sc->rx_chainmask, longcal,
374 &iscaldone)) {
375 if (longcal)
376 sc->ani.noise_floor =
377 ath9k_hw_getchan_noise(ah,
378 ah->curchan);
379
380 DPRINTF(sc, ATH_DBG_ANI,
381 "calibrate chan %u/%x nf: %d\n",
382 ah->curchan->channel,
383 ah->curchan->channelFlags,
384 sc->ani.noise_floor);
385 } else {
386 DPRINTF(sc, ATH_DBG_ANY,
387 "calibrate chan %u/%x failed\n",
388 ah->curchan->channel,
389 ah->curchan->channelFlags);
390 }
391 sc->ani.caldone = iscaldone;
392 }
393 }
394
395set_timer:
396 /*
397 * Set timer interval based on previous results.
398 * The interval must be the shortest necessary to satisfy ANI,
399 * short calibration and long calibration.
400 */
401 cal_interval = ATH_LONG_CALINTERVAL;
402 if (sc->sc_ah->config.enable_ani)
403 cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL);
404 if (!sc->ani.caldone)
405 cal_interval = min(cal_interval, (u32)short_cal_interval);
406
407 mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
408}
409
410/*
411 * Update tx/rx chainmask. For legacy association,
412 * hard code chainmask to 1x1, for 11n association, use
413 * the chainmask configuration, for bt coexistence, use
414 * the chainmask configuration even in legacy mode.
415 */
416void ath_update_chainmask(struct ath_softc *sc, int is_ht)
417{
418 if (is_ht ||
419 (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) {
420 sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
421 sc->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
422 } else {
423 sc->tx_chainmask = 1;
424 sc->rx_chainmask = 1;
425 }
426
427 DPRINTF(sc, ATH_DBG_CONFIG, "tx chmask: %d, rx chmask: %d\n",
428 sc->tx_chainmask, sc->rx_chainmask);
429}
430
431static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
432{
433 struct ath_node *an;
434
435 an = (struct ath_node *)sta->drv_priv;
436
437 if (sc->sc_flags & SC_OP_TXAGGR) {
438 ath_tx_node_init(sc, an);
439 an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
440 sta->ht_cap.ampdu_factor);
441 an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
442 }
443}
444
445static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
446{
447 struct ath_node *an = (struct ath_node *)sta->drv_priv;
448
449 if (sc->sc_flags & SC_OP_TXAGGR)
450 ath_tx_node_cleanup(sc, an);
451}
452
453static void ath9k_tasklet(unsigned long data)
454{
455 struct ath_softc *sc = (struct ath_softc *)data;
456 u32 status = sc->intrstatus;
457
458 if (status & ATH9K_INT_FATAL) {
459 ath_reset(sc, false);
460 return;
461 }
462
463 if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
464 spin_lock_bh(&sc->rx.rxflushlock);
465 ath_rx_tasklet(sc, 0);
466 spin_unlock_bh(&sc->rx.rxflushlock);
467 }
468
469 if (status & ATH9K_INT_TX)
470 ath_tx_tasklet(sc);
471
472 /* re-enable hardware interrupt */
473 ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
474}
475
476irqreturn_t ath_isr(int irq, void *dev)
477{
478#define SCHED_INTR ( \
479 ATH9K_INT_FATAL | \
480 ATH9K_INT_RXORN | \
481 ATH9K_INT_RXEOL | \
482 ATH9K_INT_RX | \
483 ATH9K_INT_TX | \
484 ATH9K_INT_BMISS | \
485 ATH9K_INT_CST | \
486 ATH9K_INT_TSFOOR)
487
488 struct ath_softc *sc = dev;
489 struct ath_hw *ah = sc->sc_ah;
490 enum ath9k_int status;
491 bool sched = false;
492
493 /*
494 * The hardware is not ready/present, don't
495 * touch anything. Note this can happen early
496 * on if the IRQ is shared.
497 */
498 if (sc->sc_flags & SC_OP_INVALID)
499 return IRQ_NONE;
500
501 ath9k_ps_wakeup(sc);
502
503 /* shared irq, not for us */
504
505 if (!ath9k_hw_intrpend(ah)) {
506 ath9k_ps_restore(sc);
507 return IRQ_NONE;
508 }
509
510 /*
511 * Figure out the reason(s) for the interrupt. Note
512 * that the hal returns a pseudo-ISR that may include
513 * bits we haven't explicitly enabled so we mask the
514 * value to insure we only process bits we requested.
515 */
516 ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */
517 status &= sc->imask; /* discard unasked-for bits */
518
519 /*
520 * If there are no status bits set, then this interrupt was not
521 * for me (should have been caught above).
522 */
523 if (!status) {
524 ath9k_ps_restore(sc);
525 return IRQ_NONE;
526 }
527
528 /* Cache the status */
529 sc->intrstatus = status;
530
531 if (status & SCHED_INTR)
532 sched = true;
533
534 /*
535 * If a FATAL or RXORN interrupt is received, we have to reset the
536 * chip immediately.
537 */
538 if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN))
539 goto chip_reset;
540
541 if (status & ATH9K_INT_SWBA)
542 tasklet_schedule(&sc->bcon_tasklet);
543
544 if (status & ATH9K_INT_TXURN)
545 ath9k_hw_updatetxtriglevel(ah, true);
546
547 if (status & ATH9K_INT_MIB) {
548 /*
549 * Disable interrupts until we service the MIB
550 * interrupt; otherwise it will continue to
551 * fire.
552 */
553 ath9k_hw_set_interrupts(ah, 0);
554 /*
555 * Let the hal handle the event. We assume
556 * it will clear whatever condition caused
557 * the interrupt.
558 */
559 ath9k_hw_procmibevent(ah, &sc->nodestats);
560 ath9k_hw_set_interrupts(ah, sc->imask);
561 }
562
563 if (status & ATH9K_INT_TIM_TIMER) {
564 if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
565 /* Clear RxAbort bit so that we can
566 * receive frames */
567 ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
568 ath9k_hw_setrxabort(ah, 0);
569 sched = true;
570 sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
571 }
572 }
573
574chip_reset:
575
576 ath9k_ps_restore(sc);
577 ath_debug_stat_interrupt(sc, status);
578
579 if (sched) {
580 /* turn off every interrupt except SWBA */
581 ath9k_hw_set_interrupts(ah, (sc->imask & ATH9K_INT_SWBA));
582 tasklet_schedule(&sc->intr_tq);
583 }
584
585 return IRQ_HANDLED;
586
587#undef SCHED_INTR
588}
589
590static u32 ath_get_extchanmode(struct ath_softc *sc,
591 struct ieee80211_channel *chan,
592 enum nl80211_channel_type channel_type)
593{
594 u32 chanmode = 0;
595
596 switch (chan->band) {
597 case IEEE80211_BAND_2GHZ:
598 switch(channel_type) {
599 case NL80211_CHAN_NO_HT:
600 case NL80211_CHAN_HT20:
601 chanmode = CHANNEL_G_HT20;
602 break;
603 case NL80211_CHAN_HT40PLUS:
604 chanmode = CHANNEL_G_HT40PLUS;
605 break;
606 case NL80211_CHAN_HT40MINUS:
607 chanmode = CHANNEL_G_HT40MINUS;
608 break;
609 }
610 break;
611 case IEEE80211_BAND_5GHZ:
612 switch(channel_type) {
613 case NL80211_CHAN_NO_HT:
614 case NL80211_CHAN_HT20:
615 chanmode = CHANNEL_A_HT20;
616 break;
617 case NL80211_CHAN_HT40PLUS:
618 chanmode = CHANNEL_A_HT40PLUS;
619 break;
620 case NL80211_CHAN_HT40MINUS:
621 chanmode = CHANNEL_A_HT40MINUS;
622 break;
623 }
624 break;
625 default:
626 break;
627 }
628
629 return chanmode;
630}
631
632static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key,
633 struct ath9k_keyval *hk, const u8 *addr,
634 bool authenticator)
635{
636 const u8 *key_rxmic;
637 const u8 *key_txmic;
638
639 key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
640 key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
641
642 if (addr == NULL) {
643 /*
644 * Group key installation - only two key cache entries are used
645 * regardless of splitmic capability since group key is only
646 * used either for TX or RX.
647 */
648 if (authenticator) {
649 memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
650 memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
651 } else {
652 memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
653 memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
654 }
655 return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr);
656 }
657 if (!sc->splitmic) {
658 /* TX and RX keys share the same key cache entry. */
659 memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
660 memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
661 return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr);
662 }
663
664 /* Separate key cache entries for TX and RX */
665
666 /* TX key goes at first index, RX key at +32. */
667 memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
668 if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) {
669 /* TX MIC entry failed. No need to proceed further */
670 DPRINTF(sc, ATH_DBG_FATAL,
671 "Setting TX MIC Key Failed\n");
672 return 0;
673 }
674
675 memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
676 /* XXX delete tx key on failure? */
677 return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix + 32, hk, addr);
678}
679
680static int ath_reserve_key_cache_slot_tkip(struct ath_softc *sc)
681{
682 int i;
683
684 for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) {
685 if (test_bit(i, sc->keymap) ||
686 test_bit(i + 64, sc->keymap))
687 continue; /* At least one part of TKIP key allocated */
688 if (sc->splitmic &&
689 (test_bit(i + 32, sc->keymap) ||
690 test_bit(i + 64 + 32, sc->keymap)))
691 continue; /* At least one part of TKIP key allocated */
692
693 /* Found a free slot for a TKIP key */
694 return i;
695 }
696 return -1;
697}
698
699static int ath_reserve_key_cache_slot(struct ath_softc *sc)
700{
701 int i;
702
703 /* First, try to find slots that would not be available for TKIP. */
704 if (sc->splitmic) {
705 for (i = IEEE80211_WEP_NKID; i < sc->keymax / 4; i++) {
706 if (!test_bit(i, sc->keymap) &&
707 (test_bit(i + 32, sc->keymap) ||
708 test_bit(i + 64, sc->keymap) ||
709 test_bit(i + 64 + 32, sc->keymap)))
710 return i;
711 if (!test_bit(i + 32, sc->keymap) &&
712 (test_bit(i, sc->keymap) ||
713 test_bit(i + 64, sc->keymap) ||
714 test_bit(i + 64 + 32, sc->keymap)))
715 return i + 32;
716 if (!test_bit(i + 64, sc->keymap) &&
717 (test_bit(i , sc->keymap) ||
718 test_bit(i + 32, sc->keymap) ||
719 test_bit(i + 64 + 32, sc->keymap)))
720 return i + 64;
721 if (!test_bit(i + 64 + 32, sc->keymap) &&
722 (test_bit(i, sc->keymap) ||
723 test_bit(i + 32, sc->keymap) ||
724 test_bit(i + 64, sc->keymap)))
725 return i + 64 + 32;
726 }
727 } else {
728 for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) {
729 if (!test_bit(i, sc->keymap) &&
730 test_bit(i + 64, sc->keymap))
731 return i;
732 if (test_bit(i, sc->keymap) &&
733 !test_bit(i + 64, sc->keymap))
734 return i + 64;
735 }
736 }
737
738 /* No partially used TKIP slots, pick any available slot */
739 for (i = IEEE80211_WEP_NKID; i < sc->keymax; i++) {
740 /* Do not allow slots that could be needed for TKIP group keys
741 * to be used. This limitation could be removed if we know that
742 * TKIP will not be used. */
743 if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
744 continue;
745 if (sc->splitmic) {
746 if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
747 continue;
748 if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
749 continue;
750 }
751
752 if (!test_bit(i, sc->keymap))
753 return i; /* Found a free slot for a key */
754 }
755
756 /* No free slot found */
757 return -1;
758}
759
760static int ath_key_config(struct ath_softc *sc,
761 struct ieee80211_vif *vif,
762 struct ieee80211_sta *sta,
763 struct ieee80211_key_conf *key)
764{
765 struct ath9k_keyval hk;
766 const u8 *mac = NULL;
767 int ret = 0;
768 int idx;
769
770 memset(&hk, 0, sizeof(hk));
771
772 switch (key->alg) {
773 case ALG_WEP:
774 hk.kv_type = ATH9K_CIPHER_WEP;
775 break;
776 case ALG_TKIP:
777 hk.kv_type = ATH9K_CIPHER_TKIP;
778 break;
779 case ALG_CCMP:
780 hk.kv_type = ATH9K_CIPHER_AES_CCM;
781 break;
782 default:
783 return -EOPNOTSUPP;
784 }
785
786 hk.kv_len = key->keylen;
787 memcpy(hk.kv_val, key->key, key->keylen);
788
789 if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
790 /* For now, use the default keys for broadcast keys. This may
791 * need to change with virtual interfaces. */
792 idx = key->keyidx;
793 } else if (key->keyidx) {
794 if (WARN_ON(!sta))
795 return -EOPNOTSUPP;
796 mac = sta->addr;
797
798 if (vif->type != NL80211_IFTYPE_AP) {
799 /* Only keyidx 0 should be used with unicast key, but
800 * allow this for client mode for now. */
801 idx = key->keyidx;
802 } else
803 return -EIO;
804 } else {
805 if (WARN_ON(!sta))
806 return -EOPNOTSUPP;
807 mac = sta->addr;
808
809 if (key->alg == ALG_TKIP)
810 idx = ath_reserve_key_cache_slot_tkip(sc);
811 else
812 idx = ath_reserve_key_cache_slot(sc);
813 if (idx < 0)
814 return -ENOSPC; /* no free key cache entries */
815 }
816
817 if (key->alg == ALG_TKIP)
818 ret = ath_setkey_tkip(sc, idx, key->key, &hk, mac,
819 vif->type == NL80211_IFTYPE_AP);
820 else
821 ret = ath9k_hw_set_keycache_entry(sc->sc_ah, idx, &hk, mac);
822
823 if (!ret)
824 return -EIO;
825
826 set_bit(idx, sc->keymap);
827 if (key->alg == ALG_TKIP) {
828 set_bit(idx + 64, sc->keymap);
829 if (sc->splitmic) {
830 set_bit(idx + 32, sc->keymap);
831 set_bit(idx + 64 + 32, sc->keymap);
832 }
833 }
834
835 return idx;
836}
837
838static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
839{
840 ath9k_hw_keyreset(sc->sc_ah, key->hw_key_idx);
841 if (key->hw_key_idx < IEEE80211_WEP_NKID)
842 return;
843
844 clear_bit(key->hw_key_idx, sc->keymap);
845 if (key->alg != ALG_TKIP)
846 return;
847
848 clear_bit(key->hw_key_idx + 64, sc->keymap);
849 if (sc->splitmic) {
850 clear_bit(key->hw_key_idx + 32, sc->keymap);
851 clear_bit(key->hw_key_idx + 64 + 32, sc->keymap);
852 }
853}
854
855static void setup_ht_cap(struct ath_softc *sc,
856 struct ieee80211_sta_ht_cap *ht_info)
857{
858#define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */
859#define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */
860
861 ht_info->ht_supported = true;
862 ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
863 IEEE80211_HT_CAP_SM_PS |
864 IEEE80211_HT_CAP_SGI_40 |
865 IEEE80211_HT_CAP_DSSSCCK40;
866
867 ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536;
868 ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8;
869
870 /* set up supported mcs set */
871 memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
872
873 switch(sc->rx_chainmask) {
874 case 1:
875 ht_info->mcs.rx_mask[0] = 0xff;
876 break;
877 case 3:
878 case 5:
879 case 7:
880 default:
881 ht_info->mcs.rx_mask[0] = 0xff;
882 ht_info->mcs.rx_mask[1] = 0xff;
883 break;
884 }
885
886 ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
887}
888
889static void ath9k_bss_assoc_info(struct ath_softc *sc,
890 struct ieee80211_vif *vif,
891 struct ieee80211_bss_conf *bss_conf)
892{
893 struct ath_vif *avp = (void *)vif->drv_priv;
894
895 if (bss_conf->assoc) {
896 DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d, bssid: %pM\n",
897 bss_conf->aid, sc->curbssid);
898
899 /* New association, store aid */
900 if (avp->av_opmode == NL80211_IFTYPE_STATION) {
901 sc->curaid = bss_conf->aid;
902 ath9k_hw_write_associd(sc);
903 }
904
905 /* Configure the beacon */
906 ath_beacon_config(sc, vif);
907
908 /* Reset rssi stats */
909 sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
910 sc->nodestats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
911 sc->nodestats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
912 sc->nodestats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER;
913
914 /* Start ANI */
915 mod_timer(&sc->ani.timer,
916 jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
917 } else {
918 DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
919 sc->curaid = 0;
920 }
921}
922
923/********************************/
924/* LED functions */
925/********************************/
926
927static void ath_led_blink_work(struct work_struct *work)
928{
929 struct ath_softc *sc = container_of(work, struct ath_softc,
930 ath_led_blink_work.work);
931
932 if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED))
933 return;
934
935 if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
936 (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
937 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
938 else
939 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
940 (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
941
942 queue_delayed_work(sc->hw->workqueue, &sc->ath_led_blink_work,
943 (sc->sc_flags & SC_OP_LED_ON) ?
944 msecs_to_jiffies(sc->led_off_duration) :
945 msecs_to_jiffies(sc->led_on_duration));
946
947 sc->led_on_duration = sc->led_on_cnt ?
948 max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) :
949 ATH_LED_ON_DURATION_IDLE;
950 sc->led_off_duration = sc->led_off_cnt ?
951 max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) :
952 ATH_LED_OFF_DURATION_IDLE;
953 sc->led_on_cnt = sc->led_off_cnt = 0;
954 if (sc->sc_flags & SC_OP_LED_ON)
955 sc->sc_flags &= ~SC_OP_LED_ON;
956 else
957 sc->sc_flags |= SC_OP_LED_ON;
958}
959
960static void ath_led_brightness(struct led_classdev *led_cdev,
961 enum led_brightness brightness)
962{
963 struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
964 struct ath_softc *sc = led->sc;
965
966 switch (brightness) {
967 case LED_OFF:
968 if (led->led_type == ATH_LED_ASSOC ||
969 led->led_type == ATH_LED_RADIO) {
970 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
971 (led->led_type == ATH_LED_RADIO));
972 sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
973 if (led->led_type == ATH_LED_RADIO)
974 sc->sc_flags &= ~SC_OP_LED_ON;
975 } else {
976 sc->led_off_cnt++;
977 }
978 break;
979 case LED_FULL:
980 if (led->led_type == ATH_LED_ASSOC) {
981 sc->sc_flags |= SC_OP_LED_ASSOCIATED;
982 queue_delayed_work(sc->hw->workqueue,
983 &sc->ath_led_blink_work, 0);
984 } else if (led->led_type == ATH_LED_RADIO) {
985 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
986 sc->sc_flags |= SC_OP_LED_ON;
987 } else {
988 sc->led_on_cnt++;
989 }
990 break;
991 default:
992 break;
993 }
994}
995
996static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
997 char *trigger)
998{
999 int ret;
1000
1001 led->sc = sc;
1002 led->led_cdev.name = led->name;
1003 led->led_cdev.default_trigger = trigger;
1004 led->led_cdev.brightness_set = ath_led_brightness;
1005
1006 ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
1007 if (ret)
1008 DPRINTF(sc, ATH_DBG_FATAL,
1009 "Failed to register led:%s", led->name);
1010 else
1011 led->registered = 1;
1012 return ret;
1013}
1014
1015static void ath_unregister_led(struct ath_led *led)
1016{
1017 if (led->registered) {
1018 led_classdev_unregister(&led->led_cdev);
1019 led->registered = 0;
1020 }
1021}
1022
1023static void ath_deinit_leds(struct ath_softc *sc)
1024{
1025 cancel_delayed_work_sync(&sc->ath_led_blink_work);
1026 ath_unregister_led(&sc->assoc_led);
1027 sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
1028 ath_unregister_led(&sc->tx_led);
1029 ath_unregister_led(&sc->rx_led);
1030 ath_unregister_led(&sc->radio_led);
1031 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
1032}
1033
1034static void ath_init_leds(struct ath_softc *sc)
1035{
1036 char *trigger;
1037 int ret;
1038
1039 /* Configure gpio 1 for output */
1040 ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
1041 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
1042 /* LED off, active low */
1043 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
1044
1045 INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work);
1046
1047 trigger = ieee80211_get_radio_led_name(sc->hw);
1048 snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
1049 "ath9k-%s::radio", wiphy_name(sc->hw->wiphy));
1050 ret = ath_register_led(sc, &sc->radio_led, trigger);
1051 sc->radio_led.led_type = ATH_LED_RADIO;
1052 if (ret)
1053 goto fail;
1054
1055 trigger = ieee80211_get_assoc_led_name(sc->hw);
1056 snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name),
1057 "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy));
1058 ret = ath_register_led(sc, &sc->assoc_led, trigger);
1059 sc->assoc_led.led_type = ATH_LED_ASSOC;
1060 if (ret)
1061 goto fail;
1062
1063 trigger = ieee80211_get_tx_led_name(sc->hw);
1064 snprintf(sc->tx_led.name, sizeof(sc->tx_led.name),
1065 "ath9k-%s::tx", wiphy_name(sc->hw->wiphy));
1066 ret = ath_register_led(sc, &sc->tx_led, trigger);
1067 sc->tx_led.led_type = ATH_LED_TX;
1068 if (ret)
1069 goto fail;
1070
1071 trigger = ieee80211_get_rx_led_name(sc->hw);
1072 snprintf(sc->rx_led.name, sizeof(sc->rx_led.name),
1073 "ath9k-%s::rx", wiphy_name(sc->hw->wiphy));
1074 ret = ath_register_led(sc, &sc->rx_led, trigger);
1075 sc->rx_led.led_type = ATH_LED_RX;
1076 if (ret)
1077 goto fail;
1078
1079 return;
1080
1081fail:
1082 ath_deinit_leds(sc);
1083}
1084
1085void ath_radio_enable(struct ath_softc *sc)
1086{
1087 struct ath_hw *ah = sc->sc_ah;
1088 struct ieee80211_channel *channel = sc->hw->conf.channel;
1089 int r;
1090
1091 ath9k_ps_wakeup(sc);
1092 spin_lock_bh(&sc->sc_resetlock);
1093
1094 r = ath9k_hw_reset(ah, ah->curchan, false);
1095
1096 if (r) {
1097 DPRINTF(sc, ATH_DBG_FATAL,
1098 "Unable to reset channel %u (%uMhz) ",
1099 "reset status %u\n",
1100 channel->center_freq, r);
1101 }
1102 spin_unlock_bh(&sc->sc_resetlock);
1103
1104 ath_update_txpow(sc);
1105 if (ath_startrecv(sc) != 0) {
1106 DPRINTF(sc, ATH_DBG_FATAL,
1107 "Unable to restart recv logic\n");
1108 return;
1109 }
1110
1111 if (sc->sc_flags & SC_OP_BEACONS)
1112 ath_beacon_config(sc, NULL); /* restart beacons */
1113
1114 /* Re-Enable interrupts */
1115 ath9k_hw_set_interrupts(ah, sc->imask);
1116
1117 /* Enable LED */
1118 ath9k_hw_cfg_output(ah, ATH_LED_PIN,
1119 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
1120 ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0);
1121
1122 ieee80211_wake_queues(sc->hw);
1123 ath9k_ps_restore(sc);
1124}
1125
1126void ath_radio_disable(struct ath_softc *sc)
1127{
1128 struct ath_hw *ah = sc->sc_ah;
1129 struct ieee80211_channel *channel = sc->hw->conf.channel;
1130 int r;
1131
1132 ath9k_ps_wakeup(sc);
1133 ieee80211_stop_queues(sc->hw);
1134
1135 /* Disable LED */
1136 ath9k_hw_set_gpio(ah, ATH_LED_PIN, 1);
1137 ath9k_hw_cfg_gpio_input(ah, ATH_LED_PIN);
1138
1139 /* Disable interrupts */
1140 ath9k_hw_set_interrupts(ah, 0);
1141
1142 ath_drain_all_txq(sc, false); /* clear pending tx frames */
1143 ath_stoprecv(sc); /* turn off frame recv */
1144 ath_flushrecv(sc); /* flush recv queue */
1145
1146 spin_lock_bh(&sc->sc_resetlock);
1147 r = ath9k_hw_reset(ah, ah->curchan, false);
1148 if (r) {
1149 DPRINTF(sc, ATH_DBG_FATAL,
1150 "Unable to reset channel %u (%uMhz) "
1151 "reset status %u\n",
1152 channel->center_freq, r);
1153 }
1154 spin_unlock_bh(&sc->sc_resetlock);
1155
1156 ath9k_hw_phy_disable(ah);
1157 ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
1158 ath9k_ps_restore(sc);
1159}
1160
1161#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
1162
1163/*******************/
1164/* Rfkill */
1165/*******************/
1166
1167static bool ath_is_rfkill_set(struct ath_softc *sc)
1168{
1169 struct ath_hw *ah = sc->sc_ah;
1170
1171 return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) ==
1172 ah->rfkill_polarity;
1173}
1174
1175/* h/w rfkill poll function */
1176static void ath_rfkill_poll(struct work_struct *work)
1177{
1178 struct ath_softc *sc = container_of(work, struct ath_softc,
1179 rf_kill.rfkill_poll.work);
1180 bool radio_on;
1181
1182 if (sc->sc_flags & SC_OP_INVALID)
1183 return;
1184
1185 radio_on = !ath_is_rfkill_set(sc);
1186
1187 /*
1188 * enable/disable radio only when there is a
1189 * state change in RF switch
1190 */
1191 if (radio_on == !!(sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED)) {
1192 enum rfkill_state state;
1193
1194 if (sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED) {
1195 state = radio_on ? RFKILL_STATE_SOFT_BLOCKED
1196 : RFKILL_STATE_HARD_BLOCKED;
1197 } else if (radio_on) {
1198 ath_radio_enable(sc);
1199 state = RFKILL_STATE_UNBLOCKED;
1200 } else {
1201 ath_radio_disable(sc);
1202 state = RFKILL_STATE_HARD_BLOCKED;
1203 }
1204
1205 if (state == RFKILL_STATE_HARD_BLOCKED)
1206 sc->sc_flags |= SC_OP_RFKILL_HW_BLOCKED;
1207 else
1208 sc->sc_flags &= ~SC_OP_RFKILL_HW_BLOCKED;
1209
1210 rfkill_force_state(sc->rf_kill.rfkill, state);
1211 }
1212
1213 queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll,
1214 msecs_to_jiffies(ATH_RFKILL_POLL_INTERVAL));
1215}
1216
1217/* s/w rfkill handler */
1218static int ath_sw_toggle_radio(void *data, enum rfkill_state state)
1219{
1220 struct ath_softc *sc = data;
1221
1222 switch (state) {
1223 case RFKILL_STATE_SOFT_BLOCKED:
1224 if (!(sc->sc_flags & (SC_OP_RFKILL_HW_BLOCKED |
1225 SC_OP_RFKILL_SW_BLOCKED)))
1226 ath_radio_disable(sc);
1227 sc->sc_flags |= SC_OP_RFKILL_SW_BLOCKED;
1228 return 0;
1229 case RFKILL_STATE_UNBLOCKED:
1230 if ((sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED)) {
1231 sc->sc_flags &= ~SC_OP_RFKILL_SW_BLOCKED;
1232 if (sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED) {
1233 DPRINTF(sc, ATH_DBG_FATAL, "Can't turn on the"
1234 "radio as it is disabled by h/w\n");
1235 return -EPERM;
1236 }
1237 ath_radio_enable(sc);
1238 }
1239 return 0;
1240 default:
1241 return -EINVAL;
1242 }
1243}
1244
1245/* Init s/w rfkill */
1246static int ath_init_sw_rfkill(struct ath_softc *sc)
1247{
1248 sc->rf_kill.rfkill = rfkill_allocate(wiphy_dev(sc->hw->wiphy),
1249 RFKILL_TYPE_WLAN);
1250 if (!sc->rf_kill.rfkill) {
1251 DPRINTF(sc, ATH_DBG_FATAL, "Failed to allocate rfkill\n");
1252 return -ENOMEM;
1253 }
1254
1255 snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name),
1256 "ath9k-%s::rfkill", wiphy_name(sc->hw->wiphy));
1257 sc->rf_kill.rfkill->name = sc->rf_kill.rfkill_name;
1258 sc->rf_kill.rfkill->data = sc;
1259 sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio;
1260 sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED;
1261
1262 return 0;
1263}
1264
1265/* Deinitialize rfkill */
1266static void ath_deinit_rfkill(struct ath_softc *sc)
1267{
1268 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
1269 cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
1270
1271 if (sc->sc_flags & SC_OP_RFKILL_REGISTERED) {
1272 rfkill_unregister(sc->rf_kill.rfkill);
1273 sc->sc_flags &= ~SC_OP_RFKILL_REGISTERED;
1274 sc->rf_kill.rfkill = NULL;
1275 }
1276}
1277
1278static int ath_start_rfkill_poll(struct ath_softc *sc)
1279{
1280 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
1281 queue_delayed_work(sc->hw->workqueue,
1282 &sc->rf_kill.rfkill_poll, 0);
1283
1284 if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) {
1285 if (rfkill_register(sc->rf_kill.rfkill)) {
1286 DPRINTF(sc, ATH_DBG_FATAL,
1287 "Unable to register rfkill\n");
1288 rfkill_free(sc->rf_kill.rfkill);
1289
1290 /* Deinitialize the device */
1291 ath_cleanup(sc);
1292 return -EIO;
1293 } else {
1294 sc->sc_flags |= SC_OP_RFKILL_REGISTERED;
1295 }
1296 }
1297
1298 return 0;
1299}
1300#endif /* CONFIG_RFKILL */
1301
1302void ath_cleanup(struct ath_softc *sc)
1303{
1304 ath_detach(sc);
1305 free_irq(sc->irq, sc);
1306 ath_bus_cleanup(sc);
1307 kfree(sc->sec_wiphy);
1308 ieee80211_free_hw(sc->hw);
1309}
1310
1311void ath_detach(struct ath_softc *sc)
1312{
1313 struct ieee80211_hw *hw = sc->hw;
1314 int i = 0;
1315
1316 ath9k_ps_wakeup(sc);
1317
1318 DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n");
1319
1320#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
1321 ath_deinit_rfkill(sc);
1322#endif
1323 ath_deinit_leds(sc);
1324 cancel_work_sync(&sc->chan_work);
1325 cancel_delayed_work_sync(&sc->wiphy_work);
1326
1327 for (i = 0; i < sc->num_sec_wiphy; i++) {
1328 struct ath_wiphy *aphy = sc->sec_wiphy[i];
1329 if (aphy == NULL)
1330 continue;
1331 sc->sec_wiphy[i] = NULL;
1332 ieee80211_unregister_hw(aphy->hw);
1333 ieee80211_free_hw(aphy->hw);
1334 }
1335 ieee80211_unregister_hw(hw);
1336 ath_rx_cleanup(sc);
1337 ath_tx_cleanup(sc);
1338
1339 tasklet_kill(&sc->intr_tq);
1340 tasklet_kill(&sc->bcon_tasklet);
1341
1342 if (!(sc->sc_flags & SC_OP_INVALID))
1343 ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
1344
1345 /* cleanup tx queues */
1346 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
1347 if (ATH_TXQ_SETUP(sc, i))
1348 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
1349
1350 ath9k_hw_detach(sc->sc_ah);
1351 ath9k_exit_debug(sc);
1352 ath9k_ps_restore(sc);
1353}
1354
1355static int ath9k_reg_notifier(struct wiphy *wiphy,
1356 struct regulatory_request *request)
1357{
1358 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
1359 struct ath_wiphy *aphy = hw->priv;
1360 struct ath_softc *sc = aphy->sc;
1361 struct ath_regulatory *reg = &sc->sc_ah->regulatory;
1362
1363 return ath_reg_notifier_apply(wiphy, request, reg);
1364}
1365
1366static int ath_init(u16 devid, struct ath_softc *sc)
1367{
1368 struct ath_hw *ah = NULL;
1369 int status;
1370 int error = 0, i;
1371 int csz = 0;
1372
1373 /* XXX: hardware will not be ready until ath_open() being called */
1374 sc->sc_flags |= SC_OP_INVALID;
1375
1376 if (ath9k_init_debug(sc) < 0)
1377 printk(KERN_ERR "Unable to create debugfs files\n");
1378
1379 spin_lock_init(&sc->wiphy_lock);
1380 spin_lock_init(&sc->sc_resetlock);
1381 spin_lock_init(&sc->sc_serial_rw);
1382 mutex_init(&sc->mutex);
1383 tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
1384 tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
1385 (unsigned long)sc);
1386
1387 /*
1388 * Cache line size is used to size and align various
1389 * structures used to communicate with the hardware.
1390 */
1391 ath_read_cachesize(sc, &csz);
1392 /* XXX assert csz is non-zero */
1393 sc->cachelsz = csz << 2; /* convert to bytes */
1394
1395 ah = ath9k_hw_attach(devid, sc, &status);
1396 if (ah == NULL) {
1397 DPRINTF(sc, ATH_DBG_FATAL,
1398 "Unable to attach hardware; HAL status %d\n", status);
1399 error = -ENXIO;
1400 goto bad;
1401 }
1402 sc->sc_ah = ah;
1403
1404 /* Get the hardware key cache size. */
1405 sc->keymax = ah->caps.keycache_size;
1406 if (sc->keymax > ATH_KEYMAX) {
1407 DPRINTF(sc, ATH_DBG_ANY,
1408 "Warning, using only %u entries in %u key cache\n",
1409 ATH_KEYMAX, sc->keymax);
1410 sc->keymax = ATH_KEYMAX;
1411 }
1412
1413 /*
1414 * Reset the key cache since some parts do not
1415 * reset the contents on initial power up.
1416 */
1417 for (i = 0; i < sc->keymax; i++)
1418 ath9k_hw_keyreset(ah, (u16) i);
1419
1420 if (ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy,
1421 ath9k_reg_notifier))
1422 goto bad;
1423
1424 /* default to MONITOR mode */
1425 sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR;
1426
1427 /* Setup rate tables */
1428
1429 ath_rate_attach(sc);
1430 ath_setup_rates(sc, IEEE80211_BAND_2GHZ);
1431 ath_setup_rates(sc, IEEE80211_BAND_5GHZ);
1432
1433 /*
1434 * Allocate hardware transmit queues: one queue for
1435 * beacon frames and one data queue for each QoS
1436 * priority. Note that the hal handles reseting
1437 * these queues at the needed time.
1438 */
1439 sc->beacon.beaconq = ath_beaconq_setup(ah);
1440 if (sc->beacon.beaconq == -1) {
1441 DPRINTF(sc, ATH_DBG_FATAL,
1442 "Unable to setup a beacon xmit queue\n");
1443 error = -EIO;
1444 goto bad2;
1445 }
1446 sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
1447 if (sc->beacon.cabq == NULL) {
1448 DPRINTF(sc, ATH_DBG_FATAL,
1449 "Unable to setup CAB xmit queue\n");
1450 error = -EIO;
1451 goto bad2;
1452 }
1453
1454 sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
1455 ath_cabq_update(sc);
1456
1457 for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
1458 sc->tx.hwq_map[i] = -1;
1459
1460 /* Setup data queues */
1461 /* NB: ensure BK queue is the lowest priority h/w queue */
1462 if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) {
1463 DPRINTF(sc, ATH_DBG_FATAL,
1464 "Unable to setup xmit queue for BK traffic\n");
1465 error = -EIO;
1466 goto bad2;
1467 }
1468
1469 if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) {
1470 DPRINTF(sc, ATH_DBG_FATAL,
1471 "Unable to setup xmit queue for BE traffic\n");
1472 error = -EIO;
1473 goto bad2;
1474 }
1475 if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) {
1476 DPRINTF(sc, ATH_DBG_FATAL,
1477 "Unable to setup xmit queue for VI traffic\n");
1478 error = -EIO;
1479 goto bad2;
1480 }
1481 if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) {
1482 DPRINTF(sc, ATH_DBG_FATAL,
1483 "Unable to setup xmit queue for VO traffic\n");
1484 error = -EIO;
1485 goto bad2;
1486 }
1487
1488 /* Initializes the noise floor to a reasonable default value.
1489 * Later on this will be updated during ANI processing. */
1490
1491 sc->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR;
1492 setup_timer(&sc->ani.timer, ath_ani_calibrate, (unsigned long)sc);
1493
1494 if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
1495 ATH9K_CIPHER_TKIP, NULL)) {
1496 /*
1497 * Whether we should enable h/w TKIP MIC.
1498 * XXX: if we don't support WME TKIP MIC, then we wouldn't
1499 * report WMM capable, so it's always safe to turn on
1500 * TKIP MIC in this case.
1501 */
1502 ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC,
1503 0, 1, NULL);
1504 }
1505
1506 /*
1507 * Check whether the separate key cache entries
1508 * are required to handle both tx+rx MIC keys.
1509 * With split mic keys the number of stations is limited
1510 * to 27 otherwise 59.
1511 */
1512 if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
1513 ATH9K_CIPHER_TKIP, NULL)
1514 && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
1515 ATH9K_CIPHER_MIC, NULL)
1516 && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT,
1517 0, NULL))
1518 sc->splitmic = 1;
1519
1520 /* turn on mcast key search if possible */
1521 if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL))
1522 (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1,
1523 1, NULL);
1524
1525 sc->config.txpowlimit = ATH_TXPOWER_MAX;
1526
1527 /* 11n Capabilities */
1528 if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
1529 sc->sc_flags |= SC_OP_TXAGGR;
1530 sc->sc_flags |= SC_OP_RXAGGR;
1531 }
1532
1533 sc->tx_chainmask = ah->caps.tx_chainmask;
1534 sc->rx_chainmask = ah->caps.rx_chainmask;
1535
1536 ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
1537 sc->rx.defant = ath9k_hw_getdefantenna(ah);
1538
1539 if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
1540 memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN);
1541
1542 sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */
1543
1544 /* initialize beacon slots */
1545 for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
1546 sc->beacon.bslot[i] = NULL;
1547 sc->beacon.bslot_aphy[i] = NULL;
1548 }
1549
1550 /* setup channels and rates */
1551
1552 sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
1553 sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
1554 sc->rates[IEEE80211_BAND_2GHZ];
1555 sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
1556 sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
1557 ARRAY_SIZE(ath9k_2ghz_chantable);
1558
1559 if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
1560 sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable;
1561 sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
1562 sc->rates[IEEE80211_BAND_5GHZ];
1563 sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
1564 sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
1565 ARRAY_SIZE(ath9k_5ghz_chantable);
1566 }
1567
1568 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)
1569 ath9k_hw_btcoex_enable(sc->sc_ah);
1570
1571 return 0;
1572bad2:
1573 /* cleanup tx queues */
1574 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
1575 if (ATH_TXQ_SETUP(sc, i))
1576 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
1577bad:
1578 if (ah)
1579 ath9k_hw_detach(ah);
1580 ath9k_exit_debug(sc);
1581
1582 return error;
1583}
1584
1585void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
1586{
1587 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
1588 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
1589 IEEE80211_HW_SIGNAL_DBM |
1590 IEEE80211_HW_AMPDU_AGGREGATION |
1591 IEEE80211_HW_SUPPORTS_PS |
1592 IEEE80211_HW_PS_NULLFUNC_STACK |
1593 IEEE80211_HW_SPECTRUM_MGMT;
1594
1595 if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt)
1596 hw->flags |= IEEE80211_HW_MFP_CAPABLE;
1597
1598 hw->wiphy->interface_modes =
1599 BIT(NL80211_IFTYPE_AP) |
1600 BIT(NL80211_IFTYPE_STATION) |
1601 BIT(NL80211_IFTYPE_ADHOC) |
1602 BIT(NL80211_IFTYPE_MESH_POINT);
1603
1604 hw->queues = 4;
1605 hw->max_rates = 4;
1606 hw->channel_change_time = 5000;
1607 hw->max_listen_interval = 10;
1608 hw->max_rate_tries = ATH_11N_TXMAXTRY;
1609 hw->sta_data_size = sizeof(struct ath_node);
1610 hw->vif_data_size = sizeof(struct ath_vif);
1611
1612 hw->rate_control_algorithm = "ath9k_rate_control";
1613
1614 hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
1615 &sc->sbands[IEEE80211_BAND_2GHZ];
1616 if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
1617 hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
1618 &sc->sbands[IEEE80211_BAND_5GHZ];
1619}
1620
1621int ath_attach(u16 devid, struct ath_softc *sc)
1622{
1623 struct ieee80211_hw *hw = sc->hw;
1624 int error = 0, i;
1625 struct ath_regulatory *reg;
1626
1627 DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n");
1628
1629 error = ath_init(devid, sc);
1630 if (error != 0)
1631 return error;
1632
1633 reg = &sc->sc_ah->regulatory;
1634
1635 /* get mac address from hardware and set in mac80211 */
1636
1637 SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr);
1638
1639 ath_set_hw_capab(sc, hw);
1640
1641 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
1642 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
1643 if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
1644 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
1645 }
1646
1647 /* initialize tx/rx engine */
1648 error = ath_tx_init(sc, ATH_TXBUF);
1649 if (error != 0)
1650 goto error_attach;
1651
1652 error = ath_rx_init(sc, ATH_RXBUF);
1653 if (error != 0)
1654 goto error_attach;
1655
1656#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
1657 /* Initialze h/w Rfkill */
1658 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
1659 INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll);
1660
1661 /* Initialize s/w rfkill */
1662 error = ath_init_sw_rfkill(sc);
1663 if (error)
1664 goto error_attach;
1665#endif
1666
1667 INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
1668 INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
1669 sc->wiphy_scheduler_int = msecs_to_jiffies(500);
1670
1671 error = ieee80211_register_hw(hw);
1672
1673 if (!ath_is_world_regd(reg)) {
1674 error = regulatory_hint(hw->wiphy, reg->alpha2);
1675 if (error)
1676 goto error_attach;
1677 }
1678
1679 /* Initialize LED control */
1680 ath_init_leds(sc);
1681
1682
1683 return 0;
1684
1685error_attach:
1686 /* cleanup tx queues */
1687 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
1688 if (ATH_TXQ_SETUP(sc, i))
1689 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
1690
1691 ath9k_hw_detach(sc->sc_ah);
1692 ath9k_exit_debug(sc);
1693
1694 return error;
1695}
1696
1697int ath_reset(struct ath_softc *sc, bool retry_tx)
1698{
1699 struct ath_hw *ah = sc->sc_ah;
1700 struct ieee80211_hw *hw = sc->hw;
1701 int r;
1702
1703 ath9k_hw_set_interrupts(ah, 0);
1704 ath_drain_all_txq(sc, retry_tx);
1705 ath_stoprecv(sc);
1706 ath_flushrecv(sc);
1707
1708 spin_lock_bh(&sc->sc_resetlock);
1709 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false);
1710 if (r)
1711 DPRINTF(sc, ATH_DBG_FATAL,
1712 "Unable to reset hardware; reset status %u\n", r);
1713 spin_unlock_bh(&sc->sc_resetlock);
1714
1715 if (ath_startrecv(sc) != 0)
1716 DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n");
1717
1718 /*
1719 * We may be doing a reset in response to a request
1720 * that changes the channel so update any state that
1721 * might change as a result.
1722 */
1723 ath_cache_conf_rate(sc, &hw->conf);
1724
1725 ath_update_txpow(sc);
1726
1727 if (sc->sc_flags & SC_OP_BEACONS)
1728 ath_beacon_config(sc, NULL); /* restart beacons */
1729
1730 ath9k_hw_set_interrupts(ah, sc->imask);
1731
1732 if (retry_tx) {
1733 int i;
1734 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
1735 if (ATH_TXQ_SETUP(sc, i)) {
1736 spin_lock_bh(&sc->tx.txq[i].axq_lock);
1737 ath_txq_schedule(sc, &sc->tx.txq[i]);
1738 spin_unlock_bh(&sc->tx.txq[i].axq_lock);
1739 }
1740 }
1741 }
1742
1743 return r;
1744}
1745
1746/*
1747 * This function will allocate both the DMA descriptor structure, and the
1748 * buffers it contains. These are used to contain the descriptors used
1749 * by the system.
1750*/
1751int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
1752 struct list_head *head, const char *name,
1753 int nbuf, int ndesc)
1754{
1755#define DS2PHYS(_dd, _ds) \
1756 ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
1757#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
1758#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
1759
1760 struct ath_desc *ds;
1761 struct ath_buf *bf;
1762 int i, bsize, error;
1763
1764 DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
1765 name, nbuf, ndesc);
1766
1767 INIT_LIST_HEAD(head);
1768 /* ath_desc must be a multiple of DWORDs */
1769 if ((sizeof(struct ath_desc) % 4) != 0) {
1770 DPRINTF(sc, ATH_DBG_FATAL, "ath_desc not DWORD aligned\n");
1771 ASSERT((sizeof(struct ath_desc) % 4) == 0);
1772 error = -ENOMEM;
1773 goto fail;
1774 }
1775
1776 dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
1777
1778 /*
1779 * Need additional DMA memory because we can't use
1780 * descriptors that cross the 4K page boundary. Assume
1781 * one skipped descriptor per 4K page.
1782 */
1783 if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
1784 u32 ndesc_skipped =
1785 ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len);
1786 u32 dma_len;
1787
1788 while (ndesc_skipped) {
1789 dma_len = ndesc_skipped * sizeof(struct ath_desc);
1790 dd->dd_desc_len += dma_len;
1791
1792 ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
1793 };
1794 }
1795
1796 /* allocate descriptors */
1797 dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
1798 &dd->dd_desc_paddr, GFP_KERNEL);
1799 if (dd->dd_desc == NULL) {
1800 error = -ENOMEM;
1801 goto fail;
1802 }
1803 ds = dd->dd_desc;
1804 DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
1805 name, ds, (u32) dd->dd_desc_len,
1806 ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
1807
1808 /* allocate buffers */
1809 bsize = sizeof(struct ath_buf) * nbuf;
1810 bf = kzalloc(bsize, GFP_KERNEL);
1811 if (bf == NULL) {
1812 error = -ENOMEM;
1813 goto fail2;
1814 }
1815 dd->dd_bufptr = bf;
1816
1817 for (i = 0; i < nbuf; i++, bf++, ds += ndesc) {
1818 bf->bf_desc = ds;
1819 bf->bf_daddr = DS2PHYS(dd, ds);
1820
1821 if (!(sc->sc_ah->caps.hw_caps &
1822 ATH9K_HW_CAP_4KB_SPLITTRANS)) {
1823 /*
1824 * Skip descriptor addresses which can cause 4KB
1825 * boundary crossing (addr + length) with a 32 dword
1826 * descriptor fetch.
1827 */
1828 while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
1829 ASSERT((caddr_t) bf->bf_desc <
1830 ((caddr_t) dd->dd_desc +
1831 dd->dd_desc_len));
1832
1833 ds += ndesc;
1834 bf->bf_desc = ds;
1835 bf->bf_daddr = DS2PHYS(dd, ds);
1836 }
1837 }
1838 list_add_tail(&bf->list, head);
1839 }
1840 return 0;
1841fail2:
1842 dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
1843 dd->dd_desc_paddr);
1844fail:
1845 memset(dd, 0, sizeof(*dd));
1846 return error;
1847#undef ATH_DESC_4KB_BOUND_CHECK
1848#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
1849#undef DS2PHYS
1850}
1851
1852void ath_descdma_cleanup(struct ath_softc *sc,
1853 struct ath_descdma *dd,
1854 struct list_head *head)
1855{
1856 dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
1857 dd->dd_desc_paddr);
1858
1859 INIT_LIST_HEAD(head);
1860 kfree(dd->dd_bufptr);
1861 memset(dd, 0, sizeof(*dd));
1862}
1863
1864int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
1865{
1866 int qnum;
1867
1868 switch (queue) {
1869 case 0:
1870 qnum = sc->tx.hwq_map[ATH9K_WME_AC_VO];
1871 break;
1872 case 1:
1873 qnum = sc->tx.hwq_map[ATH9K_WME_AC_VI];
1874 break;
1875 case 2:
1876 qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE];
1877 break;
1878 case 3:
1879 qnum = sc->tx.hwq_map[ATH9K_WME_AC_BK];
1880 break;
1881 default:
1882 qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE];
1883 break;
1884 }
1885
1886 return qnum;
1887}
1888
1889int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
1890{
1891 int qnum;
1892
1893 switch (queue) {
1894 case ATH9K_WME_AC_VO:
1895 qnum = 0;
1896 break;
1897 case ATH9K_WME_AC_VI:
1898 qnum = 1;
1899 break;
1900 case ATH9K_WME_AC_BE:
1901 qnum = 2;
1902 break;
1903 case ATH9K_WME_AC_BK:
1904 qnum = 3;
1905 break;
1906 default:
1907 qnum = -1;
1908 break;
1909 }
1910
1911 return qnum;
1912}
1913
1914/* XXX: Remove me once we don't depend on ath9k_channel for all
1915 * this redundant data */
1916void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
1917 struct ath9k_channel *ichan)
1918{
1919 struct ieee80211_channel *chan = hw->conf.channel;
1920 struct ieee80211_conf *conf = &hw->conf;
1921
1922 ichan->channel = chan->center_freq;
1923 ichan->chan = chan;
1924
1925 if (chan->band == IEEE80211_BAND_2GHZ) {
1926 ichan->chanmode = CHANNEL_G;
1927 ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM;
1928 } else {
1929 ichan->chanmode = CHANNEL_A;
1930 ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
1931 }
1932
1933 sc->tx_chan_width = ATH9K_HT_MACMODE_20;
1934
1935 if (conf_is_ht(conf)) {
1936 if (conf_is_ht40(conf))
1937 sc->tx_chan_width = ATH9K_HT_MACMODE_2040;
1938
1939 ichan->chanmode = ath_get_extchanmode(sc, chan,
1940 conf->channel_type);
1941 }
1942}
1943
1944/**********************/
1945/* mac80211 callbacks */
1946/**********************/
1947
1948static int ath9k_start(struct ieee80211_hw *hw)
1949{
1950 struct ath_wiphy *aphy = hw->priv;
1951 struct ath_softc *sc = aphy->sc;
1952 struct ieee80211_channel *curchan = hw->conf.channel;
1953 struct ath9k_channel *init_channel;
1954 int r, pos;
1955
1956 DPRINTF(sc, ATH_DBG_CONFIG, "Starting driver with "
1957 "initial channel: %d MHz\n", curchan->center_freq);
1958
1959 mutex_lock(&sc->mutex);
1960
1961 if (ath9k_wiphy_started(sc)) {
1962 if (sc->chan_idx == curchan->hw_value) {
1963 /*
1964 * Already on the operational channel, the new wiphy
1965 * can be marked active.
1966 */
1967 aphy->state = ATH_WIPHY_ACTIVE;
1968 ieee80211_wake_queues(hw);
1969 } else {
1970 /*
1971 * Another wiphy is on another channel, start the new
1972 * wiphy in paused state.
1973 */
1974 aphy->state = ATH_WIPHY_PAUSED;
1975 ieee80211_stop_queues(hw);
1976 }
1977 mutex_unlock(&sc->mutex);
1978 return 0;
1979 }
1980 aphy->state = ATH_WIPHY_ACTIVE;
1981
1982 /* setup initial channel */
1983
1984 pos = curchan->hw_value;
1985
1986 sc->chan_idx = pos;
1987 init_channel = &sc->sc_ah->channels[pos];
1988 ath9k_update_ichannel(sc, hw, init_channel);
1989
1990 /* Reset SERDES registers */
1991 ath9k_hw_configpcipowersave(sc->sc_ah, 0);
1992
1993 /*
1994 * The basic interface to setting the hardware in a good
1995 * state is ``reset''. On return the hardware is known to
1996 * be powered up and with interrupts disabled. This must
1997 * be followed by initialization of the appropriate bits
1998 * and then setup of the interrupt mask.
1999 */
2000 spin_lock_bh(&sc->sc_resetlock);
2001 r = ath9k_hw_reset(sc->sc_ah, init_channel, false);
2002 if (r) {
2003 DPRINTF(sc, ATH_DBG_FATAL,
2004 "Unable to reset hardware; reset status %u "
2005 "(freq %u MHz)\n", r,
2006 curchan->center_freq);
2007 spin_unlock_bh(&sc->sc_resetlock);
2008 goto mutex_unlock;
2009 }
2010 spin_unlock_bh(&sc->sc_resetlock);
2011
2012 /*
2013 * This is needed only to setup initial state
2014 * but it's best done after a reset.
2015 */
2016 ath_update_txpow(sc);
2017
2018 /*
2019 * Setup the hardware after reset:
2020 * The receive engine is set going.
2021 * Frame transmit is handled entirely
2022 * in the frame output path; there's nothing to do
2023 * here except setup the interrupt mask.
2024 */
2025 if (ath_startrecv(sc) != 0) {
2026 DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n");
2027 r = -EIO;
2028 goto mutex_unlock;
2029 }
2030
2031 /* Setup our intr mask. */
2032 sc->imask = ATH9K_INT_RX | ATH9K_INT_TX
2033 | ATH9K_INT_RXEOL | ATH9K_INT_RXORN
2034 | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL;
2035
2036 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_GTT)
2037 sc->imask |= ATH9K_INT_GTT;
2038
2039 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
2040 sc->imask |= ATH9K_INT_CST;
2041
2042 ath_cache_conf_rate(sc, &hw->conf);
2043
2044 sc->sc_flags &= ~SC_OP_INVALID;
2045
2046 /* Disable BMISS interrupt when we're not associated */
2047 sc->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
2048 ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
2049
2050 ieee80211_wake_queues(hw);
2051
2052#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
2053 r = ath_start_rfkill_poll(sc);
2054#endif
2055
2056mutex_unlock:
2057 mutex_unlock(&sc->mutex);
2058
2059 return r;
2060}
2061
2062static int ath9k_tx(struct ieee80211_hw *hw,
2063 struct sk_buff *skb)
2064{
2065 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
2066 struct ath_wiphy *aphy = hw->priv;
2067 struct ath_softc *sc = aphy->sc;
2068 struct ath_tx_control txctl;
2069 int hdrlen, padsize;
2070
2071 if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
2072 printk(KERN_DEBUG "ath9k: %s: TX in unexpected wiphy state "
2073 "%d\n", wiphy_name(hw->wiphy), aphy->state);
2074 goto exit;
2075 }
2076
2077 memset(&txctl, 0, sizeof(struct ath_tx_control));
2078
2079 /*
2080 * As a temporary workaround, assign seq# here; this will likely need
2081 * to be cleaned up to work better with Beacon transmission and virtual
2082 * BSSes.
2083 */
2084 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
2085 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2086 if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
2087 sc->tx.seq_no += 0x10;
2088 hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
2089 hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
2090 }
2091
2092 /* Add the padding after the header if this is not already done */
2093 hdrlen = ieee80211_get_hdrlen_from_skb(skb);
2094 if (hdrlen & 3) {
2095 padsize = hdrlen % 4;
2096 if (skb_headroom(skb) < padsize)
2097 return -1;
2098 skb_push(skb, padsize);
2099 memmove(skb->data, skb->data + padsize, hdrlen);
2100 }
2101
2102 /* Check if a tx queue is available */
2103
2104 txctl.txq = ath_test_get_txq(sc, skb);
2105 if (!txctl.txq)
2106 goto exit;
2107
2108 DPRINTF(sc, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
2109
2110 if (ath_tx_start(hw, skb, &txctl) != 0) {
2111 DPRINTF(sc, ATH_DBG_XMIT, "TX failed\n");
2112 goto exit;
2113 }
2114
2115 return 0;
2116exit:
2117 dev_kfree_skb_any(skb);
2118 return 0;
2119}
2120
2121static void ath9k_stop(struct ieee80211_hw *hw)
2122{
2123 struct ath_wiphy *aphy = hw->priv;
2124 struct ath_softc *sc = aphy->sc;
2125
2126 aphy->state = ATH_WIPHY_INACTIVE;
2127
2128 if (sc->sc_flags & SC_OP_INVALID) {
2129 DPRINTF(sc, ATH_DBG_ANY, "Device not present\n");
2130 return;
2131 }
2132
2133 mutex_lock(&sc->mutex);
2134
2135 ieee80211_stop_queues(hw);
2136
2137 if (ath9k_wiphy_started(sc)) {
2138 mutex_unlock(&sc->mutex);
2139 return; /* another wiphy still in use */
2140 }
2141
2142 /* make sure h/w will not generate any interrupt
2143 * before setting the invalid flag. */
2144 ath9k_hw_set_interrupts(sc->sc_ah, 0);
2145
2146 if (!(sc->sc_flags & SC_OP_INVALID)) {
2147 ath_drain_all_txq(sc, false);
2148 ath_stoprecv(sc);
2149 ath9k_hw_phy_disable(sc->sc_ah);
2150 } else
2151 sc->rx.rxlink = NULL;
2152
2153#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
2154 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
2155 cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
2156#endif
2157 /* disable HAL and put h/w to sleep */
2158 ath9k_hw_disable(sc->sc_ah);
2159 ath9k_hw_configpcipowersave(sc->sc_ah, 1);
2160
2161 sc->sc_flags |= SC_OP_INVALID;
2162
2163 mutex_unlock(&sc->mutex);
2164
2165 DPRINTF(sc, ATH_DBG_CONFIG, "Driver halt\n");
2166}
2167
2168static int ath9k_add_interface(struct ieee80211_hw *hw,
2169 struct ieee80211_if_init_conf *conf)
2170{
2171 struct ath_wiphy *aphy = hw->priv;
2172 struct ath_softc *sc = aphy->sc;
2173 struct ath_vif *avp = (void *)conf->vif->drv_priv;
2174 enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
2175 int ret = 0;
2176
2177 mutex_lock(&sc->mutex);
2178
2179 if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) &&
2180 sc->nvifs > 0) {
2181 ret = -ENOBUFS;
2182 goto out;
2183 }
2184
2185 switch (conf->type) {
2186 case NL80211_IFTYPE_STATION:
2187 ic_opmode = NL80211_IFTYPE_STATION;
2188 break;
2189 case NL80211_IFTYPE_ADHOC:
2190 case NL80211_IFTYPE_AP:
2191 case NL80211_IFTYPE_MESH_POINT:
2192 if (sc->nbcnvifs >= ATH_BCBUF) {
2193 ret = -ENOBUFS;
2194 goto out;
2195 }
2196 ic_opmode = conf->type;
2197 break;
2198 default:
2199 DPRINTF(sc, ATH_DBG_FATAL,
2200 "Interface type %d not yet supported\n", conf->type);
2201 ret = -EOPNOTSUPP;
2202 goto out;
2203 }
2204
2205 DPRINTF(sc, ATH_DBG_CONFIG, "Attach a VIF of type: %d\n", ic_opmode);
2206
2207 /* Set the VIF opmode */
2208 avp->av_opmode = ic_opmode;
2209 avp->av_bslot = -1;
2210
2211 sc->nvifs++;
2212
2213 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
2214 ath9k_set_bssid_mask(hw);
2215
2216 if (sc->nvifs > 1)
2217 goto out; /* skip global settings for secondary vif */
2218
2219 if (ic_opmode == NL80211_IFTYPE_AP) {
2220 ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
2221 sc->sc_flags |= SC_OP_TSF_RESET;
2222 }
2223
2224 /* Set the device opmode */
2225 sc->sc_ah->opmode = ic_opmode;
2226
2227 /*
2228 * Enable MIB interrupts when there are hardware phy counters.
2229 * Note we only do this (at the moment) for station mode.
2230 */
2231 if ((conf->type == NL80211_IFTYPE_STATION) ||
2232 (conf->type == NL80211_IFTYPE_ADHOC) ||
2233 (conf->type == NL80211_IFTYPE_MESH_POINT)) {
2234 if (ath9k_hw_phycounters(sc->sc_ah))
2235 sc->imask |= ATH9K_INT_MIB;
2236 sc->imask |= ATH9K_INT_TSFOOR;
2237 }
2238
2239 ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
2240
2241 if (conf->type == NL80211_IFTYPE_AP) {
2242 /* TODO: is this a suitable place to start ANI for AP mode? */
2243 /* Start ANI */
2244 mod_timer(&sc->ani.timer,
2245 jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
2246 }
2247
2248out:
2249 mutex_unlock(&sc->mutex);
2250 return ret;
2251}
2252
2253static void ath9k_remove_interface(struct ieee80211_hw *hw,
2254 struct ieee80211_if_init_conf *conf)
2255{
2256 struct ath_wiphy *aphy = hw->priv;
2257 struct ath_softc *sc = aphy->sc;
2258 struct ath_vif *avp = (void *)conf->vif->drv_priv;
2259 int i;
2260
2261 DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n");
2262
2263 mutex_lock(&sc->mutex);
2264
2265 /* Stop ANI */
2266 del_timer_sync(&sc->ani.timer);
2267
2268 /* Reclaim beacon resources */
2269 if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
2270 (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
2271 (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
2272 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
2273 ath_beacon_return(sc, avp);
2274 }
2275
2276 sc->sc_flags &= ~SC_OP_BEACONS;
2277
2278 for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
2279 if (sc->beacon.bslot[i] == conf->vif) {
2280 printk(KERN_DEBUG "%s: vif had allocated beacon "
2281 "slot\n", __func__);
2282 sc->beacon.bslot[i] = NULL;
2283 sc->beacon.bslot_aphy[i] = NULL;
2284 }
2285 }
2286
2287 sc->nvifs--;
2288
2289 mutex_unlock(&sc->mutex);
2290}
2291
2292static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
2293{
2294 struct ath_wiphy *aphy = hw->priv;
2295 struct ath_softc *sc = aphy->sc;
2296 struct ieee80211_conf *conf = &hw->conf;
2297 struct ath_hw *ah = sc->sc_ah;
2298
2299 mutex_lock(&sc->mutex);
2300
2301 if (changed & IEEE80211_CONF_CHANGE_PS) {
2302 if (conf->flags & IEEE80211_CONF_PS) {
2303 if (!(ah->caps.hw_caps &
2304 ATH9K_HW_CAP_AUTOSLEEP)) {
2305 if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) {
2306 sc->imask |= ATH9K_INT_TIM_TIMER;
2307 ath9k_hw_set_interrupts(sc->sc_ah,
2308 sc->imask);
2309 }
2310 ath9k_hw_setrxabort(sc->sc_ah, 1);
2311 }
2312 ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
2313 } else {
2314 ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
2315 if (!(ah->caps.hw_caps &
2316 ATH9K_HW_CAP_AUTOSLEEP)) {
2317 ath9k_hw_setrxabort(sc->sc_ah, 0);
2318 sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON;
2319 if (sc->imask & ATH9K_INT_TIM_TIMER) {
2320 sc->imask &= ~ATH9K_INT_TIM_TIMER;
2321 ath9k_hw_set_interrupts(sc->sc_ah,
2322 sc->imask);
2323 }
2324 }
2325 }
2326 }
2327
2328 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
2329 struct ieee80211_channel *curchan = hw->conf.channel;
2330 int pos = curchan->hw_value;
2331
2332 aphy->chan_idx = pos;
2333 aphy->chan_is_ht = conf_is_ht(conf);
2334
2335 if (aphy->state == ATH_WIPHY_SCAN ||
2336 aphy->state == ATH_WIPHY_ACTIVE)
2337 ath9k_wiphy_pause_all_forced(sc, aphy);
2338 else {
2339 /*
2340 * Do not change operational channel based on a paused
2341 * wiphy changes.
2342 */
2343 goto skip_chan_change;
2344 }
2345
2346 DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
2347 curchan->center_freq);
2348
2349 /* XXX: remove me eventualy */
2350 ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]);
2351
2352 ath_update_chainmask(sc, conf_is_ht(conf));
2353
2354 if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
2355 DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n");
2356 mutex_unlock(&sc->mutex);
2357 return -EINVAL;
2358 }
2359 }
2360
2361skip_chan_change:
2362 if (changed & IEEE80211_CONF_CHANGE_POWER)
2363 sc->config.txpowlimit = 2 * conf->power_level;
2364
2365 /*
2366 * The HW TSF has to be reset when the beacon interval changes.
2367 * We set the flag here, and ath_beacon_config_ap() would take this
2368 * into account when it gets called through the subsequent
2369 * config_interface() call - with IFCC_BEACON in the changed field.
2370 */
2371
2372 if (changed & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
2373 sc->sc_flags |= SC_OP_TSF_RESET;
2374
2375 mutex_unlock(&sc->mutex);
2376
2377 return 0;
2378}
2379
2380static int ath9k_config_interface(struct ieee80211_hw *hw,
2381 struct ieee80211_vif *vif,
2382 struct ieee80211_if_conf *conf)
2383{
2384 struct ath_wiphy *aphy = hw->priv;
2385 struct ath_softc *sc = aphy->sc;
2386 struct ath_hw *ah = sc->sc_ah;
2387 struct ath_vif *avp = (void *)vif->drv_priv;
2388 u32 rfilt = 0;
2389 int error, i;
2390
2391 mutex_lock(&sc->mutex);
2392
2393 /* TODO: Need to decide which hw opmode to use for multi-interface
2394 * cases */
2395 if (vif->type == NL80211_IFTYPE_AP &&
2396 ah->opmode != NL80211_IFTYPE_AP) {
2397 ah->opmode = NL80211_IFTYPE_STATION;
2398 ath9k_hw_setopmode(ah);
2399 memcpy(sc->curbssid, sc->sc_ah->macaddr, ETH_ALEN);
2400 sc->curaid = 0;
2401 ath9k_hw_write_associd(sc);
2402 /* Request full reset to get hw opmode changed properly */
2403 sc->sc_flags |= SC_OP_FULL_RESET;
2404 }
2405
2406 if ((conf->changed & IEEE80211_IFCC_BSSID) &&
2407 !is_zero_ether_addr(conf->bssid)) {
2408 switch (vif->type) {
2409 case NL80211_IFTYPE_STATION:
2410 case NL80211_IFTYPE_ADHOC:
2411 case NL80211_IFTYPE_MESH_POINT:
2412 /* Set BSSID */
2413 memcpy(sc->curbssid, conf->bssid, ETH_ALEN);
2414 memcpy(avp->bssid, conf->bssid, ETH_ALEN);
2415 sc->curaid = 0;
2416 ath9k_hw_write_associd(sc);
2417
2418 /* Set aggregation protection mode parameters */
2419 sc->config.ath_aggr_prot = 0;
2420
2421 DPRINTF(sc, ATH_DBG_CONFIG,
2422 "RX filter 0x%x bssid %pM aid 0x%x\n",
2423 rfilt, sc->curbssid, sc->curaid);
2424
2425 /* need to reconfigure the beacon */
2426 sc->sc_flags &= ~SC_OP_BEACONS ;
2427
2428 break;
2429 default:
2430 break;
2431 }
2432 }
2433
2434 if ((vif->type == NL80211_IFTYPE_ADHOC) ||
2435 (vif->type == NL80211_IFTYPE_AP) ||
2436 (vif->type == NL80211_IFTYPE_MESH_POINT)) {
2437 if ((conf->changed & IEEE80211_IFCC_BEACON) ||
2438 (conf->changed & IEEE80211_IFCC_BEACON_ENABLED &&
2439 conf->enable_beacon)) {
2440 /*
2441 * Allocate and setup the beacon frame.
2442 *
2443 * Stop any previous beacon DMA. This may be
2444 * necessary, for example, when an ibss merge
2445 * causes reconfiguration; we may be called
2446 * with beacon transmission active.
2447 */
2448 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
2449
2450 error = ath_beacon_alloc(aphy, vif);
2451 if (error != 0) {
2452 mutex_unlock(&sc->mutex);
2453 return error;
2454 }
2455
2456 ath_beacon_config(sc, vif);
2457 }
2458 }
2459
2460 /* Check for WLAN_CAPABILITY_PRIVACY ? */
2461 if ((avp->av_opmode != NL80211_IFTYPE_STATION)) {
2462 for (i = 0; i < IEEE80211_WEP_NKID; i++)
2463 if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i))
2464 ath9k_hw_keysetmac(sc->sc_ah,
2465 (u16)i,
2466 sc->curbssid);
2467 }
2468
2469 /* Only legacy IBSS for now */
2470 if (vif->type == NL80211_IFTYPE_ADHOC)
2471 ath_update_chainmask(sc, 0);
2472
2473 mutex_unlock(&sc->mutex);
2474
2475 return 0;
2476}
2477
2478#define SUPPORTED_FILTERS \
2479 (FIF_PROMISC_IN_BSS | \
2480 FIF_ALLMULTI | \
2481 FIF_CONTROL | \
2482 FIF_OTHER_BSS | \
2483 FIF_BCN_PRBRESP_PROMISC | \
2484 FIF_FCSFAIL)
2485
2486/* FIXME: sc->sc_full_reset ? */
2487static void ath9k_configure_filter(struct ieee80211_hw *hw,
2488 unsigned int changed_flags,
2489 unsigned int *total_flags,
2490 int mc_count,
2491 struct dev_mc_list *mclist)
2492{
2493 struct ath_wiphy *aphy = hw->priv;
2494 struct ath_softc *sc = aphy->sc;
2495 u32 rfilt;
2496
2497 changed_flags &= SUPPORTED_FILTERS;
2498 *total_flags &= SUPPORTED_FILTERS;
2499
2500 sc->rx.rxfilter = *total_flags;
2501 rfilt = ath_calcrxfilter(sc);
2502 ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
2503
2504 DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", sc->rx.rxfilter);
2505}
2506
2507static void ath9k_sta_notify(struct ieee80211_hw *hw,
2508 struct ieee80211_vif *vif,
2509 enum sta_notify_cmd cmd,
2510 struct ieee80211_sta *sta)
2511{
2512 struct ath_wiphy *aphy = hw->priv;
2513 struct ath_softc *sc = aphy->sc;
2514
2515 switch (cmd) {
2516 case STA_NOTIFY_ADD:
2517 ath_node_attach(sc, sta);
2518 break;
2519 case STA_NOTIFY_REMOVE:
2520 ath_node_detach(sc, sta);
2521 break;
2522 default:
2523 break;
2524 }
2525}
2526
2527static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
2528 const struct ieee80211_tx_queue_params *params)
2529{
2530 struct ath_wiphy *aphy = hw->priv;
2531 struct ath_softc *sc = aphy->sc;
2532 struct ath9k_tx_queue_info qi;
2533 int ret = 0, qnum;
2534
2535 if (queue >= WME_NUM_AC)
2536 return 0;
2537
2538 mutex_lock(&sc->mutex);
2539
2540 memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
2541
2542 qi.tqi_aifs = params->aifs;
2543 qi.tqi_cwmin = params->cw_min;
2544 qi.tqi_cwmax = params->cw_max;
2545 qi.tqi_burstTime = params->txop;
2546 qnum = ath_get_hal_qnum(queue, sc);
2547
2548 DPRINTF(sc, ATH_DBG_CONFIG,
2549 "Configure tx [queue/halq] [%d/%d], "
2550 "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
2551 queue, qnum, params->aifs, params->cw_min,
2552 params->cw_max, params->txop);
2553
2554 ret = ath_txq_update(sc, qnum, &qi);
2555 if (ret)
2556 DPRINTF(sc, ATH_DBG_FATAL, "TXQ Update failed\n");
2557
2558 mutex_unlock(&sc->mutex);
2559
2560 return ret;
2561}
2562
2563static int ath9k_set_key(struct ieee80211_hw *hw,
2564 enum set_key_cmd cmd,
2565 struct ieee80211_vif *vif,
2566 struct ieee80211_sta *sta,
2567 struct ieee80211_key_conf *key)
2568{
2569 struct ath_wiphy *aphy = hw->priv;
2570 struct ath_softc *sc = aphy->sc;
2571 int ret = 0;
2572
2573 if (modparam_nohwcrypt)
2574 return -ENOSPC;
2575
2576 mutex_lock(&sc->mutex);
2577 ath9k_ps_wakeup(sc);
2578 DPRINTF(sc, ATH_DBG_CONFIG, "Set HW Key\n");
2579
2580 switch (cmd) {
2581 case SET_KEY:
2582 ret = ath_key_config(sc, vif, sta, key);
2583 if (ret >= 0) {
2584 key->hw_key_idx = ret;
2585 /* push IV and Michael MIC generation to stack */
2586 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
2587 if (key->alg == ALG_TKIP)
2588 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
2589 if (sc->sc_ah->sw_mgmt_crypto && key->alg == ALG_CCMP)
2590 key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
2591 ret = 0;
2592 }
2593 break;
2594 case DISABLE_KEY:
2595 ath_key_delete(sc, key);
2596 break;
2597 default:
2598 ret = -EINVAL;
2599 }
2600
2601 ath9k_ps_restore(sc);
2602 mutex_unlock(&sc->mutex);
2603
2604 return ret;
2605}
2606
2607static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
2608 struct ieee80211_vif *vif,
2609 struct ieee80211_bss_conf *bss_conf,
2610 u32 changed)
2611{
2612 struct ath_wiphy *aphy = hw->priv;
2613 struct ath_softc *sc = aphy->sc;
2614
2615 mutex_lock(&sc->mutex);
2616
2617 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
2618 DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n",
2619 bss_conf->use_short_preamble);
2620 if (bss_conf->use_short_preamble)
2621 sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
2622 else
2623 sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT;
2624 }
2625
2626 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
2627 DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n",
2628 bss_conf->use_cts_prot);
2629 if (bss_conf->use_cts_prot &&
2630 hw->conf.channel->band != IEEE80211_BAND_5GHZ)
2631 sc->sc_flags |= SC_OP_PROTECT_ENABLE;
2632 else
2633 sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
2634 }
2635
2636 if (changed & BSS_CHANGED_ASSOC) {
2637 DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
2638 bss_conf->assoc);
2639 ath9k_bss_assoc_info(sc, vif, bss_conf);
2640 }
2641
2642 mutex_unlock(&sc->mutex);
2643}
2644
2645static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
2646{
2647 u64 tsf;
2648 struct ath_wiphy *aphy = hw->priv;
2649 struct ath_softc *sc = aphy->sc;
2650
2651 mutex_lock(&sc->mutex);
2652 tsf = ath9k_hw_gettsf64(sc->sc_ah);
2653 mutex_unlock(&sc->mutex);
2654
2655 return tsf;
2656}
2657
2658static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
2659{
2660 struct ath_wiphy *aphy = hw->priv;
2661 struct ath_softc *sc = aphy->sc;
2662
2663 mutex_lock(&sc->mutex);
2664 ath9k_hw_settsf64(sc->sc_ah, tsf);
2665 mutex_unlock(&sc->mutex);
2666}
2667
2668static void ath9k_reset_tsf(struct ieee80211_hw *hw)
2669{
2670 struct ath_wiphy *aphy = hw->priv;
2671 struct ath_softc *sc = aphy->sc;
2672
2673 mutex_lock(&sc->mutex);
2674 ath9k_hw_reset_tsf(sc->sc_ah);
2675 mutex_unlock(&sc->mutex);
2676}
2677
2678static int ath9k_ampdu_action(struct ieee80211_hw *hw,
2679 enum ieee80211_ampdu_mlme_action action,
2680 struct ieee80211_sta *sta,
2681 u16 tid, u16 *ssn)
2682{
2683 struct ath_wiphy *aphy = hw->priv;
2684 struct ath_softc *sc = aphy->sc;
2685 int ret = 0;
2686
2687 switch (action) {
2688 case IEEE80211_AMPDU_RX_START:
2689 if (!(sc->sc_flags & SC_OP_RXAGGR))
2690 ret = -ENOTSUPP;
2691 break;
2692 case IEEE80211_AMPDU_RX_STOP:
2693 break;
2694 case IEEE80211_AMPDU_TX_START:
2695 ret = ath_tx_aggr_start(sc, sta, tid, ssn);
2696 if (ret < 0)
2697 DPRINTF(sc, ATH_DBG_FATAL,
2698 "Unable to start TX aggregation\n");
2699 else
2700 ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
2701 break;
2702 case IEEE80211_AMPDU_TX_STOP:
2703 ret = ath_tx_aggr_stop(sc, sta, tid);
2704 if (ret < 0)
2705 DPRINTF(sc, ATH_DBG_FATAL,
2706 "Unable to stop TX aggregation\n");
2707
2708 ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
2709 break;
2710 case IEEE80211_AMPDU_TX_OPERATIONAL:
2711 ath_tx_aggr_resume(sc, sta, tid);
2712 break;
2713 default:
2714 DPRINTF(sc, ATH_DBG_FATAL, "Unknown AMPDU action\n");
2715 }
2716
2717 return ret;
2718}
2719
2720static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
2721{
2722 struct ath_wiphy *aphy = hw->priv;
2723 struct ath_softc *sc = aphy->sc;
2724
2725 if (ath9k_wiphy_scanning(sc)) {
2726 printk(KERN_DEBUG "ath9k: Two wiphys trying to scan at the "
2727 "same time\n");
2728 /*
2729 * Do not allow the concurrent scanning state for now. This
2730 * could be improved with scanning control moved into ath9k.
2731 */
2732 return;
2733 }
2734
2735 aphy->state = ATH_WIPHY_SCAN;
2736 ath9k_wiphy_pause_all_forced(sc, aphy);
2737
2738 mutex_lock(&sc->mutex);
2739 sc->sc_flags |= SC_OP_SCANNING;
2740 mutex_unlock(&sc->mutex);
2741}
2742
2743static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
2744{
2745 struct ath_wiphy *aphy = hw->priv;
2746 struct ath_softc *sc = aphy->sc;
2747
2748 mutex_lock(&sc->mutex);
2749 aphy->state = ATH_WIPHY_ACTIVE;
2750 sc->sc_flags &= ~SC_OP_SCANNING;
2751 mutex_unlock(&sc->mutex);
2752}
2753
2754struct ieee80211_ops ath9k_ops = {
2755 .tx = ath9k_tx,
2756 .start = ath9k_start,
2757 .stop = ath9k_stop,
2758 .add_interface = ath9k_add_interface,
2759 .remove_interface = ath9k_remove_interface,
2760 .config = ath9k_config,
2761 .config_interface = ath9k_config_interface,
2762 .configure_filter = ath9k_configure_filter,
2763 .sta_notify = ath9k_sta_notify,
2764 .conf_tx = ath9k_conf_tx,
2765 .bss_info_changed = ath9k_bss_info_changed,
2766 .set_key = ath9k_set_key,
2767 .get_tsf = ath9k_get_tsf,
2768 .set_tsf = ath9k_set_tsf,
2769 .reset_tsf = ath9k_reset_tsf,
2770 .ampdu_action = ath9k_ampdu_action,
2771 .sw_scan_start = ath9k_sw_scan_start,
2772 .sw_scan_complete = ath9k_sw_scan_complete,
2773};
2774
2775static struct {
2776 u32 version;
2777 const char * name;
2778} ath_mac_bb_names[] = {
2779 { AR_SREV_VERSION_5416_PCI, "5416" },
2780 { AR_SREV_VERSION_5416_PCIE, "5418" },
2781 { AR_SREV_VERSION_9100, "9100" },
2782 { AR_SREV_VERSION_9160, "9160" },
2783 { AR_SREV_VERSION_9280, "9280" },
2784 { AR_SREV_VERSION_9285, "9285" }
2785};
2786
2787static struct {
2788 u16 version;
2789 const char * name;
2790} ath_rf_names[] = {
2791 { 0, "5133" },
2792 { AR_RAD5133_SREV_MAJOR, "5133" },
2793 { AR_RAD5122_SREV_MAJOR, "5122" },
2794 { AR_RAD2133_SREV_MAJOR, "2133" },
2795 { AR_RAD2122_SREV_MAJOR, "2122" }
2796};
2797
2798/*
2799 * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown.
2800 */
2801const char *
2802ath_mac_bb_name(u32 mac_bb_version)
2803{
2804 int i;
2805
2806 for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) {
2807 if (ath_mac_bb_names[i].version == mac_bb_version) {
2808 return ath_mac_bb_names[i].name;
2809 }
2810 }
2811
2812 return "????";
2813}
2814
2815/*
2816 * Return the RF name. "????" is returned if the RF is unknown.
2817 */
2818const char *
2819ath_rf_name(u16 rf_version)
2820{
2821 int i;
2822
2823 for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) {
2824 if (ath_rf_names[i].version == rf_version) {
2825 return ath_rf_names[i].name;
2826 }
2827 }
2828
2829 return "????";
2830}
2831
2832static int __init ath9k_init(void)
2833{
2834 int error;
2835
2836 /* Register rate control algorithm */
2837 error = ath_rate_control_register();
2838 if (error != 0) {
2839 printk(KERN_ERR
2840 "ath9k: Unable to register rate control "
2841 "algorithm: %d\n",
2842 error);
2843 goto err_out;
2844 }
2845
2846 error = ath9k_debug_create_root();
2847 if (error) {
2848 printk(KERN_ERR
2849 "ath9k: Unable to create debugfs root: %d\n",
2850 error);
2851 goto err_rate_unregister;
2852 }
2853
2854 error = ath_pci_init();
2855 if (error < 0) {
2856 printk(KERN_ERR
2857 "ath9k: No PCI devices found, driver not installed.\n");
2858 error = -ENODEV;
2859 goto err_remove_root;
2860 }
2861
2862 error = ath_ahb_init();
2863 if (error < 0) {
2864 error = -ENODEV;
2865 goto err_pci_exit;
2866 }
2867
2868 return 0;
2869
2870 err_pci_exit:
2871 ath_pci_exit();
2872
2873 err_remove_root:
2874 ath9k_debug_remove_root();
2875 err_rate_unregister:
2876 ath_rate_control_unregister();
2877 err_out:
2878 return error;
2879}
2880module_init(ath9k_init);
2881
2882static void __exit ath9k_exit(void)
2883{
2884 ath_ahb_exit();
2885 ath_pci_exit();
2886 ath9k_debug_remove_root();
2887 ath_rate_control_unregister();
2888 printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
2889}
2890module_exit(ath9k_exit);
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
new file mode 100644
index 000000000000..6dbc58580abb
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -0,0 +1,295 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <linux/nl80211.h>
18#include <linux/pci.h>
19#include "ath9k.h"
20
21static struct pci_device_id ath_pci_id_table[] __devinitdata = {
22 { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */
23 { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
24 { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */
25 { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
26 { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
27 { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
28 { 0 }
29};
30
31/* return bus cachesize in 4B word units */
32static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz)
33{
34 u8 u8tmp;
35
36 pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE,
37 (u8 *)&u8tmp);
38 *csz = (int)u8tmp;
39
40 /*
41 * This check was put in to avoid "unplesant" consequences if
42 * the bootrom has not fully initialized all PCI devices.
43 * Sometimes the cache line size register is not set
44 */
45
46 if (*csz == 0)
47 *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */
48}
49
50static void ath_pci_cleanup(struct ath_softc *sc)
51{
52 struct pci_dev *pdev = to_pci_dev(sc->dev);
53
54 pci_iounmap(pdev, sc->mem);
55 pci_disable_device(pdev);
56 pci_release_region(pdev, 0);
57}
58
59static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data)
60{
61 (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
62
63 if (!ath9k_hw_wait(ah,
64 AR_EEPROM_STATUS_DATA,
65 AR_EEPROM_STATUS_DATA_BUSY |
66 AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
67 AH_WAIT_TIMEOUT)) {
68 return false;
69 }
70
71 *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
72 AR_EEPROM_STATUS_DATA_VAL);
73
74 return true;
75}
76
77static struct ath_bus_ops ath_pci_bus_ops = {
78 .read_cachesize = ath_pci_read_cachesize,
79 .cleanup = ath_pci_cleanup,
80 .eeprom_read = ath_pci_eeprom_read,
81};
82
83static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
84{
85 void __iomem *mem;
86 struct ath_wiphy *aphy;
87 struct ath_softc *sc;
88 struct ieee80211_hw *hw;
89 u8 csz;
90 int ret = 0;
91 struct ath_hw *ah;
92
93 if (pci_enable_device(pdev))
94 return -EIO;
95
96 ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
97
98 if (ret) {
99 printk(KERN_ERR "ath9k: 32-bit DMA not available\n");
100 goto bad;
101 }
102
103 ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
104
105 if (ret) {
106 printk(KERN_ERR "ath9k: 32-bit DMA consistent "
107 "DMA enable failed\n");
108 goto bad;
109 }
110
111 /*
112 * Cache line size is used to size and align various
113 * structures used to communicate with the hardware.
114 */
115 pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
116 if (csz == 0) {
117 /*
118 * Linux 2.4.18 (at least) writes the cache line size
119 * register as a 16-bit wide register which is wrong.
120 * We must have this setup properly for rx buffer
121 * DMA to work so force a reasonable value here if it
122 * comes up zero.
123 */
124 csz = L1_CACHE_BYTES / sizeof(u32);
125 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
126 }
127 /*
128 * The default setting of latency timer yields poor results,
129 * set it to the value used by other systems. It may be worth
130 * tweaking this setting more.
131 */
132 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
133
134 pci_set_master(pdev);
135
136 ret = pci_request_region(pdev, 0, "ath9k");
137 if (ret) {
138 dev_err(&pdev->dev, "PCI memory region reserve error\n");
139 ret = -ENODEV;
140 goto bad;
141 }
142
143 mem = pci_iomap(pdev, 0, 0);
144 if (!mem) {
145 printk(KERN_ERR "PCI memory map error\n") ;
146 ret = -EIO;
147 goto bad1;
148 }
149
150 hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) +
151 sizeof(struct ath_softc), &ath9k_ops);
152 if (hw == NULL) {
153 printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n");
154 goto bad2;
155 }
156
157 SET_IEEE80211_DEV(hw, &pdev->dev);
158 pci_set_drvdata(pdev, hw);
159
160 aphy = hw->priv;
161 sc = (struct ath_softc *) (aphy + 1);
162 aphy->sc = sc;
163 aphy->hw = hw;
164 sc->pri_wiphy = aphy;
165 sc->hw = hw;
166 sc->dev = &pdev->dev;
167 sc->mem = mem;
168 sc->bus_ops = &ath_pci_bus_ops;
169
170 if (ath_attach(id->device, sc) != 0) {
171 ret = -ENODEV;
172 goto bad3;
173 }
174
175 /* setup interrupt service routine */
176
177 if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) {
178 printk(KERN_ERR "%s: request_irq failed\n",
179 wiphy_name(hw->wiphy));
180 ret = -EIO;
181 goto bad4;
182 }
183
184 sc->irq = pdev->irq;
185
186 ah = sc->sc_ah;
187 printk(KERN_INFO
188 "%s: Atheros AR%s MAC/BB Rev:%x "
189 "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n",
190 wiphy_name(hw->wiphy),
191 ath_mac_bb_name(ah->hw_version.macVersion),
192 ah->hw_version.macRev,
193 ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)),
194 ah->hw_version.phyRev,
195 (unsigned long)mem, pdev->irq);
196
197 return 0;
198bad4:
199 ath_detach(sc);
200bad3:
201 ieee80211_free_hw(hw);
202bad2:
203 pci_iounmap(pdev, mem);
204bad1:
205 pci_release_region(pdev, 0);
206bad:
207 pci_disable_device(pdev);
208 return ret;
209}
210
211static void ath_pci_remove(struct pci_dev *pdev)
212{
213 struct ieee80211_hw *hw = pci_get_drvdata(pdev);
214 struct ath_wiphy *aphy = hw->priv;
215 struct ath_softc *sc = aphy->sc;
216
217 ath_cleanup(sc);
218}
219
220#ifdef CONFIG_PM
221
222static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
223{
224 struct ieee80211_hw *hw = pci_get_drvdata(pdev);
225 struct ath_wiphy *aphy = hw->priv;
226 struct ath_softc *sc = aphy->sc;
227
228 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
229
230#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
231 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
232 cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
233#endif
234
235 pci_save_state(pdev);
236 pci_disable_device(pdev);
237 pci_set_power_state(pdev, PCI_D3hot);
238
239 return 0;
240}
241
242static int ath_pci_resume(struct pci_dev *pdev)
243{
244 struct ieee80211_hw *hw = pci_get_drvdata(pdev);
245 struct ath_wiphy *aphy = hw->priv;
246 struct ath_softc *sc = aphy->sc;
247 int err;
248
249 err = pci_enable_device(pdev);
250 if (err)
251 return err;
252 pci_restore_state(pdev);
253
254 /* Enable LED */
255 ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
256 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
257 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
258
259#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
260 /*
261 * check the h/w rfkill state on resume
262 * and start the rfkill poll timer
263 */
264 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
265 queue_delayed_work(sc->hw->workqueue,
266 &sc->rf_kill.rfkill_poll, 0);
267#endif
268
269 return 0;
270}
271
272#endif /* CONFIG_PM */
273
274MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
275
276static struct pci_driver ath_pci_driver = {
277 .name = "ath9k",
278 .id_table = ath_pci_id_table,
279 .probe = ath_pci_probe,
280 .remove = ath_pci_remove,
281#ifdef CONFIG_PM
282 .suspend = ath_pci_suspend,
283 .resume = ath_pci_resume,
284#endif /* CONFIG_PM */
285};
286
287int ath_pci_init(void)
288{
289 return pci_register_driver(&ath_pci_driver);
290}
291
292void ath_pci_exit(void)
293{
294 pci_unregister_driver(&ath_pci_driver);
295}
diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c
new file mode 100644
index 000000000000..5ec9ce91d979
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/phy.c
@@ -0,0 +1,424 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "ath9k.h"
18
19void
20ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex,
21 int regWrites)
22{
23 REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites);
24}
25
26bool
27ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
28{
29 u32 channelSel = 0;
30 u32 bModeSynth = 0;
31 u32 aModeRefSel = 0;
32 u32 reg32 = 0;
33 u16 freq;
34 struct chan_centers centers;
35
36 ath9k_hw_get_channel_centers(ah, chan, &centers);
37 freq = centers.synth_center;
38
39 if (freq < 4800) {
40 u32 txctl;
41
42 if (((freq - 2192) % 5) == 0) {
43 channelSel = ((freq - 672) * 2 - 3040) / 10;
44 bModeSynth = 0;
45 } else if (((freq - 2224) % 5) == 0) {
46 channelSel = ((freq - 704) * 2 - 3040) / 10;
47 bModeSynth = 1;
48 } else {
49 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
50 "Invalid channel %u MHz\n", freq);
51 return false;
52 }
53
54 channelSel = (channelSel << 2) & 0xff;
55 channelSel = ath9k_hw_reverse_bits(channelSel, 8);
56
57 txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
58 if (freq == 2484) {
59
60 REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
61 txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
62 } else {
63 REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
64 txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
65 }
66
67 } else if ((freq % 20) == 0 && freq >= 5120) {
68 channelSel =
69 ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8);
70 aModeRefSel = ath9k_hw_reverse_bits(1, 2);
71 } else if ((freq % 10) == 0) {
72 channelSel =
73 ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8);
74 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
75 aModeRefSel = ath9k_hw_reverse_bits(2, 2);
76 else
77 aModeRefSel = ath9k_hw_reverse_bits(1, 2);
78 } else if ((freq % 5) == 0) {
79 channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);
80 aModeRefSel = ath9k_hw_reverse_bits(1, 2);
81 } else {
82 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
83 "Invalid channel %u MHz\n", freq);
84 return false;
85 }
86
87 reg32 =
88 (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |
89 (1 << 5) | 0x1;
90
91 REG_WRITE(ah, AR_PHY(0x37), reg32);
92
93 ah->curchan = chan;
94 ah->curchan_rad_index = -1;
95
96 return true;
97}
98
99bool
100ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
101 struct ath9k_channel *chan)
102{
103 u16 bMode, fracMode, aModeRefSel = 0;
104 u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
105 struct chan_centers centers;
106 u32 refDivA = 24;
107
108 ath9k_hw_get_channel_centers(ah, chan, &centers);
109 freq = centers.synth_center;
110
111 reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL);
112 reg32 &= 0xc0000000;
113
114 if (freq < 4800) {
115 u32 txctl;
116
117 bMode = 1;
118 fracMode = 1;
119 aModeRefSel = 0;
120 channelSel = (freq * 0x10000) / 15;
121
122 txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
123 if (freq == 2484) {
124
125 REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
126 txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
127 } else {
128 REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
129 txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
130 }
131 } else {
132 bMode = 0;
133 fracMode = 0;
134
135 switch(ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
136 case 0:
137 if ((freq % 20) == 0) {
138 aModeRefSel = 3;
139 } else if ((freq % 10) == 0) {
140 aModeRefSel = 2;
141 }
142 if (aModeRefSel)
143 break;
144 case 1:
145 default:
146 aModeRefSel = 0;
147 fracMode = 1;
148 refDivA = 1;
149 channelSel = (freq * 0x8000) / 15;
150
151 REG_RMW_FIELD(ah, AR_AN_SYNTH9,
152 AR_AN_SYNTH9_REFDIVA, refDivA);
153
154 }
155
156 if (!fracMode) {
157 ndiv = (freq * (refDivA >> aModeRefSel)) / 60;
158 channelSel = ndiv & 0x1ff;
159 channelFrac = (ndiv & 0xfffffe00) * 2;
160 channelSel = (channelSel << 17) | channelFrac;
161 }
162 }
163
164 reg32 = reg32 |
165 (bMode << 29) |
166 (fracMode << 28) | (aModeRefSel << 26) | (channelSel);
167
168 REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
169
170 ah->curchan = chan;
171 ah->curchan_rad_index = -1;
172
173 return true;
174}
175
176static void
177ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32,
178 u32 numBits, u32 firstBit,
179 u32 column)
180{
181 u32 tmp32, mask, arrayEntry, lastBit;
182 int32_t bitPosition, bitsLeft;
183
184 tmp32 = ath9k_hw_reverse_bits(reg32, numBits);
185 arrayEntry = (firstBit - 1) / 8;
186 bitPosition = (firstBit - 1) % 8;
187 bitsLeft = numBits;
188 while (bitsLeft > 0) {
189 lastBit = (bitPosition + bitsLeft > 8) ?
190 8 : bitPosition + bitsLeft;
191 mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) <<
192 (column * 8);
193 rfBuf[arrayEntry] &= ~mask;
194 rfBuf[arrayEntry] |= ((tmp32 << bitPosition) <<
195 (column * 8)) & mask;
196 bitsLeft -= 8 - bitPosition;
197 tmp32 = tmp32 >> (8 - bitPosition);
198 bitPosition = 0;
199 arrayEntry++;
200 }
201}
202
203bool
204ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan,
205 u16 modesIndex)
206{
207 u32 eepMinorRev;
208 u32 ob5GHz = 0, db5GHz = 0;
209 u32 ob2GHz = 0, db2GHz = 0;
210 int regWrites = 0;
211
212 if (AR_SREV_9280_10_OR_LATER(ah))
213 return true;
214
215 eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV);
216
217 RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1);
218
219 RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1);
220
221 RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1);
222
223 RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3,
224 modesIndex);
225 {
226 int i;
227 for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) {
228 ah->analogBank6Data[i] =
229 INI_RA(&ah->iniBank6TPC, i, modesIndex);
230 }
231 }
232
233 if (eepMinorRev >= 2) {
234 if (IS_CHAN_2GHZ(chan)) {
235 ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2);
236 db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2);
237 ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
238 ob2GHz, 3, 197, 0);
239 ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
240 db2GHz, 3, 194, 0);
241 } else {
242 ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5);
243 db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5);
244 ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
245 ob5GHz, 3, 203, 0);
246 ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
247 db5GHz, 3, 200, 0);
248 }
249 }
250
251 RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1);
252
253 REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data,
254 regWrites);
255 REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data,
256 regWrites);
257 REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data,
258 regWrites);
259 REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data,
260 regWrites);
261 REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data,
262 regWrites);
263 REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data,
264 regWrites);
265
266 return true;
267}
268
269void
270ath9k_hw_rfdetach(struct ath_hw *ah)
271{
272 if (ah->analogBank0Data != NULL) {
273 kfree(ah->analogBank0Data);
274 ah->analogBank0Data = NULL;
275 }
276 if (ah->analogBank1Data != NULL) {
277 kfree(ah->analogBank1Data);
278 ah->analogBank1Data = NULL;
279 }
280 if (ah->analogBank2Data != NULL) {
281 kfree(ah->analogBank2Data);
282 ah->analogBank2Data = NULL;
283 }
284 if (ah->analogBank3Data != NULL) {
285 kfree(ah->analogBank3Data);
286 ah->analogBank3Data = NULL;
287 }
288 if (ah->analogBank6Data != NULL) {
289 kfree(ah->analogBank6Data);
290 ah->analogBank6Data = NULL;
291 }
292 if (ah->analogBank6TPCData != NULL) {
293 kfree(ah->analogBank6TPCData);
294 ah->analogBank6TPCData = NULL;
295 }
296 if (ah->analogBank7Data != NULL) {
297 kfree(ah->analogBank7Data);
298 ah->analogBank7Data = NULL;
299 }
300 if (ah->addac5416_21 != NULL) {
301 kfree(ah->addac5416_21);
302 ah->addac5416_21 = NULL;
303 }
304 if (ah->bank6Temp != NULL) {
305 kfree(ah->bank6Temp);
306 ah->bank6Temp = NULL;
307 }
308}
309
310bool ath9k_hw_init_rf(struct ath_hw *ah, int *status)
311{
312 if (!AR_SREV_9280_10_OR_LATER(ah)) {
313 ah->analogBank0Data =
314 kzalloc((sizeof(u32) *
315 ah->iniBank0.ia_rows), GFP_KERNEL);
316 ah->analogBank1Data =
317 kzalloc((sizeof(u32) *
318 ah->iniBank1.ia_rows), GFP_KERNEL);
319 ah->analogBank2Data =
320 kzalloc((sizeof(u32) *
321 ah->iniBank2.ia_rows), GFP_KERNEL);
322 ah->analogBank3Data =
323 kzalloc((sizeof(u32) *
324 ah->iniBank3.ia_rows), GFP_KERNEL);
325 ah->analogBank6Data =
326 kzalloc((sizeof(u32) *
327 ah->iniBank6.ia_rows), GFP_KERNEL);
328 ah->analogBank6TPCData =
329 kzalloc((sizeof(u32) *
330 ah->iniBank6TPC.ia_rows), GFP_KERNEL);
331 ah->analogBank7Data =
332 kzalloc((sizeof(u32) *
333 ah->iniBank7.ia_rows), GFP_KERNEL);
334
335 if (ah->analogBank0Data == NULL
336 || ah->analogBank1Data == NULL
337 || ah->analogBank2Data == NULL
338 || ah->analogBank3Data == NULL
339 || ah->analogBank6Data == NULL
340 || ah->analogBank6TPCData == NULL
341 || ah->analogBank7Data == NULL) {
342 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
343 "Cannot allocate RF banks\n");
344 *status = -ENOMEM;
345 return false;
346 }
347
348 ah->addac5416_21 =
349 kzalloc((sizeof(u32) *
350 ah->iniAddac.ia_rows *
351 ah->iniAddac.ia_columns), GFP_KERNEL);
352 if (ah->addac5416_21 == NULL) {
353 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
354 "Cannot allocate addac5416_21\n");
355 *status = -ENOMEM;
356 return false;
357 }
358
359 ah->bank6Temp =
360 kzalloc((sizeof(u32) *
361 ah->iniBank6.ia_rows), GFP_KERNEL);
362 if (ah->bank6Temp == NULL) {
363 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
364 "Cannot allocate bank6Temp\n");
365 *status = -ENOMEM;
366 return false;
367 }
368 }
369
370 return true;
371}
372
373void
374ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan)
375{
376 int i, regWrites = 0;
377 u32 bank6SelMask;
378 u32 *bank6Temp = ah->bank6Temp;
379
380 switch (ah->diversity_control) {
381 case ATH9K_ANT_FIXED_A:
382 bank6SelMask =
383 (ah->
384 antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_0 :
385 REDUCE_CHAIN_1;
386 break;
387 case ATH9K_ANT_FIXED_B:
388 bank6SelMask =
389 (ah->
390 antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_1 :
391 REDUCE_CHAIN_0;
392 break;
393 case ATH9K_ANT_VARIABLE:
394 return;
395 break;
396 default:
397 return;
398 break;
399 }
400
401 for (i = 0; i < ah->iniBank6.ia_rows; i++)
402 bank6Temp[i] = ah->analogBank6Data[i];
403
404 REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask);
405
406 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0);
407 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0);
408 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0);
409 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0);
410 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0);
411 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0);
412 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0);
413 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0);
414 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0);
415
416 REG_WRITE_RF_ARRAY(&ah->iniBank6, bank6Temp, regWrites);
417
418 REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053);
419#ifdef ALTER_SWITCH
420 REG_WRITE(ah, PHY_SWITCH_CHAIN_0,
421 (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38)
422 | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38));
423#endif
424}
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h
new file mode 100644
index 000000000000..296d0e985f25
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/phy.h
@@ -0,0 +1,576 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef PHY_H
18#define PHY_H
19
20bool ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
21 struct ath9k_channel
22 *chan);
23bool ath9k_hw_set_channel(struct ath_hw *ah,
24 struct ath9k_channel *chan);
25void ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex,
26 u32 freqIndex, int regWrites);
27bool ath9k_hw_set_rf_regs(struct ath_hw *ah,
28 struct ath9k_channel *chan,
29 u16 modesIndex);
30void ath9k_hw_decrease_chain_power(struct ath_hw *ah,
31 struct ath9k_channel *chan);
32bool ath9k_hw_init_rf(struct ath_hw *ah,
33 int *status);
34
35#define AR_PHY_BASE 0x9800
36#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2))
37
38#define AR_PHY_TEST 0x9800
39#define PHY_AGC_CLR 0x10000000
40#define RFSILENT_BB 0x00002000
41
42#define AR_PHY_TURBO 0x9804
43#define AR_PHY_FC_TURBO_MODE 0x00000001
44#define AR_PHY_FC_TURBO_SHORT 0x00000002
45#define AR_PHY_FC_DYN2040_EN 0x00000004
46#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008
47#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010
48#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020
49#define AR_PHY_FC_HT_EN 0x00000040
50#define AR_PHY_FC_SHORT_GI_40 0x00000080
51#define AR_PHY_FC_WALSH 0x00000100
52#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200
53#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800
54
55#define AR_PHY_TEST2 0x9808
56
57#define AR_PHY_TIMING2 0x9810
58#define AR_PHY_TIMING3 0x9814
59#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000
60#define AR_PHY_TIMING3_DSC_MAN_S 17
61#define AR_PHY_TIMING3_DSC_EXP 0x0001E000
62#define AR_PHY_TIMING3_DSC_EXP_S 13
63
64#define AR_PHY_CHIP_ID 0x9818
65#define AR_PHY_CHIP_ID_REV_0 0x80
66#define AR_PHY_CHIP_ID_REV_1 0x81
67#define AR_PHY_CHIP_ID_9160_REV_0 0xb0
68
69#define AR_PHY_ACTIVE 0x981C
70#define AR_PHY_ACTIVE_EN 0x00000001
71#define AR_PHY_ACTIVE_DIS 0x00000000
72
73#define AR_PHY_RF_CTL2 0x9824
74#define AR_PHY_TX_END_DATA_START 0x000000FF
75#define AR_PHY_TX_END_DATA_START_S 0
76#define AR_PHY_TX_END_PA_ON 0x0000FF00
77#define AR_PHY_TX_END_PA_ON_S 8
78
79#define AR_PHY_RF_CTL3 0x9828
80#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000
81#define AR_PHY_TX_END_TO_A2_RX_ON_S 16
82
83#define AR_PHY_ADC_CTL 0x982C
84#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003
85#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0
86#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000
87#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000
88#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000
89#define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000
90#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16
91
92#define AR_PHY_ADC_SERIAL_CTL 0x9830
93#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000
94#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001
95
96#define AR_PHY_RF_CTL4 0x9834
97#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000
98#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24
99#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000
100#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16
101#define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00
102#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8
103#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF
104#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0
105
106#define AR_PHY_TSTDAC_CONST 0x983c
107
108#define AR_PHY_SETTLING 0x9844
109#define AR_PHY_SETTLING_SWITCH 0x00003F80
110#define AR_PHY_SETTLING_SWITCH_S 7
111
112#define AR_PHY_RXGAIN 0x9848
113#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000
114#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12
115#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000
116#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18
117#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80
118#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7
119#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000
120#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14
121
122#define AR_PHY_DESIRED_SZ 0x9850
123#define AR_PHY_DESIRED_SZ_ADC 0x000000FF
124#define AR_PHY_DESIRED_SZ_ADC_S 0
125#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00
126#define AR_PHY_DESIRED_SZ_PGA_S 8
127#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000
128#define AR_PHY_DESIRED_SZ_TOT_DES_S 20
129
130#define AR_PHY_FIND_SIG 0x9858
131#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000
132#define AR_PHY_FIND_SIG_FIRSTEP_S 12
133#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000
134#define AR_PHY_FIND_SIG_FIRPWR_S 18
135
136#define AR_PHY_AGC_CTL1 0x985C
137#define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80
138#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7
139#define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000
140#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15
141
142#define AR_PHY_AGC_CONTROL 0x9860
143#define AR_PHY_AGC_CONTROL_CAL 0x00000001
144#define AR_PHY_AGC_CONTROL_NF 0x00000002
145#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000
146#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000
147#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000
148
149#define AR_PHY_CCA 0x9864
150#define AR_PHY_MINCCA_PWR 0x0FF80000
151#define AR_PHY_MINCCA_PWR_S 19
152#define AR_PHY_CCA_THRESH62 0x0007F000
153#define AR_PHY_CCA_THRESH62_S 12
154#define AR9280_PHY_MINCCA_PWR 0x1FF00000
155#define AR9280_PHY_MINCCA_PWR_S 20
156#define AR9280_PHY_CCA_THRESH62 0x000FF000
157#define AR9280_PHY_CCA_THRESH62_S 12
158
159#define AR_PHY_SFCORR_LOW 0x986C
160#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001
161#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00
162#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8
163#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000
164#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14
165#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000
166#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21
167
168#define AR_PHY_SFCORR 0x9868
169#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F
170#define AR_PHY_SFCORR_M2COUNT_THR_S 0
171#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000
172#define AR_PHY_SFCORR_M1_THRESH_S 17
173#define AR_PHY_SFCORR_M2_THRESH 0x7F000000
174#define AR_PHY_SFCORR_M2_THRESH_S 24
175
176#define AR_PHY_SLEEP_CTR_CONTROL 0x9870
177#define AR_PHY_SLEEP_CTR_LIMIT 0x9874
178#define AR_PHY_SYNTH_CONTROL 0x9874
179#define AR_PHY_SLEEP_SCAL 0x9878
180
181#define AR_PHY_PLL_CTL 0x987c
182#define AR_PHY_PLL_CTL_40 0xaa
183#define AR_PHY_PLL_CTL_40_5413 0x04
184#define AR_PHY_PLL_CTL_44 0xab
185#define AR_PHY_PLL_CTL_44_2133 0xeb
186#define AR_PHY_PLL_CTL_40_2133 0xea
187
188#define AR_PHY_RX_DELAY 0x9914
189#define AR_PHY_SEARCH_START_DELAY 0x9918
190#define AR_PHY_RX_DELAY_DELAY 0x00003FFF
191
192#define AR_PHY_TIMING_CTRL4(_i) (0x9920 + ((_i) << 12))
193#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F
194#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0
195#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0
196#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5
197#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800
198#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000
199#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12
200#define AR_PHY_TIMING_CTRL4_DO_CAL 0x10000
201
202#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000
203#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000
204#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000
205#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000
206
207#define AR_PHY_TIMING5 0x9924
208#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE
209#define AR_PHY_TIMING5_CYCPWR_THR1_S 1
210
211#define AR_PHY_POWER_TX_RATE1 0x9934
212#define AR_PHY_POWER_TX_RATE2 0x9938
213#define AR_PHY_POWER_TX_RATE_MAX 0x993c
214#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
215
216#define AR_PHY_FRAME_CTL 0x9944
217#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038
218#define AR_PHY_FRAME_CTL_TX_CLIP_S 3
219
220#define AR_PHY_TXPWRADJ 0x994C
221#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0
222#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6
223#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000
224#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18
225
226#define AR_PHY_RADAR_EXT 0x9940
227#define AR_PHY_RADAR_EXT_ENA 0x00004000
228
229#define AR_PHY_RADAR_0 0x9954
230#define AR_PHY_RADAR_0_ENA 0x00000001
231#define AR_PHY_RADAR_0_FFT_ENA 0x80000000
232#define AR_PHY_RADAR_0_INBAND 0x0000003e
233#define AR_PHY_RADAR_0_INBAND_S 1
234#define AR_PHY_RADAR_0_PRSSI 0x00000FC0
235#define AR_PHY_RADAR_0_PRSSI_S 6
236#define AR_PHY_RADAR_0_HEIGHT 0x0003F000
237#define AR_PHY_RADAR_0_HEIGHT_S 12
238#define AR_PHY_RADAR_0_RRSSI 0x00FC0000
239#define AR_PHY_RADAR_0_RRSSI_S 18
240#define AR_PHY_RADAR_0_FIRPWR 0x7F000000
241#define AR_PHY_RADAR_0_FIRPWR_S 24
242
243#define AR_PHY_RADAR_1 0x9958
244#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000
245#define AR_PHY_RADAR_1_USE_FIR128 0x00400000
246#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000
247#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16
248#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000
249#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000
250#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000
251#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00
252#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8
253#define AR_PHY_RADAR_1_MAXLEN 0x000000FF
254#define AR_PHY_RADAR_1_MAXLEN_S 0
255
256#define AR_PHY_SWITCH_CHAIN_0 0x9960
257#define AR_PHY_SWITCH_COM 0x9964
258
259#define AR_PHY_SIGMA_DELTA 0x996C
260#define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003
261#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0
262#define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8
263#define AR_PHY_SIGMA_DELTA_FILT2_S 3
264#define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00
265#define AR_PHY_SIGMA_DELTA_FILT1_S 8
266#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000
267#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13
268
269#define AR_PHY_RESTART 0x9970
270#define AR_PHY_RESTART_DIV_GC 0x001C0000
271#define AR_PHY_RESTART_DIV_GC_S 18
272
273#define AR_PHY_RFBUS_REQ 0x997C
274#define AR_PHY_RFBUS_REQ_EN 0x00000001
275
276#define AR_PHY_TIMING7 0x9980
277#define AR_PHY_TIMING8 0x9984
278#define AR_PHY_TIMING8_PILOT_MASK_2 0x000FFFFF
279#define AR_PHY_TIMING8_PILOT_MASK_2_S 0
280
281#define AR_PHY_BIN_MASK2_1 0x9988
282#define AR_PHY_BIN_MASK2_2 0x998c
283#define AR_PHY_BIN_MASK2_3 0x9990
284#define AR_PHY_BIN_MASK2_4 0x9994
285
286#define AR_PHY_BIN_MASK_1 0x9900
287#define AR_PHY_BIN_MASK_2 0x9904
288#define AR_PHY_BIN_MASK_3 0x9908
289
290#define AR_PHY_MASK_CTL 0x990c
291
292#define AR_PHY_BIN_MASK2_4_MASK_4 0x00003FFF
293#define AR_PHY_BIN_MASK2_4_MASK_4_S 0
294
295#define AR_PHY_TIMING9 0x9998
296#define AR_PHY_TIMING10 0x999c
297#define AR_PHY_TIMING10_PILOT_MASK_2 0x000FFFFF
298#define AR_PHY_TIMING10_PILOT_MASK_2_S 0
299
300#define AR_PHY_TIMING11 0x99a0
301#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF
302#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0
303#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000
304#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20
305#define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000
306#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000
307
308#define AR_PHY_RX_CHAINMASK 0x99a4
309#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12))
310#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
311#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
312#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac
313
314#define AR_PHY_EXT_CCA0 0x99b8
315#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF
316#define AR_PHY_EXT_CCA0_THRESH62_S 0
317
318#define AR_PHY_EXT_CCA 0x99bc
319#define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00
320#define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9
321#define AR_PHY_EXT_CCA_THRESH62 0x007F0000
322#define AR_PHY_EXT_CCA_THRESH62_S 16
323#define AR_PHY_EXT_MINCCA_PWR 0xFF800000
324#define AR_PHY_EXT_MINCCA_PWR_S 23
325#define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000
326#define AR9280_PHY_EXT_MINCCA_PWR_S 16
327
328#define AR_PHY_SFCORR_EXT 0x99c0
329#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F
330#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0
331#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80
332#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7
333#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000
334#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
335#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000
336#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
337#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28
338
339#define AR_PHY_HALFGI 0x99D0
340#define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0
341#define AR_PHY_HALFGI_DSC_MAN_S 4
342#define AR_PHY_HALFGI_DSC_EXP 0x0000000F
343#define AR_PHY_HALFGI_DSC_EXP_S 0
344
345#define AR_PHY_CHAN_INFO_MEMORY 0x99DC
346#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001
347
348#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0
349
350#define AR_PHY_M_SLEEP 0x99f0
351#define AR_PHY_REFCLKDLY 0x99f4
352#define AR_PHY_REFCLKPD 0x99f8
353
354#define AR_PHY_CALMODE 0x99f0
355
356#define AR_PHY_CALMODE_IQ 0x00000000
357#define AR_PHY_CALMODE_ADC_GAIN 0x00000001
358#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002
359#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003
360
361#define AR_PHY_CAL_MEAS_0(_i) (0x9c10 + ((_i) << 12))
362#define AR_PHY_CAL_MEAS_1(_i) (0x9c14 + ((_i) << 12))
363#define AR_PHY_CAL_MEAS_2(_i) (0x9c18 + ((_i) << 12))
364#define AR_PHY_CAL_MEAS_3(_i) (0x9c1c + ((_i) << 12))
365
366#define AR_PHY_CURRENT_RSSI 0x9c1c
367#define AR9280_PHY_CURRENT_RSSI 0x9c3c
368
369#define AR_PHY_RFBUS_GRANT 0x9C20
370#define AR_PHY_RFBUS_GRANT_EN 0x00000001
371
372#define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4
373#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
374
375#define AR_PHY_CHAN_INFO_GAIN 0x9CFC
376
377#define AR_PHY_MODE 0xA200
378#define AR_PHY_MODE_AR2133 0x08
379#define AR_PHY_MODE_AR5111 0x00
380#define AR_PHY_MODE_AR5112 0x08
381#define AR_PHY_MODE_DYNAMIC 0x04
382#define AR_PHY_MODE_RF2GHZ 0x02
383#define AR_PHY_MODE_RF5GHZ 0x00
384#define AR_PHY_MODE_CCK 0x01
385#define AR_PHY_MODE_OFDM 0x00
386#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100
387
388#define AR_PHY_CCK_TX_CTRL 0xA204
389#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
390#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C
391#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2
392
393#define AR_PHY_CCK_DETECT 0xA208
394#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F
395#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0
396/* [12:6] settling time for antenna switch */
397#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0
398#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6
399#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
400
401#define AR_PHY_GAIN_2GHZ 0xA20C
402#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000
403#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18
404#define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00
405#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10
406#define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F
407#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0
408
409#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003E0000
410#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17
411#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001F000
412#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12
413#define AR_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000FC0
414#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S 6
415#define AR_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003F
416#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S 0
417
418#define AR_PHY_CCK_RXCTRL4 0xA21C
419#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000
420#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19
421
422#define AR_PHY_DAG_CTRLCCK 0xA228
423#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200
424#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00
425#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10
426
427#define AR_PHY_FORCE_CLKEN_CCK 0xA22C
428#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040
429
430#define AR_PHY_POWER_TX_RATE3 0xA234
431#define AR_PHY_POWER_TX_RATE4 0xA238
432
433#define AR_PHY_SCRM_SEQ_XR 0xA23C
434#define AR_PHY_HEADER_DETECT_XR 0xA240
435#define AR_PHY_CHIRP_DETECTED_XR 0xA244
436#define AR_PHY_BLUETOOTH 0xA254
437
438#define AR_PHY_TPCRG1 0xA258
439#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000
440#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14
441
442#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000
443#define AR_PHY_TPCRG1_PD_GAIN_1_S 16
444#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000
445#define AR_PHY_TPCRG1_PD_GAIN_2_S 18
446#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000
447#define AR_PHY_TPCRG1_PD_GAIN_3_S 20
448
449#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000
450#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22
451
452#define AR_PHY_TX_PWRCTRL4 0xa264
453#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001
454#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0
455#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE
456#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1
457
458#define AR_PHY_TX_PWRCTRL6_0 0xa270
459#define AR_PHY_TX_PWRCTRL6_1 0xb270
460#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000
461#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24
462
463#define AR_PHY_TX_PWRCTRL7 0xa274
464#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000
465#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19
466
467#define AR_PHY_TX_PWRCTRL9 0xa27C
468#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00
469#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10
470
471#define AR_PHY_TX_GAIN_TBL1 0xa300
472#define AR_PHY_TX_GAIN 0x0007F000
473#define AR_PHY_TX_GAIN_S 12
474
475#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
476#define AR_PHY_MASK2_M_31_45 0xa3a4
477#define AR_PHY_MASK2_M_16_30 0xa3a8
478#define AR_PHY_MASK2_M_00_15 0xa3ac
479#define AR_PHY_MASK2_P_15_01 0xa3b8
480#define AR_PHY_MASK2_P_30_16 0xa3bc
481#define AR_PHY_MASK2_P_45_31 0xa3c0
482#define AR_PHY_MASK2_P_61_45 0xa3c4
483#define AR_PHY_SPUR_REG 0x994c
484
485#define AR_PHY_SPUR_REG_MASK_RATE_CNTL (0xFF << 18)
486#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18
487
488#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000
489#define AR_PHY_SPUR_REG_MASK_RATE_SELECT (0xFF << 9)
490#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S 9
491#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100
492#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7F
493#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0
494
495#define AR_PHY_PILOT_MASK_01_30 0xa3b0
496#define AR_PHY_PILOT_MASK_31_60 0xa3b4
497
498#define AR_PHY_CHANNEL_MASK_01_30 0x99d4
499#define AR_PHY_CHANNEL_MASK_31_60 0x99d8
500
501#define AR_PHY_ANALOG_SWAP 0xa268
502#define AR_PHY_SWAP_ALT_CHAIN 0x00000040
503
504#define AR_PHY_TPCRG5 0xA26C
505#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F
506#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0
507#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0
508#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4
509#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00
510#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10
511#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000
512#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16
513#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000
514#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22
515
516/* Carrier leak calibration control, do it after AGC calibration */
517#define AR_PHY_CL_CAL_CTL 0xA358
518#define AR_PHY_CL_CAL_ENABLE 0x00000002
519#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001
520
521#define AR_PHY_POWER_TX_RATE5 0xA38C
522#define AR_PHY_POWER_TX_RATE6 0xA390
523
524#define AR_PHY_CAL_CHAINMASK 0xA39C
525
526#define AR_PHY_POWER_TX_SUB 0xA3C8
527#define AR_PHY_POWER_TX_RATE7 0xA3CC
528#define AR_PHY_POWER_TX_RATE8 0xA3D0
529#define AR_PHY_POWER_TX_RATE9 0xA3D4
530
531#define AR_PHY_XPA_CFG 0xA3D8
532#define AR_PHY_FORCE_XPA_CFG 0x000000001
533#define AR_PHY_FORCE_XPA_CFG_S 0
534
535#define AR_PHY_CH1_CCA 0xa864
536#define AR_PHY_CH1_MINCCA_PWR 0x0FF80000
537#define AR_PHY_CH1_MINCCA_PWR_S 19
538#define AR9280_PHY_CH1_MINCCA_PWR 0x1FF00000
539#define AR9280_PHY_CH1_MINCCA_PWR_S 20
540
541#define AR_PHY_CH2_CCA 0xb864
542#define AR_PHY_CH2_MINCCA_PWR 0x0FF80000
543#define AR_PHY_CH2_MINCCA_PWR_S 19
544
545#define AR_PHY_CH1_EXT_CCA 0xa9bc
546#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000
547#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23
548#define AR9280_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000
549#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16
550
551#define AR_PHY_CH2_EXT_CCA 0xb9bc
552#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000
553#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23
554
555#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do { \
556 int r; \
557 for (r = 0; r < ((iniarray)->ia_rows); r++) { \
558 REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \
559 DO_DELAY(regWr); \
560 } \
561 } while (0)
562
563#define ATH9K_IS_MIC_ENABLED(ah) \
564 ((ah)->sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE)
565
566#define ANTSWAP_AB 0x0001
567#define REDUCE_CHAIN_0 0x00000050
568#define REDUCE_CHAIN_1 0x00000051
569
570#define RF_BANK_SETUP(_bank, _iniarray, _col) do { \
571 int i; \
572 for (i = 0; i < (_iniarray)->ia_rows; i++) \
573 (_bank)[i] = INI_RA((_iniarray), i, _col);; \
574 } while (0)
575
576#endif
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
new file mode 100644
index 000000000000..a13668b9b6dc
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -0,0 +1,1752 @@
1/*
2 * Copyright (c) 2004 Video54 Technologies, Inc.
3 * Copyright (c) 2004-2009 Atheros Communications, Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include "ath9k.h"
19
20static struct ath_rate_table ar5416_11na_ratetable = {
21 42,
22 {
23 { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
24 5400, 0x0b, 0x00, 12,
25 0, 2, 1, 0, 0, 0, 0, 0 },
26 { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
27 7800, 0x0f, 0x00, 18,
28 0, 3, 1, 1, 1, 1, 1, 0 },
29 { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
30 10000, 0x0a, 0x00, 24,
31 2, 4, 2, 2, 2, 2, 2, 0 },
32 { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
33 13900, 0x0e, 0x00, 36,
34 2, 6, 2, 3, 3, 3, 3, 0 },
35 { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
36 17300, 0x09, 0x00, 48,
37 4, 10, 3, 4, 4, 4, 4, 0 },
38 { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
39 23000, 0x0d, 0x00, 72,
40 4, 14, 3, 5, 5, 5, 5, 0 },
41 { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
42 27400, 0x08, 0x00, 96,
43 4, 20, 3, 6, 6, 6, 6, 0 },
44 { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
45 29300, 0x0c, 0x00, 108,
46 4, 23, 3, 7, 7, 7, 7, 0 },
47 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
48 6400, 0x80, 0x00, 0,
49 0, 2, 3, 8, 24, 8, 24, 3216 },
50 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
51 12700, 0x81, 0x00, 1,
52 2, 4, 3, 9, 25, 9, 25, 6434 },
53 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
54 18800, 0x82, 0x00, 2,
55 2, 6, 3, 10, 26, 10, 26, 9650 },
56 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
57 25000, 0x83, 0x00, 3,
58 4, 10, 3, 11, 27, 11, 27, 12868 },
59 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
60 36700, 0x84, 0x00, 4,
61 4, 14, 3, 12, 28, 12, 28, 19304 },
62 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
63 48100, 0x85, 0x00, 5,
64 4, 20, 3, 13, 29, 13, 29, 25740 },
65 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
66 53500, 0x86, 0x00, 6,
67 4, 23, 3, 14, 30, 14, 30, 28956 },
68 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
69 59000, 0x87, 0x00, 7,
70 4, 25, 3, 15, 31, 15, 32, 32180 },
71 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
72 12700, 0x88, 0x00,
73 8, 0, 2, 3, 16, 33, 16, 33, 6430 },
74 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
75 24800, 0x89, 0x00, 9,
76 2, 4, 3, 17, 34, 17, 34, 12860 },
77 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
78 36600, 0x8a, 0x00, 10,
79 2, 6, 3, 18, 35, 18, 35, 19300 },
80 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
81 48100, 0x8b, 0x00, 11,
82 4, 10, 3, 19, 36, 19, 36, 25736 },
83 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
84 69500, 0x8c, 0x00, 12,
85 4, 14, 3, 20, 37, 20, 37, 38600 },
86 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
87 89500, 0x8d, 0x00, 13,
88 4, 20, 3, 21, 38, 21, 38, 51472 },
89 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
90 98900, 0x8e, 0x00, 14,
91 4, 23, 3, 22, 39, 22, 39, 57890 },
92 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
93 108300, 0x8f, 0x00, 15,
94 4, 25, 3, 23, 40, 23, 41, 64320 },
95 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
96 13200, 0x80, 0x00, 0,
97 0, 2, 3, 8, 24, 24, 24, 6684 },
98 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
99 25900, 0x81, 0x00, 1,
100 2, 4, 3, 9, 25, 25, 25, 13368 },
101 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
102 38600, 0x82, 0x00, 2,
103 2, 6, 3, 10, 26, 26, 26, 20052 },
104 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
105 49800, 0x83, 0x00, 3,
106 4, 10, 3, 11, 27, 27, 27, 26738 },
107 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
108 72200, 0x84, 0x00, 4,
109 4, 14, 3, 12, 28, 28, 28, 40104 },
110 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
111 92900, 0x85, 0x00, 5,
112 4, 20, 3, 13, 29, 29, 29, 53476 },
113 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
114 102700, 0x86, 0x00, 6,
115 4, 23, 3, 14, 30, 30, 30, 60156 },
116 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
117 112000, 0x87, 0x00, 7,
118 4, 25, 3, 15, 31, 32, 32, 66840 },
119 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
120 122000, 0x87, 0x00, 7,
121 4, 25, 3, 15, 31, 32, 32, 74200 },
122 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
123 25800, 0x88, 0x00, 8,
124 0, 2, 3, 16, 33, 33, 33, 13360 },
125 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
126 49800, 0x89, 0x00, 9,
127 2, 4, 3, 17, 34, 34, 34, 26720 },
128 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
129 71900, 0x8a, 0x00, 10,
130 2, 6, 3, 18, 35, 35, 35, 40080 },
131 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
132 92500, 0x8b, 0x00, 11,
133 4, 10, 3, 19, 36, 36, 36, 53440 },
134 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
135 130300, 0x8c, 0x00, 12,
136 4, 14, 3, 20, 37, 37, 37, 80160 },
137 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
138 162800, 0x8d, 0x00, 13,
139 4, 20, 3, 21, 38, 38, 38, 106880 },
140 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
141 178200, 0x8e, 0x00, 14,
142 4, 23, 3, 22, 39, 39, 39, 120240 },
143 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
144 192100, 0x8f, 0x00, 15,
145 4, 25, 3, 23, 40, 41, 41, 133600 },
146 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
147 207000, 0x8f, 0x00, 15,
148 4, 25, 3, 23, 40, 41, 41, 148400 },
149 },
150 50, /* probe interval */
151 50, /* rssi reduce interval */
152 WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
153};
154
155/* 4ms frame limit not used for NG mode. The values filled
156 * for HT are the 64K max aggregate limit */
157
158static struct ath_rate_table ar5416_11ng_ratetable = {
159 46,
160 {
161 { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
162 900, 0x1b, 0x00, 2,
163 0, 0, 1, 0, 0, 0, 0, 0 },
164 { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
165 1900, 0x1a, 0x04, 4,
166 1, 1, 1, 1, 1, 1, 1, 0 },
167 { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
168 4900, 0x19, 0x04, 11,
169 2, 2, 2, 2, 2, 2, 2, 0 },
170 { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
171 8100, 0x18, 0x04, 22,
172 3, 3, 2, 3, 3, 3, 3, 0 },
173 { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
174 5400, 0x0b, 0x00, 12,
175 4, 2, 1, 4, 4, 4, 4, 0 },
176 { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
177 7800, 0x0f, 0x00, 18,
178 4, 3, 1, 5, 5, 5, 5, 0 },
179 { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
180 10100, 0x0a, 0x00, 24,
181 6, 4, 1, 6, 6, 6, 6, 0 },
182 { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
183 14100, 0x0e, 0x00, 36,
184 6, 6, 2, 7, 7, 7, 7, 0 },
185 { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
186 17700, 0x09, 0x00, 48,
187 8, 10, 3, 8, 8, 8, 8, 0 },
188 { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
189 23700, 0x0d, 0x00, 72,
190 8, 14, 3, 9, 9, 9, 9, 0 },
191 { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
192 27400, 0x08, 0x00, 96,
193 8, 20, 3, 10, 10, 10, 10, 0 },
194 { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
195 30900, 0x0c, 0x00, 108,
196 8, 23, 3, 11, 11, 11, 11, 0 },
197 { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
198 6400, 0x80, 0x00, 0,
199 4, 2, 3, 12, 28, 12, 28, 3216 },
200 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
201 12700, 0x81, 0x00, 1,
202 6, 4, 3, 13, 29, 13, 29, 6434 },
203 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
204 18800, 0x82, 0x00, 2,
205 6, 6, 3, 14, 30, 14, 30, 9650 },
206 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
207 25000, 0x83, 0x00, 3,
208 8, 10, 3, 15, 31, 15, 31, 12868 },
209 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
210 36700, 0x84, 0x00, 4,
211 8, 14, 3, 16, 32, 16, 32, 19304 },
212 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
213 48100, 0x85, 0x00, 5,
214 8, 20, 3, 17, 33, 17, 33, 25740 },
215 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
216 53500, 0x86, 0x00, 6,
217 8, 23, 3, 18, 34, 18, 34, 28956 },
218 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
219 59000, 0x87, 0x00, 7,
220 8, 25, 3, 19, 35, 19, 36, 32180 },
221 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
222 12700, 0x88, 0x00, 8,
223 4, 2, 3, 20, 37, 20, 37, 6430 },
224 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
225 24800, 0x89, 0x00, 9,
226 6, 4, 3, 21, 38, 21, 38, 12860 },
227 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
228 36600, 0x8a, 0x00, 10,
229 6, 6, 3, 22, 39, 22, 39, 19300 },
230 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
231 48100, 0x8b, 0x00, 11,
232 8, 10, 3, 23, 40, 23, 40, 25736 },
233 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
234 69500, 0x8c, 0x00, 12,
235 8, 14, 3, 24, 41, 24, 41, 38600 },
236 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
237 89500, 0x8d, 0x00, 13,
238 8, 20, 3, 25, 42, 25, 42, 51472 },
239 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
240 98900, 0x8e, 0x00, 14,
241 8, 23, 3, 26, 43, 26, 44, 57890 },
242 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
243 108300, 0x8f, 0x00, 15,
244 8, 25, 3, 27, 44, 27, 45, 64320 },
245 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
246 13200, 0x80, 0x00, 0,
247 8, 2, 3, 12, 28, 28, 28, 6684 },
248 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
249 25900, 0x81, 0x00, 1,
250 8, 4, 3, 13, 29, 29, 29, 13368 },
251 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
252 38600, 0x82, 0x00, 2,
253 8, 6, 3, 14, 30, 30, 30, 20052 },
254 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
255 49800, 0x83, 0x00, 3,
256 8, 10, 3, 15, 31, 31, 31, 26738 },
257 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
258 72200, 0x84, 0x00, 4,
259 8, 14, 3, 16, 32, 32, 32, 40104 },
260 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
261 92900, 0x85, 0x00, 5,
262 8, 20, 3, 17, 33, 33, 33, 53476 },
263 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
264 102700, 0x86, 0x00, 6,
265 8, 23, 3, 18, 34, 34, 34, 60156 },
266 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
267 112000, 0x87, 0x00, 7,
268 8, 23, 3, 19, 35, 36, 36, 66840 },
269 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
270 122000, 0x87, 0x00, 7,
271 8, 25, 3, 19, 35, 36, 36, 74200 },
272 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
273 25800, 0x88, 0x00, 8,
274 8, 2, 3, 20, 37, 37, 37, 13360 },
275 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
276 49800, 0x89, 0x00, 9,
277 8, 4, 3, 21, 38, 38, 38, 26720 },
278 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
279 71900, 0x8a, 0x00, 10,
280 8, 6, 3, 22, 39, 39, 39, 40080 },
281 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
282 92500, 0x8b, 0x00, 11,
283 8, 10, 3, 23, 40, 40, 40, 53440 },
284 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
285 130300, 0x8c, 0x00, 12,
286 8, 14, 3, 24, 41, 41, 41, 80160 },
287 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
288 162800, 0x8d, 0x00, 13,
289 8, 20, 3, 25, 42, 42, 42, 106880 },
290 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
291 178200, 0x8e, 0x00, 14,
292 8, 23, 3, 26, 43, 43, 43, 120240 },
293 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
294 192100, 0x8f, 0x00, 15,
295 8, 23, 3, 27, 44, 45, 45, 133600 },
296 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
297 207000, 0x8f, 0x00, 15,
298 8, 25, 3, 27, 44, 45, 45, 148400 },
299 },
300 50, /* probe interval */
301 50, /* rssi reduce interval */
302 WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
303};
304
305static struct ath_rate_table ar5416_11a_ratetable = {
306 8,
307 {
308 { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
309 5400, 0x0b, 0x00, (0x80|12),
310 0, 2, 1, 0, 0 },
311 { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
312 7800, 0x0f, 0x00, 18,
313 0, 3, 1, 1, 0 },
314 { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
315 10000, 0x0a, 0x00, (0x80|24),
316 2, 4, 2, 2, 0 },
317 { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
318 13900, 0x0e, 0x00, 36,
319 2, 6, 2, 3, 0 },
320 { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
321 17300, 0x09, 0x00, (0x80|48),
322 4, 10, 3, 4, 0 },
323 { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
324 23000, 0x0d, 0x00, 72,
325 4, 14, 3, 5, 0 },
326 { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
327 27400, 0x08, 0x00, 96,
328 4, 19, 3, 6, 0 },
329 { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
330 29300, 0x0c, 0x00, 108,
331 4, 23, 3, 7, 0 },
332 },
333 50, /* probe interval */
334 50, /* rssi reduce interval */
335 0, /* Phy rates allowed initially */
336};
337
338static struct ath_rate_table ar5416_11g_ratetable = {
339 12,
340 {
341 { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
342 900, 0x1b, 0x00, 2,
343 0, 0, 1, 0, 0 },
344 { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
345 1900, 0x1a, 0x04, 4,
346 1, 1, 1, 1, 0 },
347 { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
348 4900, 0x19, 0x04, 11,
349 2, 2, 2, 2, 0 },
350 { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
351 8100, 0x18, 0x04, 22,
352 3, 3, 2, 3, 0 },
353 { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
354 5400, 0x0b, 0x00, 12,
355 4, 2, 1, 4, 0 },
356 { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
357 7800, 0x0f, 0x00, 18,
358 4, 3, 1, 5, 0 },
359 { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
360 10000, 0x0a, 0x00, 24,
361 6, 4, 1, 6, 0 },
362 { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
363 13900, 0x0e, 0x00, 36,
364 6, 6, 2, 7, 0 },
365 { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
366 17300, 0x09, 0x00, 48,
367 8, 10, 3, 8, 0 },
368 { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
369 23000, 0x0d, 0x00, 72,
370 8, 14, 3, 9, 0 },
371 { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
372 27400, 0x08, 0x00, 96,
373 8, 19, 3, 10, 0 },
374 { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
375 29300, 0x0c, 0x00, 108,
376 8, 23, 3, 11, 0 },
377 },
378 50, /* probe interval */
379 50, /* rssi reduce interval */
380 0, /* Phy rates allowed initially */
381};
382
383static struct ath_rate_table ar5416_11b_ratetable = {
384 4,
385 {
386 { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
387 900, 0x1b, 0x00, (0x80|2),
388 0, 0, 1, 0, 0 },
389 { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
390 1800, 0x1a, 0x04, (0x80|4),
391 1, 1, 1, 1, 0 },
392 { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
393 4300, 0x19, 0x04, (0x80|11),
394 1, 2, 2, 2, 0 },
395 { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
396 7100, 0x18, 0x04, (0x80|22),
397 1, 4, 100, 3, 0 },
398 },
399 100, /* probe interval */
400 100, /* rssi reduce interval */
401 0, /* Phy rates allowed initially */
402};
403
404static inline int8_t median(int8_t a, int8_t b, int8_t c)
405{
406 if (a >= b) {
407 if (b >= c)
408 return b;
409 else if (a > c)
410 return c;
411 else
412 return a;
413 } else {
414 if (a >= c)
415 return a;
416 else if (b >= c)
417 return c;
418 else
419 return b;
420 }
421}
422
423static void ath_rc_sort_validrates(struct ath_rate_table *rate_table,
424 struct ath_rate_priv *ath_rc_priv)
425{
426 u8 i, j, idx, idx_next;
427
428 for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) {
429 for (j = 0; j <= i-1; j++) {
430 idx = ath_rc_priv->valid_rate_index[j];
431 idx_next = ath_rc_priv->valid_rate_index[j+1];
432
433 if (rate_table->info[idx].ratekbps >
434 rate_table->info[idx_next].ratekbps) {
435 ath_rc_priv->valid_rate_index[j] = idx_next;
436 ath_rc_priv->valid_rate_index[j+1] = idx;
437 }
438 }
439 }
440}
441
442static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv)
443{
444 u8 i;
445
446 for (i = 0; i < ath_rc_priv->rate_table_size; i++)
447 ath_rc_priv->valid_rate_index[i] = 0;
448}
449
450static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv,
451 u8 index, int valid_tx_rate)
452{
453 ASSERT(index <= ath_rc_priv->rate_table_size);
454 ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0;
455}
456
457static inline int ath_rc_isvalid_txmask(struct ath_rate_priv *ath_rc_priv,
458 u8 index)
459{
460 ASSERT(index <= ath_rc_priv->rate_table_size);
461 return ath_rc_priv->valid_rate_index[index];
462}
463
464static inline int ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table,
465 struct ath_rate_priv *ath_rc_priv,
466 u8 cur_valid_txrate,
467 u8 *next_idx)
468{
469 u8 i;
470
471 for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) {
472 if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
473 *next_idx = ath_rc_priv->valid_rate_index[i+1];
474 return 1;
475 }
476 }
477
478 /* No more valid rates */
479 *next_idx = 0;
480
481 return 0;
482}
483
484/* Return true only for single stream */
485
486static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
487{
488 if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG))
489 return 0;
490 if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
491 return 0;
492 if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG))
493 return 0;
494 if (!ignore_cw && WLAN_RC_PHY_HT(phy))
495 if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG))
496 return 0;
497 if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG))
498 return 0;
499 return 1;
500}
501
502static inline int
503ath_rc_get_nextlowervalid_txrate(struct ath_rate_table *rate_table,
504 struct ath_rate_priv *ath_rc_priv,
505 u8 cur_valid_txrate, u8 *next_idx)
506{
507 int8_t i;
508
509 for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) {
510 if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
511 *next_idx = ath_rc_priv->valid_rate_index[i-1];
512 return 1;
513 }
514 }
515
516 return 0;
517}
518
519static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv,
520 struct ath_rate_table *rate_table,
521 u32 capflag)
522{
523 u8 i, hi = 0;
524 u32 valid;
525
526 for (i = 0; i < rate_table->rate_cnt; i++) {
527 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
528 rate_table->info[i].valid_single_stream :
529 rate_table->info[i].valid);
530 if (valid == 1) {
531 u32 phy = rate_table->info[i].phy;
532 u8 valid_rate_count = 0;
533
534 if (!ath_rc_valid_phyrate(phy, capflag, 0))
535 continue;
536
537 valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy];
538
539 ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i;
540 ath_rc_priv->valid_phy_ratecnt[phy] += 1;
541 ath_rc_set_valid_txmask(ath_rc_priv, i, 1);
542 hi = A_MAX(hi, i);
543 }
544 }
545
546 return hi;
547}
548
549static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
550 struct ath_rate_table *rate_table,
551 struct ath_rateset *rateset,
552 u32 capflag)
553{
554 u8 i, j, hi = 0;
555
556 /* Use intersection of working rates and valid rates */
557 for (i = 0; i < rateset->rs_nrates; i++) {
558 for (j = 0; j < rate_table->rate_cnt; j++) {
559 u32 phy = rate_table->info[j].phy;
560 u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
561 rate_table->info[j].valid_single_stream :
562 rate_table->info[j].valid);
563 u8 rate = rateset->rs_rates[i];
564 u8 dot11rate = rate_table->info[j].dot11rate;
565
566 /* We allow a rate only if its valid and the
567 * capflag matches one of the validity
568 * (VALID/VALID_20/VALID_40) flags */
569
570 if (((rate & 0x7F) == (dot11rate & 0x7F)) &&
571 ((valid & WLAN_RC_CAP_MODE(capflag)) ==
572 WLAN_RC_CAP_MODE(capflag)) &&
573 !WLAN_RC_PHY_HT(phy)) {
574 u8 valid_rate_count = 0;
575
576 if (!ath_rc_valid_phyrate(phy, capflag, 0))
577 continue;
578
579 valid_rate_count =
580 ath_rc_priv->valid_phy_ratecnt[phy];
581
582 ath_rc_priv->valid_phy_rateidx[phy]
583 [valid_rate_count] = j;
584 ath_rc_priv->valid_phy_ratecnt[phy] += 1;
585 ath_rc_set_valid_txmask(ath_rc_priv, j, 1);
586 hi = A_MAX(hi, j);
587 }
588 }
589 }
590
591 return hi;
592}
593
594static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
595 struct ath_rate_table *rate_table,
596 u8 *mcs_set, u32 capflag)
597{
598 struct ath_rateset *rateset = (struct ath_rateset *)mcs_set;
599
600 u8 i, j, hi = 0;
601
602 /* Use intersection of working rates and valid rates */
603 for (i = 0; i < rateset->rs_nrates; i++) {
604 for (j = 0; j < rate_table->rate_cnt; j++) {
605 u32 phy = rate_table->info[j].phy;
606 u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
607 rate_table->info[j].valid_single_stream :
608 rate_table->info[j].valid);
609 u8 rate = rateset->rs_rates[i];
610 u8 dot11rate = rate_table->info[j].dot11rate;
611
612 if (((rate & 0x7F) != (dot11rate & 0x7F)) ||
613 !WLAN_RC_PHY_HT(phy) ||
614 !WLAN_RC_PHY_HT_VALID(valid, capflag))
615 continue;
616
617 if (!ath_rc_valid_phyrate(phy, capflag, 0))
618 continue;
619
620 ath_rc_priv->valid_phy_rateidx[phy]
621 [ath_rc_priv->valid_phy_ratecnt[phy]] = j;
622 ath_rc_priv->valid_phy_ratecnt[phy] += 1;
623 ath_rc_set_valid_txmask(ath_rc_priv, j, 1);
624 hi = A_MAX(hi, j);
625 }
626 }
627
628 return hi;
629}
630
631static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
632 struct ath_rate_priv *ath_rc_priv,
633 struct ath_rate_table *rate_table,
634 int *is_probing)
635{
636 u32 dt, best_thruput, this_thruput, now_msec;
637 u8 rate, next_rate, best_rate, maxindex, minindex;
638 int8_t rssi_last, rssi_reduce = 0, index = 0;
639
640 *is_probing = 0;
641
642 rssi_last = median(ath_rc_priv->rssi_last,
643 ath_rc_priv->rssi_last_prev,
644 ath_rc_priv->rssi_last_prev2);
645
646 /*
647 * Age (reduce) last ack rssi based on how old it is.
648 * The bizarre numbers are so the delta is 160msec,
649 * meaning we divide by 16.
650 * 0msec <= dt <= 25msec: don't derate
651 * 25msec <= dt <= 185msec: derate linearly from 0 to 10dB
652 * 185msec <= dt: derate by 10dB
653 */
654
655 now_msec = jiffies_to_msecs(jiffies);
656 dt = now_msec - ath_rc_priv->rssi_time;
657
658 if (dt >= 185)
659 rssi_reduce = 10;
660 else if (dt >= 25)
661 rssi_reduce = (u8)((dt - 25) >> 4);
662
663 /* Now reduce rssi_last by rssi_reduce */
664 if (rssi_last < rssi_reduce)
665 rssi_last = 0;
666 else
667 rssi_last -= rssi_reduce;
668
669 /*
670 * Now look up the rate in the rssi table and return it.
671 * If no rates match then we return 0 (lowest rate)
672 */
673
674 best_thruput = 0;
675 maxindex = ath_rc_priv->max_valid_rate-1;
676
677 minindex = 0;
678 best_rate = minindex;
679
680 /*
681 * Try the higher rate first. It will reduce memory moving time
682 * if we have very good channel characteristics.
683 */
684 for (index = maxindex; index >= minindex ; index--) {
685 u8 per_thres;
686
687 rate = ath_rc_priv->valid_rate_index[index];
688 if (rate > ath_rc_priv->rate_max_phy)
689 continue;
690
691 /*
692 * For TCP the average collision rate is around 11%,
693 * so we ignore PERs less than this. This is to
694 * prevent the rate we are currently using (whose
695 * PER might be in the 10-15 range because of TCP
696 * collisions) looking worse than the next lower
697 * rate whose PER has decayed close to 0. If we
698 * used to next lower rate, its PER would grow to
699 * 10-15 and we would be worse off then staying
700 * at the current rate.
701 */
702 per_thres = ath_rc_priv->state[rate].per;
703 if (per_thres < 12)
704 per_thres = 12;
705
706 this_thruput = rate_table->info[rate].user_ratekbps *
707 (100 - per_thres);
708
709 if (best_thruput <= this_thruput) {
710 best_thruput = this_thruput;
711 best_rate = rate;
712 }
713 }
714
715 rate = best_rate;
716 ath_rc_priv->rssi_last_lookup = rssi_last;
717
718 /*
719 * Must check the actual rate (ratekbps) to account for
720 * non-monoticity of 11g's rate table
721 */
722
723 if (rate >= ath_rc_priv->rate_max_phy) {
724 rate = ath_rc_priv->rate_max_phy;
725
726 /* Probe the next allowed phy state */
727 if (ath_rc_get_nextvalid_txrate(rate_table,
728 ath_rc_priv, rate, &next_rate) &&
729 (now_msec - ath_rc_priv->probe_time >
730 rate_table->probe_interval) &&
731 (ath_rc_priv->hw_maxretry_pktcnt >= 1)) {
732 rate = next_rate;
733 ath_rc_priv->probe_rate = rate;
734 ath_rc_priv->probe_time = now_msec;
735 ath_rc_priv->hw_maxretry_pktcnt = 0;
736 *is_probing = 1;
737 }
738 }
739
740 if (rate > (ath_rc_priv->rate_table_size - 1))
741 rate = ath_rc_priv->rate_table_size - 1;
742
743 ASSERT((rate_table->info[rate].valid &&
744 (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) ||
745 (rate_table->info[rate].valid_single_stream &&
746 !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)));
747
748 return rate;
749}
750
751static void ath_rc_rate_set_series(struct ath_rate_table *rate_table,
752 struct ieee80211_tx_rate *rate,
753 struct ieee80211_tx_rate_control *txrc,
754 u8 tries, u8 rix, int rtsctsenable)
755{
756 rate->count = tries;
757 rate->idx = rix;
758
759 if (txrc->short_preamble)
760 rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
761 if (txrc->rts || rtsctsenable)
762 rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
763 if (WLAN_RC_PHY_40(rate_table->info[rix].phy))
764 rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
765 if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy))
766 rate->flags |= IEEE80211_TX_RC_SHORT_GI;
767 if (WLAN_RC_PHY_HT(rate_table->info[rix].phy))
768 rate->flags |= IEEE80211_TX_RC_MCS;
769}
770
771static void ath_rc_rate_set_rtscts(struct ath_softc *sc,
772 struct ath_rate_table *rate_table,
773 struct ieee80211_tx_info *tx_info)
774{
775 struct ieee80211_tx_rate *rates = tx_info->control.rates;
776 int i = 0, rix = 0, cix, enable_g_protection = 0;
777
778 /* get the cix for the lowest valid rix */
779 for (i = 3; i >= 0; i--) {
780 if (rates[i].count && (rates[i].idx >= 0)) {
781 rix = rates[i].idx;
782 break;
783 }
784 }
785 cix = rate_table->info[rix].ctrl_rate;
786
787 /* All protection frames are transmited at 2Mb/s for 802.11g,
788 * otherwise we transmit them at 1Mb/s */
789 if (sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ &&
790 !conf_is_ht(&sc->hw->conf))
791 enable_g_protection = 1;
792
793 /*
794 * If 802.11g protection is enabled, determine whether to use RTS/CTS or
795 * just CTS. Note that this is only done for OFDM/HT unicast frames.
796 */
797 if ((sc->sc_flags & SC_OP_PROTECT_ENABLE) &&
798 !(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) &&
799 (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM ||
800 WLAN_RC_PHY_HT(rate_table->info[rix].phy))) {
801 rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT;
802 cix = rate_table->info[enable_g_protection].ctrl_rate;
803 }
804
805 tx_info->control.rts_cts_rate_idx = cix;
806}
807
808static u8 ath_rc_rate_getidx(struct ath_softc *sc,
809 struct ath_rate_priv *ath_rc_priv,
810 struct ath_rate_table *rate_table,
811 u8 rix, u16 stepdown,
812 u16 min_rate)
813{
814 u32 j;
815 u8 nextindex;
816
817 if (min_rate) {
818 for (j = RATE_TABLE_SIZE; j > 0; j--) {
819 if (ath_rc_get_nextlowervalid_txrate(rate_table,
820 ath_rc_priv, rix, &nextindex))
821 rix = nextindex;
822 else
823 break;
824 }
825 } else {
826 for (j = stepdown; j > 0; j--) {
827 if (ath_rc_get_nextlowervalid_txrate(rate_table,
828 ath_rc_priv, rix, &nextindex))
829 rix = nextindex;
830 else
831 break;
832 }
833 }
834 return rix;
835}
836
837static void ath_rc_ratefind(struct ath_softc *sc,
838 struct ath_rate_priv *ath_rc_priv,
839 struct ieee80211_tx_rate_control *txrc)
840{
841 struct ath_rate_table *rate_table;
842 struct sk_buff *skb = txrc->skb;
843 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
844 struct ieee80211_tx_rate *rates = tx_info->control.rates;
845 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
846 __le16 fc = hdr->frame_control;
847 u8 try_per_rate = 0, i = 0, rix, nrix;
848 int is_probe = 0;
849
850 rate_table = sc->cur_rate_table;
851 rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, &is_probe);
852 nrix = rix;
853
854 if (is_probe) {
855 /* set one try for probe rates. For the
856 * probes don't enable rts */
857 ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
858 1, nrix, 0);
859
860 try_per_rate = (ATH_11N_TXMAXTRY/4);
861 /* Get the next tried/allowed rate. No RTS for the next series
862 * after the probe rate
863 */
864 nrix = ath_rc_rate_getidx(sc, ath_rc_priv,
865 rate_table, nrix, 1, 0);
866 ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
867 try_per_rate, nrix, 0);
868
869 tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
870 } else {
871 try_per_rate = (ATH_11N_TXMAXTRY/4);
872 /* Set the choosen rate. No RTS for first series entry. */
873 ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
874 try_per_rate, nrix, 0);
875 }
876
877 /* Fill in the other rates for multirate retry */
878 for ( ; i < 4; i++) {
879 u8 try_num;
880 u8 min_rate;
881
882 try_num = ((i + 1) == 4) ?
883 ATH_11N_TXMAXTRY - (try_per_rate * i) : try_per_rate ;
884 min_rate = (((i + 1) == 4) && 0);
885
886 nrix = ath_rc_rate_getidx(sc, ath_rc_priv,
887 rate_table, nrix, 1, min_rate);
888 /* All other rates in the series have RTS enabled */
889 ath_rc_rate_set_series(rate_table, &rates[i], txrc,
890 try_num, nrix, 1);
891 }
892
893 /*
894 * NB:Change rate series to enable aggregation when operating
895 * at lower MCS rates. When first rate in series is MCS2
896 * in HT40 @ 2.4GHz, series should look like:
897 *
898 * {MCS2, MCS1, MCS0, MCS0}.
899 *
900 * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should
901 * look like:
902 *
903 * {MCS3, MCS2, MCS1, MCS1}
904 *
905 * So, set fourth rate in series to be same as third one for
906 * above conditions.
907 */
908 if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
909 (conf_is_ht(&sc->hw->conf))) {
910 u8 dot11rate = rate_table->info[rix].dot11rate;
911 u8 phy = rate_table->info[rix].phy;
912 if (i == 4 &&
913 ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
914 (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) {
915 rates[3].idx = rates[2].idx;
916 rates[3].flags = rates[2].flags;
917 }
918 }
919
920 /*
921 * Force hardware to use computed duration for next
922 * fragment by disabling multi-rate retry, which
923 * updates duration based on the multi-rate duration table.
924 *
925 * FIXME: Fix duration
926 */
927 if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) &&
928 (ieee80211_has_morefrags(fc) ||
929 (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG))) {
930 rates[1].count = rates[2].count = rates[3].count = 0;
931 rates[1].idx = rates[2].idx = rates[3].idx = 0;
932 rates[0].count = ATH_TXMAXTRY;
933 }
934
935 /* Setup RTS/CTS */
936 ath_rc_rate_set_rtscts(sc, rate_table, tx_info);
937}
938
939static bool ath_rc_update_per(struct ath_softc *sc,
940 struct ath_rate_table *rate_table,
941 struct ath_rate_priv *ath_rc_priv,
942 struct ath_tx_info_priv *tx_info_priv,
943 int tx_rate, int xretries, int retries,
944 u32 now_msec)
945{
946 bool state_change = false;
947 int count;
948 u8 last_per;
949 static u32 nretry_to_per_lookup[10] = {
950 100 * 0 / 1,
951 100 * 1 / 4,
952 100 * 1 / 2,
953 100 * 3 / 4,
954 100 * 4 / 5,
955 100 * 5 / 6,
956 100 * 6 / 7,
957 100 * 7 / 8,
958 100 * 8 / 9,
959 100 * 9 / 10
960 };
961
962 last_per = ath_rc_priv->state[tx_rate].per;
963
964 if (xretries) {
965 if (xretries == 1) {
966 ath_rc_priv->state[tx_rate].per += 30;
967 if (ath_rc_priv->state[tx_rate].per > 100)
968 ath_rc_priv->state[tx_rate].per = 100;
969 } else {
970 /* xretries == 2 */
971 count = ARRAY_SIZE(nretry_to_per_lookup);
972 if (retries >= count)
973 retries = count - 1;
974
975 /* new_PER = 7/8*old_PER + 1/8*(currentPER) */
976 ath_rc_priv->state[tx_rate].per =
977 (u8)(last_per - (last_per >> 3) + (100 >> 3));
978 }
979
980 /* xretries == 1 or 2 */
981
982 if (ath_rc_priv->probe_rate == tx_rate)
983 ath_rc_priv->probe_rate = 0;
984
985 } else { /* xretries == 0 */
986 count = ARRAY_SIZE(nretry_to_per_lookup);
987 if (retries >= count)
988 retries = count - 1;
989
990 if (tx_info_priv->n_bad_frames) {
991 /* new_PER = 7/8*old_PER + 1/8*(currentPER)
992 * Assuming that n_frames is not 0. The current PER
993 * from the retries is 100 * retries / (retries+1),
994 * since the first retries attempts failed, and the
995 * next one worked. For the one that worked,
996 * n_bad_frames subframes out of n_frames wored,
997 * so the PER for that part is
998 * 100 * n_bad_frames / n_frames, and it contributes
999 * 100 * n_bad_frames / (n_frames * (retries+1)) to
1000 * the above PER. The expression below is a
1001 * simplified version of the sum of these two terms.
1002 */
1003 if (tx_info_priv->n_frames > 0) {
1004 int n_frames, n_bad_frames;
1005 u8 cur_per, new_per;
1006
1007 n_bad_frames = retries * tx_info_priv->n_frames +
1008 tx_info_priv->n_bad_frames;
1009 n_frames = tx_info_priv->n_frames * (retries + 1);
1010 cur_per = (100 * n_bad_frames / n_frames) >> 3;
1011 new_per = (u8)(last_per - (last_per >> 3) + cur_per);
1012 ath_rc_priv->state[tx_rate].per = new_per;
1013 }
1014 } else {
1015 ath_rc_priv->state[tx_rate].per =
1016 (u8)(last_per - (last_per >> 3) +
1017 (nretry_to_per_lookup[retries] >> 3));
1018 }
1019
1020 ath_rc_priv->rssi_last_prev2 = ath_rc_priv->rssi_last_prev;
1021 ath_rc_priv->rssi_last_prev = ath_rc_priv->rssi_last;
1022 ath_rc_priv->rssi_last = tx_info_priv->tx.ts_rssi;
1023 ath_rc_priv->rssi_time = now_msec;
1024
1025 /*
1026 * If we got at most one retry then increase the max rate if
1027 * this was a probe. Otherwise, ignore the probe.
1028 */
1029 if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) {
1030 if (retries > 0 || 2 * tx_info_priv->n_bad_frames >
1031 tx_info_priv->n_frames) {
1032 /*
1033 * Since we probed with just a single attempt,
1034 * any retries means the probe failed. Also,
1035 * if the attempt worked, but more than half
1036 * the subframes were bad then also consider
1037 * the probe a failure.
1038 */
1039 ath_rc_priv->probe_rate = 0;
1040 } else {
1041 u8 probe_rate = 0;
1042
1043 ath_rc_priv->rate_max_phy =
1044 ath_rc_priv->probe_rate;
1045 probe_rate = ath_rc_priv->probe_rate;
1046
1047 if (ath_rc_priv->state[probe_rate].per > 30)
1048 ath_rc_priv->state[probe_rate].per = 20;
1049
1050 ath_rc_priv->probe_rate = 0;
1051
1052 /*
1053 * Since this probe succeeded, we allow the next
1054 * probe twice as soon. This allows the maxRate
1055 * to move up faster if the probes are
1056 * succesful.
1057 */
1058 ath_rc_priv->probe_time =
1059 now_msec - rate_table->probe_interval / 2;
1060 }
1061 }
1062
1063 if (retries > 0) {
1064 /*
1065 * Don't update anything. We don't know if
1066 * this was because of collisions or poor signal.
1067 *
1068 * Later: if rssi_ack is close to
1069 * ath_rc_priv->state[txRate].rssi_thres and we see lots
1070 * of retries, then we could increase
1071 * ath_rc_priv->state[txRate].rssi_thres.
1072 */
1073 ath_rc_priv->hw_maxretry_pktcnt = 0;
1074 } else {
1075 int32_t rssi_ackAvg;
1076 int8_t rssi_thres;
1077 int8_t rssi_ack_vmin;
1078
1079 /*
1080 * It worked with no retries. First ignore bogus (small)
1081 * rssi_ack values.
1082 */
1083 if (tx_rate == ath_rc_priv->rate_max_phy &&
1084 ath_rc_priv->hw_maxretry_pktcnt < 255) {
1085 ath_rc_priv->hw_maxretry_pktcnt++;
1086 }
1087
1088 if (tx_info_priv->tx.ts_rssi <
1089 rate_table->info[tx_rate].rssi_ack_validmin)
1090 goto exit;
1091
1092 /* Average the rssi */
1093 if (tx_rate != ath_rc_priv->rssi_sum_rate) {
1094 ath_rc_priv->rssi_sum_rate = tx_rate;
1095 ath_rc_priv->rssi_sum =
1096 ath_rc_priv->rssi_sum_cnt = 0;
1097 }
1098
1099 ath_rc_priv->rssi_sum += tx_info_priv->tx.ts_rssi;
1100 ath_rc_priv->rssi_sum_cnt++;
1101
1102 if (ath_rc_priv->rssi_sum_cnt < 4)
1103 goto exit;
1104
1105 rssi_ackAvg =
1106 (ath_rc_priv->rssi_sum + 2) / 4;
1107 rssi_thres =
1108 ath_rc_priv->state[tx_rate].rssi_thres;
1109 rssi_ack_vmin =
1110 rate_table->info[tx_rate].rssi_ack_validmin;
1111
1112 ath_rc_priv->rssi_sum =
1113 ath_rc_priv->rssi_sum_cnt = 0;
1114
1115 /* Now reduce the current rssi threshold */
1116 if ((rssi_ackAvg < rssi_thres + 2) &&
1117 (rssi_thres > rssi_ack_vmin)) {
1118 ath_rc_priv->state[tx_rate].rssi_thres--;
1119 }
1120
1121 state_change = true;
1122 }
1123 }
1124exit:
1125 return state_change;
1126}
1127
1128/* Update PER, RSSI and whatever else that the code thinks it is doing.
1129 If you can make sense of all this, you really need to go out more. */
1130
1131static void ath_rc_update_ht(struct ath_softc *sc,
1132 struct ath_rate_priv *ath_rc_priv,
1133 struct ath_tx_info_priv *tx_info_priv,
1134 int tx_rate, int xretries, int retries)
1135{
1136#define CHK_RSSI(rate) \
1137 ((ath_rc_priv->state[(rate)].rssi_thres + \
1138 rate_table->info[(rate)].rssi_ack_deltamin) > \
1139 ath_rc_priv->state[(rate)+1].rssi_thres)
1140
1141 u32 now_msec = jiffies_to_msecs(jiffies);
1142 int rate;
1143 u8 last_per;
1144 bool state_change = false;
1145 struct ath_rate_table *rate_table = sc->cur_rate_table;
1146 int size = ath_rc_priv->rate_table_size;
1147
1148 if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
1149 return;
1150
1151 /* To compensate for some imbalance between ctrl and ext. channel */
1152
1153 if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy))
1154 tx_info_priv->tx.ts_rssi =
1155 tx_info_priv->tx.ts_rssi < 3 ? 0 :
1156 tx_info_priv->tx.ts_rssi - 3;
1157
1158 last_per = ath_rc_priv->state[tx_rate].per;
1159
1160 /* Update PER first */
1161 state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv,
1162 tx_info_priv, tx_rate, xretries,
1163 retries, now_msec);
1164
1165 /*
1166 * If this rate looks bad (high PER) then stop using it for
1167 * a while (except if we are probing).
1168 */
1169 if (ath_rc_priv->state[tx_rate].per >= 55 && tx_rate > 0 &&
1170 rate_table->info[tx_rate].ratekbps <=
1171 rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) {
1172 ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv,
1173 (u8)tx_rate, &ath_rc_priv->rate_max_phy);
1174
1175 /* Don't probe for a little while. */
1176 ath_rc_priv->probe_time = now_msec;
1177 }
1178
1179 if (state_change) {
1180 /*
1181 * Make sure the rates above this have higher rssi thresholds.
1182 * (Note: Monotonicity is kept within the OFDM rates and
1183 * within the CCK rates. However, no adjustment is
1184 * made to keep the rssi thresholds monotonically
1185 * increasing between the CCK and OFDM rates.)
1186 */
1187 for (rate = tx_rate; rate < size - 1; rate++) {
1188 if (rate_table->info[rate+1].phy !=
1189 rate_table->info[tx_rate].phy)
1190 break;
1191
1192 if (CHK_RSSI(rate)) {
1193 ath_rc_priv->state[rate+1].rssi_thres =
1194 ath_rc_priv->state[rate].rssi_thres +
1195 rate_table->info[rate].rssi_ack_deltamin;
1196 }
1197 }
1198
1199 /* Make sure the rates below this have lower rssi thresholds. */
1200 for (rate = tx_rate - 1; rate >= 0; rate--) {
1201 if (rate_table->info[rate].phy !=
1202 rate_table->info[tx_rate].phy)
1203 break;
1204
1205 if (CHK_RSSI(rate)) {
1206 if (ath_rc_priv->state[rate+1].rssi_thres <
1207 rate_table->info[rate].rssi_ack_deltamin)
1208 ath_rc_priv->state[rate].rssi_thres = 0;
1209 else {
1210 ath_rc_priv->state[rate].rssi_thres =
1211 ath_rc_priv->state[rate+1].rssi_thres -
1212 rate_table->info[rate].rssi_ack_deltamin;
1213 }
1214
1215 if (ath_rc_priv->state[rate].rssi_thres <
1216 rate_table->info[rate].rssi_ack_validmin) {
1217 ath_rc_priv->state[rate].rssi_thres =
1218 rate_table->info[rate].rssi_ack_validmin;
1219 }
1220 }
1221 }
1222 }
1223
1224 /* Make sure the rates below this have lower PER */
1225 /* Monotonicity is kept only for rates below the current rate. */
1226 if (ath_rc_priv->state[tx_rate].per < last_per) {
1227 for (rate = tx_rate - 1; rate >= 0; rate--) {
1228 if (rate_table->info[rate].phy !=
1229 rate_table->info[tx_rate].phy)
1230 break;
1231
1232 if (ath_rc_priv->state[rate].per >
1233 ath_rc_priv->state[rate+1].per) {
1234 ath_rc_priv->state[rate].per =
1235 ath_rc_priv->state[rate+1].per;
1236 }
1237 }
1238 }
1239
1240 /* Maintain monotonicity for rates above the current rate */
1241 for (rate = tx_rate; rate < size - 1; rate++) {
1242 if (ath_rc_priv->state[rate+1].per <
1243 ath_rc_priv->state[rate].per)
1244 ath_rc_priv->state[rate+1].per =
1245 ath_rc_priv->state[rate].per;
1246 }
1247
1248 /* Every so often, we reduce the thresholds and
1249 * PER (different for CCK and OFDM). */
1250 if (now_msec - ath_rc_priv->rssi_down_time >=
1251 rate_table->rssi_reduce_interval) {
1252
1253 for (rate = 0; rate < size; rate++) {
1254 if (ath_rc_priv->state[rate].rssi_thres >
1255 rate_table->info[rate].rssi_ack_validmin)
1256 ath_rc_priv->state[rate].rssi_thres -= 1;
1257 }
1258 ath_rc_priv->rssi_down_time = now_msec;
1259 }
1260
1261 /* Every so often, we reduce the thresholds
1262 * and PER (different for CCK and OFDM). */
1263 if (now_msec - ath_rc_priv->per_down_time >=
1264 rate_table->rssi_reduce_interval) {
1265 for (rate = 0; rate < size; rate++) {
1266 ath_rc_priv->state[rate].per =
1267 7 * ath_rc_priv->state[rate].per / 8;
1268 }
1269
1270 ath_rc_priv->per_down_time = now_msec;
1271 }
1272
1273 ath_debug_stat_retries(sc, tx_rate, xretries, retries,
1274 ath_rc_priv->state[tx_rate].per);
1275
1276#undef CHK_RSSI
1277}
1278
1279static int ath_rc_get_rateindex(struct ath_rate_table *rate_table,
1280 struct ieee80211_tx_rate *rate)
1281{
1282 int rix;
1283
1284 if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
1285 (rate->flags & IEEE80211_TX_RC_SHORT_GI))
1286 rix = rate_table->info[rate->idx].ht_index;
1287 else if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
1288 rix = rate_table->info[rate->idx].sgi_index;
1289 else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
1290 rix = rate_table->info[rate->idx].cw40index;
1291 else
1292 rix = rate_table->info[rate->idx].base_index;
1293
1294 return rix;
1295}
1296
1297static void ath_rc_tx_status(struct ath_softc *sc,
1298 struct ath_rate_priv *ath_rc_priv,
1299 struct ieee80211_tx_info *tx_info,
1300 int final_ts_idx, int xretries, int long_retry)
1301{
1302 struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
1303 struct ath_rate_table *rate_table;
1304 struct ieee80211_tx_rate *rates = tx_info->status.rates;
1305 u8 flags;
1306 u32 i = 0, rix;
1307
1308 rate_table = sc->cur_rate_table;
1309
1310 /*
1311 * If the first rate is not the final index, there
1312 * are intermediate rate failures to be processed.
1313 */
1314 if (final_ts_idx != 0) {
1315 /* Process intermediate rates that failed.*/
1316 for (i = 0; i < final_ts_idx ; i++) {
1317 if (rates[i].count != 0 && (rates[i].idx >= 0)) {
1318 flags = rates[i].flags;
1319
1320 /* If HT40 and we have switched mode from
1321 * 40 to 20 => don't update */
1322
1323 if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
1324 !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
1325 return;
1326
1327 rix = ath_rc_get_rateindex(rate_table, &rates[i]);
1328 ath_rc_update_ht(sc, ath_rc_priv,
1329 tx_info_priv, rix,
1330 xretries ? 1 : 2,
1331 rates[i].count);
1332 }
1333 }
1334 } else {
1335 /*
1336 * Handle the special case of MIMO PS burst, where the second
1337 * aggregate is sent out with only one rate and one try.
1338 * Treating it as an excessive retry penalizes the rate
1339 * inordinately.
1340 */
1341 if (rates[0].count == 1 && xretries == 1)
1342 xretries = 2;
1343 }
1344
1345 flags = rates[i].flags;
1346
1347 /* If HT40 and we have switched mode from 40 to 20 => don't update */
1348 if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
1349 !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
1350 return;
1351
1352 rix = ath_rc_get_rateindex(rate_table, &rates[i]);
1353 ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix,
1354 xretries, long_retry);
1355}
1356
1357static struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
1358 enum ieee80211_band band,
1359 bool is_ht, bool is_cw_40)
1360{
1361 int mode = 0;
1362
1363 switch(band) {
1364 case IEEE80211_BAND_2GHZ:
1365 mode = ATH9K_MODE_11G;
1366 if (is_ht)
1367 mode = ATH9K_MODE_11NG_HT20;
1368 if (is_cw_40)
1369 mode = ATH9K_MODE_11NG_HT40PLUS;
1370 break;
1371 case IEEE80211_BAND_5GHZ:
1372 mode = ATH9K_MODE_11A;
1373 if (is_ht)
1374 mode = ATH9K_MODE_11NA_HT20;
1375 if (is_cw_40)
1376 mode = ATH9K_MODE_11NA_HT40PLUS;
1377 break;
1378 default:
1379 DPRINTF(sc, ATH_DBG_CONFIG, "Invalid band\n");
1380 return NULL;
1381 }
1382
1383 BUG_ON(mode >= ATH9K_MODE_MAX);
1384
1385 DPRINTF(sc, ATH_DBG_CONFIG, "Choosing rate table for mode: %d\n", mode);
1386 return sc->hw_rate_table[mode];
1387}
1388
1389static void ath_rc_init(struct ath_softc *sc,
1390 struct ath_rate_priv *ath_rc_priv,
1391 struct ieee80211_supported_band *sband,
1392 struct ieee80211_sta *sta,
1393 struct ath_rate_table *rate_table)
1394{
1395 struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
1396 u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;
1397 u8 i, j, k, hi = 0, hthi = 0;
1398
1399 if (!rate_table) {
1400 DPRINTF(sc, ATH_DBG_FATAL, "Rate table not initialized\n");
1401 return;
1402 }
1403
1404 /* Initial rate table size. Will change depending
1405 * on the working rate set */
1406 ath_rc_priv->rate_table_size = RATE_TABLE_SIZE;
1407
1408 /* Initialize thresholds according to the global rate table */
1409 for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) {
1410 ath_rc_priv->state[i].rssi_thres =
1411 rate_table->info[i].rssi_ack_validmin;
1412 ath_rc_priv->state[i].per = 0;
1413 }
1414
1415 /* Determine the valid rates */
1416 ath_rc_init_valid_txmask(ath_rc_priv);
1417
1418 for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
1419 for (j = 0; j < MAX_TX_RATE_PHY; j++)
1420 ath_rc_priv->valid_phy_rateidx[i][j] = 0;
1421 ath_rc_priv->valid_phy_ratecnt[i] = 0;
1422 }
1423
1424 if (!rateset->rs_nrates) {
1425 /* No working rate, just initialize valid rates */
1426 hi = ath_rc_init_validrates(ath_rc_priv, rate_table,
1427 ath_rc_priv->ht_cap);
1428 } else {
1429 /* Use intersection of working rates and valid rates */
1430 hi = ath_rc_setvalid_rates(ath_rc_priv, rate_table,
1431 rateset, ath_rc_priv->ht_cap);
1432 if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) {
1433 hthi = ath_rc_setvalid_htrates(ath_rc_priv,
1434 rate_table,
1435 ht_mcs,
1436 ath_rc_priv->ht_cap);
1437 }
1438 hi = A_MAX(hi, hthi);
1439 }
1440
1441 ath_rc_priv->rate_table_size = hi + 1;
1442 ath_rc_priv->rate_max_phy = 0;
1443 ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE);
1444
1445 for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) {
1446 for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) {
1447 ath_rc_priv->valid_rate_index[k++] =
1448 ath_rc_priv->valid_phy_rateidx[i][j];
1449 }
1450
1451 if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1)
1452 || !ath_rc_priv->valid_phy_ratecnt[i])
1453 continue;
1454
1455 ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1];
1456 }
1457 ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE);
1458 ASSERT(k <= RATE_TABLE_SIZE);
1459
1460 ath_rc_priv->max_valid_rate = k;
1461 ath_rc_sort_validrates(rate_table, ath_rc_priv);
1462 ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
1463 sc->cur_rate_table = rate_table;
1464
1465 DPRINTF(sc, ATH_DBG_CONFIG, "RC Initialized with capabilities: 0x%x\n",
1466 ath_rc_priv->ht_cap);
1467}
1468
1469static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta,
1470 bool is_cw40, bool is_sgi40)
1471{
1472 u8 caps = 0;
1473
1474 if (sta->ht_cap.ht_supported) {
1475 caps = WLAN_RC_HT_FLAG;
1476 if (sc->sc_ah->caps.tx_chainmask != 1 &&
1477 ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL)) {
1478 if (sta->ht_cap.mcs.rx_mask[1])
1479 caps |= WLAN_RC_DS_FLAG;
1480 }
1481 if (is_cw40)
1482 caps |= WLAN_RC_40_FLAG;
1483 if (is_sgi40)
1484 caps |= WLAN_RC_SGI_FLAG;
1485 }
1486
1487 return caps;
1488}
1489
1490/***********************************/
1491/* mac80211 Rate Control callbacks */
1492/***********************************/
1493
1494static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
1495 struct ieee80211_sta *sta, void *priv_sta,
1496 struct sk_buff *skb)
1497{
1498 struct ath_softc *sc = priv;
1499 struct ath_rate_priv *ath_rc_priv = priv_sta;
1500 struct ath_tx_info_priv *tx_info_priv = NULL;
1501 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1502 struct ieee80211_hdr *hdr;
1503 int final_ts_idx, tx_status = 0, is_underrun = 0;
1504 __le16 fc;
1505
1506 hdr = (struct ieee80211_hdr *)skb->data;
1507 fc = hdr->frame_control;
1508 tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
1509 final_ts_idx = tx_info_priv->tx.ts_rateindex;
1510
1511 if (!priv_sta || !ieee80211_is_data(fc) ||
1512 !tx_info_priv->update_rc)
1513 goto exit;
1514
1515 if (tx_info_priv->tx.ts_status & ATH9K_TXERR_FILT)
1516 goto exit;
1517
1518 /*
1519 * If underrun error is seen assume it as an excessive retry only
1520 * if prefetch trigger level have reached the max (0x3f for 5416)
1521 * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY
1522 * times. This affects how ratectrl updates PER for the failed rate.
1523 */
1524 if (tx_info_priv->tx.ts_flags &
1525 (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) &&
1526 ((sc->sc_ah->tx_trig_level) >= ath_rc_priv->tx_triglevel_max)) {
1527 tx_status = 1;
1528 is_underrun = 1;
1529 }
1530
1531 if ((tx_info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) ||
1532 (tx_info_priv->tx.ts_status & ATH9K_TXERR_FIFO))
1533 tx_status = 1;
1534
1535 ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status,
1536 (is_underrun) ? ATH_11N_TXMAXTRY :
1537 tx_info_priv->tx.ts_longretry);
1538
1539 /* Check if aggregation has to be enabled for this tid */
1540 if (conf_is_ht(&sc->hw->conf) &&
1541 !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
1542 if (ieee80211_is_data_qos(fc)) {
1543 u8 *qc, tid;
1544 struct ath_node *an;
1545
1546 qc = ieee80211_get_qos_ctl(hdr);
1547 tid = qc[0] & 0xf;
1548 an = (struct ath_node *)sta->drv_priv;
1549
1550 if(ath_tx_aggr_check(sc, an, tid))
1551 ieee80211_start_tx_ba_session(sc->hw, hdr->addr1, tid);
1552 }
1553 }
1554
1555 ath_debug_stat_rc(sc, skb);
1556exit:
1557 kfree(tx_info_priv);
1558}
1559
1560static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
1561 struct ieee80211_tx_rate_control *txrc)
1562{
1563 struct ieee80211_supported_band *sband = txrc->sband;
1564 struct sk_buff *skb = txrc->skb;
1565 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1566 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1567 struct ath_softc *sc = priv;
1568 struct ath_rate_priv *ath_rc_priv = priv_sta;
1569 __le16 fc = hdr->frame_control;
1570
1571 /* lowest rate for management and multicast/broadcast frames */
1572 if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
1573 !sta) {
1574 tx_info->control.rates[0].idx = rate_lowest_index(sband, sta);
1575 tx_info->control.rates[0].count =
1576 is_multicast_ether_addr(hdr->addr1) ? 1 : ATH_MGT_TXMAXTRY;
1577 return;
1578 }
1579
1580 /* Find tx rate for unicast frames */
1581 ath_rc_ratefind(sc, ath_rc_priv, txrc);
1582}
1583
1584static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
1585 struct ieee80211_sta *sta, void *priv_sta)
1586{
1587 struct ath_softc *sc = priv;
1588 struct ath_rate_priv *ath_rc_priv = priv_sta;
1589 struct ath_rate_table *rate_table = NULL;
1590 bool is_cw40, is_sgi40;
1591 int i, j = 0;
1592
1593 for (i = 0; i < sband->n_bitrates; i++) {
1594 if (sta->supp_rates[sband->band] & BIT(i)) {
1595 ath_rc_priv->neg_rates.rs_rates[j]
1596 = (sband->bitrates[i].bitrate * 2) / 10;
1597 j++;
1598 }
1599 }
1600 ath_rc_priv->neg_rates.rs_nrates = j;
1601
1602 if (sta->ht_cap.ht_supported) {
1603 for (i = 0, j = 0; i < 77; i++) {
1604 if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
1605 ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
1606 if (j == ATH_RATE_MAX)
1607 break;
1608 }
1609 ath_rc_priv->neg_ht_rates.rs_nrates = j;
1610 }
1611
1612 is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
1613 is_sgi40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40;
1614
1615 /* Choose rate table first */
1616
1617 if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) ||
1618 (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) ||
1619 (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) {
1620 rate_table = ath_choose_rate_table(sc, sband->band,
1621 sta->ht_cap.ht_supported,
1622 is_cw40);
1623 } else if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
1624 /* cur_rate_table would be set on init through config() */
1625 rate_table = sc->cur_rate_table;
1626 }
1627
1628 ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40);
1629 ath_rc_init(sc, priv_sta, sband, sta, rate_table);
1630}
1631
1632static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
1633 struct ieee80211_sta *sta, void *priv_sta,
1634 u32 changed)
1635{
1636 struct ath_softc *sc = priv;
1637 struct ath_rate_priv *ath_rc_priv = priv_sta;
1638 struct ath_rate_table *rate_table = NULL;
1639 bool oper_cw40 = false, oper_sgi40;
1640 bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ?
1641 true : false;
1642 bool local_sgi40 = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ?
1643 true : false;
1644
1645 /* FIXME: Handle AP mode later when we support CWM */
1646
1647 if (changed & IEEE80211_RC_HT_CHANGED) {
1648 if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
1649 return;
1650
1651 if (sc->hw->conf.channel_type == NL80211_CHAN_HT40MINUS ||
1652 sc->hw->conf.channel_type == NL80211_CHAN_HT40PLUS)
1653 oper_cw40 = true;
1654
1655 oper_sgi40 = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
1656 true : false;
1657
1658 if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) {
1659 rate_table = ath_choose_rate_table(sc, sband->band,
1660 sta->ht_cap.ht_supported,
1661 oper_cw40);
1662 ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta,
1663 oper_cw40, oper_sgi40);
1664 ath_rc_init(sc, priv_sta, sband, sta, rate_table);
1665
1666 DPRINTF(sc, ATH_DBG_CONFIG,
1667 "Operating HT Bandwidth changed to: %d\n",
1668 sc->hw->conf.channel_type);
1669 }
1670 }
1671}
1672
1673static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
1674{
1675 struct ath_wiphy *aphy = hw->priv;
1676 return aphy->sc;
1677}
1678
1679static void ath_rate_free(void *priv)
1680{
1681 return;
1682}
1683
1684static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
1685{
1686 struct ath_softc *sc = priv;
1687 struct ath_rate_priv *rate_priv;
1688
1689 rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp);
1690 if (!rate_priv) {
1691 DPRINTF(sc, ATH_DBG_FATAL,
1692 "Unable to allocate private rc structure\n");
1693 return NULL;
1694 }
1695
1696 rate_priv->rssi_down_time = jiffies_to_msecs(jiffies);
1697 rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max;
1698
1699 return rate_priv;
1700}
1701
1702static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
1703 void *priv_sta)
1704{
1705 struct ath_rate_priv *rate_priv = priv_sta;
1706 kfree(rate_priv);
1707}
1708
1709static struct rate_control_ops ath_rate_ops = {
1710 .module = NULL,
1711 .name = "ath9k_rate_control",
1712 .tx_status = ath_tx_status,
1713 .get_rate = ath_get_rate,
1714 .rate_init = ath_rate_init,
1715 .rate_update = ath_rate_update,
1716 .alloc = ath_rate_alloc,
1717 .free = ath_rate_free,
1718 .alloc_sta = ath_rate_alloc_sta,
1719 .free_sta = ath_rate_free_sta,
1720};
1721
1722void ath_rate_attach(struct ath_softc *sc)
1723{
1724 sc->hw_rate_table[ATH9K_MODE_11B] =
1725 &ar5416_11b_ratetable;
1726 sc->hw_rate_table[ATH9K_MODE_11A] =
1727 &ar5416_11a_ratetable;
1728 sc->hw_rate_table[ATH9K_MODE_11G] =
1729 &ar5416_11g_ratetable;
1730 sc->hw_rate_table[ATH9K_MODE_11NA_HT20] =
1731 &ar5416_11na_ratetable;
1732 sc->hw_rate_table[ATH9K_MODE_11NG_HT20] =
1733 &ar5416_11ng_ratetable;
1734 sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] =
1735 &ar5416_11na_ratetable;
1736 sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] =
1737 &ar5416_11na_ratetable;
1738 sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] =
1739 &ar5416_11ng_ratetable;
1740 sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] =
1741 &ar5416_11ng_ratetable;
1742}
1743
1744int ath_rate_control_register(void)
1745{
1746 return ieee80211_rate_control_register(&ath_rate_ops);
1747}
1748
1749void ath_rate_control_unregister(void)
1750{
1751 ieee80211_rate_control_unregister(&ath_rate_ops);
1752}
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
new file mode 100644
index 000000000000..e3abd76103fd
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -0,0 +1,216 @@
1/*
2 * Copyright (c) 2004 Sam Leffler, Errno Consulting
3 * Copyright (c) 2004 Video54 Technologies, Inc.
4 * Copyright (c) 2008-2009 Atheros Communications Inc.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#ifndef RC_H
20#define RC_H
21
22struct ath_softc;
23
24#define ATH_RATE_MAX 30
25#define RATE_TABLE_SIZE 64
26#define MAX_TX_RATE_PHY 48
27
28/* VALID_ALL - valid for 20/40/Legacy,
29 * VALID - Legacy only,
30 * VALID_20 - HT 20 only,
31 * VALID_40 - HT 40 only */
32
33#define INVALID 0x0
34#define VALID 0x1
35#define VALID_20 0x2
36#define VALID_40 0x4
37#define VALID_2040 (VALID_20|VALID_40)
38#define VALID_ALL (VALID_2040|VALID)
39
40enum {
41 WLAN_RC_PHY_OFDM,
42 WLAN_RC_PHY_CCK,
43 WLAN_RC_PHY_HT_20_SS,
44 WLAN_RC_PHY_HT_20_DS,
45 WLAN_RC_PHY_HT_40_SS,
46 WLAN_RC_PHY_HT_40_DS,
47 WLAN_RC_PHY_HT_20_SS_HGI,
48 WLAN_RC_PHY_HT_20_DS_HGI,
49 WLAN_RC_PHY_HT_40_SS_HGI,
50 WLAN_RC_PHY_HT_40_DS_HGI,
51 WLAN_RC_PHY_MAX
52};
53
54#define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \
55 || (_phy == WLAN_RC_PHY_HT_40_DS) \
56 || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
57 || (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
58#define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \
59 || (_phy == WLAN_RC_PHY_HT_40_DS) \
60 || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \
61 || (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
62#define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) \
63 || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
64 || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \
65 || (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
66
67#define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS)
68
69#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \
70 (capflag & WLAN_RC_40_FLAG) ? VALID_40 : VALID_20 : VALID))
71
72/* Return TRUE if flag supports HT20 && client supports HT20 or
73 * return TRUE if flag supports HT40 && client supports HT40.
74 * This is used becos some rates overlap between HT20/HT40.
75 */
76#define WLAN_RC_PHY_HT_VALID(flag, capflag) \
77 (((flag & VALID_20) && !(capflag & WLAN_RC_40_FLAG)) || \
78 ((flag & VALID_40) && (capflag & WLAN_RC_40_FLAG)))
79
80#define WLAN_RC_DS_FLAG (0x01)
81#define WLAN_RC_40_FLAG (0x02)
82#define WLAN_RC_SGI_FLAG (0x04)
83#define WLAN_RC_HT_FLAG (0x08)
84
85/**
86 * struct ath_rate_table - Rate Control table
87 * @valid: valid for use in rate control
88 * @valid_single_stream: valid for use in rate control for
89 * single stream operation
90 * @phy: CCK/OFDM
91 * @ratekbps: rate in Kbits per second
92 * @user_ratekbps: user rate in Kbits per second
93 * @ratecode: rate that goes into HW descriptors
94 * @short_preamble: Mask for enabling short preamble in ratecode for CCK
95 * @dot11rate: value that goes into supported
96 * rates info element of MLME
97 * @ctrl_rate: Index of next lower basic rate, used for duration computation
98 * @max_4ms_framelen: maximum frame length(bytes) for tx duration
99 * @probe_interval: interval for rate control to probe for other rates
100 * @rssi_reduce_interval: interval for rate control to reduce rssi
101 * @initial_ratemax: initial ratemax value
102 */
103struct ath_rate_table {
104 int rate_cnt;
105 struct {
106 int valid;
107 int valid_single_stream;
108 u8 phy;
109 u32 ratekbps;
110 u32 user_ratekbps;
111 u8 ratecode;
112 u8 short_preamble;
113 u8 dot11rate;
114 u8 ctrl_rate;
115 int8_t rssi_ack_validmin;
116 int8_t rssi_ack_deltamin;
117 u8 base_index;
118 u8 cw40index;
119 u8 sgi_index;
120 u8 ht_index;
121 u32 max_4ms_framelen;
122 } info[RATE_TABLE_SIZE];
123 u32 probe_interval;
124 u32 rssi_reduce_interval;
125 u8 initial_ratemax;
126};
127
128struct ath_tx_ratectrl_state {
129 int8_t rssi_thres; /* required rssi for this rate (dB) */
130 u8 per; /* recent estimate of packet error rate (%) */
131};
132
133struct ath_rateset {
134 u8 rs_nrates;
135 u8 rs_rates[ATH_RATE_MAX];
136};
137
138/**
139 * struct ath_rate_priv - Rate Control priv data
140 * @state: RC state
141 * @rssi_last: last ACK rssi
142 * @rssi_last_lookup: last ACK rssi used for lookup
143 * @rssi_last_prev: previous last ACK rssi
144 * @rssi_last_prev2: 2nd previous last ACK rssi
145 * @rssi_sum_cnt: count of rssi_sum for averaging
146 * @rssi_sum_rate: rate that we are averaging
147 * @rssi_sum: running sum of rssi for averaging
148 * @probe_rate: rate we are probing at
149 * @rssi_time: msec timestamp for last ack rssi
150 * @rssi_down_time: msec timestamp for last down step
151 * @probe_time: msec timestamp for last probe
152 * @hw_maxretry_pktcnt: num of packets since we got HW max retry error
153 * @max_valid_rate: maximum number of valid rate
154 * @per_down_time: msec timestamp for last PER down step
155 * @valid_phy_ratecnt: valid rate count
156 * @rate_max_phy: phy index for the max rate
157 * @probe_interval: interval for ratectrl to probe for other rates
158 * @prev_data_rix: rate idx of last data frame
159 * @ht_cap: HT capabilities
160 * @neg_rates: Negotatied rates
161 * @neg_ht_rates: Negotiated HT rates
162 */
163struct ath_rate_priv {
164 int8_t rssi_last;
165 int8_t rssi_last_lookup;
166 int8_t rssi_last_prev;
167 int8_t rssi_last_prev2;
168 int32_t rssi_sum_cnt;
169 int32_t rssi_sum_rate;
170 int32_t rssi_sum;
171 u8 rate_table_size;
172 u8 probe_rate;
173 u8 hw_maxretry_pktcnt;
174 u8 max_valid_rate;
175 u8 valid_rate_index[RATE_TABLE_SIZE];
176 u8 ht_cap;
177 u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
178 u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE];
179 u8 rate_max_phy;
180 u32 rssi_time;
181 u32 rssi_down_time;
182 u32 probe_time;
183 u32 per_down_time;
184 u32 probe_interval;
185 u32 prev_data_rix;
186 u32 tx_triglevel_max;
187 struct ath_tx_ratectrl_state state[RATE_TABLE_SIZE];
188 struct ath_rateset neg_rates;
189 struct ath_rateset neg_ht_rates;
190 struct ath_rate_softc *asc;
191};
192
193enum ath9k_internal_frame_type {
194 ATH9K_NOT_INTERNAL,
195 ATH9K_INT_PAUSE,
196 ATH9K_INT_UNPAUSE
197};
198
199struct ath_tx_info_priv {
200 struct ath_wiphy *aphy;
201 struct ath_tx_status tx;
202 int n_frames;
203 int n_bad_frames;
204 bool update_rc;
205 enum ath9k_internal_frame_type frame_type;
206};
207
208#define ATH_TX_INFO_PRIV(tx_info) \
209 ((struct ath_tx_info_priv *)((tx_info)->rate_driver_data[0]))
210
211void ath_rate_attach(struct ath_softc *sc);
212u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate);
213int ath_rate_control_register(void);
214void ath_rate_control_unregister(void);
215
216#endif /* RC_H */
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
new file mode 100644
index 000000000000..b46badd21f73
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -0,0 +1,704 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "ath9k.h"
18
19static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc,
20 struct ieee80211_hdr *hdr)
21{
22 struct ieee80211_hw *hw = sc->pri_wiphy->hw;
23 int i;
24
25 spin_lock_bh(&sc->wiphy_lock);
26 for (i = 0; i < sc->num_sec_wiphy; i++) {
27 struct ath_wiphy *aphy = sc->sec_wiphy[i];
28 if (aphy == NULL)
29 continue;
30 if (compare_ether_addr(hdr->addr1, aphy->hw->wiphy->perm_addr)
31 == 0) {
32 hw = aphy->hw;
33 break;
34 }
35 }
36 spin_unlock_bh(&sc->wiphy_lock);
37 return hw;
38}
39
40/*
41 * Setup and link descriptors.
42 *
43 * 11N: we can no longer afford to self link the last descriptor.
44 * MAC acknowledges BA status as long as it copies frames to host
45 * buffer (or rx fifo). This can incorrectly acknowledge packets
46 * to a sender if last desc is self-linked.
47 */
48static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
49{
50 struct ath_hw *ah = sc->sc_ah;
51 struct ath_desc *ds;
52 struct sk_buff *skb;
53
54 ATH_RXBUF_RESET(bf);
55
56 ds = bf->bf_desc;
57 ds->ds_link = 0; /* link to null */
58 ds->ds_data = bf->bf_buf_addr;
59
60 /* virtual addr of the beginning of the buffer. */
61 skb = bf->bf_mpdu;
62 ASSERT(skb != NULL);
63 ds->ds_vdata = skb->data;
64
65 /* setup rx descriptors. The rx.bufsize here tells the harware
66 * how much data it can DMA to us and that we are prepared
67 * to process */
68 ath9k_hw_setuprxdesc(ah, ds,
69 sc->rx.bufsize,
70 0);
71
72 if (sc->rx.rxlink == NULL)
73 ath9k_hw_putrxbuf(ah, bf->bf_daddr);
74 else
75 *sc->rx.rxlink = bf->bf_daddr;
76
77 sc->rx.rxlink = &ds->ds_link;
78 ath9k_hw_rxena(ah);
79}
80
81static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
82{
83 /* XXX block beacon interrupts */
84 ath9k_hw_setantenna(sc->sc_ah, antenna);
85 sc->rx.defant = antenna;
86 sc->rx.rxotherant = 0;
87}
88
89/*
90 * Extend 15-bit time stamp from rx descriptor to
91 * a full 64-bit TSF using the current h/w TSF.
92*/
93static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp)
94{
95 u64 tsf;
96
97 tsf = ath9k_hw_gettsf64(sc->sc_ah);
98 if ((tsf & 0x7fff) < rstamp)
99 tsf -= 0x8000;
100 return (tsf & ~0x7fff) | rstamp;
101}
102
103static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len, gfp_t gfp_mask)
104{
105 struct sk_buff *skb;
106 u32 off;
107
108 /*
109 * Cache-line-align. This is important (for the
110 * 5210 at least) as not doing so causes bogus data
111 * in rx'd frames.
112 */
113
114 /* Note: the kernel can allocate a value greater than
115 * what we ask it to give us. We really only need 4 KB as that
116 * is this hardware supports and in fact we need at least 3849
117 * as that is the MAX AMSDU size this hardware supports.
118 * Unfortunately this means we may get 8 KB here from the
119 * kernel... and that is actually what is observed on some
120 * systems :( */
121 skb = __dev_alloc_skb(len + sc->cachelsz - 1, gfp_mask);
122 if (skb != NULL) {
123 off = ((unsigned long) skb->data) % sc->cachelsz;
124 if (off != 0)
125 skb_reserve(skb, sc->cachelsz - off);
126 } else {
127 DPRINTF(sc, ATH_DBG_FATAL,
128 "skbuff alloc of size %u failed\n", len);
129 return NULL;
130 }
131
132 return skb;
133}
134
135/*
136 * For Decrypt or Demic errors, we only mark packet status here and always push
137 * up the frame up to let mac80211 handle the actual error case, be it no
138 * decryption key or real decryption error. This let us keep statistics there.
139 */
140static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds,
141 struct ieee80211_rx_status *rx_status, bool *decrypt_error,
142 struct ath_softc *sc)
143{
144 struct ieee80211_hdr *hdr;
145 u8 ratecode;
146 __le16 fc;
147 struct ieee80211_hw *hw;
148
149 hdr = (struct ieee80211_hdr *)skb->data;
150 fc = hdr->frame_control;
151 memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
152 hw = ath_get_virt_hw(sc, hdr);
153
154 if (ds->ds_rxstat.rs_more) {
155 /*
156 * Frame spans multiple descriptors; this cannot happen yet
157 * as we don't support jumbograms. If not in monitor mode,
158 * discard the frame. Enable this if you want to see
159 * error frames in Monitor mode.
160 */
161 if (sc->sc_ah->opmode != NL80211_IFTYPE_MONITOR)
162 goto rx_next;
163 } else if (ds->ds_rxstat.rs_status != 0) {
164 if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC)
165 rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
166 if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY)
167 goto rx_next;
168
169 if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) {
170 *decrypt_error = true;
171 } else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) {
172 if (ieee80211_is_ctl(fc))
173 /*
174 * Sometimes, we get invalid
175 * MIC failures on valid control frames.
176 * Remove these mic errors.
177 */
178 ds->ds_rxstat.rs_status &= ~ATH9K_RXERR_MIC;
179 else
180 rx_status->flag |= RX_FLAG_MMIC_ERROR;
181 }
182 /*
183 * Reject error frames with the exception of
184 * decryption and MIC failures. For monitor mode,
185 * we also ignore the CRC error.
186 */
187 if (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR) {
188 if (ds->ds_rxstat.rs_status &
189 ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
190 ATH9K_RXERR_CRC))
191 goto rx_next;
192 } else {
193 if (ds->ds_rxstat.rs_status &
194 ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
195 goto rx_next;
196 }
197 }
198 }
199
200 ratecode = ds->ds_rxstat.rs_rate;
201
202 if (ratecode & 0x80) {
203 /* HT rate */
204 rx_status->flag |= RX_FLAG_HT;
205 if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040)
206 rx_status->flag |= RX_FLAG_40MHZ;
207 if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI)
208 rx_status->flag |= RX_FLAG_SHORT_GI;
209 rx_status->rate_idx = ratecode & 0x7f;
210 } else {
211 int i = 0, cur_band, n_rates;
212
213 cur_band = hw->conf.channel->band;
214 n_rates = sc->sbands[cur_band].n_bitrates;
215
216 for (i = 0; i < n_rates; i++) {
217 if (sc->sbands[cur_band].bitrates[i].hw_value ==
218 ratecode) {
219 rx_status->rate_idx = i;
220 break;
221 }
222
223 if (sc->sbands[cur_band].bitrates[i].hw_value_short ==
224 ratecode) {
225 rx_status->rate_idx = i;
226 rx_status->flag |= RX_FLAG_SHORTPRE;
227 break;
228 }
229 }
230 }
231
232 rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
233 rx_status->band = hw->conf.channel->band;
234 rx_status->freq = hw->conf.channel->center_freq;
235 rx_status->noise = sc->ani.noise_floor;
236 rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi;
237 rx_status->antenna = ds->ds_rxstat.rs_antenna;
238
239 /* at 45 you will be able to use MCS 15 reliably. A more elaborate
240 * scheme can be used here but it requires tables of SNR/throughput for
241 * each possible mode used. */
242 rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 45;
243
244 /* rssi can be more than 45 though, anything above that
245 * should be considered at 100% */
246 if (rx_status->qual > 100)
247 rx_status->qual = 100;
248
249 rx_status->flag |= RX_FLAG_TSFT;
250
251 return 1;
252rx_next:
253 return 0;
254}
255
256static void ath_opmode_init(struct ath_softc *sc)
257{
258 struct ath_hw *ah = sc->sc_ah;
259 u32 rfilt, mfilt[2];
260
261 /* configure rx filter */
262 rfilt = ath_calcrxfilter(sc);
263 ath9k_hw_setrxfilter(ah, rfilt);
264
265 /* configure bssid mask */
266 if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
267 ath9k_hw_setbssidmask(sc);
268
269 /* configure operational mode */
270 ath9k_hw_setopmode(ah);
271
272 /* Handle any link-level address change. */
273 ath9k_hw_setmac(ah, sc->sc_ah->macaddr);
274
275 /* calculate and install multicast filter */
276 mfilt[0] = mfilt[1] = ~0;
277 ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
278}
279
280int ath_rx_init(struct ath_softc *sc, int nbufs)
281{
282 struct sk_buff *skb;
283 struct ath_buf *bf;
284 int error = 0;
285
286 spin_lock_init(&sc->rx.rxflushlock);
287 sc->sc_flags &= ~SC_OP_RXFLUSH;
288 spin_lock_init(&sc->rx.rxbuflock);
289
290 sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
291 min(sc->cachelsz, (u16)64));
292
293 DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
294 sc->cachelsz, sc->rx.bufsize);
295
296 /* Initialize rx descriptors */
297
298 error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
299 "rx", nbufs, 1);
300 if (error != 0) {
301 DPRINTF(sc, ATH_DBG_FATAL,
302 "failed to allocate rx descriptors: %d\n", error);
303 goto err;
304 }
305
306 list_for_each_entry(bf, &sc->rx.rxbuf, list) {
307 skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL);
308 if (skb == NULL) {
309 error = -ENOMEM;
310 goto err;
311 }
312
313 bf->bf_mpdu = skb;
314 bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
315 sc->rx.bufsize,
316 DMA_FROM_DEVICE);
317 if (unlikely(dma_mapping_error(sc->dev,
318 bf->bf_buf_addr))) {
319 dev_kfree_skb_any(skb);
320 bf->bf_mpdu = NULL;
321 DPRINTF(sc, ATH_DBG_FATAL,
322 "dma_mapping_error() on RX init\n");
323 error = -ENOMEM;
324 goto err;
325 }
326 bf->bf_dmacontext = bf->bf_buf_addr;
327 }
328 sc->rx.rxlink = NULL;
329
330err:
331 if (error)
332 ath_rx_cleanup(sc);
333
334 return error;
335}
336
337void ath_rx_cleanup(struct ath_softc *sc)
338{
339 struct sk_buff *skb;
340 struct ath_buf *bf;
341
342 list_for_each_entry(bf, &sc->rx.rxbuf, list) {
343 skb = bf->bf_mpdu;
344 if (skb) {
345 dma_unmap_single(sc->dev, bf->bf_buf_addr,
346 sc->rx.bufsize, DMA_FROM_DEVICE);
347 dev_kfree_skb(skb);
348 }
349 }
350
351 if (sc->rx.rxdma.dd_desc_len != 0)
352 ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf);
353}
354
355/*
356 * Calculate the receive filter according to the
357 * operating mode and state:
358 *
359 * o always accept unicast, broadcast, and multicast traffic
360 * o maintain current state of phy error reception (the hal
361 * may enable phy error frames for noise immunity work)
362 * o probe request frames are accepted only when operating in
363 * hostap, adhoc, or monitor modes
364 * o enable promiscuous mode according to the interface state
365 * o accept beacons:
366 * - when operating in adhoc mode so the 802.11 layer creates
367 * node table entries for peers,
368 * - when operating in station mode for collecting rssi data when
369 * the station is otherwise quiet, or
370 * - when operating as a repeater so we see repeater-sta beacons
371 * - when scanning
372 */
373
374u32 ath_calcrxfilter(struct ath_softc *sc)
375{
376#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
377
378 u32 rfilt;
379
380 rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE)
381 | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
382 | ATH9K_RX_FILTER_MCAST;
383
384 /* If not a STA, enable processing of Probe Requests */
385 if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
386 rfilt |= ATH9K_RX_FILTER_PROBEREQ;
387
388 /*
389 * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station
390 * mode interface or when in monitor mode. AP mode does not need this
391 * since it receives all in-BSS frames anyway.
392 */
393 if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) &&
394 (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) ||
395 (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR))
396 rfilt |= ATH9K_RX_FILTER_PROM;
397
398 if (sc->rx.rxfilter & FIF_CONTROL)
399 rfilt |= ATH9K_RX_FILTER_CONTROL;
400
401 if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
402 !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC))
403 rfilt |= ATH9K_RX_FILTER_MYBEACON;
404 else
405 rfilt |= ATH9K_RX_FILTER_BEACON;
406
407 /* If in HOSTAP mode, want to enable reception of PSPOLL frames */
408 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP)
409 rfilt |= ATH9K_RX_FILTER_PSPOLL;
410
411 if (sc->sec_wiphy) {
412 /* TODO: only needed if more than one BSSID is in use in
413 * station/adhoc mode */
414 /* TODO: for older chips, may need to add ATH9K_RX_FILTER_PROM
415 */
416 rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
417 }
418
419 return rfilt;
420
421#undef RX_FILTER_PRESERVE
422}
423
424int ath_startrecv(struct ath_softc *sc)
425{
426 struct ath_hw *ah = sc->sc_ah;
427 struct ath_buf *bf, *tbf;
428
429 spin_lock_bh(&sc->rx.rxbuflock);
430 if (list_empty(&sc->rx.rxbuf))
431 goto start_recv;
432
433 sc->rx.rxlink = NULL;
434 list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
435 ath_rx_buf_link(sc, bf);
436 }
437
438 /* We could have deleted elements so the list may be empty now */
439 if (list_empty(&sc->rx.rxbuf))
440 goto start_recv;
441
442 bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
443 ath9k_hw_putrxbuf(ah, bf->bf_daddr);
444 ath9k_hw_rxena(ah);
445
446start_recv:
447 spin_unlock_bh(&sc->rx.rxbuflock);
448 ath_opmode_init(sc);
449 ath9k_hw_startpcureceive(ah);
450
451 return 0;
452}
453
454bool ath_stoprecv(struct ath_softc *sc)
455{
456 struct ath_hw *ah = sc->sc_ah;
457 bool stopped;
458
459 ath9k_hw_stoppcurecv(ah);
460 ath9k_hw_setrxfilter(ah, 0);
461 stopped = ath9k_hw_stopdmarecv(ah);
462 sc->rx.rxlink = NULL;
463
464 return stopped;
465}
466
467void ath_flushrecv(struct ath_softc *sc)
468{
469 spin_lock_bh(&sc->rx.rxflushlock);
470 sc->sc_flags |= SC_OP_RXFLUSH;
471 ath_rx_tasklet(sc, 1);
472 sc->sc_flags &= ~SC_OP_RXFLUSH;
473 spin_unlock_bh(&sc->rx.rxflushlock);
474}
475
476int ath_rx_tasklet(struct ath_softc *sc, int flush)
477{
478#define PA2DESC(_sc, _pa) \
479 ((struct ath_desc *)((caddr_t)(_sc)->rx.rxdma.dd_desc + \
480 ((_pa) - (_sc)->rx.rxdma.dd_desc_paddr)))
481
482 struct ath_buf *bf;
483 struct ath_desc *ds;
484 struct sk_buff *skb = NULL, *requeue_skb;
485 struct ieee80211_rx_status rx_status;
486 struct ath_hw *ah = sc->sc_ah;
487 struct ieee80211_hdr *hdr;
488 int hdrlen, padsize, retval;
489 bool decrypt_error = false;
490 u8 keyix;
491 __le16 fc;
492
493 spin_lock_bh(&sc->rx.rxbuflock);
494
495 do {
496 /* If handling rx interrupt and flush is in progress => exit */
497 if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0))
498 break;
499
500 if (list_empty(&sc->rx.rxbuf)) {
501 sc->rx.rxlink = NULL;
502 break;
503 }
504
505 bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
506 ds = bf->bf_desc;
507
508 /*
509 * Must provide the virtual address of the current
510 * descriptor, the physical address, and the virtual
511 * address of the next descriptor in the h/w chain.
512 * This allows the HAL to look ahead to see if the
513 * hardware is done with a descriptor by checking the
514 * done bit in the following descriptor and the address
515 * of the current descriptor the DMA engine is working
516 * on. All this is necessary because of our use of
517 * a self-linked list to avoid rx overruns.
518 */
519 retval = ath9k_hw_rxprocdesc(ah, ds,
520 bf->bf_daddr,
521 PA2DESC(sc, ds->ds_link),
522 0);
523 if (retval == -EINPROGRESS) {
524 struct ath_buf *tbf;
525 struct ath_desc *tds;
526
527 if (list_is_last(&bf->list, &sc->rx.rxbuf)) {
528 sc->rx.rxlink = NULL;
529 break;
530 }
531
532 tbf = list_entry(bf->list.next, struct ath_buf, list);
533
534 /*
535 * On some hardware the descriptor status words could
536 * get corrupted, including the done bit. Because of
537 * this, check if the next descriptor's done bit is
538 * set or not.
539 *
540 * If the next descriptor's done bit is set, the current
541 * descriptor has been corrupted. Force s/w to discard
542 * this descriptor and continue...
543 */
544
545 tds = tbf->bf_desc;
546 retval = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr,
547 PA2DESC(sc, tds->ds_link), 0);
548 if (retval == -EINPROGRESS) {
549 break;
550 }
551 }
552
553 skb = bf->bf_mpdu;
554 if (!skb)
555 continue;
556
557 /*
558 * Synchronize the DMA transfer with CPU before
559 * 1. accessing the frame
560 * 2. requeueing the same buffer to h/w
561 */
562 dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
563 sc->rx.bufsize,
564 DMA_FROM_DEVICE);
565
566 /*
567 * If we're asked to flush receive queue, directly
568 * chain it back at the queue without processing it.
569 */
570 if (flush)
571 goto requeue;
572
573 if (!ds->ds_rxstat.rs_datalen)
574 goto requeue;
575
576 /* The status portion of the descriptor could get corrupted. */
577 if (sc->rx.bufsize < ds->ds_rxstat.rs_datalen)
578 goto requeue;
579
580 if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc))
581 goto requeue;
582
583 /* Ensure we always have an skb to requeue once we are done
584 * processing the current buffer's skb */
585 requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_ATOMIC);
586
587 /* If there is no memory we ignore the current RX'd frame,
588 * tell hardware it can give us a new frame using the old
589 * skb and put it at the tail of the sc->rx.rxbuf list for
590 * processing. */
591 if (!requeue_skb)
592 goto requeue;
593
594 /* Unmap the frame */
595 dma_unmap_single(sc->dev, bf->bf_buf_addr,
596 sc->rx.bufsize,
597 DMA_FROM_DEVICE);
598
599 skb_put(skb, ds->ds_rxstat.rs_datalen);
600 skb->protocol = cpu_to_be16(ETH_P_CONTROL);
601
602 /* see if any padding is done by the hw and remove it */
603 hdr = (struct ieee80211_hdr *)skb->data;
604 hdrlen = ieee80211_get_hdrlen_from_skb(skb);
605 fc = hdr->frame_control;
606
607 /* The MAC header is padded to have 32-bit boundary if the
608 * packet payload is non-zero. The general calculation for
609 * padsize would take into account odd header lengths:
610 * padsize = (4 - hdrlen % 4) % 4; However, since only
611 * even-length headers are used, padding can only be 0 or 2
612 * bytes and we can optimize this a bit. In addition, we must
613 * not try to remove padding from short control frames that do
614 * not have payload. */
615 padsize = hdrlen & 3;
616 if (padsize && hdrlen >= 24) {
617 memmove(skb->data + padsize, skb->data, hdrlen);
618 skb_pull(skb, padsize);
619 }
620
621 keyix = ds->ds_rxstat.rs_keyix;
622
623 if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
624 rx_status.flag |= RX_FLAG_DECRYPTED;
625 } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED)
626 && !decrypt_error && skb->len >= hdrlen + 4) {
627 keyix = skb->data[hdrlen + 3] >> 6;
628
629 if (test_bit(keyix, sc->keymap))
630 rx_status.flag |= RX_FLAG_DECRYPTED;
631 }
632 if (ah->sw_mgmt_crypto &&
633 (rx_status.flag & RX_FLAG_DECRYPTED) &&
634 ieee80211_is_mgmt(hdr->frame_control)) {
635 /* Use software decrypt for management frames. */
636 rx_status.flag &= ~RX_FLAG_DECRYPTED;
637 }
638
639 /* Send the frame to mac80211 */
640 if (hdr->addr1[5] & 0x01) {
641 int i;
642 /*
643 * Deliver broadcast/multicast frames to all suitable
644 * virtual wiphys.
645 */
646 /* TODO: filter based on channel configuration */
647 for (i = 0; i < sc->num_sec_wiphy; i++) {
648 struct ath_wiphy *aphy = sc->sec_wiphy[i];
649 struct sk_buff *nskb;
650 if (aphy == NULL)
651 continue;
652 nskb = skb_copy(skb, GFP_ATOMIC);
653 if (nskb)
654 __ieee80211_rx(aphy->hw, nskb,
655 &rx_status);
656 }
657 __ieee80211_rx(sc->hw, skb, &rx_status);
658 } else {
659 /* Deliver unicast frames based on receiver address */
660 __ieee80211_rx(ath_get_virt_hw(sc, hdr), skb,
661 &rx_status);
662 }
663
664 /* We will now give hardware our shiny new allocated skb */
665 bf->bf_mpdu = requeue_skb;
666 bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
667 sc->rx.bufsize,
668 DMA_FROM_DEVICE);
669 if (unlikely(dma_mapping_error(sc->dev,
670 bf->bf_buf_addr))) {
671 dev_kfree_skb_any(requeue_skb);
672 bf->bf_mpdu = NULL;
673 DPRINTF(sc, ATH_DBG_FATAL,
674 "dma_mapping_error() on RX\n");
675 break;
676 }
677 bf->bf_dmacontext = bf->bf_buf_addr;
678
679 /*
680 * change the default rx antenna if rx diversity chooses the
681 * other antenna 3 times in a row.
682 */
683 if (sc->rx.defant != ds->ds_rxstat.rs_antenna) {
684 if (++sc->rx.rxotherant >= 3)
685 ath_setdefantenna(sc, ds->ds_rxstat.rs_antenna);
686 } else {
687 sc->rx.rxotherant = 0;
688 }
689
690 if (ieee80211_is_beacon(fc) &&
691 (sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) {
692 sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON;
693 ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
694 }
695requeue:
696 list_move_tail(&bf->list, &sc->rx.rxbuf);
697 ath_rx_buf_link(sc, bf);
698 } while (1);
699
700 spin_unlock_bh(&sc->rx.rxbuflock);
701
702 return 0;
703#undef PA2DESC
704}
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
new file mode 100644
index 000000000000..52605246679f
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -0,0 +1,1511 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef REG_H
18#define REG_H
19
20#define AR_CR 0x0008
21#define AR_CR_RXE 0x00000004
22#define AR_CR_RXD 0x00000020
23#define AR_CR_SWI 0x00000040
24
25#define AR_RXDP 0x000C
26
27#define AR_CFG 0x0014
28#define AR_CFG_SWTD 0x00000001
29#define AR_CFG_SWTB 0x00000002
30#define AR_CFG_SWRD 0x00000004
31#define AR_CFG_SWRB 0x00000008
32#define AR_CFG_SWRG 0x00000010
33#define AR_CFG_AP_ADHOC_INDICATION 0x00000020
34#define AR_CFG_PHOK 0x00000100
35#define AR_CFG_CLK_GATE_DIS 0x00000400
36#define AR_CFG_EEBS 0x00000200
37#define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000
38#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17
39
40#define AR_MIRT 0x0020
41#define AR_MIRT_VAL 0x0000ffff
42#define AR_MIRT_VAL_S 16
43
44#define AR_IER 0x0024
45#define AR_IER_ENABLE 0x00000001
46#define AR_IER_DISABLE 0x00000000
47
48#define AR_TIMT 0x0028
49#define AR_TIMT_LAST 0x0000ffff
50#define AR_TIMT_LAST_S 0
51#define AR_TIMT_FIRST 0xffff0000
52#define AR_TIMT_FIRST_S 16
53
54#define AR_RIMT 0x002C
55#define AR_RIMT_LAST 0x0000ffff
56#define AR_RIMT_LAST_S 0
57#define AR_RIMT_FIRST 0xffff0000
58#define AR_RIMT_FIRST_S 16
59
60#define AR_DMASIZE_4B 0x00000000
61#define AR_DMASIZE_8B 0x00000001
62#define AR_DMASIZE_16B 0x00000002
63#define AR_DMASIZE_32B 0x00000003
64#define AR_DMASIZE_64B 0x00000004
65#define AR_DMASIZE_128B 0x00000005
66#define AR_DMASIZE_256B 0x00000006
67#define AR_DMASIZE_512B 0x00000007
68
69#define AR_TXCFG 0x0030
70#define AR_TXCFG_DMASZ_MASK 0x00000007
71#define AR_TXCFG_DMASZ_4B 0
72#define AR_TXCFG_DMASZ_8B 1
73#define AR_TXCFG_DMASZ_16B 2
74#define AR_TXCFG_DMASZ_32B 3
75#define AR_TXCFG_DMASZ_64B 4
76#define AR_TXCFG_DMASZ_128B 5
77#define AR_TXCFG_DMASZ_256B 6
78#define AR_TXCFG_DMASZ_512B 7
79#define AR_FTRIG 0x000003F0
80#define AR_FTRIG_S 4
81#define AR_FTRIG_IMMED 0x00000000
82#define AR_FTRIG_64B 0x00000010
83#define AR_FTRIG_128B 0x00000020
84#define AR_FTRIG_192B 0x00000030
85#define AR_FTRIG_256B 0x00000040
86#define AR_FTRIG_512B 0x00000080
87#define AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY 0x00000800
88
89#define AR_RXCFG 0x0034
90#define AR_RXCFG_CHIRP 0x00000008
91#define AR_RXCFG_ZLFDMA 0x00000010
92#define AR_RXCFG_DMASZ_MASK 0x00000007
93#define AR_RXCFG_DMASZ_4B 0
94#define AR_RXCFG_DMASZ_8B 1
95#define AR_RXCFG_DMASZ_16B 2
96#define AR_RXCFG_DMASZ_32B 3
97#define AR_RXCFG_DMASZ_64B 4
98#define AR_RXCFG_DMASZ_128B 5
99#define AR_RXCFG_DMASZ_256B 6
100#define AR_RXCFG_DMASZ_512B 7
101
102#define AR_MIBC 0x0040
103#define AR_MIBC_COW 0x00000001
104#define AR_MIBC_FMC 0x00000002
105#define AR_MIBC_CMC 0x00000004
106#define AR_MIBC_MCS 0x00000008
107
108#define AR_TOPS 0x0044
109#define AR_TOPS_MASK 0x0000FFFF
110
111#define AR_RXNPTO 0x0048
112#define AR_RXNPTO_MASK 0x000003FF
113
114#define AR_TXNPTO 0x004C
115#define AR_TXNPTO_MASK 0x000003FF
116#define AR_TXNPTO_QCU_MASK 0x000FFC00
117
118#define AR_RPGTO 0x0050
119#define AR_RPGTO_MASK 0x000003FF
120
121#define AR_RPCNT 0x0054
122#define AR_RPCNT_MASK 0x0000001F
123
124#define AR_MACMISC 0x0058
125#define AR_MACMISC_PCI_EXT_FORCE 0x00000010
126#define AR_MACMISC_DMA_OBS 0x000001E0
127#define AR_MACMISC_DMA_OBS_S 5
128#define AR_MACMISC_DMA_OBS_LINE_0 0
129#define AR_MACMISC_DMA_OBS_LINE_1 1
130#define AR_MACMISC_DMA_OBS_LINE_2 2
131#define AR_MACMISC_DMA_OBS_LINE_3 3
132#define AR_MACMISC_DMA_OBS_LINE_4 4
133#define AR_MACMISC_DMA_OBS_LINE_5 5
134#define AR_MACMISC_DMA_OBS_LINE_6 6
135#define AR_MACMISC_DMA_OBS_LINE_7 7
136#define AR_MACMISC_DMA_OBS_LINE_8 8
137#define AR_MACMISC_MISC_OBS 0x00000E00
138#define AR_MACMISC_MISC_OBS_S 9
139#define AR_MACMISC_MISC_OBS_BUS_LSB 0x00007000
140#define AR_MACMISC_MISC_OBS_BUS_LSB_S 12
141#define AR_MACMISC_MISC_OBS_BUS_MSB 0x00038000
142#define AR_MACMISC_MISC_OBS_BUS_MSB_S 15
143#define AR_MACMISC_MISC_OBS_BUS_1 1
144
145#define AR_GTXTO 0x0064
146#define AR_GTXTO_TIMEOUT_COUNTER 0x0000FFFF
147#define AR_GTXTO_TIMEOUT_LIMIT 0xFFFF0000
148#define AR_GTXTO_TIMEOUT_LIMIT_S 16
149
150#define AR_GTTM 0x0068
151#define AR_GTTM_USEC 0x00000001
152#define AR_GTTM_IGNORE_IDLE 0x00000002
153#define AR_GTTM_RESET_IDLE 0x00000004
154#define AR_GTTM_CST_USEC 0x00000008
155
156#define AR_CST 0x006C
157#define AR_CST_TIMEOUT_COUNTER 0x0000FFFF
158#define AR_CST_TIMEOUT_LIMIT 0xFFFF0000
159#define AR_CST_TIMEOUT_LIMIT_S 16
160
161#define AR_ISR 0x0080
162#define AR_ISR_RXOK 0x00000001
163#define AR_ISR_RXDESC 0x00000002
164#define AR_ISR_RXERR 0x00000004
165#define AR_ISR_RXNOPKT 0x00000008
166#define AR_ISR_RXEOL 0x00000010
167#define AR_ISR_RXORN 0x00000020
168#define AR_ISR_TXOK 0x00000040
169#define AR_ISR_TXDESC 0x00000080
170#define AR_ISR_TXERR 0x00000100
171#define AR_ISR_TXNOPKT 0x00000200
172#define AR_ISR_TXEOL 0x00000400
173#define AR_ISR_TXURN 0x00000800
174#define AR_ISR_MIB 0x00001000
175#define AR_ISR_SWI 0x00002000
176#define AR_ISR_RXPHY 0x00004000
177#define AR_ISR_RXKCM 0x00008000
178#define AR_ISR_SWBA 0x00010000
179#define AR_ISR_BRSSI 0x00020000
180#define AR_ISR_BMISS 0x00040000
181#define AR_ISR_BNR 0x00100000
182#define AR_ISR_RXCHIRP 0x00200000
183#define AR_ISR_BCNMISC 0x00800000
184#define AR_ISR_TIM 0x00800000
185#define AR_ISR_QCBROVF 0x02000000
186#define AR_ISR_QCBRURN 0x04000000
187#define AR_ISR_QTRIG 0x08000000
188#define AR_ISR_GENTMR 0x10000000
189
190#define AR_ISR_TXMINTR 0x00080000
191#define AR_ISR_RXMINTR 0x01000000
192#define AR_ISR_TXINTM 0x40000000
193#define AR_ISR_RXINTM 0x80000000
194
195#define AR_ISR_S0 0x0084
196#define AR_ISR_S0_QCU_TXOK 0x000003FF
197#define AR_ISR_S0_QCU_TXOK_S 0
198#define AR_ISR_S0_QCU_TXDESC 0x03FF0000
199#define AR_ISR_S0_QCU_TXDESC_S 16
200
201#define AR_ISR_S1 0x0088
202#define AR_ISR_S1_QCU_TXERR 0x000003FF
203#define AR_ISR_S1_QCU_TXERR_S 0
204#define AR_ISR_S1_QCU_TXEOL 0x03FF0000
205#define AR_ISR_S1_QCU_TXEOL_S 16
206
207#define AR_ISR_S2 0x008c
208#define AR_ISR_S2_QCU_TXURN 0x000003FF
209#define AR_ISR_S2_CST 0x00400000
210#define AR_ISR_S2_GTT 0x00800000
211#define AR_ISR_S2_TIM 0x01000000
212#define AR_ISR_S2_CABEND 0x02000000
213#define AR_ISR_S2_DTIMSYNC 0x04000000
214#define AR_ISR_S2_BCNTO 0x08000000
215#define AR_ISR_S2_CABTO 0x10000000
216#define AR_ISR_S2_DTIM 0x20000000
217#define AR_ISR_S2_TSFOOR 0x40000000
218#define AR_ISR_S2_TBTT_TIME 0x80000000
219
220#define AR_ISR_S3 0x0090
221#define AR_ISR_S3_QCU_QCBROVF 0x000003FF
222#define AR_ISR_S3_QCU_QCBRURN 0x03FF0000
223
224#define AR_ISR_S4 0x0094
225#define AR_ISR_S4_QCU_QTRIG 0x000003FF
226#define AR_ISR_S4_RESV0 0xFFFFFC00
227
228#define AR_ISR_S5 0x0098
229#define AR_ISR_S5_TIMER_TRIG 0x000000FF
230#define AR_ISR_S5_TIMER_THRESH 0x0007FE00
231#define AR_ISR_S5_TIM_TIMER 0x00000010
232#define AR_ISR_S5_DTIM_TIMER 0x00000020
233#define AR_ISR_S5_S 0x00d8
234#define AR_IMR_S5 0x00b8
235#define AR_IMR_S5_TIM_TIMER 0x00000010
236#define AR_IMR_S5_DTIM_TIMER 0x00000020
237
238
239#define AR_IMR 0x00a0
240#define AR_IMR_RXOK 0x00000001
241#define AR_IMR_RXDESC 0x00000002
242#define AR_IMR_RXERR 0x00000004
243#define AR_IMR_RXNOPKT 0x00000008
244#define AR_IMR_RXEOL 0x00000010
245#define AR_IMR_RXORN 0x00000020
246#define AR_IMR_TXOK 0x00000040
247#define AR_IMR_TXDESC 0x00000080
248#define AR_IMR_TXERR 0x00000100
249#define AR_IMR_TXNOPKT 0x00000200
250#define AR_IMR_TXEOL 0x00000400
251#define AR_IMR_TXURN 0x00000800
252#define AR_IMR_MIB 0x00001000
253#define AR_IMR_SWI 0x00002000
254#define AR_IMR_RXPHY 0x00004000
255#define AR_IMR_RXKCM 0x00008000
256#define AR_IMR_SWBA 0x00010000
257#define AR_IMR_BRSSI 0x00020000
258#define AR_IMR_BMISS 0x00040000
259#define AR_IMR_BNR 0x00100000
260#define AR_IMR_RXCHIRP 0x00200000
261#define AR_IMR_BCNMISC 0x00800000
262#define AR_IMR_TIM 0x00800000
263#define AR_IMR_QCBROVF 0x02000000
264#define AR_IMR_QCBRURN 0x04000000
265#define AR_IMR_QTRIG 0x08000000
266#define AR_IMR_GENTMR 0x10000000
267
268#define AR_IMR_TXMINTR 0x00080000
269#define AR_IMR_RXMINTR 0x01000000
270#define AR_IMR_TXINTM 0x40000000
271#define AR_IMR_RXINTM 0x80000000
272
273#define AR_IMR_S0 0x00a4
274#define AR_IMR_S0_QCU_TXOK 0x000003FF
275#define AR_IMR_S0_QCU_TXOK_S 0
276#define AR_IMR_S0_QCU_TXDESC 0x03FF0000
277#define AR_IMR_S0_QCU_TXDESC_S 16
278
279#define AR_IMR_S1 0x00a8
280#define AR_IMR_S1_QCU_TXERR 0x000003FF
281#define AR_IMR_S1_QCU_TXERR_S 0
282#define AR_IMR_S1_QCU_TXEOL 0x03FF0000
283#define AR_IMR_S1_QCU_TXEOL_S 16
284
285#define AR_IMR_S2 0x00ac
286#define AR_IMR_S2_QCU_TXURN 0x000003FF
287#define AR_IMR_S2_QCU_TXURN_S 0
288#define AR_IMR_S2_CST 0x00400000
289#define AR_IMR_S2_GTT 0x00800000
290#define AR_IMR_S2_TIM 0x01000000
291#define AR_IMR_S2_CABEND 0x02000000
292#define AR_IMR_S2_DTIMSYNC 0x04000000
293#define AR_IMR_S2_BCNTO 0x08000000
294#define AR_IMR_S2_CABTO 0x10000000
295#define AR_IMR_S2_DTIM 0x20000000
296#define AR_IMR_S2_TSFOOR 0x40000000
297
298#define AR_IMR_S3 0x00b0
299#define AR_IMR_S3_QCU_QCBROVF 0x000003FF
300#define AR_IMR_S3_QCU_QCBRURN 0x03FF0000
301#define AR_IMR_S3_QCU_QCBRURN_S 16
302
303#define AR_IMR_S4 0x00b4
304#define AR_IMR_S4_QCU_QTRIG 0x000003FF
305#define AR_IMR_S4_RESV0 0xFFFFFC00
306
307#define AR_IMR_S5 0x00b8
308#define AR_IMR_S5_TIMER_TRIG 0x000000FF
309#define AR_IMR_S5_TIMER_THRESH 0x0000FF00
310
311
312#define AR_ISR_RAC 0x00c0
313#define AR_ISR_S0_S 0x00c4
314#define AR_ISR_S0_QCU_TXOK 0x000003FF
315#define AR_ISR_S0_QCU_TXOK_S 0
316#define AR_ISR_S0_QCU_TXDESC 0x03FF0000
317#define AR_ISR_S0_QCU_TXDESC_S 16
318
319#define AR_ISR_S1_S 0x00c8
320#define AR_ISR_S1_QCU_TXERR 0x000003FF
321#define AR_ISR_S1_QCU_TXERR_S 0
322#define AR_ISR_S1_QCU_TXEOL 0x03FF0000
323#define AR_ISR_S1_QCU_TXEOL_S 16
324
325#define AR_ISR_S2_S 0x00cc
326#define AR_ISR_S3_S 0x00d0
327#define AR_ISR_S4_S 0x00d4
328#define AR_ISR_S5_S 0x00d8
329#define AR_DMADBG_0 0x00e0
330#define AR_DMADBG_1 0x00e4
331#define AR_DMADBG_2 0x00e8
332#define AR_DMADBG_3 0x00ec
333#define AR_DMADBG_4 0x00f0
334#define AR_DMADBG_5 0x00f4
335#define AR_DMADBG_6 0x00f8
336#define AR_DMADBG_7 0x00fc
337
338#define AR_NUM_QCU 10
339#define AR_QCU_0 0x0001
340#define AR_QCU_1 0x0002
341#define AR_QCU_2 0x0004
342#define AR_QCU_3 0x0008
343#define AR_QCU_4 0x0010
344#define AR_QCU_5 0x0020
345#define AR_QCU_6 0x0040
346#define AR_QCU_7 0x0080
347#define AR_QCU_8 0x0100
348#define AR_QCU_9 0x0200
349
350#define AR_Q0_TXDP 0x0800
351#define AR_Q1_TXDP 0x0804
352#define AR_Q2_TXDP 0x0808
353#define AR_Q3_TXDP 0x080c
354#define AR_Q4_TXDP 0x0810
355#define AR_Q5_TXDP 0x0814
356#define AR_Q6_TXDP 0x0818
357#define AR_Q7_TXDP 0x081c
358#define AR_Q8_TXDP 0x0820
359#define AR_Q9_TXDP 0x0824
360#define AR_QTXDP(_i) (AR_Q0_TXDP + ((_i)<<2))
361
362#define AR_Q_TXE 0x0840
363#define AR_Q_TXE_M 0x000003FF
364
365#define AR_Q_TXD 0x0880
366#define AR_Q_TXD_M 0x000003FF
367
368#define AR_Q0_CBRCFG 0x08c0
369#define AR_Q1_CBRCFG 0x08c4
370#define AR_Q2_CBRCFG 0x08c8
371#define AR_Q3_CBRCFG 0x08cc
372#define AR_Q4_CBRCFG 0x08d0
373#define AR_Q5_CBRCFG 0x08d4
374#define AR_Q6_CBRCFG 0x08d8
375#define AR_Q7_CBRCFG 0x08dc
376#define AR_Q8_CBRCFG 0x08e0
377#define AR_Q9_CBRCFG 0x08e4
378#define AR_QCBRCFG(_i) (AR_Q0_CBRCFG + ((_i)<<2))
379#define AR_Q_CBRCFG_INTERVAL 0x00FFFFFF
380#define AR_Q_CBRCFG_INTERVAL_S 0
381#define AR_Q_CBRCFG_OVF_THRESH 0xFF000000
382#define AR_Q_CBRCFG_OVF_THRESH_S 24
383
384#define AR_Q0_RDYTIMECFG 0x0900
385#define AR_Q1_RDYTIMECFG 0x0904
386#define AR_Q2_RDYTIMECFG 0x0908
387#define AR_Q3_RDYTIMECFG 0x090c
388#define AR_Q4_RDYTIMECFG 0x0910
389#define AR_Q5_RDYTIMECFG 0x0914
390#define AR_Q6_RDYTIMECFG 0x0918
391#define AR_Q7_RDYTIMECFG 0x091c
392#define AR_Q8_RDYTIMECFG 0x0920
393#define AR_Q9_RDYTIMECFG 0x0924
394#define AR_QRDYTIMECFG(_i) (AR_Q0_RDYTIMECFG + ((_i)<<2))
395#define AR_Q_RDYTIMECFG_DURATION 0x00FFFFFF
396#define AR_Q_RDYTIMECFG_DURATION_S 0
397#define AR_Q_RDYTIMECFG_EN 0x01000000
398
399#define AR_Q_ONESHOTARM_SC 0x0940
400#define AR_Q_ONESHOTARM_SC_M 0x000003FF
401#define AR_Q_ONESHOTARM_SC_RESV0 0xFFFFFC00
402
403#define AR_Q_ONESHOTARM_CC 0x0980
404#define AR_Q_ONESHOTARM_CC_M 0x000003FF
405#define AR_Q_ONESHOTARM_CC_RESV0 0xFFFFFC00
406
407#define AR_Q0_MISC 0x09c0
408#define AR_Q1_MISC 0x09c4
409#define AR_Q2_MISC 0x09c8
410#define AR_Q3_MISC 0x09cc
411#define AR_Q4_MISC 0x09d0
412#define AR_Q5_MISC 0x09d4
413#define AR_Q6_MISC 0x09d8
414#define AR_Q7_MISC 0x09dc
415#define AR_Q8_MISC 0x09e0
416#define AR_Q9_MISC 0x09e4
417#define AR_QMISC(_i) (AR_Q0_MISC + ((_i)<<2))
418#define AR_Q_MISC_FSP 0x0000000F
419#define AR_Q_MISC_FSP_ASAP 0
420#define AR_Q_MISC_FSP_CBR 1
421#define AR_Q_MISC_FSP_DBA_GATED 2
422#define AR_Q_MISC_FSP_TIM_GATED 3
423#define AR_Q_MISC_FSP_BEACON_SENT_GATED 4
424#define AR_Q_MISC_FSP_BEACON_RCVD_GATED 5
425#define AR_Q_MISC_ONE_SHOT_EN 0x00000010
426#define AR_Q_MISC_CBR_INCR_DIS1 0x00000020
427#define AR_Q_MISC_CBR_INCR_DIS0 0x00000040
428#define AR_Q_MISC_BEACON_USE 0x00000080
429#define AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN 0x00000100
430#define AR_Q_MISC_RDYTIME_EXP_POLICY 0x00000200
431#define AR_Q_MISC_RESET_CBR_EXP_CTR 0x00000400
432#define AR_Q_MISC_DCU_EARLY_TERM_REQ 0x00000800
433#define AR_Q_MISC_RESV0 0xFFFFF000
434
435#define AR_Q0_STS 0x0a00
436#define AR_Q1_STS 0x0a04
437#define AR_Q2_STS 0x0a08
438#define AR_Q3_STS 0x0a0c
439#define AR_Q4_STS 0x0a10
440#define AR_Q5_STS 0x0a14
441#define AR_Q6_STS 0x0a18
442#define AR_Q7_STS 0x0a1c
443#define AR_Q8_STS 0x0a20
444#define AR_Q9_STS 0x0a24
445#define AR_QSTS(_i) (AR_Q0_STS + ((_i)<<2))
446#define AR_Q_STS_PEND_FR_CNT 0x00000003
447#define AR_Q_STS_RESV0 0x000000FC
448#define AR_Q_STS_CBR_EXP_CNT 0x0000FF00
449#define AR_Q_STS_RESV1 0xFFFF0000
450
451#define AR_Q_RDYTIMESHDN 0x0a40
452#define AR_Q_RDYTIMESHDN_M 0x000003FF
453
454
455#define AR_NUM_DCU 10
456#define AR_DCU_0 0x0001
457#define AR_DCU_1 0x0002
458#define AR_DCU_2 0x0004
459#define AR_DCU_3 0x0008
460#define AR_DCU_4 0x0010
461#define AR_DCU_5 0x0020
462#define AR_DCU_6 0x0040
463#define AR_DCU_7 0x0080
464#define AR_DCU_8 0x0100
465#define AR_DCU_9 0x0200
466
467#define AR_D0_QCUMASK 0x1000
468#define AR_D1_QCUMASK 0x1004
469#define AR_D2_QCUMASK 0x1008
470#define AR_D3_QCUMASK 0x100c
471#define AR_D4_QCUMASK 0x1010
472#define AR_D5_QCUMASK 0x1014
473#define AR_D6_QCUMASK 0x1018
474#define AR_D7_QCUMASK 0x101c
475#define AR_D8_QCUMASK 0x1020
476#define AR_D9_QCUMASK 0x1024
477#define AR_DQCUMASK(_i) (AR_D0_QCUMASK + ((_i)<<2))
478#define AR_D_QCUMASK 0x000003FF
479#define AR_D_QCUMASK_RESV0 0xFFFFFC00
480
481#define AR_D_TXBLK_CMD 0x1038
482#define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i))
483
484#define AR_D0_LCL_IFS 0x1040
485#define AR_D1_LCL_IFS 0x1044
486#define AR_D2_LCL_IFS 0x1048
487#define AR_D3_LCL_IFS 0x104c
488#define AR_D4_LCL_IFS 0x1050
489#define AR_D5_LCL_IFS 0x1054
490#define AR_D6_LCL_IFS 0x1058
491#define AR_D7_LCL_IFS 0x105c
492#define AR_D8_LCL_IFS 0x1060
493#define AR_D9_LCL_IFS 0x1064
494#define AR_DLCL_IFS(_i) (AR_D0_LCL_IFS + ((_i)<<2))
495#define AR_D_LCL_IFS_CWMIN 0x000003FF
496#define AR_D_LCL_IFS_CWMIN_S 0
497#define AR_D_LCL_IFS_CWMAX 0x000FFC00
498#define AR_D_LCL_IFS_CWMAX_S 10
499#define AR_D_LCL_IFS_AIFS 0x0FF00000
500#define AR_D_LCL_IFS_AIFS_S 20
501
502#define AR_D_LCL_IFS_RESV0 0xF0000000
503
504#define AR_D0_RETRY_LIMIT 0x1080
505#define AR_D1_RETRY_LIMIT 0x1084
506#define AR_D2_RETRY_LIMIT 0x1088
507#define AR_D3_RETRY_LIMIT 0x108c
508#define AR_D4_RETRY_LIMIT 0x1090
509#define AR_D5_RETRY_LIMIT 0x1094
510#define AR_D6_RETRY_LIMIT 0x1098
511#define AR_D7_RETRY_LIMIT 0x109c
512#define AR_D8_RETRY_LIMIT 0x10a0
513#define AR_D9_RETRY_LIMIT 0x10a4
514#define AR_DRETRY_LIMIT(_i) (AR_D0_RETRY_LIMIT + ((_i)<<2))
515#define AR_D_RETRY_LIMIT_FR_SH 0x0000000F
516#define AR_D_RETRY_LIMIT_FR_SH_S 0
517#define AR_D_RETRY_LIMIT_STA_SH 0x00003F00
518#define AR_D_RETRY_LIMIT_STA_SH_S 8
519#define AR_D_RETRY_LIMIT_STA_LG 0x000FC000
520#define AR_D_RETRY_LIMIT_STA_LG_S 14
521#define AR_D_RETRY_LIMIT_RESV0 0xFFF00000
522
523#define AR_D0_CHNTIME 0x10c0
524#define AR_D1_CHNTIME 0x10c4
525#define AR_D2_CHNTIME 0x10c8
526#define AR_D3_CHNTIME 0x10cc
527#define AR_D4_CHNTIME 0x10d0
528#define AR_D5_CHNTIME 0x10d4
529#define AR_D6_CHNTIME 0x10d8
530#define AR_D7_CHNTIME 0x10dc
531#define AR_D8_CHNTIME 0x10e0
532#define AR_D9_CHNTIME 0x10e4
533#define AR_DCHNTIME(_i) (AR_D0_CHNTIME + ((_i)<<2))
534#define AR_D_CHNTIME_DUR 0x000FFFFF
535#define AR_D_CHNTIME_DUR_S 0
536#define AR_D_CHNTIME_EN 0x00100000
537#define AR_D_CHNTIME_RESV0 0xFFE00000
538
539#define AR_D0_MISC 0x1100
540#define AR_D1_MISC 0x1104
541#define AR_D2_MISC 0x1108
542#define AR_D3_MISC 0x110c
543#define AR_D4_MISC 0x1110
544#define AR_D5_MISC 0x1114
545#define AR_D6_MISC 0x1118
546#define AR_D7_MISC 0x111c
547#define AR_D8_MISC 0x1120
548#define AR_D9_MISC 0x1124
549#define AR_DMISC(_i) (AR_D0_MISC + ((_i)<<2))
550#define AR_D_MISC_BKOFF_THRESH 0x0000003F
551#define AR_D_MISC_RETRY_CNT_RESET_EN 0x00000040
552#define AR_D_MISC_CW_RESET_EN 0x00000080
553#define AR_D_MISC_FRAG_WAIT_EN 0x00000100
554#define AR_D_MISC_FRAG_BKOFF_EN 0x00000200
555#define AR_D_MISC_CW_BKOFF_EN 0x00001000
556#define AR_D_MISC_VIR_COL_HANDLING 0x0000C000
557#define AR_D_MISC_VIR_COL_HANDLING_S 14
558#define AR_D_MISC_VIR_COL_HANDLING_DEFAULT 0
559#define AR_D_MISC_VIR_COL_HANDLING_IGNORE 1
560#define AR_D_MISC_BEACON_USE 0x00010000
561#define AR_D_MISC_ARB_LOCKOUT_CNTRL 0x00060000
562#define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17
563#define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE 0
564#define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1
565#define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL 2
566#define AR_D_MISC_ARB_LOCKOUT_IGNORE 0x00080000
567#define AR_D_MISC_SEQ_NUM_INCR_DIS 0x00100000
568#define AR_D_MISC_POST_FR_BKOFF_DIS 0x00200000
569#define AR_D_MISC_VIT_COL_CW_BKOFF_EN 0x00400000
570#define AR_D_MISC_BLOWN_IFS_RETRY_EN 0x00800000
571#define AR_D_MISC_RESV0 0xFF000000
572
573#define AR_D_SEQNUM 0x1140
574
575#define AR_D_GBL_IFS_SIFS 0x1030
576#define AR_D_GBL_IFS_SIFS_M 0x0000FFFF
577#define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF
578
579#define AR_D_TXBLK_BASE 0x1038
580#define AR_D_TXBLK_WRITE_BITMASK 0x0000FFFF
581#define AR_D_TXBLK_WRITE_BITMASK_S 0
582#define AR_D_TXBLK_WRITE_SLICE 0x000F0000
583#define AR_D_TXBLK_WRITE_SLICE_S 16
584#define AR_D_TXBLK_WRITE_DCU 0x00F00000
585#define AR_D_TXBLK_WRITE_DCU_S 20
586#define AR_D_TXBLK_WRITE_COMMAND 0x0F000000
587#define AR_D_TXBLK_WRITE_COMMAND_S 24
588
589#define AR_D_GBL_IFS_SLOT 0x1070
590#define AR_D_GBL_IFS_SLOT_M 0x0000FFFF
591#define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000
592
593#define AR_D_GBL_IFS_EIFS 0x10b0
594#define AR_D_GBL_IFS_EIFS_M 0x0000FFFF
595#define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000
596
597#define AR_D_GBL_IFS_MISC 0x10f0
598#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007
599#define AR_D_GBL_IFS_MISC_TURBO_MODE 0x00000008
600#define AR_D_GBL_IFS_MISC_USEC_DURATION 0x000FFC00
601#define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY 0x00300000
602#define AR_D_GBL_IFS_MISC_RANDOM_LFSR_SLICE_DIS 0x01000000
603#define AR_D_GBL_IFS_MISC_SLOT_XMIT_WIND_LEN 0x06000000
604#define AR_D_GBL_IFS_MISC_FORCE_XMIT_SLOT_BOUND 0x08000000
605#define AR_D_GBL_IFS_MISC_IGNORE_BACKOFF 0x10000000
606
607#define AR_D_FPCTL 0x1230
608#define AR_D_FPCTL_DCU 0x0000000F
609#define AR_D_FPCTL_DCU_S 0
610#define AR_D_FPCTL_PREFETCH_EN 0x00000010
611#define AR_D_FPCTL_BURST_PREFETCH 0x00007FE0
612#define AR_D_FPCTL_BURST_PREFETCH_S 5
613
614#define AR_D_TXPSE 0x1270
615#define AR_D_TXPSE_CTRL 0x000003FF
616#define AR_D_TXPSE_RESV0 0x0000FC00
617#define AR_D_TXPSE_STATUS 0x00010000
618#define AR_D_TXPSE_RESV1 0xFFFE0000
619
620#define AR_D_TXSLOTMASK 0x12f0
621#define AR_D_TXSLOTMASK_NUM 0x0000000F
622
623#define AR_CFG_LED 0x1f04
624#define AR_CFG_SCLK_RATE_IND 0x00000003
625#define AR_CFG_SCLK_RATE_IND_S 0
626#define AR_CFG_SCLK_32MHZ 0x00000000
627#define AR_CFG_SCLK_4MHZ 0x00000001
628#define AR_CFG_SCLK_1MHZ 0x00000002
629#define AR_CFG_SCLK_32KHZ 0x00000003
630#define AR_CFG_LED_BLINK_SLOW 0x00000008
631#define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070
632#define AR_CFG_LED_MODE_SEL 0x00000380
633#define AR_CFG_LED_MODE_SEL_S 7
634#define AR_CFG_LED_POWER 0x00000280
635#define AR_CFG_LED_POWER_S 7
636#define AR_CFG_LED_NETWORK 0x00000300
637#define AR_CFG_LED_NETWORK_S 7
638#define AR_CFG_LED_MODE_PROP 0x0
639#define AR_CFG_LED_MODE_RPROP 0x1
640#define AR_CFG_LED_MODE_SPLIT 0x2
641#define AR_CFG_LED_MODE_RAND 0x3
642#define AR_CFG_LED_MODE_POWER_OFF 0x4
643#define AR_CFG_LED_MODE_POWER_ON 0x5
644#define AR_CFG_LED_MODE_NETWORK_OFF 0x4
645#define AR_CFG_LED_MODE_NETWORK_ON 0x6
646#define AR_CFG_LED_ASSOC_CTL 0x00000c00
647#define AR_CFG_LED_ASSOC_CTL_S 10
648#define AR_CFG_LED_ASSOC_NONE 0x0
649#define AR_CFG_LED_ASSOC_ACTIVE 0x1
650#define AR_CFG_LED_ASSOC_PENDING 0x2
651
652#define AR_CFG_LED_BLINK_SLOW 0x00000008
653#define AR_CFG_LED_BLINK_SLOW_S 3
654
655#define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070
656#define AR_CFG_LED_BLINK_THRESH_SEL_S 4
657
658#define AR_MAC_SLEEP 0x1f00
659#define AR_MAC_SLEEP_MAC_AWAKE 0x00000000
660#define AR_MAC_SLEEP_MAC_ASLEEP 0x00000001
661
662#define AR_RC 0x4000
663#define AR_RC_AHB 0x00000001
664#define AR_RC_APB 0x00000002
665#define AR_RC_HOSTIF 0x00000100
666
667#define AR_WA 0x4004
668#define AR9285_WA_DEFAULT 0x004a05cb
669#define AR9280_WA_DEFAULT 0x0040073f
670#define AR_WA_DEFAULT 0x0000073f
671
672
673#define AR_PM_STATE 0x4008
674#define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000
675
676#define AR_HOST_TIMEOUT 0x4018
677#define AR_HOST_TIMEOUT_APB_CNTR 0x0000FFFF
678#define AR_HOST_TIMEOUT_APB_CNTR_S 0
679#define AR_HOST_TIMEOUT_LCL_CNTR 0xFFFF0000
680#define AR_HOST_TIMEOUT_LCL_CNTR_S 16
681
682#define AR_EEPROM 0x401c
683#define AR_EEPROM_ABSENT 0x00000100
684#define AR_EEPROM_CORRUPT 0x00000200
685#define AR_EEPROM_PROT_MASK 0x03FFFC00
686#define AR_EEPROM_PROT_MASK_S 10
687
688#define EEPROM_PROTECT_RP_0_31 0x0001
689#define EEPROM_PROTECT_WP_0_31 0x0002
690#define EEPROM_PROTECT_RP_32_63 0x0004
691#define EEPROM_PROTECT_WP_32_63 0x0008
692#define EEPROM_PROTECT_RP_64_127 0x0010
693#define EEPROM_PROTECT_WP_64_127 0x0020
694#define EEPROM_PROTECT_RP_128_191 0x0040
695#define EEPROM_PROTECT_WP_128_191 0x0080
696#define EEPROM_PROTECT_RP_192_255 0x0100
697#define EEPROM_PROTECT_WP_192_255 0x0200
698#define EEPROM_PROTECT_RP_256_511 0x0400
699#define EEPROM_PROTECT_WP_256_511 0x0800
700#define EEPROM_PROTECT_RP_512_1023 0x1000
701#define EEPROM_PROTECT_WP_512_1023 0x2000
702#define EEPROM_PROTECT_RP_1024_2047 0x4000
703#define EEPROM_PROTECT_WP_1024_2047 0x8000
704
705#define AR_SREV \
706 ((AR_SREV_9100(ah)) ? 0x0600 : 0x4020)
707
708#define AR_SREV_ID \
709 ((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF)
710#define AR_SREV_VERSION 0x000000F0
711#define AR_SREV_VERSION_S 4
712#define AR_SREV_REVISION 0x00000007
713
714#define AR_SREV_ID2 0xFFFFFFFF
715#define AR_SREV_VERSION2 0xFFFC0000
716#define AR_SREV_VERSION2_S 18
717#define AR_SREV_TYPE2 0x0003F000
718#define AR_SREV_TYPE2_S 12
719#define AR_SREV_TYPE2_CHAIN 0x00001000
720#define AR_SREV_TYPE2_HOST_MODE 0x00002000
721#define AR_SREV_REVISION2 0x00000F00
722#define AR_SREV_REVISION2_S 8
723
724#define AR_SREV_VERSION_5416_PCI 0xD
725#define AR_SREV_VERSION_5416_PCIE 0xC
726#define AR_SREV_REVISION_5416_10 0
727#define AR_SREV_REVISION_5416_20 1
728#define AR_SREV_REVISION_5416_22 2
729#define AR_SREV_VERSION_9100 0x14
730#define AR_SREV_VERSION_9160 0x40
731#define AR_SREV_REVISION_9160_10 0
732#define AR_SREV_REVISION_9160_11 1
733#define AR_SREV_VERSION_9280 0x80
734#define AR_SREV_REVISION_9280_10 0
735#define AR_SREV_REVISION_9280_20 1
736#define AR_SREV_REVISION_9280_21 2
737#define AR_SREV_VERSION_9285 0xC0
738#define AR_SREV_REVISION_9285_10 0
739#define AR_SREV_REVISION_9285_11 1
740#define AR_SREV_REVISION_9285_12 2
741
742#define AR_SREV_5416(_ah) \
743 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
744 ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE))
745#define AR_SREV_5416_20_OR_LATER(_ah) \
746 (((AR_SREV_5416(_ah)) && \
747 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \
748 ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
749#define AR_SREV_5416_22_OR_LATER(_ah) \
750 (((AR_SREV_5416(_ah)) && \
751 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \
752 ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
753
754#define AR_SREV_9100(ah) \
755 ((ah->hw_version.macVersion) == AR_SREV_VERSION_9100)
756#define AR_SREV_9100_OR_LATER(_ah) \
757 (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
758
759#define AR_SREV_9160(_ah) \
760 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9160))
761#define AR_SREV_9160_10_OR_LATER(_ah) \
762 (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9160))
763#define AR_SREV_9160_11(_ah) \
764 (AR_SREV_9160(_ah) && \
765 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11))
766#define AR_SREV_9280(_ah) \
767 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280))
768#define AR_SREV_9280_10_OR_LATER(_ah) \
769 (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280))
770#define AR_SREV_9280_20(_ah) \
771 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \
772 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20))
773#define AR_SREV_9280_20_OR_LATER(_ah) \
774 (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9280) || \
775 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \
776 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20)))
777
778#define AR_SREV_9285(_ah) \
779 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285))
780#define AR_SREV_9285_10_OR_LATER(_ah) \
781 (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285))
782#define AR_SREV_9285_11(_ah) \
783 (AR_SREV_9285(ah) && \
784 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_11))
785#define AR_SREV_9285_11_OR_LATER(_ah) \
786 (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \
787 (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \
788 AR_SREV_REVISION_9285_11)))
789#define AR_SREV_9285_12(_ah) \
790 (AR_SREV_9285(ah) && \
791 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_12))
792#define AR_SREV_9285_12_OR_LATER(_ah) \
793 (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \
794 (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \
795 AR_SREV_REVISION_9285_12)))
796
797#define AR_RADIO_SREV_MAJOR 0xf0
798#define AR_RAD5133_SREV_MAJOR 0xc0
799#define AR_RAD2133_SREV_MAJOR 0xd0
800#define AR_RAD5122_SREV_MAJOR 0xe0
801#define AR_RAD2122_SREV_MAJOR 0xf0
802
803#define AR_AHB_MODE 0x4024
804#define AR_AHB_EXACT_WR_EN 0x00000000
805#define AR_AHB_BUF_WR_EN 0x00000001
806#define AR_AHB_EXACT_RD_EN 0x00000000
807#define AR_AHB_CACHELINE_RD_EN 0x00000002
808#define AR_AHB_PREFETCH_RD_EN 0x00000004
809#define AR_AHB_PAGE_SIZE_1K 0x00000000
810#define AR_AHB_PAGE_SIZE_2K 0x00000008
811#define AR_AHB_PAGE_SIZE_4K 0x00000010
812
813#define AR_INTR_RTC_IRQ 0x00000001
814#define AR_INTR_MAC_IRQ 0x00000002
815#define AR_INTR_EEP_PROT_ACCESS 0x00000004
816#define AR_INTR_MAC_AWAKE 0x00020000
817#define AR_INTR_MAC_ASLEEP 0x00040000
818#define AR_INTR_SPURIOUS 0xFFFFFFFF
819
820
821#define AR_INTR_SYNC_CAUSE_CLR 0x4028
822
823#define AR_INTR_SYNC_CAUSE 0x4028
824
825#define AR_INTR_SYNC_ENABLE 0x402c
826#define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000
827#define AR_INTR_SYNC_ENABLE_GPIO_S 18
828
829enum {
830 AR_INTR_SYNC_RTC_IRQ = 0x00000001,
831 AR_INTR_SYNC_MAC_IRQ = 0x00000002,
832 AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS = 0x00000004,
833 AR_INTR_SYNC_APB_TIMEOUT = 0x00000008,
834 AR_INTR_SYNC_PCI_MODE_CONFLICT = 0x00000010,
835 AR_INTR_SYNC_HOST1_FATAL = 0x00000020,
836 AR_INTR_SYNC_HOST1_PERR = 0x00000040,
837 AR_INTR_SYNC_TRCV_FIFO_PERR = 0x00000080,
838 AR_INTR_SYNC_RADM_CPL_EP = 0x00000100,
839 AR_INTR_SYNC_RADM_CPL_DLLP_ABORT = 0x00000200,
840 AR_INTR_SYNC_RADM_CPL_TLP_ABORT = 0x00000400,
841 AR_INTR_SYNC_RADM_CPL_ECRC_ERR = 0x00000800,
842 AR_INTR_SYNC_RADM_CPL_TIMEOUT = 0x00001000,
843 AR_INTR_SYNC_LOCAL_TIMEOUT = 0x00002000,
844 AR_INTR_SYNC_PM_ACCESS = 0x00004000,
845 AR_INTR_SYNC_MAC_AWAKE = 0x00008000,
846 AR_INTR_SYNC_MAC_ASLEEP = 0x00010000,
847 AR_INTR_SYNC_MAC_SLEEP_ACCESS = 0x00020000,
848 AR_INTR_SYNC_ALL = 0x0003FFFF,
849
850
851 AR_INTR_SYNC_DEFAULT = (AR_INTR_SYNC_HOST1_FATAL |
852 AR_INTR_SYNC_HOST1_PERR |
853 AR_INTR_SYNC_RADM_CPL_EP |
854 AR_INTR_SYNC_RADM_CPL_DLLP_ABORT |
855 AR_INTR_SYNC_RADM_CPL_TLP_ABORT |
856 AR_INTR_SYNC_RADM_CPL_ECRC_ERR |
857 AR_INTR_SYNC_RADM_CPL_TIMEOUT |
858 AR_INTR_SYNC_LOCAL_TIMEOUT |
859 AR_INTR_SYNC_MAC_SLEEP_ACCESS),
860
861 AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF,
862
863};
864
865#define AR_INTR_ASYNC_MASK 0x4030
866#define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000
867#define AR_INTR_ASYNC_MASK_GPIO_S 18
868
869#define AR_INTR_SYNC_MASK 0x4034
870#define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000
871#define AR_INTR_SYNC_MASK_GPIO_S 18
872
873#define AR_INTR_ASYNC_CAUSE_CLR 0x4038
874#define AR_INTR_ASYNC_CAUSE 0x4038
875
876#define AR_INTR_ASYNC_ENABLE 0x403c
877#define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000
878#define AR_INTR_ASYNC_ENABLE_GPIO_S 18
879
880#define AR_PCIE_SERDES 0x4040
881#define AR_PCIE_SERDES2 0x4044
882#define AR_PCIE_PM_CTRL 0x4014
883#define AR_PCIE_PM_CTRL_ENA 0x00080000
884
885#define AR_NUM_GPIO 14
886#define AR928X_NUM_GPIO 10
887#define AR9285_NUM_GPIO 12
888
889#define AR_GPIO_IN_OUT 0x4048
890#define AR_GPIO_IN_VAL 0x0FFFC000
891#define AR_GPIO_IN_VAL_S 14
892#define AR928X_GPIO_IN_VAL 0x000FFC00
893#define AR928X_GPIO_IN_VAL_S 10
894#define AR9285_GPIO_IN_VAL 0x00FFF000
895#define AR9285_GPIO_IN_VAL_S 12
896
897#define AR_GPIO_OE_OUT 0x404c
898#define AR_GPIO_OE_OUT_DRV 0x3
899#define AR_GPIO_OE_OUT_DRV_NO 0x0
900#define AR_GPIO_OE_OUT_DRV_LOW 0x1
901#define AR_GPIO_OE_OUT_DRV_HI 0x2
902#define AR_GPIO_OE_OUT_DRV_ALL 0x3
903
904#define AR_GPIO_INTR_POL 0x4050
905#define AR_GPIO_INTR_POL_VAL 0x00001FFF
906#define AR_GPIO_INTR_POL_VAL_S 0
907
908#define AR_GPIO_INPUT_EN_VAL 0x4054
909#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004
910#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2
911#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008
912#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_S 3
913#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_DEF 0x00000010
914#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S 4
915#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF 0x00000080
916#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7
917#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000
918#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12
919#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000
920#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15
921#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000
922#define AR_GPIO_JTAG_DISABLE 0x00020000
923
924#define AR_GPIO_INPUT_MUX1 0x4058
925#define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000
926#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16
927
928#define AR_GPIO_INPUT_MUX2 0x405c
929#define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f
930#define AR_GPIO_INPUT_MUX2_CLK25_S 0
931#define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0
932#define AR_GPIO_INPUT_MUX2_RFSILENT_S 4
933#define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00
934#define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8
935
936#define AR_GPIO_OUTPUT_MUX1 0x4060
937#define AR_GPIO_OUTPUT_MUX2 0x4064
938#define AR_GPIO_OUTPUT_MUX3 0x4068
939
940#define AR_INPUT_STATE 0x406c
941
942#define AR_EEPROM_STATUS_DATA 0x407c
943#define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff
944#define AR_EEPROM_STATUS_DATA_VAL_S 0
945#define AR_EEPROM_STATUS_DATA_BUSY 0x00010000
946#define AR_EEPROM_STATUS_DATA_BUSY_ACCESS 0x00020000
947#define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000
948#define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000
949
950#define AR_OBS 0x4080
951
952#define AR_PCIE_MSI 0x4094
953#define AR_PCIE_MSI_ENABLE 0x00000001
954
955
956#define AR_RTC_9160_PLL_DIV 0x000003ff
957#define AR_RTC_9160_PLL_DIV_S 0
958#define AR_RTC_9160_PLL_REFDIV 0x00003C00
959#define AR_RTC_9160_PLL_REFDIV_S 10
960#define AR_RTC_9160_PLL_CLKSEL 0x0000C000
961#define AR_RTC_9160_PLL_CLKSEL_S 14
962
963#define AR_RTC_BASE 0x00020000
964#define AR_RTC_RC \
965 ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0000) : 0x7000)
966#define AR_RTC_RC_M 0x00000003
967#define AR_RTC_RC_MAC_WARM 0x00000001
968#define AR_RTC_RC_MAC_COLD 0x00000002
969#define AR_RTC_RC_COLD_RESET 0x00000004
970#define AR_RTC_RC_WARM_RESET 0x00000008
971
972#define AR_RTC_PLL_CONTROL \
973 ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014)
974
975#define AR_RTC_PLL_DIV 0x0000001f
976#define AR_RTC_PLL_DIV_S 0
977#define AR_RTC_PLL_DIV2 0x00000020
978#define AR_RTC_PLL_REFDIV_5 0x000000c0
979#define AR_RTC_PLL_CLKSEL 0x00000300
980#define AR_RTC_PLL_CLKSEL_S 8
981
982#define AR_RTC_RESET \
983 ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040)
984#define AR_RTC_RESET_EN (0x00000001)
985
986#define AR_RTC_STATUS \
987 ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0044) : 0x7044)
988
989#define AR_RTC_STATUS_M \
990 ((AR_SREV_9100(ah)) ? 0x0000003f : 0x0000000f)
991
992#define AR_RTC_PM_STATUS_M 0x0000000f
993
994#define AR_RTC_STATUS_SHUTDOWN 0x00000001
995#define AR_RTC_STATUS_ON 0x00000002
996#define AR_RTC_STATUS_SLEEP 0x00000004
997#define AR_RTC_STATUS_WAKEUP 0x00000008
998
999#define AR_RTC_SLEEP_CLK \
1000 ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0048) : 0x7048)
1001#define AR_RTC_FORCE_DERIVED_CLK 0x2
1002
1003#define AR_RTC_FORCE_WAKE \
1004 ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x004c) : 0x704c)
1005#define AR_RTC_FORCE_WAKE_EN 0x00000001
1006#define AR_RTC_FORCE_WAKE_ON_INT 0x00000002
1007
1008
1009#define AR_RTC_INTR_CAUSE \
1010 ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0050) : 0x7050)
1011
1012#define AR_RTC_INTR_ENABLE \
1013 ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0054) : 0x7054)
1014
1015#define AR_RTC_INTR_MASK \
1016 ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0058) : 0x7058)
1017
1018/* RTC_DERIVED_* - only for AR9100 */
1019
1020#define AR_RTC_DERIVED_CLK (AR_RTC_BASE + 0x0038)
1021#define AR_RTC_DERIVED_CLK_PERIOD 0x0000fffe
1022#define AR_RTC_DERIVED_CLK_PERIOD_S 1
1023
1024#define AR_SEQ_MASK 0x8060
1025
1026#define AR_AN_RF2G1_CH0 0x7810
1027#define AR_AN_RF2G1_CH0_OB 0x03800000
1028#define AR_AN_RF2G1_CH0_OB_S 23
1029#define AR_AN_RF2G1_CH0_DB 0x1C000000
1030#define AR_AN_RF2G1_CH0_DB_S 26
1031
1032#define AR_AN_RF5G1_CH0 0x7818
1033#define AR_AN_RF5G1_CH0_OB5 0x00070000
1034#define AR_AN_RF5G1_CH0_OB5_S 16
1035#define AR_AN_RF5G1_CH0_DB5 0x00380000
1036#define AR_AN_RF5G1_CH0_DB5_S 19
1037
1038#define AR_AN_RF2G1_CH1 0x7834
1039#define AR_AN_RF2G1_CH1_OB 0x03800000
1040#define AR_AN_RF2G1_CH1_OB_S 23
1041#define AR_AN_RF2G1_CH1_DB 0x1C000000
1042#define AR_AN_RF2G1_CH1_DB_S 26
1043
1044#define AR_AN_RF5G1_CH1 0x783C
1045#define AR_AN_RF5G1_CH1_OB5 0x00070000
1046#define AR_AN_RF5G1_CH1_OB5_S 16
1047#define AR_AN_RF5G1_CH1_DB5 0x00380000
1048#define AR_AN_RF5G1_CH1_DB5_S 19
1049
1050#define AR_AN_TOP1 0x7890
1051#define AR_AN_TOP1_DACIPMODE 0x00040000
1052#define AR_AN_TOP1_DACIPMODE_S 18
1053
1054#define AR_AN_TOP2 0x7894
1055#define AR_AN_TOP2_XPABIAS_LVL 0xC0000000
1056#define AR_AN_TOP2_XPABIAS_LVL_S 30
1057#define AR_AN_TOP2_LOCALBIAS 0x00200000
1058#define AR_AN_TOP2_LOCALBIAS_S 21
1059#define AR_AN_TOP2_PWDCLKIND 0x00400000
1060#define AR_AN_TOP2_PWDCLKIND_S 22
1061
1062#define AR_AN_SYNTH9 0x7868
1063#define AR_AN_SYNTH9_REFDIVA 0xf8000000
1064#define AR_AN_SYNTH9_REFDIVA_S 27
1065
1066#define AR9285_AN_RF2G1 0x7820
1067#define AR9285_AN_RF2G1_ENPACAL 0x00000800
1068#define AR9285_AN_RF2G1_ENPACAL_S 11
1069#define AR9285_AN_RF2G1_PDPADRV1 0x02000000
1070#define AR9285_AN_RF2G1_PDPADRV1_S 25
1071#define AR9285_AN_RF2G1_PDPADRV2 0x01000000
1072#define AR9285_AN_RF2G1_PDPADRV2_S 24
1073#define AR9285_AN_RF2G1_PDPAOUT 0x00800000
1074#define AR9285_AN_RF2G1_PDPAOUT_S 23
1075
1076
1077#define AR9285_AN_RF2G2 0x7824
1078#define AR9285_AN_RF2G2_OFFCAL 0x00001000
1079#define AR9285_AN_RF2G2_OFFCAL_S 12
1080
1081#define AR9285_AN_RF2G3 0x7828
1082#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000
1083#define AR9285_AN_RF2G3_PDVCCOMP_S 25
1084#define AR9285_AN_RF2G3_OB_0 0x00E00000
1085#define AR9285_AN_RF2G3_OB_0_S 21
1086#define AR9285_AN_RF2G3_OB_1 0x001C0000
1087#define AR9285_AN_RF2G3_OB_1_S 18
1088#define AR9285_AN_RF2G3_OB_2 0x00038000
1089#define AR9285_AN_RF2G3_OB_2_S 15
1090#define AR9285_AN_RF2G3_OB_3 0x00007000
1091#define AR9285_AN_RF2G3_OB_3_S 12
1092#define AR9285_AN_RF2G3_OB_4 0x00000E00
1093#define AR9285_AN_RF2G3_OB_4_S 9
1094
1095#define AR9285_AN_RF2G3_DB1_0 0x000001C0
1096#define AR9285_AN_RF2G3_DB1_0_S 6
1097#define AR9285_AN_RF2G3_DB1_1 0x00000038
1098#define AR9285_AN_RF2G3_DB1_1_S 3
1099#define AR9285_AN_RF2G3_DB1_2 0x00000007
1100#define AR9285_AN_RF2G3_DB1_2_S 0
1101#define AR9285_AN_RF2G4 0x782C
1102#define AR9285_AN_RF2G4_DB1_3 0xE0000000
1103#define AR9285_AN_RF2G4_DB1_3_S 29
1104#define AR9285_AN_RF2G4_DB1_4 0x1C000000
1105#define AR9285_AN_RF2G4_DB1_4_S 26
1106
1107#define AR9285_AN_RF2G4_DB2_0 0x03800000
1108#define AR9285_AN_RF2G4_DB2_0_S 23
1109#define AR9285_AN_RF2G4_DB2_1 0x00700000
1110#define AR9285_AN_RF2G4_DB2_1_S 20
1111#define AR9285_AN_RF2G4_DB2_2 0x000E0000
1112#define AR9285_AN_RF2G4_DB2_2_S 17
1113#define AR9285_AN_RF2G4_DB2_3 0x0001C000
1114#define AR9285_AN_RF2G4_DB2_3_S 14
1115#define AR9285_AN_RF2G4_DB2_4 0x00003800
1116#define AR9285_AN_RF2G4_DB2_4_S 11
1117
1118#define AR9285_AN_RF2G6 0x7834
1119#define AR9285_AN_RF2G6_CCOMP 0x00007800
1120#define AR9285_AN_RF2G6_CCOMP_S 11
1121#define AR9285_AN_RF2G6_OFFS 0x03f00000
1122#define AR9285_AN_RF2G6_OFFS_S 20
1123
1124#define AR9285_AN_RF2G7 0x7838
1125#define AR9285_AN_RF2G7_PWDDB 0x00000002
1126#define AR9285_AN_RF2G7_PWDDB_S 1
1127#define AR9285_AN_RF2G7_PADRVGN2TAB0 0xE0000000
1128#define AR9285_AN_RF2G7_PADRVGN2TAB0_S 29
1129
1130#define AR9285_AN_RF2G8 0x783C
1131#define AR9285_AN_RF2G8_PADRVGN2TAB0 0x0001C000
1132#define AR9285_AN_RF2G8_PADRVGN2TAB0_S 14
1133
1134
1135#define AR9285_AN_RF2G9 0x7840
1136#define AR9285_AN_RXTXBB1 0x7854
1137#define AR9285_AN_RXTXBB1_PDRXTXBB1 0x00000020
1138#define AR9285_AN_RXTXBB1_PDRXTXBB1_S 5
1139#define AR9285_AN_RXTXBB1_PDV2I 0x00000080
1140#define AR9285_AN_RXTXBB1_PDV2I_S 7
1141#define AR9285_AN_RXTXBB1_PDDACIF 0x00000100
1142#define AR9285_AN_RXTXBB1_PDDACIF_S 8
1143#define AR9285_AN_RXTXBB1_SPARE9 0x00000001
1144#define AR9285_AN_RXTXBB1_SPARE9_S 0
1145
1146#define AR9285_AN_TOP2 0x7868
1147
1148#define AR9285_AN_TOP3 0x786c
1149#define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C
1150#define AR9285_AN_TOP3_XPABIAS_LVL_S 2
1151#define AR9285_AN_TOP3_PWDDAC 0x00800000
1152#define AR9285_AN_TOP3_PWDDAC_S 23
1153
1154#define AR9285_AN_TOP4 0x7870
1155#define AR9285_AN_TOP4_DEFAULT 0x10142c00
1156
1157#define AR_STA_ID0 0x8000
1158#define AR_STA_ID1 0x8004
1159#define AR_STA_ID1_SADH_MASK 0x0000FFFF
1160#define AR_STA_ID1_STA_AP 0x00010000
1161#define AR_STA_ID1_ADHOC 0x00020000
1162#define AR_STA_ID1_PWR_SAV 0x00040000
1163#define AR_STA_ID1_KSRCHDIS 0x00080000
1164#define AR_STA_ID1_PCF 0x00100000
1165#define AR_STA_ID1_USE_DEFANT 0x00200000
1166#define AR_STA_ID1_DEFANT_UPDATE 0x00400000
1167#define AR_STA_ID1_RTS_USE_DEF 0x00800000
1168#define AR_STA_ID1_ACKCTS_6MB 0x01000000
1169#define AR_STA_ID1_BASE_RATE_11B 0x02000000
1170#define AR_STA_ID1_SECTOR_SELF_GEN 0x04000000
1171#define AR_STA_ID1_CRPT_MIC_ENABLE 0x08000000
1172#define AR_STA_ID1_KSRCH_MODE 0x10000000
1173#define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000
1174#define AR_STA_ID1_CBCIV_ENDIAN 0x40000000
1175#define AR_STA_ID1_MCAST_KSRCH 0x80000000
1176
1177#define AR_BSS_ID0 0x8008
1178#define AR_BSS_ID1 0x800C
1179#define AR_BSS_ID1_U16 0x0000FFFF
1180#define AR_BSS_ID1_AID 0x07FF0000
1181#define AR_BSS_ID1_AID_S 16
1182
1183#define AR_BCN_RSSI_AVE 0x8010
1184#define AR_BCN_RSSI_AVE_MASK 0x00000FFF
1185
1186#define AR_TIME_OUT 0x8014
1187#define AR_TIME_OUT_ACK 0x00003FFF
1188#define AR_TIME_OUT_ACK_S 0
1189#define AR_TIME_OUT_CTS 0x3FFF0000
1190#define AR_TIME_OUT_CTS_S 16
1191
1192#define AR_RSSI_THR 0x8018
1193#define AR_RSSI_THR_MASK 0x000000FF
1194#define AR_RSSI_THR_BM_THR 0x0000FF00
1195#define AR_RSSI_THR_BM_THR_S 8
1196#define AR_RSSI_BCN_WEIGHT 0x1F000000
1197#define AR_RSSI_BCN_WEIGHT_S 24
1198#define AR_RSSI_BCN_RSSI_RST 0x20000000
1199
1200#define AR_USEC 0x801c
1201#define AR_USEC_USEC 0x0000007F
1202#define AR_USEC_TX_LAT 0x007FC000
1203#define AR_USEC_TX_LAT_S 14
1204#define AR_USEC_RX_LAT 0x1F800000
1205#define AR_USEC_RX_LAT_S 23
1206
1207#define AR_RESET_TSF 0x8020
1208#define AR_RESET_TSF_ONCE 0x01000000
1209
1210#define AR_MAX_CFP_DUR 0x8038
1211#define AR_CFP_VAL 0x0000FFFF
1212
1213#define AR_RX_FILTER 0x803C
1214#define AR_RX_COMPR_BAR 0x00000400
1215
1216#define AR_MCAST_FIL0 0x8040
1217#define AR_MCAST_FIL1 0x8044
1218
1219#define AR_DIAG_SW 0x8048
1220#define AR_DIAG_CACHE_ACK 0x00000001
1221#define AR_DIAG_ACK_DIS 0x00000002
1222#define AR_DIAG_CTS_DIS 0x00000004
1223#define AR_DIAG_ENCRYPT_DIS 0x00000008
1224#define AR_DIAG_DECRYPT_DIS 0x00000010
1225#define AR_DIAG_RX_DIS 0x00000020
1226#define AR_DIAG_LOOP_BACK 0x00000040
1227#define AR_DIAG_CORR_FCS 0x00000080
1228#define AR_DIAG_CHAN_INFO 0x00000100
1229#define AR_DIAG_SCRAM_SEED 0x0001FE00
1230#define AR_DIAG_SCRAM_SEED_S 8
1231#define AR_DIAG_FRAME_NV0 0x00020000
1232#define AR_DIAG_OBS_PT_SEL1 0x000C0000
1233#define AR_DIAG_OBS_PT_SEL1_S 18
1234#define AR_DIAG_FORCE_RX_CLEAR 0x00100000
1235#define AR_DIAG_IGNORE_VIRT_CS 0x00200000
1236#define AR_DIAG_FORCE_CH_IDLE_HIGH 0x00400000
1237#define AR_DIAG_EIFS_CTRL_ENA 0x00800000
1238#define AR_DIAG_DUAL_CHAIN_INFO 0x01000000
1239#define AR_DIAG_RX_ABORT 0x02000000
1240#define AR_DIAG_SATURATE_CYCLE_CNT 0x04000000
1241#define AR_DIAG_OBS_PT_SEL2 0x08000000
1242#define AR_DIAG_RX_CLEAR_CTL_LOW 0x10000000
1243#define AR_DIAG_RX_CLEAR_EXT_LOW 0x20000000
1244
1245#define AR_TSF_L32 0x804c
1246#define AR_TSF_U32 0x8050
1247
1248#define AR_TST_ADDAC 0x8054
1249#define AR_DEF_ANTENNA 0x8058
1250
1251#define AR_AES_MUTE_MASK0 0x805c
1252#define AR_AES_MUTE_MASK0_FC 0x0000FFFF
1253#define AR_AES_MUTE_MASK0_QOS 0xFFFF0000
1254#define AR_AES_MUTE_MASK0_QOS_S 16
1255
1256#define AR_AES_MUTE_MASK1 0x8060
1257#define AR_AES_MUTE_MASK1_SEQ 0x0000FFFF
1258#define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000
1259#define AR_AES_MUTE_MASK1_FC_MGMT_S 16
1260
1261#define AR_GATED_CLKS 0x8064
1262#define AR_GATED_CLKS_TX 0x00000002
1263#define AR_GATED_CLKS_RX 0x00000004
1264#define AR_GATED_CLKS_REG 0x00000008
1265
1266#define AR_OBS_BUS_CTRL 0x8068
1267#define AR_OBS_BUS_SEL_1 0x00040000
1268#define AR_OBS_BUS_SEL_2 0x00080000
1269#define AR_OBS_BUS_SEL_3 0x000C0000
1270#define AR_OBS_BUS_SEL_4 0x08040000
1271#define AR_OBS_BUS_SEL_5 0x08080000
1272
1273#define AR_OBS_BUS_1 0x806c
1274#define AR_OBS_BUS_1_PCU 0x00000001
1275#define AR_OBS_BUS_1_RX_END 0x00000002
1276#define AR_OBS_BUS_1_RX_WEP 0x00000004
1277#define AR_OBS_BUS_1_RX_BEACON 0x00000008
1278#define AR_OBS_BUS_1_RX_FILTER 0x00000010
1279#define AR_OBS_BUS_1_TX_HCF 0x00000020
1280#define AR_OBS_BUS_1_QUIET_TIME 0x00000040
1281#define AR_OBS_BUS_1_CHAN_IDLE 0x00000080
1282#define AR_OBS_BUS_1_TX_HOLD 0x00000100
1283#define AR_OBS_BUS_1_TX_FRAME 0x00000200
1284#define AR_OBS_BUS_1_RX_FRAME 0x00000400
1285#define AR_OBS_BUS_1_RX_CLEAR 0x00000800
1286#define AR_OBS_BUS_1_WEP_STATE 0x0003F000
1287#define AR_OBS_BUS_1_WEP_STATE_S 12
1288#define AR_OBS_BUS_1_RX_STATE 0x01F00000
1289#define AR_OBS_BUS_1_RX_STATE_S 20
1290#define AR_OBS_BUS_1_TX_STATE 0x7E000000
1291#define AR_OBS_BUS_1_TX_STATE_S 25
1292
1293#define AR_LAST_TSTP 0x8080
1294#define AR_NAV 0x8084
1295#define AR_RTS_OK 0x8088
1296#define AR_RTS_FAIL 0x808c
1297#define AR_ACK_FAIL 0x8090
1298#define AR_FCS_FAIL 0x8094
1299#define AR_BEACON_CNT 0x8098
1300
1301#define AR_SLEEP1 0x80d4
1302#define AR_SLEEP1_ASSUME_DTIM 0x00080000
1303#define AR_SLEEP1_CAB_TIMEOUT 0xFFE00000
1304#define AR_SLEEP1_CAB_TIMEOUT_S 21
1305
1306#define AR_SLEEP2 0x80d8
1307#define AR_SLEEP2_BEACON_TIMEOUT 0xFFE00000
1308#define AR_SLEEP2_BEACON_TIMEOUT_S 21
1309
1310#define AR_BSSMSKL 0x80e0
1311#define AR_BSSMSKU 0x80e4
1312
1313#define AR_TPC 0x80e8
1314#define AR_TPC_ACK 0x0000003f
1315#define AR_TPC_ACK_S 0x00
1316#define AR_TPC_CTS 0x00003f00
1317#define AR_TPC_CTS_S 0x08
1318#define AR_TPC_CHIRP 0x003f0000
1319#define AR_TPC_CHIRP_S 0x16
1320
1321#define AR_TFCNT 0x80ec
1322#define AR_RFCNT 0x80f0
1323#define AR_RCCNT 0x80f4
1324#define AR_CCCNT 0x80f8
1325
1326#define AR_QUIET1 0x80fc
1327#define AR_QUIET1_NEXT_QUIET_S 0
1328#define AR_QUIET1_NEXT_QUIET_M 0x0000ffff
1329#define AR_QUIET1_QUIET_ENABLE 0x00010000
1330#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000
1331#define AR_QUIET2 0x8100
1332#define AR_QUIET2_QUIET_PERIOD_S 0
1333#define AR_QUIET2_QUIET_PERIOD_M 0x0000ffff
1334#define AR_QUIET2_QUIET_DUR_S 16
1335#define AR_QUIET2_QUIET_DUR 0xffff0000
1336
1337#define AR_TSF_PARM 0x8104
1338#define AR_TSF_INCREMENT_M 0x000000ff
1339#define AR_TSF_INCREMENT_S 0x00
1340
1341#define AR_QOS_NO_ACK 0x8108
1342#define AR_QOS_NO_ACK_TWO_BIT 0x0000000f
1343#define AR_QOS_NO_ACK_TWO_BIT_S 0
1344#define AR_QOS_NO_ACK_BIT_OFF 0x00000070
1345#define AR_QOS_NO_ACK_BIT_OFF_S 4
1346#define AR_QOS_NO_ACK_BYTE_OFF 0x00000180
1347#define AR_QOS_NO_ACK_BYTE_OFF_S 7
1348
1349#define AR_PHY_ERR 0x810c
1350
1351#define AR_PHY_ERR_DCHIRP 0x00000008
1352#define AR_PHY_ERR_RADAR 0x00000020
1353#define AR_PHY_ERR_OFDM_TIMING 0x00020000
1354#define AR_PHY_ERR_CCK_TIMING 0x02000000
1355
1356#define AR_RXFIFO_CFG 0x8114
1357
1358
1359#define AR_MIC_QOS_CONTROL 0x8118
1360#define AR_MIC_QOS_SELECT 0x811c
1361
1362#define AR_PCU_MISC 0x8120
1363#define AR_PCU_FORCE_BSSID_MATCH 0x00000001
1364#define AR_PCU_MIC_NEW_LOC_ENA 0x00000004
1365#define AR_PCU_TX_ADD_TSF 0x00000008
1366#define AR_PCU_CCK_SIFS_MODE 0x00000010
1367#define AR_PCU_RX_ANT_UPDT 0x00000800
1368#define AR_PCU_TXOP_TBTT_LIMIT_ENA 0x00001000
1369#define AR_PCU_MISS_BCN_IN_SLEEP 0x00004000
1370#define AR_PCU_BUG_12306_FIX_ENA 0x00020000
1371#define AR_PCU_FORCE_QUIET_COLL 0x00040000
1372#define AR_PCU_TBTT_PROTECT 0x00200000
1373#define AR_PCU_CLEAR_VMF 0x01000000
1374#define AR_PCU_CLEAR_BA_VALID 0x04000000
1375
1376
1377#define AR_FILT_OFDM 0x8124
1378#define AR_FILT_OFDM_COUNT 0x00FFFFFF
1379
1380#define AR_FILT_CCK 0x8128
1381#define AR_FILT_CCK_COUNT 0x00FFFFFF
1382
1383#define AR_PHY_ERR_1 0x812c
1384#define AR_PHY_ERR_1_COUNT 0x00FFFFFF
1385#define AR_PHY_ERR_MASK_1 0x8130
1386
1387#define AR_PHY_ERR_2 0x8134
1388#define AR_PHY_ERR_2_COUNT 0x00FFFFFF
1389#define AR_PHY_ERR_MASK_2 0x8138
1390
1391#define AR_PHY_COUNTMAX (3 << 22)
1392#define AR_MIBCNT_INTRMASK (3 << 22)
1393
1394#define AR_TSFOOR_THRESHOLD 0x813c
1395#define AR_TSFOOR_THRESHOLD_VAL 0x0000FFFF
1396
1397#define AR_PHY_ERR_EIFS_MASK 8144
1398
1399#define AR_PHY_ERR_3 0x8168
1400#define AR_PHY_ERR_3_COUNT 0x00FFFFFF
1401#define AR_PHY_ERR_MASK_3 0x816c
1402
1403#define AR_TXSIFS 0x81d0
1404#define AR_TXSIFS_TIME 0x000000FF
1405#define AR_TXSIFS_TX_LATENCY 0x00000F00
1406#define AR_TXSIFS_TX_LATENCY_S 8
1407#define AR_TXSIFS_ACK_SHIFT 0x00007000
1408#define AR_TXSIFS_ACK_SHIFT_S 12
1409
1410#define AR_TXOP_X 0x81ec
1411#define AR_TXOP_X_VAL 0x000000FF
1412
1413
1414#define AR_TXOP_0_3 0x81f0
1415#define AR_TXOP_4_7 0x81f4
1416#define AR_TXOP_8_11 0x81f8
1417#define AR_TXOP_12_15 0x81fc
1418
1419
1420#define AR_NEXT_TBTT_TIMER 0x8200
1421#define AR_NEXT_DMA_BEACON_ALERT 0x8204
1422#define AR_NEXT_SWBA 0x8208
1423#define AR_NEXT_CFP 0x8208
1424#define AR_NEXT_HCF 0x820C
1425#define AR_NEXT_TIM 0x8210
1426#define AR_NEXT_DTIM 0x8214
1427#define AR_NEXT_QUIET_TIMER 0x8218
1428#define AR_NEXT_NDP_TIMER 0x821C
1429
1430#define AR_BEACON_PERIOD 0x8220
1431#define AR_DMA_BEACON_PERIOD 0x8224
1432#define AR_SWBA_PERIOD 0x8228
1433#define AR_HCF_PERIOD 0x822C
1434#define AR_TIM_PERIOD 0x8230
1435#define AR_DTIM_PERIOD 0x8234
1436#define AR_QUIET_PERIOD 0x8238
1437#define AR_NDP_PERIOD 0x823C
1438
1439#define AR_TIMER_MODE 0x8240
1440#define AR_TBTT_TIMER_EN 0x00000001
1441#define AR_DBA_TIMER_EN 0x00000002
1442#define AR_SWBA_TIMER_EN 0x00000004
1443#define AR_HCF_TIMER_EN 0x00000008
1444#define AR_TIM_TIMER_EN 0x00000010
1445#define AR_DTIM_TIMER_EN 0x00000020
1446#define AR_QUIET_TIMER_EN 0x00000040
1447#define AR_NDP_TIMER_EN 0x00000080
1448#define AR_TIMER_OVERFLOW_INDEX 0x00000700
1449#define AR_TIMER_OVERFLOW_INDEX_S 8
1450#define AR_TIMER_THRESH 0xFFFFF000
1451#define AR_TIMER_THRESH_S 12
1452
1453#define AR_SLP32_MODE 0x8244
1454#define AR_SLP32_HALF_CLK_LATENCY 0x000FFFFF
1455#define AR_SLP32_ENA 0x00100000
1456#define AR_SLP32_TSF_WRITE_STATUS 0x00200000
1457
1458#define AR_SLP32_WAKE 0x8248
1459#define AR_SLP32_WAKE_XTL_TIME 0x0000FFFF
1460
1461#define AR_SLP32_INC 0x824c
1462#define AR_SLP32_TST_INC 0x000FFFFF
1463
1464#define AR_SLP_CNT 0x8250
1465#define AR_SLP_CYCLE_CNT 0x8254
1466
1467#define AR_SLP_MIB_CTRL 0x8258
1468#define AR_SLP_MIB_CLEAR 0x00000001
1469#define AR_SLP_MIB_PENDING 0x00000002
1470
1471#define AR_2040_MODE 0x8318
1472#define AR_2040_JOINED_RX_CLEAR 0x00000001
1473
1474
1475#define AR_EXTRCCNT 0x8328
1476
1477#define AR_SELFGEN_MASK 0x832c
1478
1479#define AR_PCU_TXBUF_CTRL 0x8340
1480#define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF
1481#define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700
1482#define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE 0x380
1483
1484#define AR_PCU_MISC_MODE2 0x8344
1485#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002
1486#define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT 0x00000004
1487
1488#define AR_KEYTABLE_0 0x8800
1489#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32))
1490#define AR_KEY_CACHE_SIZE 128
1491#define AR_RSVD_KEYTABLE_ENTRIES 4
1492#define AR_KEY_TYPE 0x00000007
1493#define AR_KEYTABLE_TYPE_40 0x00000000
1494#define AR_KEYTABLE_TYPE_104 0x00000001
1495#define AR_KEYTABLE_TYPE_128 0x00000003
1496#define AR_KEYTABLE_TYPE_TKIP 0x00000004
1497#define AR_KEYTABLE_TYPE_AES 0x00000005
1498#define AR_KEYTABLE_TYPE_CCM 0x00000006
1499#define AR_KEYTABLE_TYPE_CLR 0x00000007
1500#define AR_KEYTABLE_ANT 0x00000008
1501#define AR_KEYTABLE_VALID 0x00008000
1502#define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0)
1503#define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4)
1504#define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8)
1505#define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12)
1506#define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16)
1507#define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20)
1508#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24)
1509#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28)
1510
1511#endif
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
new file mode 100644
index 000000000000..1ff429b027d7
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
@@ -0,0 +1,662 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "ath9k.h"
18
19struct ath9k_vif_iter_data {
20 int count;
21 u8 *addr;
22};
23
24static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
25{
26 struct ath9k_vif_iter_data *iter_data = data;
27 u8 *nbuf;
28
29 nbuf = krealloc(iter_data->addr, (iter_data->count + 1) * ETH_ALEN,
30 GFP_ATOMIC);
31 if (nbuf == NULL)
32 return;
33
34 memcpy(nbuf + iter_data->count * ETH_ALEN, mac, ETH_ALEN);
35 iter_data->addr = nbuf;
36 iter_data->count++;
37}
38
39void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
40{
41 struct ath_wiphy *aphy = hw->priv;
42 struct ath_softc *sc = aphy->sc;
43 struct ath9k_vif_iter_data iter_data;
44 int i, j;
45 u8 mask[ETH_ALEN];
46
47 /*
48 * Add primary MAC address even if it is not in active use since it
49 * will be configured to the hardware as the starting point and the
50 * BSSID mask will need to be changed if another address is active.
51 */
52 iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC);
53 if (iter_data.addr) {
54 memcpy(iter_data.addr, sc->sc_ah->macaddr, ETH_ALEN);
55 iter_data.count = 1;
56 } else
57 iter_data.count = 0;
58
59 /* Get list of all active MAC addresses */
60 spin_lock_bh(&sc->wiphy_lock);
61 ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
62 &iter_data);
63 for (i = 0; i < sc->num_sec_wiphy; i++) {
64 if (sc->sec_wiphy[i] == NULL)
65 continue;
66 ieee80211_iterate_active_interfaces_atomic(
67 sc->sec_wiphy[i]->hw, ath9k_vif_iter, &iter_data);
68 }
69 spin_unlock_bh(&sc->wiphy_lock);
70
71 /* Generate an address mask to cover all active addresses */
72 memset(mask, 0, ETH_ALEN);
73 for (i = 0; i < iter_data.count; i++) {
74 u8 *a1 = iter_data.addr + i * ETH_ALEN;
75 for (j = i + 1; j < iter_data.count; j++) {
76 u8 *a2 = iter_data.addr + j * ETH_ALEN;
77 mask[0] |= a1[0] ^ a2[0];
78 mask[1] |= a1[1] ^ a2[1];
79 mask[2] |= a1[2] ^ a2[2];
80 mask[3] |= a1[3] ^ a2[3];
81 mask[4] |= a1[4] ^ a2[4];
82 mask[5] |= a1[5] ^ a2[5];
83 }
84 }
85
86 kfree(iter_data.addr);
87
88 /* Invert the mask and configure hardware */
89 sc->bssidmask[0] = ~mask[0];
90 sc->bssidmask[1] = ~mask[1];
91 sc->bssidmask[2] = ~mask[2];
92 sc->bssidmask[3] = ~mask[3];
93 sc->bssidmask[4] = ~mask[4];
94 sc->bssidmask[5] = ~mask[5];
95
96 ath9k_hw_setbssidmask(sc);
97}
98
99int ath9k_wiphy_add(struct ath_softc *sc)
100{
101 int i, error;
102 struct ath_wiphy *aphy;
103 struct ieee80211_hw *hw;
104 u8 addr[ETH_ALEN];
105
106 hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy), &ath9k_ops);
107 if (hw == NULL)
108 return -ENOMEM;
109
110 spin_lock_bh(&sc->wiphy_lock);
111 for (i = 0; i < sc->num_sec_wiphy; i++) {
112 if (sc->sec_wiphy[i] == NULL)
113 break;
114 }
115
116 if (i == sc->num_sec_wiphy) {
117 /* No empty slot available; increase array length */
118 struct ath_wiphy **n;
119 n = krealloc(sc->sec_wiphy,
120 (sc->num_sec_wiphy + 1) *
121 sizeof(struct ath_wiphy *),
122 GFP_ATOMIC);
123 if (n == NULL) {
124 spin_unlock_bh(&sc->wiphy_lock);
125 ieee80211_free_hw(hw);
126 return -ENOMEM;
127 }
128 n[i] = NULL;
129 sc->sec_wiphy = n;
130 sc->num_sec_wiphy++;
131 }
132
133 SET_IEEE80211_DEV(hw, sc->dev);
134
135 aphy = hw->priv;
136 aphy->sc = sc;
137 aphy->hw = hw;
138 sc->sec_wiphy[i] = aphy;
139 spin_unlock_bh(&sc->wiphy_lock);
140
141 memcpy(addr, sc->sc_ah->macaddr, ETH_ALEN);
142 addr[0] |= 0x02; /* Locally managed address */
143 /*
144 * XOR virtual wiphy index into the least significant bits to generate
145 * a different MAC address for each virtual wiphy.
146 */
147 addr[5] ^= i & 0xff;
148 addr[4] ^= (i & 0xff00) >> 8;
149 addr[3] ^= (i & 0xff0000) >> 16;
150
151 SET_IEEE80211_PERM_ADDR(hw, addr);
152
153 ath_set_hw_capab(sc, hw);
154
155 error = ieee80211_register_hw(hw);
156
157 if (error == 0) {
158 /* Make sure wiphy scheduler is started (if enabled) */
159 ath9k_wiphy_set_scheduler(sc, sc->wiphy_scheduler_int);
160 }
161
162 return error;
163}
164
165int ath9k_wiphy_del(struct ath_wiphy *aphy)
166{
167 struct ath_softc *sc = aphy->sc;
168 int i;
169
170 spin_lock_bh(&sc->wiphy_lock);
171 for (i = 0; i < sc->num_sec_wiphy; i++) {
172 if (aphy == sc->sec_wiphy[i]) {
173 sc->sec_wiphy[i] = NULL;
174 spin_unlock_bh(&sc->wiphy_lock);
175 ieee80211_unregister_hw(aphy->hw);
176 ieee80211_free_hw(aphy->hw);
177 return 0;
178 }
179 }
180 spin_unlock_bh(&sc->wiphy_lock);
181 return -ENOENT;
182}
183
184static int ath9k_send_nullfunc(struct ath_wiphy *aphy,
185 struct ieee80211_vif *vif, const u8 *bssid,
186 int ps)
187{
188 struct ath_softc *sc = aphy->sc;
189 struct ath_tx_control txctl;
190 struct sk_buff *skb;
191 struct ieee80211_hdr *hdr;
192 __le16 fc;
193 struct ieee80211_tx_info *info;
194
195 skb = dev_alloc_skb(24);
196 if (skb == NULL)
197 return -ENOMEM;
198 hdr = (struct ieee80211_hdr *) skb_put(skb, 24);
199 memset(hdr, 0, 24);
200 fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
201 IEEE80211_FCTL_TODS);
202 if (ps)
203 fc |= cpu_to_le16(IEEE80211_FCTL_PM);
204 hdr->frame_control = fc;
205 memcpy(hdr->addr1, bssid, ETH_ALEN);
206 memcpy(hdr->addr2, aphy->hw->wiphy->perm_addr, ETH_ALEN);
207 memcpy(hdr->addr3, bssid, ETH_ALEN);
208
209 info = IEEE80211_SKB_CB(skb);
210 memset(info, 0, sizeof(*info));
211 info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS;
212 info->control.vif = vif;
213 info->control.rates[0].idx = 0;
214 info->control.rates[0].count = 4;
215 info->control.rates[1].idx = -1;
216
217 memset(&txctl, 0, sizeof(struct ath_tx_control));
218 txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]];
219 txctl.frame_type = ps ? ATH9K_INT_PAUSE : ATH9K_INT_UNPAUSE;
220
221 if (ath_tx_start(aphy->hw, skb, &txctl) != 0)
222 goto exit;
223
224 return 0;
225exit:
226 dev_kfree_skb_any(skb);
227 return -1;
228}
229
230static bool __ath9k_wiphy_pausing(struct ath_softc *sc)
231{
232 int i;
233 if (sc->pri_wiphy->state == ATH_WIPHY_PAUSING)
234 return true;
235 for (i = 0; i < sc->num_sec_wiphy; i++) {
236 if (sc->sec_wiphy[i] &&
237 sc->sec_wiphy[i]->state == ATH_WIPHY_PAUSING)
238 return true;
239 }
240 return false;
241}
242
243static bool ath9k_wiphy_pausing(struct ath_softc *sc)
244{
245 bool ret;
246 spin_lock_bh(&sc->wiphy_lock);
247 ret = __ath9k_wiphy_pausing(sc);
248 spin_unlock_bh(&sc->wiphy_lock);
249 return ret;
250}
251
252static bool __ath9k_wiphy_scanning(struct ath_softc *sc)
253{
254 int i;
255 if (sc->pri_wiphy->state == ATH_WIPHY_SCAN)
256 return true;
257 for (i = 0; i < sc->num_sec_wiphy; i++) {
258 if (sc->sec_wiphy[i] &&
259 sc->sec_wiphy[i]->state == ATH_WIPHY_SCAN)
260 return true;
261 }
262 return false;
263}
264
265bool ath9k_wiphy_scanning(struct ath_softc *sc)
266{
267 bool ret;
268 spin_lock_bh(&sc->wiphy_lock);
269 ret = __ath9k_wiphy_scanning(sc);
270 spin_unlock_bh(&sc->wiphy_lock);
271 return ret;
272}
273
274static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy);
275
276/* caller must hold wiphy_lock */
277static void __ath9k_wiphy_unpause_ch(struct ath_wiphy *aphy)
278{
279 if (aphy == NULL)
280 return;
281 if (aphy->chan_idx != aphy->sc->chan_idx)
282 return; /* wiphy not on the selected channel */
283 __ath9k_wiphy_unpause(aphy);
284}
285
286static void ath9k_wiphy_unpause_channel(struct ath_softc *sc)
287{
288 int i;
289 spin_lock_bh(&sc->wiphy_lock);
290 __ath9k_wiphy_unpause_ch(sc->pri_wiphy);
291 for (i = 0; i < sc->num_sec_wiphy; i++)
292 __ath9k_wiphy_unpause_ch(sc->sec_wiphy[i]);
293 spin_unlock_bh(&sc->wiphy_lock);
294}
295
296void ath9k_wiphy_chan_work(struct work_struct *work)
297{
298 struct ath_softc *sc = container_of(work, struct ath_softc, chan_work);
299 struct ath_wiphy *aphy = sc->next_wiphy;
300
301 if (aphy == NULL)
302 return;
303
304 /*
305 * All pending interfaces paused; ready to change
306 * channels.
307 */
308
309 /* Change channels */
310 mutex_lock(&sc->mutex);
311 /* XXX: remove me eventually */
312 ath9k_update_ichannel(sc, aphy->hw,
313 &sc->sc_ah->channels[sc->chan_idx]);
314 ath_update_chainmask(sc, sc->chan_is_ht);
315 if (ath_set_channel(sc, aphy->hw,
316 &sc->sc_ah->channels[sc->chan_idx]) < 0) {
317 printk(KERN_DEBUG "ath9k: Failed to set channel for new "
318 "virtual wiphy\n");
319 mutex_unlock(&sc->mutex);
320 return;
321 }
322 mutex_unlock(&sc->mutex);
323
324 ath9k_wiphy_unpause_channel(sc);
325}
326
327/*
328 * ath9k version of ieee80211_tx_status() for TX frames that are generated
329 * internally in the driver.
330 */
331void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
332{
333 struct ath_wiphy *aphy = hw->priv;
334 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
335 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
336 struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
337
338 if (tx_info_priv && tx_info_priv->frame_type == ATH9K_INT_PAUSE &&
339 aphy->state == ATH_WIPHY_PAUSING) {
340 if (!(info->flags & IEEE80211_TX_STAT_ACK)) {
341 printk(KERN_DEBUG "ath9k: %s: no ACK for pause "
342 "frame\n", wiphy_name(hw->wiphy));
343 /*
344 * The AP did not reply; ignore this to allow us to
345 * continue.
346 */
347 }
348 aphy->state = ATH_WIPHY_PAUSED;
349 if (!ath9k_wiphy_pausing(aphy->sc)) {
350 /*
351 * Drop from tasklet to work to allow mutex for channel
352 * change.
353 */
354 queue_work(aphy->sc->hw->workqueue,
355 &aphy->sc->chan_work);
356 }
357 }
358
359 kfree(tx_info_priv);
360 tx_info->rate_driver_data[0] = NULL;
361
362 dev_kfree_skb(skb);
363}
364
365static void ath9k_mark_paused(struct ath_wiphy *aphy)
366{
367 struct ath_softc *sc = aphy->sc;
368 aphy->state = ATH_WIPHY_PAUSED;
369 if (!__ath9k_wiphy_pausing(sc))
370 queue_work(sc->hw->workqueue, &sc->chan_work);
371}
372
373static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
374{
375 struct ath_wiphy *aphy = data;
376 struct ath_vif *avp = (void *) vif->drv_priv;
377
378 switch (vif->type) {
379 case NL80211_IFTYPE_STATION:
380 if (!vif->bss_conf.assoc) {
381 ath9k_mark_paused(aphy);
382 break;
383 }
384 /* TODO: could avoid this if already in PS mode */
385 if (ath9k_send_nullfunc(aphy, vif, avp->bssid, 1)) {
386 printk(KERN_DEBUG "%s: failed to send PS nullfunc\n",
387 __func__);
388 ath9k_mark_paused(aphy);
389 }
390 break;
391 case NL80211_IFTYPE_AP:
392 /* Beacon transmission is paused by aphy->state change */
393 ath9k_mark_paused(aphy);
394 break;
395 default:
396 break;
397 }
398}
399
400/* caller must hold wiphy_lock */
401static int __ath9k_wiphy_pause(struct ath_wiphy *aphy)
402{
403 ieee80211_stop_queues(aphy->hw);
404 aphy->state = ATH_WIPHY_PAUSING;
405 /*
406 * TODO: handle PAUSING->PAUSED for the case where there are multiple
407 * active vifs (now we do it on the first vif getting ready; should be
408 * on the last)
409 */
410 ieee80211_iterate_active_interfaces_atomic(aphy->hw, ath9k_pause_iter,
411 aphy);
412 return 0;
413}
414
415int ath9k_wiphy_pause(struct ath_wiphy *aphy)
416{
417 int ret;
418 spin_lock_bh(&aphy->sc->wiphy_lock);
419 ret = __ath9k_wiphy_pause(aphy);
420 spin_unlock_bh(&aphy->sc->wiphy_lock);
421 return ret;
422}
423
424static void ath9k_unpause_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
425{
426 struct ath_wiphy *aphy = data;
427 struct ath_vif *avp = (void *) vif->drv_priv;
428
429 switch (vif->type) {
430 case NL80211_IFTYPE_STATION:
431 if (!vif->bss_conf.assoc)
432 break;
433 ath9k_send_nullfunc(aphy, vif, avp->bssid, 0);
434 break;
435 case NL80211_IFTYPE_AP:
436 /* Beacon transmission is re-enabled by aphy->state change */
437 break;
438 default:
439 break;
440 }
441}
442
443/* caller must hold wiphy_lock */
444static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy)
445{
446 ieee80211_iterate_active_interfaces_atomic(aphy->hw,
447 ath9k_unpause_iter, aphy);
448 aphy->state = ATH_WIPHY_ACTIVE;
449 ieee80211_wake_queues(aphy->hw);
450 return 0;
451}
452
453int ath9k_wiphy_unpause(struct ath_wiphy *aphy)
454{
455 int ret;
456 spin_lock_bh(&aphy->sc->wiphy_lock);
457 ret = __ath9k_wiphy_unpause(aphy);
458 spin_unlock_bh(&aphy->sc->wiphy_lock);
459 return ret;
460}
461
462static void __ath9k_wiphy_mark_all_paused(struct ath_softc *sc)
463{
464 int i;
465 if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE)
466 sc->pri_wiphy->state = ATH_WIPHY_PAUSED;
467 for (i = 0; i < sc->num_sec_wiphy; i++) {
468 if (sc->sec_wiphy[i] &&
469 sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE)
470 sc->sec_wiphy[i]->state = ATH_WIPHY_PAUSED;
471 }
472}
473
474/* caller must hold wiphy_lock */
475static void __ath9k_wiphy_pause_all(struct ath_softc *sc)
476{
477 int i;
478 if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE)
479 __ath9k_wiphy_pause(sc->pri_wiphy);
480 for (i = 0; i < sc->num_sec_wiphy; i++) {
481 if (sc->sec_wiphy[i] &&
482 sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE)
483 __ath9k_wiphy_pause(sc->sec_wiphy[i]);
484 }
485}
486
487int ath9k_wiphy_select(struct ath_wiphy *aphy)
488{
489 struct ath_softc *sc = aphy->sc;
490 bool now;
491
492 spin_lock_bh(&sc->wiphy_lock);
493 if (__ath9k_wiphy_scanning(sc)) {
494 /*
495 * For now, we are using mac80211 sw scan and it expects to
496 * have full control over channel changes, so avoid wiphy
497 * scheduling during a scan. This could be optimized if the
498 * scanning control were moved into the driver.
499 */
500 spin_unlock_bh(&sc->wiphy_lock);
501 return -EBUSY;
502 }
503 if (__ath9k_wiphy_pausing(sc)) {
504 if (sc->wiphy_select_failures == 0)
505 sc->wiphy_select_first_fail = jiffies;
506 sc->wiphy_select_failures++;
507 if (time_after(jiffies, sc->wiphy_select_first_fail + HZ / 2))
508 {
509 printk(KERN_DEBUG "ath9k: Previous wiphy select timed "
510 "out; disable/enable hw to recover\n");
511 __ath9k_wiphy_mark_all_paused(sc);
512 /*
513 * TODO: this workaround to fix hardware is unlikely to
514 * be specific to virtual wiphy changes. It can happen
515 * on normal channel change, too, and as such, this
516 * should really be made more generic. For example,
517 * tricker radio disable/enable on GTT interrupt burst
518 * (say, 10 GTT interrupts received without any TX
519 * frame being completed)
520 */
521 spin_unlock_bh(&sc->wiphy_lock);
522 ath_radio_disable(sc);
523 ath_radio_enable(sc);
524 queue_work(aphy->sc->hw->workqueue,
525 &aphy->sc->chan_work);
526 return -EBUSY; /* previous select still in progress */
527 }
528 spin_unlock_bh(&sc->wiphy_lock);
529 return -EBUSY; /* previous select still in progress */
530 }
531 sc->wiphy_select_failures = 0;
532
533 /* Store the new channel */
534 sc->chan_idx = aphy->chan_idx;
535 sc->chan_is_ht = aphy->chan_is_ht;
536 sc->next_wiphy = aphy;
537
538 __ath9k_wiphy_pause_all(sc);
539 now = !__ath9k_wiphy_pausing(aphy->sc);
540 spin_unlock_bh(&sc->wiphy_lock);
541
542 if (now) {
543 /* Ready to request channel change immediately */
544 queue_work(aphy->sc->hw->workqueue, &aphy->sc->chan_work);
545 }
546
547 /*
548 * wiphys will be unpaused in ath9k_tx_status() once channel has been
549 * changed if any wiphy needs time to become paused.
550 */
551
552 return 0;
553}
554
555bool ath9k_wiphy_started(struct ath_softc *sc)
556{
557 int i;
558 spin_lock_bh(&sc->wiphy_lock);
559 if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) {
560 spin_unlock_bh(&sc->wiphy_lock);
561 return true;
562 }
563 for (i = 0; i < sc->num_sec_wiphy; i++) {
564 if (sc->sec_wiphy[i] &&
565 sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) {
566 spin_unlock_bh(&sc->wiphy_lock);
567 return true;
568 }
569 }
570 spin_unlock_bh(&sc->wiphy_lock);
571 return false;
572}
573
574static void ath9k_wiphy_pause_chan(struct ath_wiphy *aphy,
575 struct ath_wiphy *selected)
576{
577 if (selected->state == ATH_WIPHY_SCAN) {
578 if (aphy == selected)
579 return;
580 /*
581 * Pause all other wiphys for the duration of the scan even if
582 * they are on the current channel now.
583 */
584 } else if (aphy->chan_idx == selected->chan_idx)
585 return;
586 aphy->state = ATH_WIPHY_PAUSED;
587 ieee80211_stop_queues(aphy->hw);
588}
589
590void ath9k_wiphy_pause_all_forced(struct ath_softc *sc,
591 struct ath_wiphy *selected)
592{
593 int i;
594 spin_lock_bh(&sc->wiphy_lock);
595 if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE)
596 ath9k_wiphy_pause_chan(sc->pri_wiphy, selected);
597 for (i = 0; i < sc->num_sec_wiphy; i++) {
598 if (sc->sec_wiphy[i] &&
599 sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE)
600 ath9k_wiphy_pause_chan(sc->sec_wiphy[i], selected);
601 }
602 spin_unlock_bh(&sc->wiphy_lock);
603}
604
605void ath9k_wiphy_work(struct work_struct *work)
606{
607 struct ath_softc *sc = container_of(work, struct ath_softc,
608 wiphy_work.work);
609 struct ath_wiphy *aphy = NULL;
610 bool first = true;
611
612 spin_lock_bh(&sc->wiphy_lock);
613
614 if (sc->wiphy_scheduler_int == 0) {
615 /* wiphy scheduler is disabled */
616 spin_unlock_bh(&sc->wiphy_lock);
617 return;
618 }
619
620try_again:
621 sc->wiphy_scheduler_index++;
622 while (sc->wiphy_scheduler_index <= sc->num_sec_wiphy) {
623 aphy = sc->sec_wiphy[sc->wiphy_scheduler_index - 1];
624 if (aphy && aphy->state != ATH_WIPHY_INACTIVE)
625 break;
626
627 sc->wiphy_scheduler_index++;
628 aphy = NULL;
629 }
630 if (aphy == NULL) {
631 sc->wiphy_scheduler_index = 0;
632 if (sc->pri_wiphy->state == ATH_WIPHY_INACTIVE) {
633 if (first) {
634 first = false;
635 goto try_again;
636 }
637 /* No wiphy is ready to be scheduled */
638 } else
639 aphy = sc->pri_wiphy;
640 }
641
642 spin_unlock_bh(&sc->wiphy_lock);
643
644 if (aphy &&
645 aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN &&
646 ath9k_wiphy_select(aphy)) {
647 printk(KERN_DEBUG "ath9k: Failed to schedule virtual wiphy "
648 "change\n");
649 }
650
651 queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work,
652 sc->wiphy_scheduler_int);
653}
654
655void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
656{
657 cancel_delayed_work_sync(&sc->wiphy_work);
658 sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int);
659 if (sc->wiphy_scheduler_int)
660 queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work,
661 sc->wiphy_scheduler_int);
662}
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
new file mode 100644
index 000000000000..628b780d8844
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -0,0 +1,2171 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "ath9k.h"
18
19#define BITS_PER_BYTE 8
20#define OFDM_PLCP_BITS 22
21#define HT_RC_2_MCS(_rc) ((_rc) & 0x0f)
22#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
23#define L_STF 8
24#define L_LTF 8
25#define L_SIG 4
26#define HT_SIG 8
27#define HT_STF 4
28#define HT_LTF(_ns) (4 * (_ns))
29#define SYMBOL_TIME(_ns) ((_ns) << 2) /* ns * 4 us */
30#define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5) /* ns * 3.6 us */
31#define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2)
32#define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18)
33
34#define OFDM_SIFS_TIME 16
35
36static u32 bits_per_symbol[][2] = {
37 /* 20MHz 40MHz */
38 { 26, 54 }, /* 0: BPSK */
39 { 52, 108 }, /* 1: QPSK 1/2 */
40 { 78, 162 }, /* 2: QPSK 3/4 */
41 { 104, 216 }, /* 3: 16-QAM 1/2 */
42 { 156, 324 }, /* 4: 16-QAM 3/4 */
43 { 208, 432 }, /* 5: 64-QAM 2/3 */
44 { 234, 486 }, /* 6: 64-QAM 3/4 */
45 { 260, 540 }, /* 7: 64-QAM 5/6 */
46 { 52, 108 }, /* 8: BPSK */
47 { 104, 216 }, /* 9: QPSK 1/2 */
48 { 156, 324 }, /* 10: QPSK 3/4 */
49 { 208, 432 }, /* 11: 16-QAM 1/2 */
50 { 312, 648 }, /* 12: 16-QAM 3/4 */
51 { 416, 864 }, /* 13: 64-QAM 2/3 */
52 { 468, 972 }, /* 14: 64-QAM 3/4 */
53 { 520, 1080 }, /* 15: 64-QAM 5/6 */
54};
55
56#define IS_HT_RATE(_rate) ((_rate) & 0x80)
57
58static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
59 struct ath_atx_tid *tid,
60 struct list_head *bf_head);
61static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
62 struct list_head *bf_q,
63 int txok, int sendbar);
64static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
65 struct list_head *head);
66static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf);
67static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
68 int txok);
69static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
70 int nbad, int txok, bool update_rc);
71
72/*********************/
73/* Aggregation logic */
74/*********************/
75
76static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno)
77{
78 struct ath_atx_tid *tid;
79 tid = ATH_AN_2_TID(an, tidno);
80
81 if (tid->state & AGGR_ADDBA_COMPLETE ||
82 tid->state & AGGR_ADDBA_PROGRESS)
83 return 1;
84 else
85 return 0;
86}
87
88static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
89{
90 struct ath_atx_ac *ac = tid->ac;
91
92 if (tid->paused)
93 return;
94
95 if (tid->sched)
96 return;
97
98 tid->sched = true;
99 list_add_tail(&tid->list, &ac->tid_q);
100
101 if (ac->sched)
102 return;
103
104 ac->sched = true;
105 list_add_tail(&ac->list, &txq->axq_acq);
106}
107
108static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
109{
110 struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
111
112 spin_lock_bh(&txq->axq_lock);
113 tid->paused++;
114 spin_unlock_bh(&txq->axq_lock);
115}
116
117static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
118{
119 struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
120
121 ASSERT(tid->paused > 0);
122 spin_lock_bh(&txq->axq_lock);
123
124 tid->paused--;
125
126 if (tid->paused > 0)
127 goto unlock;
128
129 if (list_empty(&tid->buf_q))
130 goto unlock;
131
132 ath_tx_queue_tid(txq, tid);
133 ath_txq_schedule(sc, txq);
134unlock:
135 spin_unlock_bh(&txq->axq_lock);
136}
137
138static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
139{
140 struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
141 struct ath_buf *bf;
142 struct list_head bf_head;
143 INIT_LIST_HEAD(&bf_head);
144
145 ASSERT(tid->paused > 0);
146 spin_lock_bh(&txq->axq_lock);
147
148 tid->paused--;
149
150 if (tid->paused > 0) {
151 spin_unlock_bh(&txq->axq_lock);
152 return;
153 }
154
155 while (!list_empty(&tid->buf_q)) {
156 bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
157 ASSERT(!bf_isretried(bf));
158 list_move_tail(&bf->list, &bf_head);
159 ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
160 }
161
162 spin_unlock_bh(&txq->axq_lock);
163}
164
165static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
166 int seqno)
167{
168 int index, cindex;
169
170 index = ATH_BA_INDEX(tid->seq_start, seqno);
171 cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
172
173 tid->tx_buf[cindex] = NULL;
174
175 while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) {
176 INCR(tid->seq_start, IEEE80211_SEQ_MAX);
177 INCR(tid->baw_head, ATH_TID_MAX_BUFS);
178 }
179}
180
181static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
182 struct ath_buf *bf)
183{
184 int index, cindex;
185
186 if (bf_isretried(bf))
187 return;
188
189 index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno);
190 cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
191
192 ASSERT(tid->tx_buf[cindex] == NULL);
193 tid->tx_buf[cindex] = bf;
194
195 if (index >= ((tid->baw_tail - tid->baw_head) &
196 (ATH_TID_MAX_BUFS - 1))) {
197 tid->baw_tail = cindex;
198 INCR(tid->baw_tail, ATH_TID_MAX_BUFS);
199 }
200}
201
202/*
203 * TODO: For frame(s) that are in the retry state, we will reuse the
204 * sequence number(s) without setting the retry bit. The
205 * alternative is to give up on these and BAR the receiver's window
206 * forward.
207 */
208static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
209 struct ath_atx_tid *tid)
210
211{
212 struct ath_buf *bf;
213 struct list_head bf_head;
214 INIT_LIST_HEAD(&bf_head);
215
216 for (;;) {
217 if (list_empty(&tid->buf_q))
218 break;
219
220 bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
221 list_move_tail(&bf->list, &bf_head);
222
223 if (bf_isretried(bf))
224 ath_tx_update_baw(sc, tid, bf->bf_seqno);
225
226 spin_unlock(&txq->axq_lock);
227 ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
228 spin_lock(&txq->axq_lock);
229 }
230
231 tid->seq_next = tid->seq_start;
232 tid->baw_tail = tid->baw_head;
233}
234
235static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf)
236{
237 struct sk_buff *skb;
238 struct ieee80211_hdr *hdr;
239
240 bf->bf_state.bf_type |= BUF_RETRY;
241 bf->bf_retries++;
242
243 skb = bf->bf_mpdu;
244 hdr = (struct ieee80211_hdr *)skb->data;
245 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
246}
247
248static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
249{
250 struct ath_buf *tbf;
251
252 spin_lock_bh(&sc->tx.txbuflock);
253 ASSERT(!list_empty((&sc->tx.txbuf)));
254 tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
255 list_del(&tbf->list);
256 spin_unlock_bh(&sc->tx.txbuflock);
257
258 ATH_TXBUF_RESET(tbf);
259
260 tbf->bf_mpdu = bf->bf_mpdu;
261 tbf->bf_buf_addr = bf->bf_buf_addr;
262 *(tbf->bf_desc) = *(bf->bf_desc);
263 tbf->bf_state = bf->bf_state;
264 tbf->bf_dmacontext = bf->bf_dmacontext;
265
266 return tbf;
267}
268
269static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
270 struct ath_buf *bf, struct list_head *bf_q,
271 int txok)
272{
273 struct ath_node *an = NULL;
274 struct sk_buff *skb;
275 struct ieee80211_sta *sta;
276 struct ieee80211_hdr *hdr;
277 struct ath_atx_tid *tid = NULL;
278 struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
279 struct ath_desc *ds = bf_last->bf_desc;
280 struct list_head bf_head, bf_pending;
281 u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
282 u32 ba[WME_BA_BMP_SIZE >> 5];
283 int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
284 bool rc_update = true;
285
286 skb = bf->bf_mpdu;
287 hdr = (struct ieee80211_hdr *)skb->data;
288
289 rcu_read_lock();
290
291 sta = ieee80211_find_sta(sc->hw, hdr->addr1);
292 if (!sta) {
293 rcu_read_unlock();
294 return;
295 }
296
297 an = (struct ath_node *)sta->drv_priv;
298 tid = ATH_AN_2_TID(an, bf->bf_tidno);
299
300 isaggr = bf_isaggr(bf);
301 memset(ba, 0, WME_BA_BMP_SIZE >> 3);
302
303 if (isaggr && txok) {
304 if (ATH_DS_TX_BA(ds)) {
305 seq_st = ATH_DS_BA_SEQ(ds);
306 memcpy(ba, ATH_DS_BA_BITMAP(ds),
307 WME_BA_BMP_SIZE >> 3);
308 } else {
309 /*
310 * AR5416 can become deaf/mute when BA
311 * issue happens. Chip needs to be reset.
312 * But AP code may have sychronization issues
313 * when perform internal reset in this routine.
314 * Only enable reset in STA mode for now.
315 */
316 if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION)
317 needreset = 1;
318 }
319 }
320
321 INIT_LIST_HEAD(&bf_pending);
322 INIT_LIST_HEAD(&bf_head);
323
324 nbad = ath_tx_num_badfrms(sc, bf, txok);
325 while (bf) {
326 txfail = txpending = 0;
327 bf_next = bf->bf_next;
328
329 if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) {
330 /* transmit completion, subframe is
331 * acked by block ack */
332 acked_cnt++;
333 } else if (!isaggr && txok) {
334 /* transmit completion */
335 acked_cnt++;
336 } else {
337 if (!(tid->state & AGGR_CLEANUP) &&
338 ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) {
339 if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
340 ath_tx_set_retry(sc, bf);
341 txpending = 1;
342 } else {
343 bf->bf_state.bf_type |= BUF_XRETRY;
344 txfail = 1;
345 sendbar = 1;
346 txfail_cnt++;
347 }
348 } else {
349 /*
350 * cleanup in progress, just fail
351 * the un-acked sub-frames
352 */
353 txfail = 1;
354 }
355 }
356
357 if (bf_next == NULL) {
358 INIT_LIST_HEAD(&bf_head);
359 } else {
360 ASSERT(!list_empty(bf_q));
361 list_move_tail(&bf->list, &bf_head);
362 }
363
364 if (!txpending) {
365 /*
366 * complete the acked-ones/xretried ones; update
367 * block-ack window
368 */
369 spin_lock_bh(&txq->axq_lock);
370 ath_tx_update_baw(sc, tid, bf->bf_seqno);
371 spin_unlock_bh(&txq->axq_lock);
372
373 if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
374 ath_tx_rc_status(bf, ds, nbad, txok, true);
375 rc_update = false;
376 } else {
377 ath_tx_rc_status(bf, ds, nbad, txok, false);
378 }
379
380 ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar);
381 } else {
382 /* retry the un-acked ones */
383 if (bf->bf_next == NULL && bf_last->bf_stale) {
384 struct ath_buf *tbf;
385
386 tbf = ath_clone_txbuf(sc, bf_last);
387 ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc);
388 list_add_tail(&tbf->list, &bf_head);
389 } else {
390 /*
391 * Clear descriptor status words for
392 * software retry
393 */
394 ath9k_hw_cleartxdesc(sc->sc_ah, bf->bf_desc);
395 }
396
397 /*
398 * Put this buffer to the temporary pending
399 * queue to retain ordering
400 */
401 list_splice_tail_init(&bf_head, &bf_pending);
402 }
403
404 bf = bf_next;
405 }
406
407 if (tid->state & AGGR_CLEANUP) {
408 if (tid->baw_head == tid->baw_tail) {
409 tid->state &= ~AGGR_ADDBA_COMPLETE;
410 tid->addba_exchangeattempts = 0;
411 tid->state &= ~AGGR_CLEANUP;
412
413 /* send buffered frames as singles */
414 ath_tx_flush_tid(sc, tid);
415 }
416 rcu_read_unlock();
417 return;
418 }
419
420 /* prepend un-acked frames to the beginning of the pending frame queue */
421 if (!list_empty(&bf_pending)) {
422 spin_lock_bh(&txq->axq_lock);
423 list_splice(&bf_pending, &tid->buf_q);
424 ath_tx_queue_tid(txq, tid);
425 spin_unlock_bh(&txq->axq_lock);
426 }
427
428 rcu_read_unlock();
429
430 if (needreset)
431 ath_reset(sc, false);
432}
433
434static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
435 struct ath_atx_tid *tid)
436{
437 struct ath_rate_table *rate_table = sc->cur_rate_table;
438 struct sk_buff *skb;
439 struct ieee80211_tx_info *tx_info;
440 struct ieee80211_tx_rate *rates;
441 struct ath_tx_info_priv *tx_info_priv;
442 u32 max_4ms_framelen, frmlen;
443 u16 aggr_limit, legacy = 0, maxampdu;
444 int i;
445
446 skb = bf->bf_mpdu;
447 tx_info = IEEE80211_SKB_CB(skb);
448 rates = tx_info->control.rates;
449 tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
450
451 /*
452 * Find the lowest frame length among the rate series that will have a
453 * 4ms transmit duration.
454 * TODO - TXOP limit needs to be considered.
455 */
456 max_4ms_framelen = ATH_AMPDU_LIMIT_MAX;
457
458 for (i = 0; i < 4; i++) {
459 if (rates[i].count) {
460 if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) {
461 legacy = 1;
462 break;
463 }
464
465 frmlen = rate_table->info[rates[i].idx].max_4ms_framelen;
466 max_4ms_framelen = min(max_4ms_framelen, frmlen);
467 }
468 }
469
470 /*
471 * limit aggregate size by the minimum rate if rate selected is
472 * not a probe rate, if rate selected is a probe rate then
473 * avoid aggregation of this packet.
474 */
475 if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy)
476 return 0;
477
478 aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_DEFAULT);
479
480 /*
481 * h/w can accept aggregates upto 16 bit lengths (65535).
482 * The IE, however can hold upto 65536, which shows up here
483 * as zero. Ignore 65536 since we are constrained by hw.
484 */
485 maxampdu = tid->an->maxampdu;
486 if (maxampdu)
487 aggr_limit = min(aggr_limit, maxampdu);
488
489 return aggr_limit;
490}
491
492/*
493 * Returns the number of delimiters to be added to
494 * meet the minimum required mpdudensity.
495 * caller should make sure that the rate is HT rate .
496 */
497static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
498 struct ath_buf *bf, u16 frmlen)
499{
500 struct ath_rate_table *rt = sc->cur_rate_table;
501 struct sk_buff *skb = bf->bf_mpdu;
502 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
503 u32 nsymbits, nsymbols, mpdudensity;
504 u16 minlen;
505 u8 rc, flags, rix;
506 int width, half_gi, ndelim, mindelim;
507
508 /* Select standard number of delimiters based on frame length alone */
509 ndelim = ATH_AGGR_GET_NDELIM(frmlen);
510
511 /*
512 * If encryption enabled, hardware requires some more padding between
513 * subframes.
514 * TODO - this could be improved to be dependent on the rate.
515 * The hardware can keep up at lower rates, but not higher rates
516 */
517 if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR)
518 ndelim += ATH_AGGR_ENCRYPTDELIM;
519
520 /*
521 * Convert desired mpdu density from microeconds to bytes based
522 * on highest rate in rate series (i.e. first rate) to determine
523 * required minimum length for subframe. Take into account
524 * whether high rate is 20 or 40Mhz and half or full GI.
525 */
526 mpdudensity = tid->an->mpdudensity;
527
528 /*
529 * If there is no mpdu density restriction, no further calculation
530 * is needed.
531 */
532 if (mpdudensity == 0)
533 return ndelim;
534
535 rix = tx_info->control.rates[0].idx;
536 flags = tx_info->control.rates[0].flags;
537 rc = rt->info[rix].ratecode;
538 width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0;
539 half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
540
541 if (half_gi)
542 nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
543 else
544 nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
545
546 if (nsymbols == 0)
547 nsymbols = 1;
548
549 nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
550 minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
551
552 if (frmlen < minlen) {
553 mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ;
554 ndelim = max(mindelim, ndelim);
555 }
556
557 return ndelim;
558}
559
560static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
561 struct ath_atx_tid *tid,
562 struct list_head *bf_q)
563{
564#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
565 struct ath_buf *bf, *bf_first, *bf_prev = NULL;
566 int rl = 0, nframes = 0, ndelim, prev_al = 0;
567 u16 aggr_limit = 0, al = 0, bpad = 0,
568 al_delta, h_baw = tid->baw_size / 2;
569 enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
570
571 bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
572
573 do {
574 bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
575
576 /* do not step over block-ack window */
577 if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) {
578 status = ATH_AGGR_BAW_CLOSED;
579 break;
580 }
581
582 if (!rl) {
583 aggr_limit = ath_lookup_rate(sc, bf, tid);
584 rl = 1;
585 }
586
587 /* do not exceed aggregation limit */
588 al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen;
589
590 if (nframes &&
591 (aggr_limit < (al + bpad + al_delta + prev_al))) {
592 status = ATH_AGGR_LIMITED;
593 break;
594 }
595
596 /* do not exceed subframe limit */
597 if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) {
598 status = ATH_AGGR_LIMITED;
599 break;
600 }
601 nframes++;
602
603 /* add padding for previous frame to aggregation length */
604 al += bpad + al_delta;
605
606 /*
607 * Get the delimiters needed to meet the MPDU
608 * density for this node.
609 */
610 ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen);
611 bpad = PADBYTES(al_delta) + (ndelim << 2);
612
613 bf->bf_next = NULL;
614 bf->bf_desc->ds_link = 0;
615
616 /* link buffers of this frame to the aggregate */
617 ath_tx_addto_baw(sc, tid, bf);
618 ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
619 list_move_tail(&bf->list, bf_q);
620 if (bf_prev) {
621 bf_prev->bf_next = bf;
622 bf_prev->bf_desc->ds_link = bf->bf_daddr;
623 }
624 bf_prev = bf;
625 } while (!list_empty(&tid->buf_q));
626
627 bf_first->bf_al = al;
628 bf_first->bf_nframes = nframes;
629
630 return status;
631#undef PADBYTES
632}
633
634static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
635 struct ath_atx_tid *tid)
636{
637 struct ath_buf *bf;
638 enum ATH_AGGR_STATUS status;
639 struct list_head bf_q;
640
641 do {
642 if (list_empty(&tid->buf_q))
643 return;
644
645 INIT_LIST_HEAD(&bf_q);
646
647 status = ath_tx_form_aggr(sc, tid, &bf_q);
648
649 /*
650 * no frames picked up to be aggregated;
651 * block-ack window is not open.
652 */
653 if (list_empty(&bf_q))
654 break;
655
656 bf = list_first_entry(&bf_q, struct ath_buf, list);
657 bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
658
659 /* if only one frame, send as non-aggregate */
660 if (bf->bf_nframes == 1) {
661 bf->bf_state.bf_type &= ~BUF_AGGR;
662 ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
663 ath_buf_set_rate(sc, bf);
664 ath_tx_txqaddbuf(sc, txq, &bf_q);
665 continue;
666 }
667
668 /* setup first desc of aggregate */
669 bf->bf_state.bf_type |= BUF_AGGR;
670 ath_buf_set_rate(sc, bf);
671 ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al);
672
673 /* anchor last desc of aggregate */
674 ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
675
676 txq->axq_aggr_depth++;
677 ath_tx_txqaddbuf(sc, txq, &bf_q);
678
679 } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH &&
680 status != ATH_AGGR_BAW_CLOSED);
681}
682
683int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
684 u16 tid, u16 *ssn)
685{
686 struct ath_atx_tid *txtid;
687 struct ath_node *an;
688
689 an = (struct ath_node *)sta->drv_priv;
690
691 if (sc->sc_flags & SC_OP_TXAGGR) {
692 txtid = ATH_AN_2_TID(an, tid);
693 txtid->state |= AGGR_ADDBA_PROGRESS;
694 ath_tx_pause_tid(sc, txtid);
695 *ssn = txtid->seq_start;
696 }
697
698 return 0;
699}
700
701int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
702{
703 struct ath_node *an = (struct ath_node *)sta->drv_priv;
704 struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
705 struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
706 struct ath_buf *bf;
707 struct list_head bf_head;
708 INIT_LIST_HEAD(&bf_head);
709
710 if (txtid->state & AGGR_CLEANUP)
711 return 0;
712
713 if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
714 txtid->addba_exchangeattempts = 0;
715 return 0;
716 }
717
718 ath_tx_pause_tid(sc, txtid);
719
720 /* drop all software retried frames and mark this TID */
721 spin_lock_bh(&txq->axq_lock);
722 while (!list_empty(&txtid->buf_q)) {
723 bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
724 if (!bf_isretried(bf)) {
725 /*
726 * NB: it's based on the assumption that
727 * software retried frame will always stay
728 * at the head of software queue.
729 */
730 break;
731 }
732 list_move_tail(&bf->list, &bf_head);
733 ath_tx_update_baw(sc, txtid, bf->bf_seqno);
734 ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
735 }
736 spin_unlock_bh(&txq->axq_lock);
737
738 if (txtid->baw_head != txtid->baw_tail) {
739 txtid->state |= AGGR_CLEANUP;
740 } else {
741 txtid->state &= ~AGGR_ADDBA_COMPLETE;
742 txtid->addba_exchangeattempts = 0;
743 ath_tx_flush_tid(sc, txtid);
744 }
745
746 return 0;
747}
748
749void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
750{
751 struct ath_atx_tid *txtid;
752 struct ath_node *an;
753
754 an = (struct ath_node *)sta->drv_priv;
755
756 if (sc->sc_flags & SC_OP_TXAGGR) {
757 txtid = ATH_AN_2_TID(an, tid);
758 txtid->baw_size =
759 IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
760 txtid->state |= AGGR_ADDBA_COMPLETE;
761 txtid->state &= ~AGGR_ADDBA_PROGRESS;
762 ath_tx_resume_tid(sc, txtid);
763 }
764}
765
766bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno)
767{
768 struct ath_atx_tid *txtid;
769
770 if (!(sc->sc_flags & SC_OP_TXAGGR))
771 return false;
772
773 txtid = ATH_AN_2_TID(an, tidno);
774
775 if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
776 if (!(txtid->state & AGGR_ADDBA_PROGRESS) &&
777 (txtid->addba_exchangeattempts < ADDBA_EXCHANGE_ATTEMPTS)) {
778 txtid->addba_exchangeattempts++;
779 return true;
780 }
781 }
782
783 return false;
784}
785
786/********************/
787/* Queue Management */
788/********************/
789
790static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
791 struct ath_txq *txq)
792{
793 struct ath_atx_ac *ac, *ac_tmp;
794 struct ath_atx_tid *tid, *tid_tmp;
795
796 list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
797 list_del(&ac->list);
798 ac->sched = false;
799 list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) {
800 list_del(&tid->list);
801 tid->sched = false;
802 ath_tid_drain(sc, txq, tid);
803 }
804 }
805}
806
807struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
808{
809 struct ath_hw *ah = sc->sc_ah;
810 struct ath9k_tx_queue_info qi;
811 int qnum;
812
813 memset(&qi, 0, sizeof(qi));
814 qi.tqi_subtype = subtype;
815 qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
816 qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
817 qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
818 qi.tqi_physCompBuf = 0;
819
820 /*
821 * Enable interrupts only for EOL and DESC conditions.
822 * We mark tx descriptors to receive a DESC interrupt
823 * when a tx queue gets deep; otherwise waiting for the
824 * EOL to reap descriptors. Note that this is done to
825 * reduce interrupt load and this only defers reaping
826 * descriptors, never transmitting frames. Aside from
827 * reducing interrupts this also permits more concurrency.
828 * The only potential downside is if the tx queue backs
829 * up in which case the top half of the kernel may backup
830 * due to a lack of tx descriptors.
831 *
832 * The UAPSD queue is an exception, since we take a desc-
833 * based intr on the EOSP frames.
834 */
835 if (qtype == ATH9K_TX_QUEUE_UAPSD)
836 qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE;
837 else
838 qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
839 TXQ_FLAG_TXDESCINT_ENABLE;
840 qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
841 if (qnum == -1) {
842 /*
843 * NB: don't print a message, this happens
844 * normally on parts with too few tx queues
845 */
846 return NULL;
847 }
848 if (qnum >= ARRAY_SIZE(sc->tx.txq)) {
849 DPRINTF(sc, ATH_DBG_FATAL,
850 "qnum %u out of range, max %u!\n",
851 qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq));
852 ath9k_hw_releasetxqueue(ah, qnum);
853 return NULL;
854 }
855 if (!ATH_TXQ_SETUP(sc, qnum)) {
856 struct ath_txq *txq = &sc->tx.txq[qnum];
857
858 txq->axq_qnum = qnum;
859 txq->axq_link = NULL;
860 INIT_LIST_HEAD(&txq->axq_q);
861 INIT_LIST_HEAD(&txq->axq_acq);
862 spin_lock_init(&txq->axq_lock);
863 txq->axq_depth = 0;
864 txq->axq_aggr_depth = 0;
865 txq->axq_totalqueued = 0;
866 txq->axq_linkbuf = NULL;
867 sc->tx.txqsetup |= 1<<qnum;
868 }
869 return &sc->tx.txq[qnum];
870}
871
872static int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
873{
874 int qnum;
875
876 switch (qtype) {
877 case ATH9K_TX_QUEUE_DATA:
878 if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
879 DPRINTF(sc, ATH_DBG_FATAL,
880 "HAL AC %u out of range, max %zu!\n",
881 haltype, ARRAY_SIZE(sc->tx.hwq_map));
882 return -1;
883 }
884 qnum = sc->tx.hwq_map[haltype];
885 break;
886 case ATH9K_TX_QUEUE_BEACON:
887 qnum = sc->beacon.beaconq;
888 break;
889 case ATH9K_TX_QUEUE_CAB:
890 qnum = sc->beacon.cabq->axq_qnum;
891 break;
892 default:
893 qnum = -1;
894 }
895 return qnum;
896}
897
898struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
899{
900 struct ath_txq *txq = NULL;
901 int qnum;
902
903 qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
904 txq = &sc->tx.txq[qnum];
905
906 spin_lock_bh(&txq->axq_lock);
907
908 if (txq->axq_depth >= (ATH_TXBUF - 20)) {
909 DPRINTF(sc, ATH_DBG_XMIT,
910 "TX queue: %d is full, depth: %d\n",
911 qnum, txq->axq_depth);
912 ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb));
913 txq->stopped = 1;
914 spin_unlock_bh(&txq->axq_lock);
915 return NULL;
916 }
917
918 spin_unlock_bh(&txq->axq_lock);
919
920 return txq;
921}
922
923int ath_txq_update(struct ath_softc *sc, int qnum,
924 struct ath9k_tx_queue_info *qinfo)
925{
926 struct ath_hw *ah = sc->sc_ah;
927 int error = 0;
928 struct ath9k_tx_queue_info qi;
929
930 if (qnum == sc->beacon.beaconq) {
931 /*
932 * XXX: for beacon queue, we just save the parameter.
933 * It will be picked up by ath_beaconq_config when
934 * it's necessary.
935 */
936 sc->beacon.beacon_qi = *qinfo;
937 return 0;
938 }
939
940 ASSERT(sc->tx.txq[qnum].axq_qnum == qnum);
941
942 ath9k_hw_get_txq_props(ah, qnum, &qi);
943 qi.tqi_aifs = qinfo->tqi_aifs;
944 qi.tqi_cwmin = qinfo->tqi_cwmin;
945 qi.tqi_cwmax = qinfo->tqi_cwmax;
946 qi.tqi_burstTime = qinfo->tqi_burstTime;
947 qi.tqi_readyTime = qinfo->tqi_readyTime;
948
949 if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) {
950 DPRINTF(sc, ATH_DBG_FATAL,
951 "Unable to update hardware queue %u!\n", qnum);
952 error = -EIO;
953 } else {
954 ath9k_hw_resettxqueue(ah, qnum);
955 }
956
957 return error;
958}
959
960int ath_cabq_update(struct ath_softc *sc)
961{
962 struct ath9k_tx_queue_info qi;
963 int qnum = sc->beacon.cabq->axq_qnum;
964
965 ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
966 /*
967 * Ensure the readytime % is within the bounds.
968 */
969 if (sc->config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND)
970 sc->config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND;
971 else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
972 sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
973
974 qi.tqi_readyTime = (sc->hw->conf.beacon_int *
975 sc->config.cabqReadytime) / 100;
976 ath_txq_update(sc, qnum, &qi);
977
978 return 0;
979}
980
981/*
982 * Drain a given TX queue (could be Beacon or Data)
983 *
984 * This assumes output has been stopped and
985 * we do not need to block ath_tx_tasklet.
986 */
987void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
988{
989 struct ath_buf *bf, *lastbf;
990 struct list_head bf_head;
991
992 INIT_LIST_HEAD(&bf_head);
993
994 for (;;) {
995 spin_lock_bh(&txq->axq_lock);
996
997 if (list_empty(&txq->axq_q)) {
998 txq->axq_link = NULL;
999 txq->axq_linkbuf = NULL;
1000 spin_unlock_bh(&txq->axq_lock);
1001 break;
1002 }
1003
1004 bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
1005
1006 if (bf->bf_stale) {
1007 list_del(&bf->list);
1008 spin_unlock_bh(&txq->axq_lock);
1009
1010 spin_lock_bh(&sc->tx.txbuflock);
1011 list_add_tail(&bf->list, &sc->tx.txbuf);
1012 spin_unlock_bh(&sc->tx.txbuflock);
1013 continue;
1014 }
1015
1016 lastbf = bf->bf_lastbf;
1017 if (!retry_tx)
1018 lastbf->bf_desc->ds_txstat.ts_flags =
1019 ATH9K_TX_SW_ABORTED;
1020
1021 /* remove ath_buf's of the same mpdu from txq */
1022 list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
1023 txq->axq_depth--;
1024
1025 spin_unlock_bh(&txq->axq_lock);
1026
1027 if (bf_isampdu(bf))
1028 ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0);
1029 else
1030 ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
1031 }
1032
1033 /* flush any pending frames if aggregation is enabled */
1034 if (sc->sc_flags & SC_OP_TXAGGR) {
1035 if (!retry_tx) {
1036 spin_lock_bh(&txq->axq_lock);
1037 ath_txq_drain_pending_buffers(sc, txq);
1038 spin_unlock_bh(&txq->axq_lock);
1039 }
1040 }
1041}
1042
1043void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
1044{
1045 struct ath_hw *ah = sc->sc_ah;
1046 struct ath_txq *txq;
1047 int i, npend = 0;
1048
1049 if (sc->sc_flags & SC_OP_INVALID)
1050 return;
1051
1052 /* Stop beacon queue */
1053 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
1054
1055 /* Stop data queues */
1056 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
1057 if (ATH_TXQ_SETUP(sc, i)) {
1058 txq = &sc->tx.txq[i];
1059 ath9k_hw_stoptxdma(ah, txq->axq_qnum);
1060 npend += ath9k_hw_numtxpending(ah, txq->axq_qnum);
1061 }
1062 }
1063
1064 if (npend) {
1065 int r;
1066
1067 DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n");
1068
1069 spin_lock_bh(&sc->sc_resetlock);
1070 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true);
1071 if (r)
1072 DPRINTF(sc, ATH_DBG_FATAL,
1073 "Unable to reset hardware; reset status %u\n",
1074 r);
1075 spin_unlock_bh(&sc->sc_resetlock);
1076 }
1077
1078 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
1079 if (ATH_TXQ_SETUP(sc, i))
1080 ath_draintxq(sc, &sc->tx.txq[i], retry_tx);
1081 }
1082}
1083
1084void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
1085{
1086 ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum);
1087 sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
1088}
1089
1090void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
1091{
1092 struct ath_atx_ac *ac;
1093 struct ath_atx_tid *tid;
1094
1095 if (list_empty(&txq->axq_acq))
1096 return;
1097
1098 ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
1099 list_del(&ac->list);
1100 ac->sched = false;
1101
1102 do {
1103 if (list_empty(&ac->tid_q))
1104 return;
1105
1106 tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list);
1107 list_del(&tid->list);
1108 tid->sched = false;
1109
1110 if (tid->paused)
1111 continue;
1112
1113 if ((txq->axq_depth % 2) == 0)
1114 ath_tx_sched_aggr(sc, txq, tid);
1115
1116 /*
1117 * add tid to round-robin queue if more frames
1118 * are pending for the tid
1119 */
1120 if (!list_empty(&tid->buf_q))
1121 ath_tx_queue_tid(txq, tid);
1122
1123 break;
1124 } while (!list_empty(&ac->tid_q));
1125
1126 if (!list_empty(&ac->tid_q)) {
1127 if (!ac->sched) {
1128 ac->sched = true;
1129 list_add_tail(&ac->list, &txq->axq_acq);
1130 }
1131 }
1132}
1133
1134int ath_tx_setup(struct ath_softc *sc, int haltype)
1135{
1136 struct ath_txq *txq;
1137
1138 if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
1139 DPRINTF(sc, ATH_DBG_FATAL,
1140 "HAL AC %u out of range, max %zu!\n",
1141 haltype, ARRAY_SIZE(sc->tx.hwq_map));
1142 return 0;
1143 }
1144 txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype);
1145 if (txq != NULL) {
1146 sc->tx.hwq_map[haltype] = txq->axq_qnum;
1147 return 1;
1148 } else
1149 return 0;
1150}
1151
1152/***********/
1153/* TX, DMA */
1154/***********/
1155
1156/*
1157 * Insert a chain of ath_buf (descriptors) on a txq and
1158 * assume the descriptors are already chained together by caller.
1159 */
1160static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
1161 struct list_head *head)
1162{
1163 struct ath_hw *ah = sc->sc_ah;
1164 struct ath_buf *bf;
1165
1166 /*
1167 * Insert the frame on the outbound list and
1168 * pass it on to the hardware.
1169 */
1170
1171 if (list_empty(head))
1172 return;
1173
1174 bf = list_first_entry(head, struct ath_buf, list);
1175
1176 list_splice_tail_init(head, &txq->axq_q);
1177 txq->axq_depth++;
1178 txq->axq_totalqueued++;
1179 txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
1180
1181 DPRINTF(sc, ATH_DBG_QUEUE,
1182 "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
1183
1184 if (txq->axq_link == NULL) {
1185 ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
1186 DPRINTF(sc, ATH_DBG_XMIT,
1187 "TXDP[%u] = %llx (%p)\n",
1188 txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
1189 } else {
1190 *txq->axq_link = bf->bf_daddr;
1191 DPRINTF(sc, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n",
1192 txq->axq_qnum, txq->axq_link,
1193 ito64(bf->bf_daddr), bf->bf_desc);
1194 }
1195 txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link);
1196 ath9k_hw_txstart(ah, txq->axq_qnum);
1197}
1198
1199static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
1200{
1201 struct ath_buf *bf = NULL;
1202
1203 spin_lock_bh(&sc->tx.txbuflock);
1204
1205 if (unlikely(list_empty(&sc->tx.txbuf))) {
1206 spin_unlock_bh(&sc->tx.txbuflock);
1207 return NULL;
1208 }
1209
1210 bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
1211 list_del(&bf->list);
1212
1213 spin_unlock_bh(&sc->tx.txbuflock);
1214
1215 return bf;
1216}
1217
1218static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
1219 struct list_head *bf_head,
1220 struct ath_tx_control *txctl)
1221{
1222 struct ath_buf *bf;
1223
1224 bf = list_first_entry(bf_head, struct ath_buf, list);
1225 bf->bf_state.bf_type |= BUF_AMPDU;
1226
1227 /*
1228 * Do not queue to h/w when any of the following conditions is true:
1229 * - there are pending frames in software queue
1230 * - the TID is currently paused for ADDBA/BAR request
1231 * - seqno is not within block-ack window
1232 * - h/w queue depth exceeds low water mark
1233 */
1234 if (!list_empty(&tid->buf_q) || tid->paused ||
1235 !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) ||
1236 txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) {
1237 /*
1238 * Add this frame to software queue for scheduling later
1239 * for aggregation.
1240 */
1241 list_move_tail(&bf->list, &tid->buf_q);
1242 ath_tx_queue_tid(txctl->txq, tid);
1243 return;
1244 }
1245
1246 /* Add sub-frame to BAW */
1247 ath_tx_addto_baw(sc, tid, bf);
1248
1249 /* Queue to h/w without aggregation */
1250 bf->bf_nframes = 1;
1251 bf->bf_lastbf = bf;
1252 ath_buf_set_rate(sc, bf);
1253 ath_tx_txqaddbuf(sc, txctl->txq, bf_head);
1254}
1255
1256static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
1257 struct ath_atx_tid *tid,
1258 struct list_head *bf_head)
1259{
1260 struct ath_buf *bf;
1261
1262 bf = list_first_entry(bf_head, struct ath_buf, list);
1263 bf->bf_state.bf_type &= ~BUF_AMPDU;
1264
1265 /* update starting sequence number for subsequent ADDBA request */
1266 INCR(tid->seq_start, IEEE80211_SEQ_MAX);
1267
1268 bf->bf_nframes = 1;
1269 bf->bf_lastbf = bf;
1270 ath_buf_set_rate(sc, bf);
1271 ath_tx_txqaddbuf(sc, txq, bf_head);
1272}
1273
1274static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
1275 struct list_head *bf_head)
1276{
1277 struct ath_buf *bf;
1278
1279 bf = list_first_entry(bf_head, struct ath_buf, list);
1280
1281 bf->bf_lastbf = bf;
1282 bf->bf_nframes = 1;
1283 ath_buf_set_rate(sc, bf);
1284 ath_tx_txqaddbuf(sc, txq, bf_head);
1285}
1286
1287static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
1288{
1289 struct ieee80211_hdr *hdr;
1290 enum ath9k_pkt_type htype;
1291 __le16 fc;
1292
1293 hdr = (struct ieee80211_hdr *)skb->data;
1294 fc = hdr->frame_control;
1295
1296 if (ieee80211_is_beacon(fc))
1297 htype = ATH9K_PKT_TYPE_BEACON;
1298 else if (ieee80211_is_probe_resp(fc))
1299 htype = ATH9K_PKT_TYPE_PROBE_RESP;
1300 else if (ieee80211_is_atim(fc))
1301 htype = ATH9K_PKT_TYPE_ATIM;
1302 else if (ieee80211_is_pspoll(fc))
1303 htype = ATH9K_PKT_TYPE_PSPOLL;
1304 else
1305 htype = ATH9K_PKT_TYPE_NORMAL;
1306
1307 return htype;
1308}
1309
1310static bool is_pae(struct sk_buff *skb)
1311{
1312 struct ieee80211_hdr *hdr;
1313 __le16 fc;
1314
1315 hdr = (struct ieee80211_hdr *)skb->data;
1316 fc = hdr->frame_control;
1317
1318 if (ieee80211_is_data(fc)) {
1319 if (ieee80211_is_nullfunc(fc) ||
1320 /* Port Access Entity (IEEE 802.1X) */
1321 (skb->protocol == cpu_to_be16(ETH_P_PAE))) {
1322 return true;
1323 }
1324 }
1325
1326 return false;
1327}
1328
1329static int get_hw_crypto_keytype(struct sk_buff *skb)
1330{
1331 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1332
1333 if (tx_info->control.hw_key) {
1334 if (tx_info->control.hw_key->alg == ALG_WEP)
1335 return ATH9K_KEY_TYPE_WEP;
1336 else if (tx_info->control.hw_key->alg == ALG_TKIP)
1337 return ATH9K_KEY_TYPE_TKIP;
1338 else if (tx_info->control.hw_key->alg == ALG_CCMP)
1339 return ATH9K_KEY_TYPE_AES;
1340 }
1341
1342 return ATH9K_KEY_TYPE_CLEAR;
1343}
1344
1345static void assign_aggr_tid_seqno(struct sk_buff *skb,
1346 struct ath_buf *bf)
1347{
1348 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1349 struct ieee80211_hdr *hdr;
1350 struct ath_node *an;
1351 struct ath_atx_tid *tid;
1352 __le16 fc;
1353 u8 *qc;
1354
1355 if (!tx_info->control.sta)
1356 return;
1357
1358 an = (struct ath_node *)tx_info->control.sta->drv_priv;
1359 hdr = (struct ieee80211_hdr *)skb->data;
1360 fc = hdr->frame_control;
1361
1362 if (ieee80211_is_data_qos(fc)) {
1363 qc = ieee80211_get_qos_ctl(hdr);
1364 bf->bf_tidno = qc[0] & 0xf;
1365 }
1366
1367 /*
1368 * For HT capable stations, we save tidno for later use.
1369 * We also override seqno set by upper layer with the one
1370 * in tx aggregation state.
1371 *
1372 * If fragmentation is on, the sequence number is
1373 * not overridden, since it has been
1374 * incremented by the fragmentation routine.
1375 *
1376 * FIXME: check if the fragmentation threshold exceeds
1377 * IEEE80211 max.
1378 */
1379 tid = ATH_AN_2_TID(an, bf->bf_tidno);
1380 hdr->seq_ctrl = cpu_to_le16(tid->seq_next <<
1381 IEEE80211_SEQ_SEQ_SHIFT);
1382 bf->bf_seqno = tid->seq_next;
1383 INCR(tid->seq_next, IEEE80211_SEQ_MAX);
1384}
1385
1386static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb,
1387 struct ath_txq *txq)
1388{
1389 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1390 int flags = 0;
1391
1392 flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
1393 flags |= ATH9K_TXDESC_INTREQ;
1394
1395 if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
1396 flags |= ATH9K_TXDESC_NOACK;
1397
1398 return flags;
1399}
1400
1401/*
1402 * rix - rate index
1403 * pktlen - total bytes (delims + data + fcs + pads + pad delims)
1404 * width - 0 for 20 MHz, 1 for 40 MHz
1405 * half_gi - to use 4us v/s 3.6 us for symbol time
1406 */
1407static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
1408 int width, int half_gi, bool shortPreamble)
1409{
1410 struct ath_rate_table *rate_table = sc->cur_rate_table;
1411 u32 nbits, nsymbits, duration, nsymbols;
1412 u8 rc;
1413 int streams, pktlen;
1414
1415 pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
1416 rc = rate_table->info[rix].ratecode;
1417
1418 /* for legacy rates, use old function to compute packet duration */
1419 if (!IS_HT_RATE(rc))
1420 return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen,
1421 rix, shortPreamble);
1422
1423 /* find number of symbols: PLCP + data */
1424 nbits = (pktlen << 3) + OFDM_PLCP_BITS;
1425 nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
1426 nsymbols = (nbits + nsymbits - 1) / nsymbits;
1427
1428 if (!half_gi)
1429 duration = SYMBOL_TIME(nsymbols);
1430 else
1431 duration = SYMBOL_TIME_HALFGI(nsymbols);
1432
1433 /* addup duration for legacy/ht training and signal fields */
1434 streams = HT_RC_2_STREAMS(rc);
1435 duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
1436
1437 return duration;
1438}
1439
1440static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
1441{
1442 struct ath_rate_table *rt = sc->cur_rate_table;
1443 struct ath9k_11n_rate_series series[4];
1444 struct sk_buff *skb;
1445 struct ieee80211_tx_info *tx_info;
1446 struct ieee80211_tx_rate *rates;
1447 struct ieee80211_hdr *hdr;
1448 int i, flags = 0;
1449 u8 rix = 0, ctsrate = 0;
1450 bool is_pspoll;
1451
1452 memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
1453
1454 skb = bf->bf_mpdu;
1455 tx_info = IEEE80211_SKB_CB(skb);
1456 rates = tx_info->control.rates;
1457 hdr = (struct ieee80211_hdr *)skb->data;
1458 is_pspoll = ieee80211_is_pspoll(hdr->frame_control);
1459
1460 /*
1461 * We check if Short Preamble is needed for the CTS rate by
1462 * checking the BSS's global flag.
1463 * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
1464 */
1465 if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
1466 ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode |
1467 rt->info[tx_info->control.rts_cts_rate_idx].short_preamble;
1468 else
1469 ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode;
1470
1471 /*
1472 * ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive.
1473 * Check the first rate in the series to decide whether RTS/CTS
1474 * or CTS-to-self has to be used.
1475 */
1476 if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
1477 flags = ATH9K_TXDESC_CTSENA;
1478 else if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
1479 flags = ATH9K_TXDESC_RTSENA;
1480
1481 /* FIXME: Handle aggregation protection */
1482 if (sc->config.ath_aggr_prot &&
1483 (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) {
1484 flags = ATH9K_TXDESC_RTSENA;
1485 }
1486
1487 /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
1488 if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit))
1489 flags &= ~(ATH9K_TXDESC_RTSENA);
1490
1491 for (i = 0; i < 4; i++) {
1492 if (!rates[i].count || (rates[i].idx < 0))
1493 continue;
1494
1495 rix = rates[i].idx;
1496 series[i].Tries = rates[i].count;
1497 series[i].ChSel = sc->tx_chainmask;
1498
1499 if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
1500 series[i].Rate = rt->info[rix].ratecode |
1501 rt->info[rix].short_preamble;
1502 else
1503 series[i].Rate = rt->info[rix].ratecode;
1504
1505 if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)
1506 series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
1507 if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
1508 series[i].RateFlags |= ATH9K_RATESERIES_2040;
1509 if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
1510 series[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
1511
1512 series[i].PktDuration = ath_pkt_duration(sc, rix, bf,
1513 (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) != 0,
1514 (rates[i].flags & IEEE80211_TX_RC_SHORT_GI),
1515 (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE));
1516 }
1517
1518 /* set dur_update_en for l-sig computation except for PS-Poll frames */
1519 ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc,
1520 bf->bf_lastbf->bf_desc,
1521 !is_pspoll, ctsrate,
1522 0, series, 4, flags);
1523
1524 if (sc->config.ath_aggr_prot && flags)
1525 ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192);
1526}
1527
1528static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
1529 struct sk_buff *skb,
1530 struct ath_tx_control *txctl)
1531{
1532 struct ath_wiphy *aphy = hw->priv;
1533 struct ath_softc *sc = aphy->sc;
1534 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1535 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1536 struct ath_tx_info_priv *tx_info_priv;
1537 int hdrlen;
1538 __le16 fc;
1539
1540 tx_info_priv = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC);
1541 if (unlikely(!tx_info_priv))
1542 return -ENOMEM;
1543 tx_info->rate_driver_data[0] = tx_info_priv;
1544 tx_info_priv->aphy = aphy;
1545 tx_info_priv->frame_type = txctl->frame_type;
1546 hdrlen = ieee80211_get_hdrlen_from_skb(skb);
1547 fc = hdr->frame_control;
1548
1549 ATH_TXBUF_RESET(bf);
1550
1551 bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3);
1552
1553 if (conf_is_ht(&sc->hw->conf) && !is_pae(skb))
1554 bf->bf_state.bf_type |= BUF_HT;
1555
1556 bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq);
1557
1558 bf->bf_keytype = get_hw_crypto_keytype(skb);
1559 if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) {
1560 bf->bf_frmlen += tx_info->control.hw_key->icv_len;
1561 bf->bf_keyix = tx_info->control.hw_key->hw_key_idx;
1562 } else {
1563 bf->bf_keyix = ATH9K_TXKEYIX_INVALID;
1564 }
1565
1566 if (ieee80211_is_data_qos(fc) && (sc->sc_flags & SC_OP_TXAGGR))
1567 assign_aggr_tid_seqno(skb, bf);
1568
1569 bf->bf_mpdu = skb;
1570
1571 bf->bf_dmacontext = dma_map_single(sc->dev, skb->data,
1572 skb->len, DMA_TO_DEVICE);
1573 if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) {
1574 bf->bf_mpdu = NULL;
1575 DPRINTF(sc, ATH_DBG_CONFIG,
1576 "dma_mapping_error() on TX\n");
1577 return -ENOMEM;
1578 }
1579
1580 bf->bf_buf_addr = bf->bf_dmacontext;
1581 return 0;
1582}
1583
1584/* FIXME: tx power */
1585static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
1586 struct ath_tx_control *txctl)
1587{
1588 struct sk_buff *skb = bf->bf_mpdu;
1589 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1590 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1591 struct ath_node *an = NULL;
1592 struct list_head bf_head;
1593 struct ath_desc *ds;
1594 struct ath_atx_tid *tid;
1595 struct ath_hw *ah = sc->sc_ah;
1596 int frm_type;
1597 __le16 fc;
1598
1599 frm_type = get_hw_packet_type(skb);
1600 fc = hdr->frame_control;
1601
1602 INIT_LIST_HEAD(&bf_head);
1603 list_add_tail(&bf->list, &bf_head);
1604
1605 ds = bf->bf_desc;
1606 ds->ds_link = 0;
1607 ds->ds_data = bf->bf_buf_addr;
1608
1609 ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER,
1610 bf->bf_keyix, bf->bf_keytype, bf->bf_flags);
1611
1612 ath9k_hw_filltxdesc(ah, ds,
1613 skb->len, /* segment length */
1614 true, /* first segment */
1615 true, /* last segment */
1616 ds); /* first descriptor */
1617
1618 spin_lock_bh(&txctl->txq->axq_lock);
1619
1620 if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) &&
1621 tx_info->control.sta) {
1622 an = (struct ath_node *)tx_info->control.sta->drv_priv;
1623 tid = ATH_AN_2_TID(an, bf->bf_tidno);
1624
1625 if (!ieee80211_is_data_qos(fc)) {
1626 ath_tx_send_normal(sc, txctl->txq, &bf_head);
1627 goto tx_done;
1628 }
1629
1630 if (ath_aggr_query(sc, an, bf->bf_tidno)) {
1631 /*
1632 * Try aggregation if it's a unicast data frame
1633 * and the destination is HT capable.
1634 */
1635 ath_tx_send_ampdu(sc, tid, &bf_head, txctl);
1636 } else {
1637 /*
1638 * Send this frame as regular when ADDBA
1639 * exchange is neither complete nor pending.
1640 */
1641 ath_tx_send_ht_normal(sc, txctl->txq,
1642 tid, &bf_head);
1643 }
1644 } else {
1645 ath_tx_send_normal(sc, txctl->txq, &bf_head);
1646 }
1647
1648tx_done:
1649 spin_unlock_bh(&txctl->txq->axq_lock);
1650}
1651
1652/* Upon failure caller should free skb */
1653int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
1654 struct ath_tx_control *txctl)
1655{
1656 struct ath_wiphy *aphy = hw->priv;
1657 struct ath_softc *sc = aphy->sc;
1658 struct ath_buf *bf;
1659 int r;
1660
1661 bf = ath_tx_get_buffer(sc);
1662 if (!bf) {
1663 DPRINTF(sc, ATH_DBG_XMIT, "TX buffers are full\n");
1664 return -1;
1665 }
1666
1667 r = ath_tx_setup_buffer(hw, bf, skb, txctl);
1668 if (unlikely(r)) {
1669 struct ath_txq *txq = txctl->txq;
1670
1671 DPRINTF(sc, ATH_DBG_FATAL, "TX mem alloc failure\n");
1672
1673 /* upon ath_tx_processq() this TX queue will be resumed, we
1674 * guarantee this will happen by knowing beforehand that
1675 * we will at least have to run TX completionon one buffer
1676 * on the queue */
1677 spin_lock_bh(&txq->axq_lock);
1678 if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) {
1679 ieee80211_stop_queue(sc->hw,
1680 skb_get_queue_mapping(skb));
1681 txq->stopped = 1;
1682 }
1683 spin_unlock_bh(&txq->axq_lock);
1684
1685 spin_lock_bh(&sc->tx.txbuflock);
1686 list_add_tail(&bf->list, &sc->tx.txbuf);
1687 spin_unlock_bh(&sc->tx.txbuflock);
1688
1689 return r;
1690 }
1691
1692 ath_tx_start_dma(sc, bf, txctl);
1693
1694 return 0;
1695}
1696
1697void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
1698{
1699 struct ath_wiphy *aphy = hw->priv;
1700 struct ath_softc *sc = aphy->sc;
1701 int hdrlen, padsize;
1702 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1703 struct ath_tx_control txctl;
1704
1705 memset(&txctl, 0, sizeof(struct ath_tx_control));
1706
1707 /*
1708 * As a temporary workaround, assign seq# here; this will likely need
1709 * to be cleaned up to work better with Beacon transmission and virtual
1710 * BSSes.
1711 */
1712 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
1713 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1714 if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
1715 sc->tx.seq_no += 0x10;
1716 hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
1717 hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
1718 }
1719
1720 /* Add the padding after the header if this is not already done */
1721 hdrlen = ieee80211_get_hdrlen_from_skb(skb);
1722 if (hdrlen & 3) {
1723 padsize = hdrlen % 4;
1724 if (skb_headroom(skb) < padsize) {
1725 DPRINTF(sc, ATH_DBG_XMIT, "TX CABQ padding failed\n");
1726 dev_kfree_skb_any(skb);
1727 return;
1728 }
1729 skb_push(skb, padsize);
1730 memmove(skb->data, skb->data + padsize, hdrlen);
1731 }
1732
1733 txctl.txq = sc->beacon.cabq;
1734
1735 DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb);
1736
1737 if (ath_tx_start(hw, skb, &txctl) != 0) {
1738 DPRINTF(sc, ATH_DBG_XMIT, "CABQ TX failed\n");
1739 goto exit;
1740 }
1741
1742 return;
1743exit:
1744 dev_kfree_skb_any(skb);
1745}
1746
1747/*****************/
1748/* TX Completion */
1749/*****************/
1750
1751static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
1752 int tx_flags)
1753{
1754 struct ieee80211_hw *hw = sc->hw;
1755 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1756 struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
1757 int hdrlen, padsize;
1758 int frame_type = ATH9K_NOT_INTERNAL;
1759
1760 DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
1761
1762 if (tx_info_priv) {
1763 hw = tx_info_priv->aphy->hw;
1764 frame_type = tx_info_priv->frame_type;
1765 }
1766
1767 if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
1768 tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
1769 kfree(tx_info_priv);
1770 tx_info->rate_driver_data[0] = NULL;
1771 }
1772
1773 if (tx_flags & ATH_TX_BAR)
1774 tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
1775
1776 if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) {
1777 /* Frame was ACKed */
1778 tx_info->flags |= IEEE80211_TX_STAT_ACK;
1779 }
1780
1781 hdrlen = ieee80211_get_hdrlen_from_skb(skb);
1782 padsize = hdrlen & 3;
1783 if (padsize && hdrlen >= 24) {
1784 /*
1785 * Remove MAC header padding before giving the frame back to
1786 * mac80211.
1787 */
1788 memmove(skb->data + padsize, skb->data, hdrlen);
1789 skb_pull(skb, padsize);
1790 }
1791
1792 if (frame_type == ATH9K_NOT_INTERNAL)
1793 ieee80211_tx_status(hw, skb);
1794 else
1795 ath9k_tx_status(hw, skb);
1796}
1797
1798static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
1799 struct list_head *bf_q,
1800 int txok, int sendbar)
1801{
1802 struct sk_buff *skb = bf->bf_mpdu;
1803 unsigned long flags;
1804 int tx_flags = 0;
1805
1806
1807 if (sendbar)
1808 tx_flags = ATH_TX_BAR;
1809
1810 if (!txok) {
1811 tx_flags |= ATH_TX_ERROR;
1812
1813 if (bf_isxretried(bf))
1814 tx_flags |= ATH_TX_XRETRY;
1815 }
1816
1817 dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
1818 ath_tx_complete(sc, skb, tx_flags);
1819
1820 /*
1821 * Return the list of ath_buf of this mpdu to free queue
1822 */
1823 spin_lock_irqsave(&sc->tx.txbuflock, flags);
1824 list_splice_tail_init(bf_q, &sc->tx.txbuf);
1825 spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
1826}
1827
1828static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
1829 int txok)
1830{
1831 struct ath_buf *bf_last = bf->bf_lastbf;
1832 struct ath_desc *ds = bf_last->bf_desc;
1833 u16 seq_st = 0;
1834 u32 ba[WME_BA_BMP_SIZE >> 5];
1835 int ba_index;
1836 int nbad = 0;
1837 int isaggr = 0;
1838
1839 if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
1840 return 0;
1841
1842 isaggr = bf_isaggr(bf);
1843 if (isaggr) {
1844 seq_st = ATH_DS_BA_SEQ(ds);
1845 memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3);
1846 }
1847
1848 while (bf) {
1849 ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno);
1850 if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
1851 nbad++;
1852
1853 bf = bf->bf_next;
1854 }
1855
1856 return nbad;
1857}
1858
1859static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
1860 int nbad, int txok, bool update_rc)
1861{
1862 struct sk_buff *skb = bf->bf_mpdu;
1863 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1864 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1865 struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
1866 struct ieee80211_hw *hw = tx_info_priv->aphy->hw;
1867 u8 i, tx_rateindex;
1868
1869 if (txok)
1870 tx_info->status.ack_signal = ds->ds_txstat.ts_rssi;
1871
1872 tx_rateindex = ds->ds_txstat.ts_rateindex;
1873 WARN_ON(tx_rateindex >= hw->max_rates);
1874
1875 tx_info_priv->update_rc = update_rc;
1876 if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT)
1877 tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
1878
1879 if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 &&
1880 (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
1881 if (ieee80211_is_data(hdr->frame_control)) {
1882 memcpy(&tx_info_priv->tx, &ds->ds_txstat,
1883 sizeof(tx_info_priv->tx));
1884 tx_info_priv->n_frames = bf->bf_nframes;
1885 tx_info_priv->n_bad_frames = nbad;
1886 }
1887 }
1888
1889 for (i = tx_rateindex + 1; i < hw->max_rates; i++)
1890 tx_info->status.rates[i].count = 0;
1891
1892 tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1;
1893}
1894
1895static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
1896{
1897 int qnum;
1898
1899 spin_lock_bh(&txq->axq_lock);
1900 if (txq->stopped &&
1901 sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) {
1902 qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc);
1903 if (qnum != -1) {
1904 ieee80211_wake_queue(sc->hw, qnum);
1905 txq->stopped = 0;
1906 }
1907 }
1908 spin_unlock_bh(&txq->axq_lock);
1909}
1910
1911static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
1912{
1913 struct ath_hw *ah = sc->sc_ah;
1914 struct ath_buf *bf, *lastbf, *bf_held = NULL;
1915 struct list_head bf_head;
1916 struct ath_desc *ds;
1917 int txok;
1918 int status;
1919
1920 DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
1921 txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
1922 txq->axq_link);
1923
1924 for (;;) {
1925 spin_lock_bh(&txq->axq_lock);
1926 if (list_empty(&txq->axq_q)) {
1927 txq->axq_link = NULL;
1928 txq->axq_linkbuf = NULL;
1929 spin_unlock_bh(&txq->axq_lock);
1930 break;
1931 }
1932 bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
1933
1934 /*
1935 * There is a race condition that a BH gets scheduled
1936 * after sw writes TxE and before hw re-load the last
1937 * descriptor to get the newly chained one.
1938 * Software must keep the last DONE descriptor as a
1939 * holding descriptor - software does so by marking
1940 * it with the STALE flag.
1941 */
1942 bf_held = NULL;
1943 if (bf->bf_stale) {
1944 bf_held = bf;
1945 if (list_is_last(&bf_held->list, &txq->axq_q)) {
1946 txq->axq_link = NULL;
1947 txq->axq_linkbuf = NULL;
1948 spin_unlock_bh(&txq->axq_lock);
1949
1950 /*
1951 * The holding descriptor is the last
1952 * descriptor in queue. It's safe to remove
1953 * the last holding descriptor in BH context.
1954 */
1955 spin_lock_bh(&sc->tx.txbuflock);
1956 list_move_tail(&bf_held->list, &sc->tx.txbuf);
1957 spin_unlock_bh(&sc->tx.txbuflock);
1958
1959 break;
1960 } else {
1961 bf = list_entry(bf_held->list.next,
1962 struct ath_buf, list);
1963 }
1964 }
1965
1966 lastbf = bf->bf_lastbf;
1967 ds = lastbf->bf_desc;
1968
1969 status = ath9k_hw_txprocdesc(ah, ds);
1970 if (status == -EINPROGRESS) {
1971 spin_unlock_bh(&txq->axq_lock);
1972 break;
1973 }
1974 if (bf->bf_desc == txq->axq_lastdsWithCTS)
1975 txq->axq_lastdsWithCTS = NULL;
1976 if (ds == txq->axq_gatingds)
1977 txq->axq_gatingds = NULL;
1978
1979 /*
1980 * Remove ath_buf's of the same transmit unit from txq,
1981 * however leave the last descriptor back as the holding
1982 * descriptor for hw.
1983 */
1984 lastbf->bf_stale = true;
1985 INIT_LIST_HEAD(&bf_head);
1986 if (!list_is_singular(&lastbf->list))
1987 list_cut_position(&bf_head,
1988 &txq->axq_q, lastbf->list.prev);
1989
1990 txq->axq_depth--;
1991 if (bf_isaggr(bf))
1992 txq->axq_aggr_depth--;
1993
1994 txok = (ds->ds_txstat.ts_status == 0);
1995 spin_unlock_bh(&txq->axq_lock);
1996
1997 if (bf_held) {
1998 spin_lock_bh(&sc->tx.txbuflock);
1999 list_move_tail(&bf_held->list, &sc->tx.txbuf);
2000 spin_unlock_bh(&sc->tx.txbuflock);
2001 }
2002
2003 if (!bf_isampdu(bf)) {
2004 /*
2005 * This frame is sent out as a single frame.
2006 * Use hardware retry status for this frame.
2007 */
2008 bf->bf_retries = ds->ds_txstat.ts_longretry;
2009 if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY)
2010 bf->bf_state.bf_type |= BUF_XRETRY;
2011 ath_tx_rc_status(bf, ds, 0, txok, true);
2012 }
2013
2014 if (bf_isampdu(bf))
2015 ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok);
2016 else
2017 ath_tx_complete_buf(sc, bf, &bf_head, txok, 0);
2018
2019 ath_wake_mac80211_queue(sc, txq);
2020
2021 spin_lock_bh(&txq->axq_lock);
2022 if (sc->sc_flags & SC_OP_TXAGGR)
2023 ath_txq_schedule(sc, txq);
2024 spin_unlock_bh(&txq->axq_lock);
2025 }
2026}
2027
2028
2029void ath_tx_tasklet(struct ath_softc *sc)
2030{
2031 int i;
2032 u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1);
2033
2034 ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask);
2035
2036 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
2037 if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
2038 ath_tx_processq(sc, &sc->tx.txq[i]);
2039 }
2040}
2041
2042/*****************/
2043/* Init, Cleanup */
2044/*****************/
2045
2046int ath_tx_init(struct ath_softc *sc, int nbufs)
2047{
2048 int error = 0;
2049
2050 spin_lock_init(&sc->tx.txbuflock);
2051
2052 error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
2053 "tx", nbufs, 1);
2054 if (error != 0) {
2055 DPRINTF(sc, ATH_DBG_FATAL,
2056 "Failed to allocate tx descriptors: %d\n", error);
2057 goto err;
2058 }
2059
2060 error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
2061 "beacon", ATH_BCBUF, 1);
2062 if (error != 0) {
2063 DPRINTF(sc, ATH_DBG_FATAL,
2064 "Failed to allocate beacon descriptors: %d\n", error);
2065 goto err;
2066 }
2067
2068err:
2069 if (error != 0)
2070 ath_tx_cleanup(sc);
2071
2072 return error;
2073}
2074
2075void ath_tx_cleanup(struct ath_softc *sc)
2076{
2077 if (sc->beacon.bdma.dd_desc_len != 0)
2078 ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf);
2079
2080 if (sc->tx.txdma.dd_desc_len != 0)
2081 ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
2082}
2083
2084void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
2085{
2086 struct ath_atx_tid *tid;
2087 struct ath_atx_ac *ac;
2088 int tidno, acno;
2089
2090 for (tidno = 0, tid = &an->tid[tidno];
2091 tidno < WME_NUM_TID;
2092 tidno++, tid++) {
2093 tid->an = an;
2094 tid->tidno = tidno;
2095 tid->seq_start = tid->seq_next = 0;
2096 tid->baw_size = WME_MAX_BA;
2097 tid->baw_head = tid->baw_tail = 0;
2098 tid->sched = false;
2099 tid->paused = false;
2100 tid->state &= ~AGGR_CLEANUP;
2101 INIT_LIST_HEAD(&tid->buf_q);
2102 acno = TID_TO_WME_AC(tidno);
2103 tid->ac = &an->ac[acno];
2104 tid->state &= ~AGGR_ADDBA_COMPLETE;
2105 tid->state &= ~AGGR_ADDBA_PROGRESS;
2106 tid->addba_exchangeattempts = 0;
2107 }
2108
2109 for (acno = 0, ac = &an->ac[acno];
2110 acno < WME_NUM_AC; acno++, ac++) {
2111 ac->sched = false;
2112 INIT_LIST_HEAD(&ac->tid_q);
2113
2114 switch (acno) {
2115 case WME_AC_BE:
2116 ac->qnum = ath_tx_get_qnum(sc,
2117 ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE);
2118 break;
2119 case WME_AC_BK:
2120 ac->qnum = ath_tx_get_qnum(sc,
2121 ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK);
2122 break;
2123 case WME_AC_VI:
2124 ac->qnum = ath_tx_get_qnum(sc,
2125 ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI);
2126 break;
2127 case WME_AC_VO:
2128 ac->qnum = ath_tx_get_qnum(sc,
2129 ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO);
2130 break;
2131 }
2132 }
2133}
2134
2135void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
2136{
2137 int i;
2138 struct ath_atx_ac *ac, *ac_tmp;
2139 struct ath_atx_tid *tid, *tid_tmp;
2140 struct ath_txq *txq;
2141
2142 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
2143 if (ATH_TXQ_SETUP(sc, i)) {
2144 txq = &sc->tx.txq[i];
2145
2146 spin_lock(&txq->axq_lock);
2147
2148 list_for_each_entry_safe(ac,
2149 ac_tmp, &txq->axq_acq, list) {
2150 tid = list_first_entry(&ac->tid_q,
2151 struct ath_atx_tid, list);
2152 if (tid && tid->an != an)
2153 continue;
2154 list_del(&ac->list);
2155 ac->sched = false;
2156
2157 list_for_each_entry_safe(tid,
2158 tid_tmp, &ac->tid_q, list) {
2159 list_del(&tid->list);
2160 tid->sched = false;
2161 ath_tid_drain(sc, txq, tid);
2162 tid->state &= ~AGGR_ADDBA_COMPLETE;
2163 tid->addba_exchangeattempts = 0;
2164 tid->state &= ~AGGR_CLEANUP;
2165 }
2166 }
2167
2168 spin_unlock(&txq->axq_lock);
2169 }
2170 }
2171}