1fb9987d0SSujith /*
25b68138eSSujith Manoharan  * Copyright (c) 2010-2011 Atheros Communications Inc.
3fb9987d0SSujith  *
4fb9987d0SSujith  * Permission to use, copy, modify, and/or distribute this software for any
5fb9987d0SSujith  * purpose with or without fee is hereby granted, provided that the above
6fb9987d0SSujith  * copyright notice and this permission notice appear in all copies.
7fb9987d0SSujith  *
8fb9987d0SSujith  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9fb9987d0SSujith  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10fb9987d0SSujith  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11fb9987d0SSujith  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12fb9987d0SSujith  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13fb9987d0SSujith  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14fb9987d0SSujith  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15fb9987d0SSujith  */
16fb9987d0SSujith 
17fb9987d0SSujith #include "htc.h"
18fb9987d0SSujith 
19fb9987d0SSujith MODULE_AUTHOR("Atheros Communications");
20fb9987d0SSujith MODULE_LICENSE("Dual BSD/GPL");
21fb9987d0SSujith MODULE_DESCRIPTION("Atheros driver 802.11n HTC based wireless devices");
22fb9987d0SSujith 
23fb9987d0SSujith static unsigned int ath9k_debug = ATH_DBG_DEFAULT;
24fb9987d0SSujith module_param_named(debug, ath9k_debug, uint, 0);
25fb9987d0SSujith MODULE_PARM_DESC(debug, "Debugging mask");
26fb9987d0SSujith 
27e1572c5eSSujith int htc_modparam_nohwcrypt;
28e1572c5eSSujith module_param_named(nohwcrypt, htc_modparam_nohwcrypt, int, 0444);
29fb9987d0SSujith MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
30fb9987d0SSujith 
31fb9987d0SSujith #define CHAN2G(_freq, _idx)  { \
32fb9987d0SSujith 	.center_freq = (_freq), \
33fb9987d0SSujith 	.hw_value = (_idx), \
34fb9987d0SSujith 	.max_power = 20, \
35fb9987d0SSujith }
36fb9987d0SSujith 
37ea46e644SSujith #define CHAN5G(_freq, _idx) { \
38ea46e644SSujith 	.band = IEEE80211_BAND_5GHZ, \
39ea46e644SSujith 	.center_freq = (_freq), \
40ea46e644SSujith 	.hw_value = (_idx), \
41ea46e644SSujith 	.max_power = 20, \
42ea46e644SSujith }
43ea46e644SSujith 
44fb9987d0SSujith static struct ieee80211_channel ath9k_2ghz_channels[] = {
45fb9987d0SSujith 	CHAN2G(2412, 0), /* Channel 1 */
46fb9987d0SSujith 	CHAN2G(2417, 1), /* Channel 2 */
47fb9987d0SSujith 	CHAN2G(2422, 2), /* Channel 3 */
48fb9987d0SSujith 	CHAN2G(2427, 3), /* Channel 4 */
49fb9987d0SSujith 	CHAN2G(2432, 4), /* Channel 5 */
50fb9987d0SSujith 	CHAN2G(2437, 5), /* Channel 6 */
51fb9987d0SSujith 	CHAN2G(2442, 6), /* Channel 7 */
52fb9987d0SSujith 	CHAN2G(2447, 7), /* Channel 8 */
53fb9987d0SSujith 	CHAN2G(2452, 8), /* Channel 9 */
54fb9987d0SSujith 	CHAN2G(2457, 9), /* Channel 10 */
55fb9987d0SSujith 	CHAN2G(2462, 10), /* Channel 11 */
56fb9987d0SSujith 	CHAN2G(2467, 11), /* Channel 12 */
57fb9987d0SSujith 	CHAN2G(2472, 12), /* Channel 13 */
58fb9987d0SSujith 	CHAN2G(2484, 13), /* Channel 14 */
59fb9987d0SSujith };
60fb9987d0SSujith 
61ea46e644SSujith static struct ieee80211_channel ath9k_5ghz_channels[] = {
62ea46e644SSujith 	/* _We_ call this UNII 1 */
63ea46e644SSujith 	CHAN5G(5180, 14), /* Channel 36 */
64ea46e644SSujith 	CHAN5G(5200, 15), /* Channel 40 */
65ea46e644SSujith 	CHAN5G(5220, 16), /* Channel 44 */
66ea46e644SSujith 	CHAN5G(5240, 17), /* Channel 48 */
67ea46e644SSujith 	/* _We_ call this UNII 2 */
68ea46e644SSujith 	CHAN5G(5260, 18), /* Channel 52 */
69ea46e644SSujith 	CHAN5G(5280, 19), /* Channel 56 */
70ea46e644SSujith 	CHAN5G(5300, 20), /* Channel 60 */
71ea46e644SSujith 	CHAN5G(5320, 21), /* Channel 64 */
72ea46e644SSujith 	/* _We_ call this "Middle band" */
73ea46e644SSujith 	CHAN5G(5500, 22), /* Channel 100 */
74ea46e644SSujith 	CHAN5G(5520, 23), /* Channel 104 */
75ea46e644SSujith 	CHAN5G(5540, 24), /* Channel 108 */
76ea46e644SSujith 	CHAN5G(5560, 25), /* Channel 112 */
77ea46e644SSujith 	CHAN5G(5580, 26), /* Channel 116 */
78ea46e644SSujith 	CHAN5G(5600, 27), /* Channel 120 */
79ea46e644SSujith 	CHAN5G(5620, 28), /* Channel 124 */
80ea46e644SSujith 	CHAN5G(5640, 29), /* Channel 128 */
81ea46e644SSujith 	CHAN5G(5660, 30), /* Channel 132 */
82ea46e644SSujith 	CHAN5G(5680, 31), /* Channel 136 */
83ea46e644SSujith 	CHAN5G(5700, 32), /* Channel 140 */
84ea46e644SSujith 	/* _We_ call this UNII 3 */
85ea46e644SSujith 	CHAN5G(5745, 33), /* Channel 149 */
86ea46e644SSujith 	CHAN5G(5765, 34), /* Channel 153 */
87ea46e644SSujith 	CHAN5G(5785, 35), /* Channel 157 */
88ea46e644SSujith 	CHAN5G(5805, 36), /* Channel 161 */
89ea46e644SSujith 	CHAN5G(5825, 37), /* Channel 165 */
90ea46e644SSujith };
91ea46e644SSujith 
92fb9987d0SSujith /* Atheros hardware rate code addition for short premble */
93fb9987d0SSujith #define SHPCHECK(__hw_rate, __flags) \
94fb9987d0SSujith 	((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0)
95fb9987d0SSujith 
96fb9987d0SSujith #define RATE(_bitrate, _hw_rate, _flags) {		\
97fb9987d0SSujith 	.bitrate	= (_bitrate),			\
98fb9987d0SSujith 	.flags		= (_flags),			\
99fb9987d0SSujith 	.hw_value	= (_hw_rate),			\
100fb9987d0SSujith 	.hw_value_short = (SHPCHECK(_hw_rate, _flags))	\
101fb9987d0SSujith }
102fb9987d0SSujith 
103fb9987d0SSujith static struct ieee80211_rate ath9k_legacy_rates[] = {
104fb9987d0SSujith 	RATE(10, 0x1b, 0),
105fb9987d0SSujith 	RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp : 0x1e */
106fb9987d0SSujith 	RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp: 0x1d */
107fb9987d0SSujith 	RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), /* short: 0x1c */
108fb9987d0SSujith 	RATE(60, 0x0b, 0),
109fb9987d0SSujith 	RATE(90, 0x0f, 0),
110fb9987d0SSujith 	RATE(120, 0x0a, 0),
111fb9987d0SSujith 	RATE(180, 0x0e, 0),
112fb9987d0SSujith 	RATE(240, 0x09, 0),
113fb9987d0SSujith 	RATE(360, 0x0d, 0),
114fb9987d0SSujith 	RATE(480, 0x08, 0),
115fb9987d0SSujith 	RATE(540, 0x0c, 0),
116fb9987d0SSujith };
117fb9987d0SSujith 
118d244f21eSSujith Manoharan #ifdef CONFIG_MAC80211_LEDS
119d244f21eSSujith Manoharan static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = {
120d244f21eSSujith Manoharan 	{ .throughput = 0 * 1024, .blink_time = 334 },
121d244f21eSSujith Manoharan 	{ .throughput = 1 * 1024, .blink_time = 260 },
122d244f21eSSujith Manoharan 	{ .throughput = 5 * 1024, .blink_time = 220 },
123d244f21eSSujith Manoharan 	{ .throughput = 10 * 1024, .blink_time = 190 },
124d244f21eSSujith Manoharan 	{ .throughput = 20 * 1024, .blink_time = 170 },
125d244f21eSSujith Manoharan 	{ .throughput = 50 * 1024, .blink_time = 150 },
126d244f21eSSujith Manoharan 	{ .throughput = 70 * 1024, .blink_time = 130 },
127d244f21eSSujith Manoharan 	{ .throughput = 100 * 1024, .blink_time = 110 },
128d244f21eSSujith Manoharan 	{ .throughput = 200 * 1024, .blink_time = 80 },
129d244f21eSSujith Manoharan 	{ .throughput = 300 * 1024, .blink_time = 50 },
130d244f21eSSujith Manoharan };
131d244f21eSSujith Manoharan #endif
132d244f21eSSujith Manoharan 
133fb9987d0SSujith static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
134fb9987d0SSujith {
135fb9987d0SSujith 	int time_left;
136fb9987d0SSujith 
137d8c49ffbSSujith.Manoharan@atheros.com 	if (atomic_read(&priv->htc->tgt_ready) > 0) {
138d8c49ffbSSujith.Manoharan@atheros.com 		atomic_dec(&priv->htc->tgt_ready);
139d8c49ffbSSujith.Manoharan@atheros.com 		return 0;
140d8c49ffbSSujith.Manoharan@atheros.com 	}
141d8c49ffbSSujith.Manoharan@atheros.com 
142fb9987d0SSujith 	/* Firmware can take up to 50ms to get ready, to be safe use 1 second */
143fb9987d0SSujith 	time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ);
144fb9987d0SSujith 	if (!time_left) {
145fb9987d0SSujith 		dev_err(priv->dev, "ath9k_htc: Target is unresponsive\n");
146fb9987d0SSujith 		return -ETIMEDOUT;
147fb9987d0SSujith 	}
148fb9987d0SSujith 
149d8c49ffbSSujith.Manoharan@atheros.com 	atomic_dec(&priv->htc->tgt_ready);
150d8c49ffbSSujith.Manoharan@atheros.com 
151fb9987d0SSujith 	return 0;
152fb9987d0SSujith }
153fb9987d0SSujith 
154fb9987d0SSujith static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
155fb9987d0SSujith {
156fb9987d0SSujith 	ath9k_hw_deinit(priv->ah);
157fb9987d0SSujith 	kfree(priv->ah);
158fb9987d0SSujith 	priv->ah = NULL;
159fb9987d0SSujith }
160fb9987d0SSujith 
161fb9987d0SSujith static void ath9k_deinit_device(struct ath9k_htc_priv *priv)
162fb9987d0SSujith {
163fb9987d0SSujith 	struct ieee80211_hw *hw = priv->hw;
164fb9987d0SSujith 
165fb9987d0SSujith 	wiphy_rfkill_stop_polling(hw->wiphy);
166fb9987d0SSujith 	ath9k_deinit_leds(priv);
167fb9987d0SSujith 	ieee80211_unregister_hw(hw);
168fb9987d0SSujith 	ath9k_rx_cleanup(priv);
169fb9987d0SSujith 	ath9k_tx_cleanup(priv);
170fb9987d0SSujith 	ath9k_deinit_priv(priv);
171fb9987d0SSujith }
172fb9987d0SSujith 
173fb9987d0SSujith static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv,
174fb9987d0SSujith 					u16 service_id,
175fb9987d0SSujith 					void (*tx) (void *,
176fb9987d0SSujith 						    struct sk_buff *,
177fb9987d0SSujith 						    enum htc_endpoint_id,
178fb9987d0SSujith 						    bool txok),
179fb9987d0SSujith 					enum htc_endpoint_id *ep_id)
180fb9987d0SSujith {
181fb9987d0SSujith 	struct htc_service_connreq req;
182fb9987d0SSujith 
183fb9987d0SSujith 	memset(&req, 0, sizeof(struct htc_service_connreq));
184fb9987d0SSujith 
185fb9987d0SSujith 	req.service_id = service_id;
186fb9987d0SSujith 	req.ep_callbacks.priv = priv;
187fb9987d0SSujith 	req.ep_callbacks.rx = ath9k_htc_rxep;
188fb9987d0SSujith 	req.ep_callbacks.tx = tx;
189fb9987d0SSujith 
190fb9987d0SSujith 	return htc_connect_service(priv->htc, &req, ep_id);
191fb9987d0SSujith }
192fb9987d0SSujith 
193fa6e15e0SRajkumar Manoharan static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid,
194fa6e15e0SRajkumar Manoharan 				   u32 drv_info)
195fb9987d0SSujith {
196fb9987d0SSujith 	int ret;
197fb9987d0SSujith 
198fb9987d0SSujith 	/* WMI CMD*/
199fb9987d0SSujith 	ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep);
200fb9987d0SSujith 	if (ret)
201fb9987d0SSujith 		goto err;
202fb9987d0SSujith 
203fb9987d0SSujith 	/* Beacon */
2049c6dda4eSSujith 	ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, ath9k_htc_beaconep,
205fb9987d0SSujith 				    &priv->beacon_ep);
206fb9987d0SSujith 	if (ret)
207fb9987d0SSujith 		goto err;
208fb9987d0SSujith 
209fb9987d0SSujith 	/* CAB */
210fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep,
211fb9987d0SSujith 				    &priv->cab_ep);
212fb9987d0SSujith 	if (ret)
213fb9987d0SSujith 		goto err;
214fb9987d0SSujith 
215fb9987d0SSujith 
216fb9987d0SSujith 	/* UAPSD */
217fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep,
218fb9987d0SSujith 				    &priv->uapsd_ep);
219fb9987d0SSujith 	if (ret)
220fb9987d0SSujith 		goto err;
221fb9987d0SSujith 
222fb9987d0SSujith 	/* MGMT */
223fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep,
224fb9987d0SSujith 				    &priv->mgmt_ep);
225fb9987d0SSujith 	if (ret)
226fb9987d0SSujith 		goto err;
227fb9987d0SSujith 
228fb9987d0SSujith 	/* DATA BE */
229fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep,
230fb9987d0SSujith 				    &priv->data_be_ep);
231fb9987d0SSujith 	if (ret)
232fb9987d0SSujith 		goto err;
233fb9987d0SSujith 
234fb9987d0SSujith 	/* DATA BK */
235fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep,
236fb9987d0SSujith 				    &priv->data_bk_ep);
237fb9987d0SSujith 	if (ret)
238fb9987d0SSujith 		goto err;
239fb9987d0SSujith 
240fb9987d0SSujith 	/* DATA VI */
241fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep,
242fb9987d0SSujith 				    &priv->data_vi_ep);
243fb9987d0SSujith 	if (ret)
244fb9987d0SSujith 		goto err;
245fb9987d0SSujith 
246fb9987d0SSujith 	/* DATA VO */
247fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep,
248fb9987d0SSujith 				    &priv->data_vo_ep);
249fb9987d0SSujith 	if (ret)
250fb9987d0SSujith 		goto err;
251fb9987d0SSujith 
2526267dc70SSujith 	/*
2536267dc70SSujith 	 * Setup required credits before initializing HTC.
2546267dc70SSujith 	 * This is a bit hacky, but, since queuing is done in
2556267dc70SSujith 	 * the HIF layer, shouldn't matter much.
2566267dc70SSujith 	 */
2576267dc70SSujith 
2580b5ead91SSujith Manoharan 	if (IS_AR7010_DEVICE(drv_info))
259d108e8b9SSujith Manoharan 		priv->htc->credits = 45;
260fa6e15e0SRajkumar Manoharan 	else
2614e63f768SSujith 		priv->htc->credits = 33;
2626267dc70SSujith 
263fb9987d0SSujith 	ret = htc_init(priv->htc);
264fb9987d0SSujith 	if (ret)
265fb9987d0SSujith 		goto err;
266fb9987d0SSujith 
2676267dc70SSujith 	dev_info(priv->dev, "ath9k_htc: HTC initialized with %d credits\n",
2686267dc70SSujith 		 priv->htc->credits);
2696267dc70SSujith 
270fb9987d0SSujith 	return 0;
271fb9987d0SSujith 
272fb9987d0SSujith err:
273fb9987d0SSujith 	dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n");
274fb9987d0SSujith 	return ret;
275fb9987d0SSujith }
276fb9987d0SSujith 
277fb9987d0SSujith static int ath9k_reg_notifier(struct wiphy *wiphy,
278fb9987d0SSujith 			      struct regulatory_request *request)
279fb9987d0SSujith {
280fb9987d0SSujith 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
281fb9987d0SSujith 	struct ath9k_htc_priv *priv = hw->priv;
282fb9987d0SSujith 
283fb9987d0SSujith 	return ath_reg_notifier_apply(wiphy, request,
284fb9987d0SSujith 				      ath9k_hw_regulatory(priv->ah));
285fb9987d0SSujith }
286fb9987d0SSujith 
2874a22fe10SSujith static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
288fb9987d0SSujith {
289fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
290fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(ah);
291fb9987d0SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
292fb9987d0SSujith 	__be32 val, reg = cpu_to_be32(reg_offset);
293fb9987d0SSujith 	int r;
294fb9987d0SSujith 
295fb9987d0SSujith 	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
296fb9987d0SSujith 			  (u8 *) &reg, sizeof(reg),
297fb9987d0SSujith 			  (u8 *) &val, sizeof(val),
298fb9987d0SSujith 			  100);
299fb9987d0SSujith 	if (unlikely(r)) {
300d2182b69SJoe Perches 		ath_dbg(common, WMI, "REGISTER READ FAILED: (0x%04x, %d)\n",
301fb9987d0SSujith 			reg_offset, r);
302fb9987d0SSujith 		return -EIO;
303fb9987d0SSujith 	}
304fb9987d0SSujith 
305fb9987d0SSujith 	return be32_to_cpu(val);
306fb9987d0SSujith }
307fb9987d0SSujith 
30809a525d3SSujith Manoharan static void ath9k_multi_regread(void *hw_priv, u32 *addr,
30909a525d3SSujith Manoharan 				u32 *val, u16 count)
31009a525d3SSujith Manoharan {
31109a525d3SSujith Manoharan 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
31209a525d3SSujith Manoharan 	struct ath_common *common = ath9k_hw_common(ah);
31309a525d3SSujith Manoharan 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
31409a525d3SSujith Manoharan 	__be32 tmpaddr[8];
31509a525d3SSujith Manoharan 	__be32 tmpval[8];
31609a525d3SSujith Manoharan 	int i, ret;
31709a525d3SSujith Manoharan 
31809a525d3SSujith Manoharan        for (i = 0; i < count; i++) {
31909a525d3SSujith Manoharan 	       tmpaddr[i] = cpu_to_be32(addr[i]);
32009a525d3SSujith Manoharan        }
32109a525d3SSujith Manoharan 
32209a525d3SSujith Manoharan        ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
32309a525d3SSujith Manoharan 			   (u8 *)tmpaddr , sizeof(u32) * count,
32409a525d3SSujith Manoharan 			   (u8 *)tmpval, sizeof(u32) * count,
32509a525d3SSujith Manoharan 			   100);
32609a525d3SSujith Manoharan 	if (unlikely(ret)) {
327d2182b69SJoe Perches 		ath_dbg(common, WMI,
32809a525d3SSujith Manoharan 			"Multiple REGISTER READ FAILED (count: %d)\n", count);
32909a525d3SSujith Manoharan 	}
33009a525d3SSujith Manoharan 
33109a525d3SSujith Manoharan        for (i = 0; i < count; i++) {
33209a525d3SSujith Manoharan 	       val[i] = be32_to_cpu(tmpval[i]);
33309a525d3SSujith Manoharan        }
33409a525d3SSujith Manoharan }
33509a525d3SSujith Manoharan 
3364a22fe10SSujith static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
337fb9987d0SSujith {
338fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
339fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(ah);
340fb9987d0SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
34107b2fa5aSJoe Perches 	const __be32 buf[2] = {
342fb9987d0SSujith 		cpu_to_be32(reg_offset),
343fb9987d0SSujith 		cpu_to_be32(val),
344fb9987d0SSujith 	};
345fb9987d0SSujith 	int r;
346fb9987d0SSujith 
347fb9987d0SSujith 	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
348fb9987d0SSujith 			  (u8 *) &buf, sizeof(buf),
349fb9987d0SSujith 			  (u8 *) &val, sizeof(val),
350fb9987d0SSujith 			  100);
351fb9987d0SSujith 	if (unlikely(r)) {
352d2182b69SJoe Perches 		ath_dbg(common, WMI, "REGISTER WRITE FAILED:(0x%04x, %d)\n",
353fb9987d0SSujith 			reg_offset, r);
354fb9987d0SSujith 	}
355fb9987d0SSujith }
356fb9987d0SSujith 
3574a22fe10SSujith static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset)
3584a22fe10SSujith {
3594a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3604a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3614a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3624a22fe10SSujith 	u32 rsp_status;
3634a22fe10SSujith 	int r;
3644a22fe10SSujith 
3654a22fe10SSujith 	mutex_lock(&priv->wmi->multi_write_mutex);
3664a22fe10SSujith 
3674a22fe10SSujith 	/* Store the register/value */
3684a22fe10SSujith 	priv->wmi->multi_write[priv->wmi->multi_write_idx].reg =
3694a22fe10SSujith 		cpu_to_be32(reg_offset);
3704a22fe10SSujith 	priv->wmi->multi_write[priv->wmi->multi_write_idx].val =
3714a22fe10SSujith 		cpu_to_be32(val);
3724a22fe10SSujith 
3734a22fe10SSujith 	priv->wmi->multi_write_idx++;
3744a22fe10SSujith 
3754a22fe10SSujith 	/* If the buffer is full, send it out. */
3764a22fe10SSujith 	if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) {
3774a22fe10SSujith 		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
3784a22fe10SSujith 			  (u8 *) &priv->wmi->multi_write,
3794a22fe10SSujith 			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
3804a22fe10SSujith 			  (u8 *) &rsp_status, sizeof(rsp_status),
3814a22fe10SSujith 			  100);
3824a22fe10SSujith 		if (unlikely(r)) {
383d2182b69SJoe Perches 			ath_dbg(common, WMI,
3844a22fe10SSujith 				"REGISTER WRITE FAILED, multi len: %d\n",
3854a22fe10SSujith 				priv->wmi->multi_write_idx);
3864a22fe10SSujith 		}
3874a22fe10SSujith 		priv->wmi->multi_write_idx = 0;
3884a22fe10SSujith 	}
3894a22fe10SSujith 
3904a22fe10SSujith 	mutex_unlock(&priv->wmi->multi_write_mutex);
3914a22fe10SSujith }
3924a22fe10SSujith 
3934a22fe10SSujith static void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset)
3944a22fe10SSujith {
3954a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3964a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3974a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3984a22fe10SSujith 
3994a22fe10SSujith 	if (atomic_read(&priv->wmi->mwrite_cnt))
4004a22fe10SSujith 		ath9k_regwrite_buffer(hw_priv, val, reg_offset);
4014a22fe10SSujith 	else
4024a22fe10SSujith 		ath9k_regwrite_single(hw_priv, val, reg_offset);
4034a22fe10SSujith }
4044a22fe10SSujith 
4054a22fe10SSujith static void ath9k_enable_regwrite_buffer(void *hw_priv)
4064a22fe10SSujith {
4074a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
4084a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
4094a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
4104a22fe10SSujith 
4114a22fe10SSujith 	atomic_inc(&priv->wmi->mwrite_cnt);
4124a22fe10SSujith }
4134a22fe10SSujith 
4144a22fe10SSujith static void ath9k_regwrite_flush(void *hw_priv)
4154a22fe10SSujith {
4164a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
4174a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
4184a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
4194a22fe10SSujith 	u32 rsp_status;
4204a22fe10SSujith 	int r;
4214a22fe10SSujith 
422435c1610SFelix Fietkau 	atomic_dec(&priv->wmi->mwrite_cnt);
423435c1610SFelix Fietkau 
4244a22fe10SSujith 	mutex_lock(&priv->wmi->multi_write_mutex);
4254a22fe10SSujith 
4264a22fe10SSujith 	if (priv->wmi->multi_write_idx) {
4274a22fe10SSujith 		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
4284a22fe10SSujith 			  (u8 *) &priv->wmi->multi_write,
4294a22fe10SSujith 			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
4304a22fe10SSujith 			  (u8 *) &rsp_status, sizeof(rsp_status),
4314a22fe10SSujith 			  100);
4324a22fe10SSujith 		if (unlikely(r)) {
433d2182b69SJoe Perches 			ath_dbg(common, WMI,
4344a22fe10SSujith 				"REGISTER WRITE FAILED, multi len: %d\n",
4354a22fe10SSujith 				priv->wmi->multi_write_idx);
4364a22fe10SSujith 		}
4374a22fe10SSujith 		priv->wmi->multi_write_idx = 0;
4384a22fe10SSujith 	}
4394a22fe10SSujith 
4404a22fe10SSujith 	mutex_unlock(&priv->wmi->multi_write_mutex);
4414a22fe10SSujith }
4424a22fe10SSujith 
443845e03c9SFelix Fietkau static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
444845e03c9SFelix Fietkau {
445845e03c9SFelix Fietkau 	u32 val;
446845e03c9SFelix Fietkau 
447845e03c9SFelix Fietkau 	val = ath9k_regread(hw_priv, reg_offset);
448845e03c9SFelix Fietkau 	val &= ~clr;
449845e03c9SFelix Fietkau 	val |= set;
450845e03c9SFelix Fietkau 	ath9k_regwrite(hw_priv, val, reg_offset);
451845e03c9SFelix Fietkau 	return val;
452845e03c9SFelix Fietkau }
453845e03c9SFelix Fietkau 
454fb9987d0SSujith static void ath_usb_read_cachesize(struct ath_common *common, int *csz)
455fb9987d0SSujith {
456fb9987d0SSujith 	*csz = L1_CACHE_BYTES >> 2;
457fb9987d0SSujith }
458fb9987d0SSujith 
459fb9987d0SSujith static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
460fb9987d0SSujith {
461fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) common->ah;
462fb9987d0SSujith 
463fb9987d0SSujith 	(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
464fb9987d0SSujith 
465fb9987d0SSujith 	if (!ath9k_hw_wait(ah,
466fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA,
467fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA_BUSY |
468fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
469fb9987d0SSujith 			   AH_WAIT_TIMEOUT))
470fb9987d0SSujith 		return false;
471fb9987d0SSujith 
472fb9987d0SSujith 	*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
473fb9987d0SSujith 		   AR_EEPROM_STATUS_DATA_VAL);
474fb9987d0SSujith 
475fb9987d0SSujith 	return true;
476fb9987d0SSujith }
477fb9987d0SSujith 
478fb9987d0SSujith static const struct ath_bus_ops ath9k_usb_bus_ops = {
479497ad9adSSujith 	.ath_bus_type = ATH_USB,
480fb9987d0SSujith 	.read_cachesize = ath_usb_read_cachesize,
481fb9987d0SSujith 	.eeprom_read = ath_usb_eeprom_read,
482fb9987d0SSujith };
483fb9987d0SSujith 
484fb9987d0SSujith static void setup_ht_cap(struct ath9k_htc_priv *priv,
485fb9987d0SSujith 			 struct ieee80211_sta_ht_cap *ht_info)
486fb9987d0SSujith {
4876debecadSSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
4886debecadSSujith 	u8 tx_streams, rx_streams;
4896debecadSSujith 	int i;
4906debecadSSujith 
491fb9987d0SSujith 	ht_info->ht_supported = true;
492fb9987d0SSujith 	ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
493fb9987d0SSujith 		       IEEE80211_HT_CAP_SM_PS |
494fb9987d0SSujith 		       IEEE80211_HT_CAP_SGI_40 |
495fb9987d0SSujith 		       IEEE80211_HT_CAP_DSSSCCK40;
496fb9987d0SSujith 
497b4dec5e8SSujith 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
498b4dec5e8SSujith 		ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
499b4dec5e8SSujith 
50017525f96SSujith 	ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
50117525f96SSujith 
502fb9987d0SSujith 	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
503fb9987d0SSujith 	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
504fb9987d0SSujith 
505fb9987d0SSujith 	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
5066debecadSSujith 
5076debecadSSujith 	/* ath9k_htc supports only 1 or 2 stream devices */
50882b2d334SFelix Fietkau 	tx_streams = ath9k_cmn_count_streams(priv->ah->txchainmask, 2);
50982b2d334SFelix Fietkau 	rx_streams = ath9k_cmn_count_streams(priv->ah->rxchainmask, 2);
5106debecadSSujith 
511d2182b69SJoe Perches 	ath_dbg(common, CONFIG, "TX streams %d, RX streams: %d\n",
5126debecadSSujith 		tx_streams, rx_streams);
5136debecadSSujith 
5146debecadSSujith 	if (tx_streams != rx_streams) {
5156debecadSSujith 		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
5166debecadSSujith 		ht_info->mcs.tx_params |= ((tx_streams - 1) <<
5176debecadSSujith 					   IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
5186debecadSSujith 	}
5196debecadSSujith 
5206debecadSSujith 	for (i = 0; i < rx_streams; i++)
5216debecadSSujith 		ht_info->mcs.rx_mask[i] = 0xff;
5226debecadSSujith 
523fb9987d0SSujith 	ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
524fb9987d0SSujith }
525fb9987d0SSujith 
526fb9987d0SSujith static int ath9k_init_queues(struct ath9k_htc_priv *priv)
527fb9987d0SSujith {
528fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
529fb9987d0SSujith 	int i;
530fb9987d0SSujith 
531fb9987d0SSujith 	for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++)
532fb9987d0SSujith 		priv->hwq_map[i] = -1;
533fb9987d0SSujith 
534ca74b83bSSujith 	priv->beaconq = ath9k_hw_beaconq_setup(priv->ah);
535ca74b83bSSujith 	if (priv->beaconq == -1) {
5363800276aSJoe Perches 		ath_err(common, "Unable to setup BEACON xmit queue\n");
537ca74b83bSSujith 		goto err;
538ca74b83bSSujith 	}
539ca74b83bSSujith 
540ca74b83bSSujith 	priv->cabq = ath9k_htc_cabq_setup(priv);
541ca74b83bSSujith 	if (priv->cabq == -1) {
5423800276aSJoe Perches 		ath_err(common, "Unable to setup CAB xmit queue\n");
543ca74b83bSSujith 		goto err;
544ca74b83bSSujith 	}
545ca74b83bSSujith 
546e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) {
5473800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for BE traffic\n");
548fb9987d0SSujith 		goto err;
549fb9987d0SSujith 	}
550fb9987d0SSujith 
551e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) {
5523800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for BK traffic\n");
553fb9987d0SSujith 		goto err;
554fb9987d0SSujith 	}
555e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) {
5563800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for VI traffic\n");
557fb9987d0SSujith 		goto err;
558fb9987d0SSujith 	}
559e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) {
5603800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for VO traffic\n");
561fb9987d0SSujith 		goto err;
562fb9987d0SSujith 	}
563fb9987d0SSujith 
564fb9987d0SSujith 	return 0;
565fb9987d0SSujith 
566fb9987d0SSujith err:
567fb9987d0SSujith 	return -EINVAL;
568fb9987d0SSujith }
569fb9987d0SSujith 
570fb9987d0SSujith static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
571fb9987d0SSujith {
572d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
573fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].channels =
574fb9987d0SSujith 			ath9k_2ghz_channels;
575fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
576fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].n_channels =
577fb9987d0SSujith 			ARRAY_SIZE(ath9k_2ghz_channels);
578fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
579fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
580fb9987d0SSujith 			ARRAY_SIZE(ath9k_legacy_rates);
581fb9987d0SSujith 	}
582ea46e644SSujith 
583d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
584ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels;
585ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
586ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].n_channels =
587ea46e644SSujith 			ARRAY_SIZE(ath9k_5ghz_channels);
588ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].bitrates =
589ea46e644SSujith 			ath9k_legacy_rates + 4;
590ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
591ea46e644SSujith 			ARRAY_SIZE(ath9k_legacy_rates) - 4;
592ea46e644SSujith 	}
593fb9987d0SSujith }
594fb9987d0SSujith 
595fb9987d0SSujith static void ath9k_init_misc(struct ath9k_htc_priv *priv)
596fb9987d0SSujith {
597fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
598fb9987d0SSujith 
599fb9987d0SSujith 	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
600fb9987d0SSujith 
6019f01a84eSSujith 	priv->ah->opmode = NL80211_IFTYPE_STATION;
602fb9987d0SSujith }
603fb9987d0SSujith 
60421cb9879SVivek Natarajan static int ath9k_init_priv(struct ath9k_htc_priv *priv,
605fa6e15e0SRajkumar Manoharan 			   u16 devid, char *product,
606fa6e15e0SRajkumar Manoharan 			   u32 drv_info)
607fb9987d0SSujith {
608fb9987d0SSujith 	struct ath_hw *ah = NULL;
609fb9987d0SSujith 	struct ath_common *common;
610832f6a18SSujith Manoharan 	int i, ret = 0, csz = 0;
611fb9987d0SSujith 
612fb9987d0SSujith 	priv->op_flags |= OP_INVALID;
613fb9987d0SSujith 
614fb9987d0SSujith 	ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
615fb9987d0SSujith 	if (!ah)
616fb9987d0SSujith 		return -ENOMEM;
617fb9987d0SSujith 
618fb9987d0SSujith 	ah->hw_version.devid = devid;
6190b5ead91SSujith Manoharan 	ah->hw_version.usbdev = drv_info;
620f8afa42bSFelix Fietkau 	ah->ah_flags |= AH_USE_EEPROM;
621f9f84e96SFelix Fietkau 	ah->reg_ops.read = ath9k_regread;
622f9f84e96SFelix Fietkau 	ah->reg_ops.multi_read = ath9k_multi_regread;
623f9f84e96SFelix Fietkau 	ah->reg_ops.write = ath9k_regwrite;
624f9f84e96SFelix Fietkau 	ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer;
625f9f84e96SFelix Fietkau 	ah->reg_ops.write_flush = ath9k_regwrite_flush;
626845e03c9SFelix Fietkau 	ah->reg_ops.rmw = ath9k_reg_rmw;
627fb9987d0SSujith 	priv->ah = ah;
628fb9987d0SSujith 
629fb9987d0SSujith 	common = ath9k_hw_common(ah);
630f9f84e96SFelix Fietkau 	common->ops = &ah->reg_ops;
631fb9987d0SSujith 	common->bus_ops = &ath9k_usb_bus_ops;
632fb9987d0SSujith 	common->ah = ah;
633fb9987d0SSujith 	common->hw = priv->hw;
634fb9987d0SSujith 	common->priv = priv;
635fb9987d0SSujith 	common->debug_mask = ath9k_debug;
636fb9987d0SSujith 
637fb9987d0SSujith 	spin_lock_init(&priv->beacon_lock);
638658ef04fSSujith Manoharan 	spin_lock_init(&priv->tx.tx_lock);
639fb9987d0SSujith 	mutex_init(&priv->mutex);
640bde748a4SVivek Natarajan 	mutex_init(&priv->htc_pm_lock);
641fb9987d0SSujith 	tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
642fb9987d0SSujith 		     (unsigned long)priv);
64327876a29SSujith Manoharan 	tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet,
64473908674SSujith Manoharan 		     (unsigned long)priv);
645a236254cSSujith Manoharan 	INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
646bde748a4SVivek Natarajan 	INIT_WORK(&priv->ps_work, ath9k_ps_work);
64773908674SSujith Manoharan 	INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
648859c3ca1SSujith Manoharan 	setup_timer(&priv->tx.cleanup_timer, ath9k_htc_tx_cleanup_timer,
649859c3ca1SSujith Manoharan 		    (unsigned long)priv);
650fb9987d0SSujith 
651fb9987d0SSujith 	/*
652fb9987d0SSujith 	 * Cache line size is used to size and align various
653fb9987d0SSujith 	 * structures used to communicate with the hardware.
654fb9987d0SSujith 	 */
655fb9987d0SSujith 	ath_read_cachesize(common, &csz);
656fb9987d0SSujith 	common->cachelsz = csz << 2; /* convert to bytes */
657fb9987d0SSujith 
658fb9987d0SSujith 	ret = ath9k_hw_init(ah);
659fb9987d0SSujith 	if (ret) {
6603800276aSJoe Perches 		ath_err(common,
6613800276aSJoe Perches 			"Unable to initialize hardware; initialization status: %d\n",
6623800276aSJoe Perches 			ret);
663fb9987d0SSujith 		goto err_hw;
664fb9987d0SSujith 	}
665fb9987d0SSujith 
666fb9987d0SSujith 	ret = ath9k_init_queues(priv);
667fb9987d0SSujith 	if (ret)
668fb9987d0SSujith 		goto err_queues;
669fb9987d0SSujith 
670832f6a18SSujith Manoharan 	for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
671832f6a18SSujith Manoharan 		priv->cur_beacon_conf.bslot[i] = NULL;
672832f6a18SSujith Manoharan 
673f82b4bdeSRajkumar Manoharan 	ath9k_cmn_init_crypto(ah);
674fb9987d0SSujith 	ath9k_init_channels_rates(priv);
675fb9987d0SSujith 	ath9k_init_misc(priv);
676cee5341dSSujith Manoharan 	ath9k_htc_init_btcoex(priv, product);
67721cb9879SVivek Natarajan 
678fb9987d0SSujith 	return 0;
679fb9987d0SSujith 
680fb9987d0SSujith err_queues:
681fb9987d0SSujith 	ath9k_hw_deinit(ah);
682fb9987d0SSujith err_hw:
683fb9987d0SSujith 
684fb9987d0SSujith 	kfree(ah);
685fb9987d0SSujith 	priv->ah = NULL;
686fb9987d0SSujith 
687fb9987d0SSujith 	return ret;
688fb9987d0SSujith }
689fb9987d0SSujith 
690fb9987d0SSujith static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
691fb9987d0SSujith 			       struct ieee80211_hw *hw)
692fb9987d0SSujith {
693fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
694fb9987d0SSujith 
695fb9987d0SSujith 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
696fb9987d0SSujith 		IEEE80211_HW_AMPDU_AGGREGATION |
697fb9987d0SSujith 		IEEE80211_HW_SPECTRUM_MGMT |
69832fbccafSSujith 		IEEE80211_HW_HAS_RATE_CONTROL |
699bde748a4SVivek Natarajan 		IEEE80211_HW_RX_INCLUDES_FCS |
700bde748a4SVivek Natarajan 		IEEE80211_HW_SUPPORTS_PS |
7017d547eb4SSujith Manoharan 		IEEE80211_HW_PS_NULLFUNC_STACK |
7028ae2e12fSRajkumar Manoharan 		IEEE80211_HW_REPORTS_TX_ACK_STATUS |
7037d547eb4SSujith Manoharan 		IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
704fb9987d0SSujith 
705fb9987d0SSujith 	hw->wiphy->interface_modes =
706fb9987d0SSujith 		BIT(NL80211_IFTYPE_STATION) |
70709d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_ADHOC) |
70809d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_AP) |
70909d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_P2P_GO) |
71009d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_P2P_CLIENT);
711fb9987d0SSujith 
712bde748a4SVivek Natarajan 	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
713bde748a4SVivek Natarajan 
714d7d312caSAntonio Quartulli 	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
715d7d312caSAntonio Quartulli 
716fb9987d0SSujith 	hw->queues = 4;
717fb9987d0SSujith 	hw->channel_change_time = 5000;
718fb9987d0SSujith 	hw->max_listen_interval = 10;
7193a0593efSSujith Manoharan 
720fb9987d0SSujith 	hw->vif_data_size = sizeof(struct ath9k_htc_vif);
721fb9987d0SSujith 	hw->sta_data_size = sizeof(struct ath9k_htc_sta);
722fb9987d0SSujith 
723fb9987d0SSujith 	/* tx_frame_hdr is larger than tx_mgmt_hdr anyway */
724fb9987d0SSujith 	hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) +
725fb9987d0SSujith 		sizeof(struct htc_frame_hdr) + 4;
726fb9987d0SSujith 
727d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
728fb9987d0SSujith 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
729fb9987d0SSujith 			&priv->sbands[IEEE80211_BAND_2GHZ];
730d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
731ea46e644SSujith 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
732ea46e644SSujith 			&priv->sbands[IEEE80211_BAND_5GHZ];
733fb9987d0SSujith 
734fb9987d0SSujith 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
735d4659912SFelix Fietkau 		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
736fb9987d0SSujith 			setup_ht_cap(priv,
737fb9987d0SSujith 				     &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap);
738d4659912SFelix Fietkau 		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
739ea46e644SSujith 			setup_ht_cap(priv,
740ea46e644SSujith 				     &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
741fb9987d0SSujith 	}
742fb9987d0SSujith 
743fb9987d0SSujith 	SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
744fb9987d0SSujith }
745fb9987d0SSujith 
74629bbfb24SSujith Manoharan static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv)
74729bbfb24SSujith Manoharan {
74829bbfb24SSujith Manoharan 	struct ieee80211_hw *hw = priv->hw;
74929bbfb24SSujith Manoharan 	struct wmi_fw_version cmd_rsp;
75029bbfb24SSujith Manoharan 	int ret;
75129bbfb24SSujith Manoharan 
75229bbfb24SSujith Manoharan 	memset(&cmd_rsp, 0, sizeof(cmd_rsp));
75329bbfb24SSujith Manoharan 
75429bbfb24SSujith Manoharan 	WMI_CMD(WMI_GET_FW_VERSION);
75529bbfb24SSujith Manoharan 	if (ret)
75629bbfb24SSujith Manoharan 		return -EINVAL;
75729bbfb24SSujith Manoharan 
75829bbfb24SSujith Manoharan 	priv->fw_version_major = be16_to_cpu(cmd_rsp.major);
75929bbfb24SSujith Manoharan 	priv->fw_version_minor = be16_to_cpu(cmd_rsp.minor);
76029bbfb24SSujith Manoharan 
76129bbfb24SSujith Manoharan 	snprintf(hw->wiphy->fw_version, ETHTOOL_BUSINFO_LEN, "%d.%d",
76229bbfb24SSujith Manoharan 		 priv->fw_version_major,
76329bbfb24SSujith Manoharan 		 priv->fw_version_minor);
76429bbfb24SSujith Manoharan 
76529bbfb24SSujith Manoharan 	dev_info(priv->dev, "ath9k_htc: FW Version: %d.%d\n",
76629bbfb24SSujith Manoharan 		 priv->fw_version_major,
76729bbfb24SSujith Manoharan 		 priv->fw_version_minor);
76829bbfb24SSujith Manoharan 
7693a0593efSSujith Manoharan 	/*
7703a0593efSSujith Manoharan 	 * Check if the available FW matches the driver's
7713a0593efSSujith Manoharan 	 * required version.
7723a0593efSSujith Manoharan 	 */
7733a0593efSSujith Manoharan 	if (priv->fw_version_major != MAJOR_VERSION_REQ ||
7743a0593efSSujith Manoharan 	    priv->fw_version_minor != MINOR_VERSION_REQ) {
7753a0593efSSujith Manoharan 		dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n",
7763a0593efSSujith Manoharan 			MAJOR_VERSION_REQ, MINOR_VERSION_REQ);
7773a0593efSSujith Manoharan 		return -EINVAL;
7783a0593efSSujith Manoharan 	}
7793a0593efSSujith Manoharan 
78029bbfb24SSujith Manoharan 	return 0;
78129bbfb24SSujith Manoharan }
78229bbfb24SSujith Manoharan 
78321cb9879SVivek Natarajan static int ath9k_init_device(struct ath9k_htc_priv *priv,
784fa6e15e0SRajkumar Manoharan 			     u16 devid, char *product, u32 drv_info)
785fb9987d0SSujith {
786fb9987d0SSujith 	struct ieee80211_hw *hw = priv->hw;
787fb9987d0SSujith 	struct ath_common *common;
788fb9987d0SSujith 	struct ath_hw *ah;
789fb9987d0SSujith 	int error = 0;
790fb9987d0SSujith 	struct ath_regulatory *reg;
7913e3f1d19SSujith Manoharan 	char hw_name[64];
792fb9987d0SSujith 
793fb9987d0SSujith 	/* Bring up device */
794fa6e15e0SRajkumar Manoharan 	error = ath9k_init_priv(priv, devid, product, drv_info);
795fb9987d0SSujith 	if (error != 0)
796fb9987d0SSujith 		goto err_init;
797fb9987d0SSujith 
798fb9987d0SSujith 	ah = priv->ah;
799fb9987d0SSujith 	common = ath9k_hw_common(ah);
800fb9987d0SSujith 	ath9k_set_hw_capab(priv, hw);
801fb9987d0SSujith 
80229bbfb24SSujith Manoharan 	error = ath9k_init_firmware_version(priv);
80329bbfb24SSujith Manoharan 	if (error != 0)
80429bbfb24SSujith Manoharan 		goto err_fw;
80529bbfb24SSujith Manoharan 
806fb9987d0SSujith 	/* Initialize regulatory */
807fb9987d0SSujith 	error = ath_regd_init(&common->regulatory, priv->hw->wiphy,
808fb9987d0SSujith 			      ath9k_reg_notifier);
809fb9987d0SSujith 	if (error)
810fb9987d0SSujith 		goto err_regd;
811fb9987d0SSujith 
812fb9987d0SSujith 	reg = &common->regulatory;
813fb9987d0SSujith 
814fb9987d0SSujith 	/* Setup TX */
815fb9987d0SSujith 	error = ath9k_tx_init(priv);
816fb9987d0SSujith 	if (error != 0)
817fb9987d0SSujith 		goto err_tx;
818fb9987d0SSujith 
819fb9987d0SSujith 	/* Setup RX */
820fb9987d0SSujith 	error = ath9k_rx_init(priv);
821fb9987d0SSujith 	if (error != 0)
822fb9987d0SSujith 		goto err_rx;
823fb9987d0SSujith 
824d244f21eSSujith Manoharan #ifdef CONFIG_MAC80211_LEDS
825d244f21eSSujith Manoharan 	/* must be initialized before ieee80211_register_hw */
826d244f21eSSujith Manoharan 	priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw,
827d244f21eSSujith Manoharan 		IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_htc_tpt_blink,
828d244f21eSSujith Manoharan 		ARRAY_SIZE(ath9k_htc_tpt_blink));
829d244f21eSSujith Manoharan #endif
830d244f21eSSujith Manoharan 
831fb9987d0SSujith 	/* Register with mac80211 */
832fb9987d0SSujith 	error = ieee80211_register_hw(hw);
833fb9987d0SSujith 	if (error)
834fb9987d0SSujith 		goto err_register;
835fb9987d0SSujith 
836fb9987d0SSujith 	/* Handle world regulatory */
837fb9987d0SSujith 	if (!ath_is_world_regd(reg)) {
838fb9987d0SSujith 		error = regulatory_hint(hw->wiphy, reg->alpha2);
839fb9987d0SSujith 		if (error)
840fb9987d0SSujith 			goto err_world;
841fb9987d0SSujith 	}
842fb9987d0SSujith 
843e5facc75SRajkumar Manoharan 	error = ath9k_htc_init_debug(priv->ah);
844e5facc75SRajkumar Manoharan 	if (error) {
845e5facc75SRajkumar Manoharan 		ath_err(common, "Unable to create debugfs files\n");
846e5facc75SRajkumar Manoharan 		goto err_world;
847e5facc75SRajkumar Manoharan 	}
848e5facc75SRajkumar Manoharan 
849d2182b69SJoe Perches 	ath_dbg(common, CONFIG,
850d2182b69SJoe Perches 		"WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, BE:%d, BK:%d, VI:%d, VO:%d\n",
8513e3f1d19SSujith Manoharan 		priv->wmi_cmd_ep,
8523e3f1d19SSujith Manoharan 		priv->beacon_ep,
8533e3f1d19SSujith Manoharan 		priv->cab_ep,
8543e3f1d19SSujith Manoharan 		priv->uapsd_ep,
8553e3f1d19SSujith Manoharan 		priv->mgmt_ep,
8563e3f1d19SSujith Manoharan 		priv->data_be_ep,
8573e3f1d19SSujith Manoharan 		priv->data_bk_ep,
8583e3f1d19SSujith Manoharan 		priv->data_vi_ep,
8593e3f1d19SSujith Manoharan 		priv->data_vo_ep);
8603e3f1d19SSujith Manoharan 
8613e3f1d19SSujith Manoharan 	ath9k_hw_name(priv->ah, hw_name, sizeof(hw_name));
8623e3f1d19SSujith Manoharan 	wiphy_info(hw->wiphy, "%s\n", hw_name);
8633e3f1d19SSujith Manoharan 
864fb9987d0SSujith 	ath9k_init_leds(priv);
865fb9987d0SSujith 	ath9k_start_rfkill_poll(priv);
866fb9987d0SSujith 
867fb9987d0SSujith 	return 0;
868fb9987d0SSujith 
869fb9987d0SSujith err_world:
870fb9987d0SSujith 	ieee80211_unregister_hw(hw);
871fb9987d0SSujith err_register:
872fb9987d0SSujith 	ath9k_rx_cleanup(priv);
873fb9987d0SSujith err_rx:
874fb9987d0SSujith 	ath9k_tx_cleanup(priv);
875fb9987d0SSujith err_tx:
876fb9987d0SSujith 	/* Nothing */
877fb9987d0SSujith err_regd:
87829bbfb24SSujith Manoharan 	/* Nothing */
87929bbfb24SSujith Manoharan err_fw:
880fb9987d0SSujith 	ath9k_deinit_priv(priv);
881fb9987d0SSujith err_init:
882fb9987d0SSujith 	return error;
883fb9987d0SSujith }
884fb9987d0SSujith 
885fb9987d0SSujith int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
886fa6e15e0SRajkumar Manoharan 			   u16 devid, char *product, u32 drv_info)
887fb9987d0SSujith {
888fb9987d0SSujith 	struct ieee80211_hw *hw;
889fb9987d0SSujith 	struct ath9k_htc_priv *priv;
890fb9987d0SSujith 	int ret;
891fb9987d0SSujith 
892fb9987d0SSujith 	hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops);
893fb9987d0SSujith 	if (!hw)
894fb9987d0SSujith 		return -ENOMEM;
895fb9987d0SSujith 
896fb9987d0SSujith 	priv = hw->priv;
897fb9987d0SSujith 	priv->hw = hw;
898fb9987d0SSujith 	priv->htc = htc_handle;
899fb9987d0SSujith 	priv->dev = dev;
900fb9987d0SSujith 	htc_handle->drv_priv = priv;
901fb9987d0SSujith 	SET_IEEE80211_DEV(hw, priv->dev);
902fb9987d0SSujith 
903fb9987d0SSujith 	ret = ath9k_htc_wait_for_target(priv);
904fb9987d0SSujith 	if (ret)
905fb9987d0SSujith 		goto err_free;
906fb9987d0SSujith 
907fb9987d0SSujith 	priv->wmi = ath9k_init_wmi(priv);
908fb9987d0SSujith 	if (!priv->wmi) {
909fb9987d0SSujith 		ret = -EINVAL;
910fb9987d0SSujith 		goto err_free;
911fb9987d0SSujith 	}
912fb9987d0SSujith 
913fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_htc_services(priv, devid, drv_info);
914fb9987d0SSujith 	if (ret)
915fb9987d0SSujith 		goto err_init;
916fb9987d0SSujith 
917fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_device(priv, devid, product, drv_info);
918fb9987d0SSujith 	if (ret)
919fb9987d0SSujith 		goto err_init;
920fb9987d0SSujith 
921fb9987d0SSujith 	return 0;
922fb9987d0SSujith 
923fb9987d0SSujith err_init:
924fb9987d0SSujith 	ath9k_deinit_wmi(priv);
925fb9987d0SSujith err_free:
926fb9987d0SSujith 	ieee80211_free_hw(hw);
927fb9987d0SSujith 	return ret;
928fb9987d0SSujith }
929fb9987d0SSujith 
930fb9987d0SSujith void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
931fb9987d0SSujith {
932fb9987d0SSujith 	if (htc_handle->drv_priv) {
933a3be14b7SSujith 
934a3be14b7SSujith 		/* Check if the device has been yanked out. */
935a3be14b7SSujith 		if (hotunplug)
93697dcec57SSujith Manoharan 			htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED;
937a3be14b7SSujith 
938fb9987d0SSujith 		ath9k_deinit_device(htc_handle->drv_priv);
939fb9987d0SSujith 		ath9k_deinit_wmi(htc_handle->drv_priv);
940fb9987d0SSujith 		ieee80211_free_hw(htc_handle->drv_priv->hw);
941fb9987d0SSujith 	}
942fb9987d0SSujith }
943fb9987d0SSujith 
944fb9987d0SSujith #ifdef CONFIG_PM
945f933ebedSSujith Manoharan 
946f933ebedSSujith Manoharan void ath9k_htc_suspend(struct htc_target *htc_handle)
947f933ebedSSujith Manoharan {
948f933ebedSSujith Manoharan 	ath9k_htc_setpower(htc_handle->drv_priv, ATH9K_PM_FULL_SLEEP);
949f933ebedSSujith Manoharan }
950f933ebedSSujith Manoharan 
951fb9987d0SSujith int ath9k_htc_resume(struct htc_target *htc_handle)
952fb9987d0SSujith {
953fa6e15e0SRajkumar Manoharan 	struct ath9k_htc_priv *priv = htc_handle->drv_priv;
954fb9987d0SSujith 	int ret;
955fb9987d0SSujith 
956fa6e15e0SRajkumar Manoharan 	ret = ath9k_htc_wait_for_target(priv);
957fb9987d0SSujith 	if (ret)
958fb9987d0SSujith 		return ret;
959fb9987d0SSujith 
960fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid,
9610b5ead91SSujith Manoharan 				      priv->ah->hw_version.usbdev);
962fb9987d0SSujith 	return ret;
963fb9987d0SSujith }
964fb9987d0SSujith #endif
965fb9987d0SSujith 
966fb9987d0SSujith static int __init ath9k_htc_init(void)
967fb9987d0SSujith {
968e5facc75SRajkumar Manoharan 	if (ath9k_hif_usb_init() < 0) {
969fb9987d0SSujith 		printk(KERN_ERR
970fb9987d0SSujith 			"ath9k_htc: No USB devices found,"
971fb9987d0SSujith 			" driver not installed.\n");
972e5facc75SRajkumar Manoharan 		return -ENODEV;
973fb9987d0SSujith 	}
974fb9987d0SSujith 
975fb9987d0SSujith 	return 0;
976fb9987d0SSujith }
977fb9987d0SSujith module_init(ath9k_htc_init);
978fb9987d0SSujith 
979fb9987d0SSujith static void __exit ath9k_htc_exit(void)
980fb9987d0SSujith {
981fb9987d0SSujith 	ath9k_hif_usb_exit();
982fb9987d0SSujith 	printk(KERN_INFO "ath9k_htc: Driver unloaded\n");
983fb9987d0SSujith }
984fb9987d0SSujith module_exit(ath9k_htc_exit);
985