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 
17516304b0SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18516304b0SJoe Perches 
19fb9987d0SSujith #include "htc.h"
20fb9987d0SSujith 
21fb9987d0SSujith MODULE_AUTHOR("Atheros Communications");
22fb9987d0SSujith MODULE_LICENSE("Dual BSD/GPL");
23fb9987d0SSujith MODULE_DESCRIPTION("Atheros driver 802.11n HTC based wireless devices");
24fb9987d0SSujith 
25fb9987d0SSujith static unsigned int ath9k_debug = ATH_DBG_DEFAULT;
26fb9987d0SSujith module_param_named(debug, ath9k_debug, uint, 0);
27fb9987d0SSujith MODULE_PARM_DESC(debug, "Debugging mask");
28fb9987d0SSujith 
29e1572c5eSSujith int htc_modparam_nohwcrypt;
30e1572c5eSSujith module_param_named(nohwcrypt, htc_modparam_nohwcrypt, int, 0444);
31fb9987d0SSujith MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
32fb9987d0SSujith 
337f34778eSMohammed Shafi Shajakhan static int ath9k_htc_btcoex_enable;
347f34778eSMohammed Shafi Shajakhan module_param_named(btcoex_enable, ath9k_htc_btcoex_enable, int, 0444);
357f34778eSMohammed Shafi Shajakhan MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
367f34778eSMohammed Shafi Shajakhan 
37fb9987d0SSujith #define CHAN2G(_freq, _idx)  { \
38fb9987d0SSujith 	.center_freq = (_freq), \
39fb9987d0SSujith 	.hw_value = (_idx), \
40fb9987d0SSujith 	.max_power = 20, \
41fb9987d0SSujith }
42fb9987d0SSujith 
43ea46e644SSujith #define CHAN5G(_freq, _idx) { \
44ea46e644SSujith 	.band = IEEE80211_BAND_5GHZ, \
45ea46e644SSujith 	.center_freq = (_freq), \
46ea46e644SSujith 	.hw_value = (_idx), \
47ea46e644SSujith 	.max_power = 20, \
48ea46e644SSujith }
49ea46e644SSujith 
50fb9987d0SSujith static struct ieee80211_channel ath9k_2ghz_channels[] = {
51fb9987d0SSujith 	CHAN2G(2412, 0), /* Channel 1 */
52fb9987d0SSujith 	CHAN2G(2417, 1), /* Channel 2 */
53fb9987d0SSujith 	CHAN2G(2422, 2), /* Channel 3 */
54fb9987d0SSujith 	CHAN2G(2427, 3), /* Channel 4 */
55fb9987d0SSujith 	CHAN2G(2432, 4), /* Channel 5 */
56fb9987d0SSujith 	CHAN2G(2437, 5), /* Channel 6 */
57fb9987d0SSujith 	CHAN2G(2442, 6), /* Channel 7 */
58fb9987d0SSujith 	CHAN2G(2447, 7), /* Channel 8 */
59fb9987d0SSujith 	CHAN2G(2452, 8), /* Channel 9 */
60fb9987d0SSujith 	CHAN2G(2457, 9), /* Channel 10 */
61fb9987d0SSujith 	CHAN2G(2462, 10), /* Channel 11 */
62fb9987d0SSujith 	CHAN2G(2467, 11), /* Channel 12 */
63fb9987d0SSujith 	CHAN2G(2472, 12), /* Channel 13 */
64fb9987d0SSujith 	CHAN2G(2484, 13), /* Channel 14 */
65fb9987d0SSujith };
66fb9987d0SSujith 
67ea46e644SSujith static struct ieee80211_channel ath9k_5ghz_channels[] = {
68ea46e644SSujith 	/* _We_ call this UNII 1 */
69ea46e644SSujith 	CHAN5G(5180, 14), /* Channel 36 */
70ea46e644SSujith 	CHAN5G(5200, 15), /* Channel 40 */
71ea46e644SSujith 	CHAN5G(5220, 16), /* Channel 44 */
72ea46e644SSujith 	CHAN5G(5240, 17), /* Channel 48 */
73ea46e644SSujith 	/* _We_ call this UNII 2 */
74ea46e644SSujith 	CHAN5G(5260, 18), /* Channel 52 */
75ea46e644SSujith 	CHAN5G(5280, 19), /* Channel 56 */
76ea46e644SSujith 	CHAN5G(5300, 20), /* Channel 60 */
77ea46e644SSujith 	CHAN5G(5320, 21), /* Channel 64 */
78ea46e644SSujith 	/* _We_ call this "Middle band" */
79ea46e644SSujith 	CHAN5G(5500, 22), /* Channel 100 */
80ea46e644SSujith 	CHAN5G(5520, 23), /* Channel 104 */
81ea46e644SSujith 	CHAN5G(5540, 24), /* Channel 108 */
82ea46e644SSujith 	CHAN5G(5560, 25), /* Channel 112 */
83ea46e644SSujith 	CHAN5G(5580, 26), /* Channel 116 */
84ea46e644SSujith 	CHAN5G(5600, 27), /* Channel 120 */
85ea46e644SSujith 	CHAN5G(5620, 28), /* Channel 124 */
86ea46e644SSujith 	CHAN5G(5640, 29), /* Channel 128 */
87ea46e644SSujith 	CHAN5G(5660, 30), /* Channel 132 */
88ea46e644SSujith 	CHAN5G(5680, 31), /* Channel 136 */
89ea46e644SSujith 	CHAN5G(5700, 32), /* Channel 140 */
90ea46e644SSujith 	/* _We_ call this UNII 3 */
91ea46e644SSujith 	CHAN5G(5745, 33), /* Channel 149 */
92ea46e644SSujith 	CHAN5G(5765, 34), /* Channel 153 */
93ea46e644SSujith 	CHAN5G(5785, 35), /* Channel 157 */
94ea46e644SSujith 	CHAN5G(5805, 36), /* Channel 161 */
95ea46e644SSujith 	CHAN5G(5825, 37), /* Channel 165 */
96ea46e644SSujith };
97ea46e644SSujith 
98fb9987d0SSujith /* Atheros hardware rate code addition for short premble */
99fb9987d0SSujith #define SHPCHECK(__hw_rate, __flags) \
100fb9987d0SSujith 	((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0)
101fb9987d0SSujith 
102fb9987d0SSujith #define RATE(_bitrate, _hw_rate, _flags) {		\
103fb9987d0SSujith 	.bitrate	= (_bitrate),			\
104fb9987d0SSujith 	.flags		= (_flags),			\
105fb9987d0SSujith 	.hw_value	= (_hw_rate),			\
106fb9987d0SSujith 	.hw_value_short = (SHPCHECK(_hw_rate, _flags))	\
107fb9987d0SSujith }
108fb9987d0SSujith 
109fb9987d0SSujith static struct ieee80211_rate ath9k_legacy_rates[] = {
110fb9987d0SSujith 	RATE(10, 0x1b, 0),
111fb9987d0SSujith 	RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp : 0x1e */
112fb9987d0SSujith 	RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp: 0x1d */
113fb9987d0SSujith 	RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), /* short: 0x1c */
114fb9987d0SSujith 	RATE(60, 0x0b, 0),
115fb9987d0SSujith 	RATE(90, 0x0f, 0),
116fb9987d0SSujith 	RATE(120, 0x0a, 0),
117fb9987d0SSujith 	RATE(180, 0x0e, 0),
118fb9987d0SSujith 	RATE(240, 0x09, 0),
119fb9987d0SSujith 	RATE(360, 0x0d, 0),
120fb9987d0SSujith 	RATE(480, 0x08, 0),
121fb9987d0SSujith 	RATE(540, 0x0c, 0),
122fb9987d0SSujith };
123fb9987d0SSujith 
124d244f21eSSujith Manoharan #ifdef CONFIG_MAC80211_LEDS
125d244f21eSSujith Manoharan static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = {
126d244f21eSSujith Manoharan 	{ .throughput = 0 * 1024, .blink_time = 334 },
127d244f21eSSujith Manoharan 	{ .throughput = 1 * 1024, .blink_time = 260 },
128d244f21eSSujith Manoharan 	{ .throughput = 5 * 1024, .blink_time = 220 },
129d244f21eSSujith Manoharan 	{ .throughput = 10 * 1024, .blink_time = 190 },
130d244f21eSSujith Manoharan 	{ .throughput = 20 * 1024, .blink_time = 170 },
131d244f21eSSujith Manoharan 	{ .throughput = 50 * 1024, .blink_time = 150 },
132d244f21eSSujith Manoharan 	{ .throughput = 70 * 1024, .blink_time = 130 },
133d244f21eSSujith Manoharan 	{ .throughput = 100 * 1024, .blink_time = 110 },
134d244f21eSSujith Manoharan 	{ .throughput = 200 * 1024, .blink_time = 80 },
135d244f21eSSujith Manoharan 	{ .throughput = 300 * 1024, .blink_time = 50 },
136d244f21eSSujith Manoharan };
137d244f21eSSujith Manoharan #endif
138d244f21eSSujith Manoharan 
139fb9987d0SSujith static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
140fb9987d0SSujith {
141fb9987d0SSujith 	int time_left;
142fb9987d0SSujith 
143d8c49ffbSSujith.Manoharan@atheros.com 	if (atomic_read(&priv->htc->tgt_ready) > 0) {
144d8c49ffbSSujith.Manoharan@atheros.com 		atomic_dec(&priv->htc->tgt_ready);
145d8c49ffbSSujith.Manoharan@atheros.com 		return 0;
146d8c49ffbSSujith.Manoharan@atheros.com 	}
147d8c49ffbSSujith.Manoharan@atheros.com 
148fb9987d0SSujith 	/* Firmware can take up to 50ms to get ready, to be safe use 1 second */
149fb9987d0SSujith 	time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ);
150fb9987d0SSujith 	if (!time_left) {
151fb9987d0SSujith 		dev_err(priv->dev, "ath9k_htc: Target is unresponsive\n");
152fb9987d0SSujith 		return -ETIMEDOUT;
153fb9987d0SSujith 	}
154fb9987d0SSujith 
155d8c49ffbSSujith.Manoharan@atheros.com 	atomic_dec(&priv->htc->tgt_ready);
156d8c49ffbSSujith.Manoharan@atheros.com 
157fb9987d0SSujith 	return 0;
158fb9987d0SSujith }
159fb9987d0SSujith 
160fb9987d0SSujith static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
161fb9987d0SSujith {
162fb9987d0SSujith 	ath9k_hw_deinit(priv->ah);
163fb9987d0SSujith 	kfree(priv->ah);
164fb9987d0SSujith 	priv->ah = NULL;
165fb9987d0SSujith }
166fb9987d0SSujith 
167fb9987d0SSujith static void ath9k_deinit_device(struct ath9k_htc_priv *priv)
168fb9987d0SSujith {
169fb9987d0SSujith 	struct ieee80211_hw *hw = priv->hw;
170fb9987d0SSujith 
171fb9987d0SSujith 	wiphy_rfkill_stop_polling(hw->wiphy);
172fb9987d0SSujith 	ath9k_deinit_leds(priv);
173fb9987d0SSujith 	ieee80211_unregister_hw(hw);
174fb9987d0SSujith 	ath9k_rx_cleanup(priv);
175fb9987d0SSujith 	ath9k_tx_cleanup(priv);
176fb9987d0SSujith 	ath9k_deinit_priv(priv);
177fb9987d0SSujith }
178fb9987d0SSujith 
179fb9987d0SSujith static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv,
180fb9987d0SSujith 					u16 service_id,
181fb9987d0SSujith 					void (*tx) (void *,
182fb9987d0SSujith 						    struct sk_buff *,
183fb9987d0SSujith 						    enum htc_endpoint_id,
184fb9987d0SSujith 						    bool txok),
185fb9987d0SSujith 					enum htc_endpoint_id *ep_id)
186fb9987d0SSujith {
187fb9987d0SSujith 	struct htc_service_connreq req;
188fb9987d0SSujith 
189fb9987d0SSujith 	memset(&req, 0, sizeof(struct htc_service_connreq));
190fb9987d0SSujith 
191fb9987d0SSujith 	req.service_id = service_id;
192fb9987d0SSujith 	req.ep_callbacks.priv = priv;
193fb9987d0SSujith 	req.ep_callbacks.rx = ath9k_htc_rxep;
194fb9987d0SSujith 	req.ep_callbacks.tx = tx;
195fb9987d0SSujith 
196fb9987d0SSujith 	return htc_connect_service(priv->htc, &req, ep_id);
197fb9987d0SSujith }
198fb9987d0SSujith 
199fa6e15e0SRajkumar Manoharan static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid,
200fa6e15e0SRajkumar Manoharan 				   u32 drv_info)
201fb9987d0SSujith {
202fb9987d0SSujith 	int ret;
203fb9987d0SSujith 
204fb9987d0SSujith 	/* WMI CMD*/
205fb9987d0SSujith 	ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep);
206fb9987d0SSujith 	if (ret)
207fb9987d0SSujith 		goto err;
208fb9987d0SSujith 
209fb9987d0SSujith 	/* Beacon */
2109c6dda4eSSujith 	ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, ath9k_htc_beaconep,
211fb9987d0SSujith 				    &priv->beacon_ep);
212fb9987d0SSujith 	if (ret)
213fb9987d0SSujith 		goto err;
214fb9987d0SSujith 
215fb9987d0SSujith 	/* CAB */
216fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep,
217fb9987d0SSujith 				    &priv->cab_ep);
218fb9987d0SSujith 	if (ret)
219fb9987d0SSujith 		goto err;
220fb9987d0SSujith 
221fb9987d0SSujith 
222fb9987d0SSujith 	/* UAPSD */
223fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep,
224fb9987d0SSujith 				    &priv->uapsd_ep);
225fb9987d0SSujith 	if (ret)
226fb9987d0SSujith 		goto err;
227fb9987d0SSujith 
228fb9987d0SSujith 	/* MGMT */
229fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep,
230fb9987d0SSujith 				    &priv->mgmt_ep);
231fb9987d0SSujith 	if (ret)
232fb9987d0SSujith 		goto err;
233fb9987d0SSujith 
234fb9987d0SSujith 	/* DATA BE */
235fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep,
236fb9987d0SSujith 				    &priv->data_be_ep);
237fb9987d0SSujith 	if (ret)
238fb9987d0SSujith 		goto err;
239fb9987d0SSujith 
240fb9987d0SSujith 	/* DATA BK */
241fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep,
242fb9987d0SSujith 				    &priv->data_bk_ep);
243fb9987d0SSujith 	if (ret)
244fb9987d0SSujith 		goto err;
245fb9987d0SSujith 
246fb9987d0SSujith 	/* DATA VI */
247fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep,
248fb9987d0SSujith 				    &priv->data_vi_ep);
249fb9987d0SSujith 	if (ret)
250fb9987d0SSujith 		goto err;
251fb9987d0SSujith 
252fb9987d0SSujith 	/* DATA VO */
253fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep,
254fb9987d0SSujith 				    &priv->data_vo_ep);
255fb9987d0SSujith 	if (ret)
256fb9987d0SSujith 		goto err;
257fb9987d0SSujith 
2586267dc70SSujith 	/*
2596267dc70SSujith 	 * Setup required credits before initializing HTC.
2606267dc70SSujith 	 * This is a bit hacky, but, since queuing is done in
2616267dc70SSujith 	 * the HIF layer, shouldn't matter much.
2626267dc70SSujith 	 */
2636267dc70SSujith 
2640b5ead91SSujith Manoharan 	if (IS_AR7010_DEVICE(drv_info))
265d108e8b9SSujith Manoharan 		priv->htc->credits = 45;
266fa6e15e0SRajkumar Manoharan 	else
2674e63f768SSujith 		priv->htc->credits = 33;
2686267dc70SSujith 
269fb9987d0SSujith 	ret = htc_init(priv->htc);
270fb9987d0SSujith 	if (ret)
271fb9987d0SSujith 		goto err;
272fb9987d0SSujith 
2736267dc70SSujith 	dev_info(priv->dev, "ath9k_htc: HTC initialized with %d credits\n",
2746267dc70SSujith 		 priv->htc->credits);
2756267dc70SSujith 
276fb9987d0SSujith 	return 0;
277fb9987d0SSujith 
278fb9987d0SSujith err:
279fb9987d0SSujith 	dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n");
280fb9987d0SSujith 	return ret;
281fb9987d0SSujith }
282fb9987d0SSujith 
2830c0280bdSLuis R. Rodriguez static void ath9k_reg_notifier(struct wiphy *wiphy,
284fb9987d0SSujith 			       struct regulatory_request *request)
285fb9987d0SSujith {
286fb9987d0SSujith 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
287fb9987d0SSujith 	struct ath9k_htc_priv *priv = hw->priv;
288fb9987d0SSujith 
2890c0280bdSLuis R. Rodriguez 	ath_reg_notifier_apply(wiphy, request,
290fb9987d0SSujith 			       ath9k_hw_regulatory(priv->ah));
291fb9987d0SSujith }
292fb9987d0SSujith 
2934a22fe10SSujith static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
294fb9987d0SSujith {
295fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
296fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(ah);
297fb9987d0SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
298fb9987d0SSujith 	__be32 val, reg = cpu_to_be32(reg_offset);
299fb9987d0SSujith 	int r;
300fb9987d0SSujith 
301fb9987d0SSujith 	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
302fb9987d0SSujith 			  (u8 *) &reg, sizeof(reg),
303fb9987d0SSujith 			  (u8 *) &val, sizeof(val),
304fb9987d0SSujith 			  100);
305fb9987d0SSujith 	if (unlikely(r)) {
306d2182b69SJoe Perches 		ath_dbg(common, WMI, "REGISTER READ FAILED: (0x%04x, %d)\n",
307fb9987d0SSujith 			reg_offset, r);
308fb9987d0SSujith 		return -EIO;
309fb9987d0SSujith 	}
310fb9987d0SSujith 
311fb9987d0SSujith 	return be32_to_cpu(val);
312fb9987d0SSujith }
313fb9987d0SSujith 
31409a525d3SSujith Manoharan static void ath9k_multi_regread(void *hw_priv, u32 *addr,
31509a525d3SSujith Manoharan 				u32 *val, u16 count)
31609a525d3SSujith Manoharan {
31709a525d3SSujith Manoharan 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
31809a525d3SSujith Manoharan 	struct ath_common *common = ath9k_hw_common(ah);
31909a525d3SSujith Manoharan 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
32009a525d3SSujith Manoharan 	__be32 tmpaddr[8];
32109a525d3SSujith Manoharan 	__be32 tmpval[8];
32209a525d3SSujith Manoharan 	int i, ret;
32309a525d3SSujith Manoharan 
32409a525d3SSujith Manoharan        for (i = 0; i < count; i++) {
32509a525d3SSujith Manoharan 	       tmpaddr[i] = cpu_to_be32(addr[i]);
32609a525d3SSujith Manoharan        }
32709a525d3SSujith Manoharan 
32809a525d3SSujith Manoharan        ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
32909a525d3SSujith Manoharan 			   (u8 *)tmpaddr , sizeof(u32) * count,
33009a525d3SSujith Manoharan 			   (u8 *)tmpval, sizeof(u32) * count,
33109a525d3SSujith Manoharan 			   100);
33209a525d3SSujith Manoharan 	if (unlikely(ret)) {
333d2182b69SJoe Perches 		ath_dbg(common, WMI,
33409a525d3SSujith Manoharan 			"Multiple REGISTER READ FAILED (count: %d)\n", count);
33509a525d3SSujith Manoharan 	}
33609a525d3SSujith Manoharan 
33709a525d3SSujith Manoharan        for (i = 0; i < count; i++) {
33809a525d3SSujith Manoharan 	       val[i] = be32_to_cpu(tmpval[i]);
33909a525d3SSujith Manoharan        }
34009a525d3SSujith Manoharan }
34109a525d3SSujith Manoharan 
3424a22fe10SSujith static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
343fb9987d0SSujith {
344fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
345fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(ah);
346fb9987d0SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
34707b2fa5aSJoe Perches 	const __be32 buf[2] = {
348fb9987d0SSujith 		cpu_to_be32(reg_offset),
349fb9987d0SSujith 		cpu_to_be32(val),
350fb9987d0SSujith 	};
351fb9987d0SSujith 	int r;
352fb9987d0SSujith 
353fb9987d0SSujith 	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
354fb9987d0SSujith 			  (u8 *) &buf, sizeof(buf),
355fb9987d0SSujith 			  (u8 *) &val, sizeof(val),
356fb9987d0SSujith 			  100);
357fb9987d0SSujith 	if (unlikely(r)) {
358d2182b69SJoe Perches 		ath_dbg(common, WMI, "REGISTER WRITE FAILED:(0x%04x, %d)\n",
359fb9987d0SSujith 			reg_offset, r);
360fb9987d0SSujith 	}
361fb9987d0SSujith }
362fb9987d0SSujith 
3634a22fe10SSujith static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset)
3644a22fe10SSujith {
3654a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3664a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3674a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3684a22fe10SSujith 	u32 rsp_status;
3694a22fe10SSujith 	int r;
3704a22fe10SSujith 
3714a22fe10SSujith 	mutex_lock(&priv->wmi->multi_write_mutex);
3724a22fe10SSujith 
3734a22fe10SSujith 	/* Store the register/value */
3744a22fe10SSujith 	priv->wmi->multi_write[priv->wmi->multi_write_idx].reg =
3754a22fe10SSujith 		cpu_to_be32(reg_offset);
3764a22fe10SSujith 	priv->wmi->multi_write[priv->wmi->multi_write_idx].val =
3774a22fe10SSujith 		cpu_to_be32(val);
3784a22fe10SSujith 
3794a22fe10SSujith 	priv->wmi->multi_write_idx++;
3804a22fe10SSujith 
3814a22fe10SSujith 	/* If the buffer is full, send it out. */
3824a22fe10SSujith 	if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) {
3834a22fe10SSujith 		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
3844a22fe10SSujith 			  (u8 *) &priv->wmi->multi_write,
3854a22fe10SSujith 			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
3864a22fe10SSujith 			  (u8 *) &rsp_status, sizeof(rsp_status),
3874a22fe10SSujith 			  100);
3884a22fe10SSujith 		if (unlikely(r)) {
389d2182b69SJoe Perches 			ath_dbg(common, WMI,
3904a22fe10SSujith 				"REGISTER WRITE FAILED, multi len: %d\n",
3914a22fe10SSujith 				priv->wmi->multi_write_idx);
3924a22fe10SSujith 		}
3934a22fe10SSujith 		priv->wmi->multi_write_idx = 0;
3944a22fe10SSujith 	}
3954a22fe10SSujith 
3964a22fe10SSujith 	mutex_unlock(&priv->wmi->multi_write_mutex);
3974a22fe10SSujith }
3984a22fe10SSujith 
3994a22fe10SSujith static void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset)
4004a22fe10SSujith {
4014a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
4024a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
4034a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
4044a22fe10SSujith 
4054a22fe10SSujith 	if (atomic_read(&priv->wmi->mwrite_cnt))
4064a22fe10SSujith 		ath9k_regwrite_buffer(hw_priv, val, reg_offset);
4074a22fe10SSujith 	else
4084a22fe10SSujith 		ath9k_regwrite_single(hw_priv, val, reg_offset);
4094a22fe10SSujith }
4104a22fe10SSujith 
4114a22fe10SSujith static void ath9k_enable_regwrite_buffer(void *hw_priv)
4124a22fe10SSujith {
4134a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
4144a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
4154a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
4164a22fe10SSujith 
4174a22fe10SSujith 	atomic_inc(&priv->wmi->mwrite_cnt);
4184a22fe10SSujith }
4194a22fe10SSujith 
4204a22fe10SSujith static void ath9k_regwrite_flush(void *hw_priv)
4214a22fe10SSujith {
4224a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
4234a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
4244a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
4254a22fe10SSujith 	u32 rsp_status;
4264a22fe10SSujith 	int r;
4274a22fe10SSujith 
428435c1610SFelix Fietkau 	atomic_dec(&priv->wmi->mwrite_cnt);
429435c1610SFelix Fietkau 
4304a22fe10SSujith 	mutex_lock(&priv->wmi->multi_write_mutex);
4314a22fe10SSujith 
4324a22fe10SSujith 	if (priv->wmi->multi_write_idx) {
4334a22fe10SSujith 		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
4344a22fe10SSujith 			  (u8 *) &priv->wmi->multi_write,
4354a22fe10SSujith 			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
4364a22fe10SSujith 			  (u8 *) &rsp_status, sizeof(rsp_status),
4374a22fe10SSujith 			  100);
4384a22fe10SSujith 		if (unlikely(r)) {
439d2182b69SJoe Perches 			ath_dbg(common, WMI,
4404a22fe10SSujith 				"REGISTER WRITE FAILED, multi len: %d\n",
4414a22fe10SSujith 				priv->wmi->multi_write_idx);
4424a22fe10SSujith 		}
4434a22fe10SSujith 		priv->wmi->multi_write_idx = 0;
4444a22fe10SSujith 	}
4454a22fe10SSujith 
4464a22fe10SSujith 	mutex_unlock(&priv->wmi->multi_write_mutex);
4474a22fe10SSujith }
4484a22fe10SSujith 
449845e03c9SFelix Fietkau static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
450845e03c9SFelix Fietkau {
451845e03c9SFelix Fietkau 	u32 val;
452845e03c9SFelix Fietkau 
453845e03c9SFelix Fietkau 	val = ath9k_regread(hw_priv, reg_offset);
454845e03c9SFelix Fietkau 	val &= ~clr;
455845e03c9SFelix Fietkau 	val |= set;
456845e03c9SFelix Fietkau 	ath9k_regwrite(hw_priv, val, reg_offset);
457845e03c9SFelix Fietkau 	return val;
458845e03c9SFelix Fietkau }
459845e03c9SFelix Fietkau 
460fb9987d0SSujith static void ath_usb_read_cachesize(struct ath_common *common, int *csz)
461fb9987d0SSujith {
462fb9987d0SSujith 	*csz = L1_CACHE_BYTES >> 2;
463fb9987d0SSujith }
464fb9987d0SSujith 
465fb9987d0SSujith static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
466fb9987d0SSujith {
467fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) common->ah;
468fb9987d0SSujith 
469fb9987d0SSujith 	(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
470fb9987d0SSujith 
471fb9987d0SSujith 	if (!ath9k_hw_wait(ah,
472fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA,
473fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA_BUSY |
474fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
475fb9987d0SSujith 			   AH_WAIT_TIMEOUT))
476fb9987d0SSujith 		return false;
477fb9987d0SSujith 
478fb9987d0SSujith 	*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
479fb9987d0SSujith 		   AR_EEPROM_STATUS_DATA_VAL);
480fb9987d0SSujith 
481fb9987d0SSujith 	return true;
482fb9987d0SSujith }
483fb9987d0SSujith 
484fb9987d0SSujith static const struct ath_bus_ops ath9k_usb_bus_ops = {
485497ad9adSSujith 	.ath_bus_type = ATH_USB,
486fb9987d0SSujith 	.read_cachesize = ath_usb_read_cachesize,
487fb9987d0SSujith 	.eeprom_read = ath_usb_eeprom_read,
488fb9987d0SSujith };
489fb9987d0SSujith 
490fb9987d0SSujith static void setup_ht_cap(struct ath9k_htc_priv *priv,
491fb9987d0SSujith 			 struct ieee80211_sta_ht_cap *ht_info)
492fb9987d0SSujith {
4936debecadSSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
4946debecadSSujith 	u8 tx_streams, rx_streams;
4956debecadSSujith 	int i;
4966debecadSSujith 
497fb9987d0SSujith 	ht_info->ht_supported = true;
498fb9987d0SSujith 	ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
499fb9987d0SSujith 		       IEEE80211_HT_CAP_SM_PS |
500fb9987d0SSujith 		       IEEE80211_HT_CAP_SGI_40 |
501fb9987d0SSujith 		       IEEE80211_HT_CAP_DSSSCCK40;
502fb9987d0SSujith 
503b4dec5e8SSujith 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
504b4dec5e8SSujith 		ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
505b4dec5e8SSujith 
50617525f96SSujith 	ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
50717525f96SSujith 
508fb9987d0SSujith 	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
509fb9987d0SSujith 	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
510fb9987d0SSujith 
511fb9987d0SSujith 	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
5126debecadSSujith 
5136debecadSSujith 	/* ath9k_htc supports only 1 or 2 stream devices */
51482b2d334SFelix Fietkau 	tx_streams = ath9k_cmn_count_streams(priv->ah->txchainmask, 2);
51582b2d334SFelix Fietkau 	rx_streams = ath9k_cmn_count_streams(priv->ah->rxchainmask, 2);
5166debecadSSujith 
517d2182b69SJoe Perches 	ath_dbg(common, CONFIG, "TX streams %d, RX streams: %d\n",
5186debecadSSujith 		tx_streams, rx_streams);
5196debecadSSujith 
5206debecadSSujith 	if (tx_streams != rx_streams) {
5216debecadSSujith 		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
5226debecadSSujith 		ht_info->mcs.tx_params |= ((tx_streams - 1) <<
5236debecadSSujith 					   IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
5246debecadSSujith 	}
5256debecadSSujith 
5266debecadSSujith 	for (i = 0; i < rx_streams; i++)
5276debecadSSujith 		ht_info->mcs.rx_mask[i] = 0xff;
5286debecadSSujith 
529fb9987d0SSujith 	ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
530fb9987d0SSujith }
531fb9987d0SSujith 
532fb9987d0SSujith static int ath9k_init_queues(struct ath9k_htc_priv *priv)
533fb9987d0SSujith {
534fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
535fb9987d0SSujith 	int i;
536fb9987d0SSujith 
537fb9987d0SSujith 	for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++)
538fb9987d0SSujith 		priv->hwq_map[i] = -1;
539fb9987d0SSujith 
540ca74b83bSSujith 	priv->beaconq = ath9k_hw_beaconq_setup(priv->ah);
541ca74b83bSSujith 	if (priv->beaconq == -1) {
5423800276aSJoe Perches 		ath_err(common, "Unable to setup BEACON xmit queue\n");
543ca74b83bSSujith 		goto err;
544ca74b83bSSujith 	}
545ca74b83bSSujith 
546ca74b83bSSujith 	priv->cabq = ath9k_htc_cabq_setup(priv);
547ca74b83bSSujith 	if (priv->cabq == -1) {
5483800276aSJoe Perches 		ath_err(common, "Unable to setup CAB xmit queue\n");
549ca74b83bSSujith 		goto err;
550ca74b83bSSujith 	}
551ca74b83bSSujith 
552bea843c7SSujith Manoharan 	if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_BE)) {
5533800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for BE traffic\n");
554fb9987d0SSujith 		goto err;
555fb9987d0SSujith 	}
556fb9987d0SSujith 
557bea843c7SSujith Manoharan 	if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_BK)) {
5583800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for BK traffic\n");
559fb9987d0SSujith 		goto err;
560fb9987d0SSujith 	}
561bea843c7SSujith Manoharan 	if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_VI)) {
5623800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for VI traffic\n");
563fb9987d0SSujith 		goto err;
564fb9987d0SSujith 	}
565bea843c7SSujith Manoharan 	if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_VO)) {
5663800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for VO traffic\n");
567fb9987d0SSujith 		goto err;
568fb9987d0SSujith 	}
569fb9987d0SSujith 
570fb9987d0SSujith 	return 0;
571fb9987d0SSujith 
572fb9987d0SSujith err:
573fb9987d0SSujith 	return -EINVAL;
574fb9987d0SSujith }
575fb9987d0SSujith 
576fb9987d0SSujith static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
577fb9987d0SSujith {
578d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
579fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].channels =
580fb9987d0SSujith 			ath9k_2ghz_channels;
581fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
582fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].n_channels =
583fb9987d0SSujith 			ARRAY_SIZE(ath9k_2ghz_channels);
584fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
585fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
586fb9987d0SSujith 			ARRAY_SIZE(ath9k_legacy_rates);
587fb9987d0SSujith 	}
588ea46e644SSujith 
589d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
590ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels;
591ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
592ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].n_channels =
593ea46e644SSujith 			ARRAY_SIZE(ath9k_5ghz_channels);
594ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].bitrates =
595ea46e644SSujith 			ath9k_legacy_rates + 4;
596ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
597ea46e644SSujith 			ARRAY_SIZE(ath9k_legacy_rates) - 4;
598ea46e644SSujith 	}
599fb9987d0SSujith }
600fb9987d0SSujith 
601fb9987d0SSujith static void ath9k_init_misc(struct ath9k_htc_priv *priv)
602fb9987d0SSujith {
603fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
604fb9987d0SSujith 
605fb9987d0SSujith 	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
606fb9987d0SSujith 
6079f01a84eSSujith 	priv->ah->opmode = NL80211_IFTYPE_STATION;
608fb9987d0SSujith }
609fb9987d0SSujith 
61021cb9879SVivek Natarajan static int ath9k_init_priv(struct ath9k_htc_priv *priv,
611fa6e15e0SRajkumar Manoharan 			   u16 devid, char *product,
612fa6e15e0SRajkumar Manoharan 			   u32 drv_info)
613fb9987d0SSujith {
614fb9987d0SSujith 	struct ath_hw *ah = NULL;
615fb9987d0SSujith 	struct ath_common *common;
616832f6a18SSujith Manoharan 	int i, ret = 0, csz = 0;
617fb9987d0SSujith 
618d8a2c51cSSujith Manoharan 	set_bit(OP_INVALID, &priv->op_flags);
619fb9987d0SSujith 
620fb9987d0SSujith 	ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
621fb9987d0SSujith 	if (!ah)
622fb9987d0SSujith 		return -ENOMEM;
623fb9987d0SSujith 
624fb9987d0SSujith 	ah->hw_version.devid = devid;
6250b5ead91SSujith Manoharan 	ah->hw_version.usbdev = drv_info;
626f8afa42bSFelix Fietkau 	ah->ah_flags |= AH_USE_EEPROM;
627f9f84e96SFelix Fietkau 	ah->reg_ops.read = ath9k_regread;
628f9f84e96SFelix Fietkau 	ah->reg_ops.multi_read = ath9k_multi_regread;
629f9f84e96SFelix Fietkau 	ah->reg_ops.write = ath9k_regwrite;
630f9f84e96SFelix Fietkau 	ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer;
631f9f84e96SFelix Fietkau 	ah->reg_ops.write_flush = ath9k_regwrite_flush;
632845e03c9SFelix Fietkau 	ah->reg_ops.rmw = ath9k_reg_rmw;
633fb9987d0SSujith 	priv->ah = ah;
634fb9987d0SSujith 
635fb9987d0SSujith 	common = ath9k_hw_common(ah);
636f9f84e96SFelix Fietkau 	common->ops = &ah->reg_ops;
637fb9987d0SSujith 	common->bus_ops = &ath9k_usb_bus_ops;
638fb9987d0SSujith 	common->ah = ah;
639fb9987d0SSujith 	common->hw = priv->hw;
640fb9987d0SSujith 	common->priv = priv;
641fb9987d0SSujith 	common->debug_mask = ath9k_debug;
6427f34778eSMohammed Shafi Shajakhan 	common->btcoex_enabled = ath9k_htc_btcoex_enable == 1;
643fb9987d0SSujith 
644fb9987d0SSujith 	spin_lock_init(&priv->beacon_lock);
645658ef04fSSujith Manoharan 	spin_lock_init(&priv->tx.tx_lock);
646fb9987d0SSujith 	mutex_init(&priv->mutex);
647bde748a4SVivek Natarajan 	mutex_init(&priv->htc_pm_lock);
648fb9987d0SSujith 	tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
649fb9987d0SSujith 		     (unsigned long)priv);
65027876a29SSujith Manoharan 	tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet,
65173908674SSujith Manoharan 		     (unsigned long)priv);
652a236254cSSujith Manoharan 	INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
653bde748a4SVivek Natarajan 	INIT_WORK(&priv->ps_work, ath9k_ps_work);
65473908674SSujith Manoharan 	INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
655859c3ca1SSujith Manoharan 	setup_timer(&priv->tx.cleanup_timer, ath9k_htc_tx_cleanup_timer,
656859c3ca1SSujith Manoharan 		    (unsigned long)priv);
657fb9987d0SSujith 
658fb9987d0SSujith 	/*
659fb9987d0SSujith 	 * Cache line size is used to size and align various
660fb9987d0SSujith 	 * structures used to communicate with the hardware.
661fb9987d0SSujith 	 */
662fb9987d0SSujith 	ath_read_cachesize(common, &csz);
663fb9987d0SSujith 	common->cachelsz = csz << 2; /* convert to bytes */
664fb9987d0SSujith 
665fb9987d0SSujith 	ret = ath9k_hw_init(ah);
666fb9987d0SSujith 	if (ret) {
6673800276aSJoe Perches 		ath_err(common,
6683800276aSJoe Perches 			"Unable to initialize hardware; initialization status: %d\n",
6693800276aSJoe Perches 			ret);
670fb9987d0SSujith 		goto err_hw;
671fb9987d0SSujith 	}
672fb9987d0SSujith 
673fb9987d0SSujith 	ret = ath9k_init_queues(priv);
674fb9987d0SSujith 	if (ret)
675fb9987d0SSujith 		goto err_queues;
676fb9987d0SSujith 
677832f6a18SSujith Manoharan 	for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
678832f6a18SSujith Manoharan 		priv->cur_beacon_conf.bslot[i] = NULL;
679832f6a18SSujith Manoharan 
680f82b4bdeSRajkumar Manoharan 	ath9k_cmn_init_crypto(ah);
681fb9987d0SSujith 	ath9k_init_channels_rates(priv);
682fb9987d0SSujith 	ath9k_init_misc(priv);
683cee5341dSSujith Manoharan 	ath9k_htc_init_btcoex(priv, product);
68421cb9879SVivek Natarajan 
685fb9987d0SSujith 	return 0;
686fb9987d0SSujith 
687fb9987d0SSujith err_queues:
688fb9987d0SSujith 	ath9k_hw_deinit(ah);
689fb9987d0SSujith err_hw:
690fb9987d0SSujith 
691fb9987d0SSujith 	kfree(ah);
692fb9987d0SSujith 	priv->ah = NULL;
693fb9987d0SSujith 
694fb9987d0SSujith 	return ret;
695fb9987d0SSujith }
696fb9987d0SSujith 
6978b0b6be5SMohammed Shafi Shajakhan static const struct ieee80211_iface_limit if_limits[] = {
6988b0b6be5SMohammed Shafi Shajakhan 	{ .max = 2,	.types = BIT(NL80211_IFTYPE_STATION) |
6998b0b6be5SMohammed Shafi Shajakhan 				 BIT(NL80211_IFTYPE_P2P_CLIENT) },
7008b0b6be5SMohammed Shafi Shajakhan 	{ .max = 2,	.types = BIT(NL80211_IFTYPE_AP) |
701594e65b6SJavier Cardona 				 BIT(NL80211_IFTYPE_P2P_GO) |
702594e65b6SJavier Cardona 				 BIT(NL80211_IFTYPE_MESH_POINT) },
7038b0b6be5SMohammed Shafi Shajakhan };
7048b0b6be5SMohammed Shafi Shajakhan 
7058b0b6be5SMohammed Shafi Shajakhan static const struct ieee80211_iface_combination if_comb = {
7068b0b6be5SMohammed Shafi Shajakhan 	.limits = if_limits,
7078b0b6be5SMohammed Shafi Shajakhan 	.n_limits = ARRAY_SIZE(if_limits),
7088b0b6be5SMohammed Shafi Shajakhan 	.max_interfaces = 2,
7098b0b6be5SMohammed Shafi Shajakhan 	.num_different_channels = 1,
7108b0b6be5SMohammed Shafi Shajakhan };
7118b0b6be5SMohammed Shafi Shajakhan 
712fb9987d0SSujith static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
713fb9987d0SSujith 			       struct ieee80211_hw *hw)
714fb9987d0SSujith {
715fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
716fb9987d0SSujith 
717fb9987d0SSujith 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
718fb9987d0SSujith 		IEEE80211_HW_AMPDU_AGGREGATION |
719fb9987d0SSujith 		IEEE80211_HW_SPECTRUM_MGMT |
72032fbccafSSujith 		IEEE80211_HW_HAS_RATE_CONTROL |
721bde748a4SVivek Natarajan 		IEEE80211_HW_RX_INCLUDES_FCS |
722bde748a4SVivek Natarajan 		IEEE80211_HW_SUPPORTS_PS |
7237d547eb4SSujith Manoharan 		IEEE80211_HW_PS_NULLFUNC_STACK |
7248ae2e12fSRajkumar Manoharan 		IEEE80211_HW_REPORTS_TX_ACK_STATUS |
725bd4a85eeSJavier Cardona 		IEEE80211_HW_MFP_CAPABLE |
7267d547eb4SSujith Manoharan 		IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
727fb9987d0SSujith 
728fb9987d0SSujith 	hw->wiphy->interface_modes =
729fb9987d0SSujith 		BIT(NL80211_IFTYPE_STATION) |
73009d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_ADHOC) |
73109d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_AP) |
73209d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_P2P_GO) |
733594e65b6SJavier Cardona 		BIT(NL80211_IFTYPE_P2P_CLIENT) |
734594e65b6SJavier Cardona 		BIT(NL80211_IFTYPE_MESH_POINT);
735fb9987d0SSujith 
7368b0b6be5SMohammed Shafi Shajakhan 	hw->wiphy->iface_combinations = &if_comb;
7378b0b6be5SMohammed Shafi Shajakhan 	hw->wiphy->n_iface_combinations = 1;
7388b0b6be5SMohammed Shafi Shajakhan 
739bde748a4SVivek Natarajan 	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
740bde748a4SVivek Natarajan 
74181ddbb5cSJohannes Berg 	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN |
74281ddbb5cSJohannes Berg 			    WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
743d7d312caSAntonio Quartulli 
744fb9987d0SSujith 	hw->queues = 4;
745fb9987d0SSujith 	hw->channel_change_time = 5000;
746fb1c078eSSujith Manoharan 	hw->max_listen_interval = 1;
7473a0593efSSujith Manoharan 
748fb9987d0SSujith 	hw->vif_data_size = sizeof(struct ath9k_htc_vif);
749fb9987d0SSujith 	hw->sta_data_size = sizeof(struct ath9k_htc_sta);
750fb9987d0SSujith 
751fb9987d0SSujith 	/* tx_frame_hdr is larger than tx_mgmt_hdr anyway */
752fb9987d0SSujith 	hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) +
753fb9987d0SSujith 		sizeof(struct htc_frame_hdr) + 4;
754fb9987d0SSujith 
755d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
756fb9987d0SSujith 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
757fb9987d0SSujith 			&priv->sbands[IEEE80211_BAND_2GHZ];
758d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
759ea46e644SSujith 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
760ea46e644SSujith 			&priv->sbands[IEEE80211_BAND_5GHZ];
761fb9987d0SSujith 
762fb9987d0SSujith 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
763d4659912SFelix Fietkau 		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
764fb9987d0SSujith 			setup_ht_cap(priv,
765fb9987d0SSujith 				     &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap);
766d4659912SFelix Fietkau 		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
767ea46e644SSujith 			setup_ht_cap(priv,
768ea46e644SSujith 				     &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
769fb9987d0SSujith 	}
770fb9987d0SSujith 
771fb9987d0SSujith 	SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
772fb9987d0SSujith }
773fb9987d0SSujith 
77429bbfb24SSujith Manoharan static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv)
77529bbfb24SSujith Manoharan {
77629bbfb24SSujith Manoharan 	struct ieee80211_hw *hw = priv->hw;
77729bbfb24SSujith Manoharan 	struct wmi_fw_version cmd_rsp;
77829bbfb24SSujith Manoharan 	int ret;
77929bbfb24SSujith Manoharan 
78029bbfb24SSujith Manoharan 	memset(&cmd_rsp, 0, sizeof(cmd_rsp));
78129bbfb24SSujith Manoharan 
78229bbfb24SSujith Manoharan 	WMI_CMD(WMI_GET_FW_VERSION);
78329bbfb24SSujith Manoharan 	if (ret)
78429bbfb24SSujith Manoharan 		return -EINVAL;
78529bbfb24SSujith Manoharan 
78629bbfb24SSujith Manoharan 	priv->fw_version_major = be16_to_cpu(cmd_rsp.major);
78729bbfb24SSujith Manoharan 	priv->fw_version_minor = be16_to_cpu(cmd_rsp.minor);
78829bbfb24SSujith Manoharan 
78981135548SJiri Pirko 	snprintf(hw->wiphy->fw_version, sizeof(hw->wiphy->fw_version), "%d.%d",
79029bbfb24SSujith Manoharan 		 priv->fw_version_major,
79129bbfb24SSujith Manoharan 		 priv->fw_version_minor);
79229bbfb24SSujith Manoharan 
79329bbfb24SSujith Manoharan 	dev_info(priv->dev, "ath9k_htc: FW Version: %d.%d\n",
79429bbfb24SSujith Manoharan 		 priv->fw_version_major,
79529bbfb24SSujith Manoharan 		 priv->fw_version_minor);
79629bbfb24SSujith Manoharan 
7973a0593efSSujith Manoharan 	/*
7983a0593efSSujith Manoharan 	 * Check if the available FW matches the driver's
7993a0593efSSujith Manoharan 	 * required version.
8003a0593efSSujith Manoharan 	 */
8013a0593efSSujith Manoharan 	if (priv->fw_version_major != MAJOR_VERSION_REQ ||
802319e7bd9SFelix Fietkau 	    priv->fw_version_minor < MINOR_VERSION_REQ) {
8033a0593efSSujith Manoharan 		dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n",
8043a0593efSSujith Manoharan 			MAJOR_VERSION_REQ, MINOR_VERSION_REQ);
8053a0593efSSujith Manoharan 		return -EINVAL;
8063a0593efSSujith Manoharan 	}
8073a0593efSSujith Manoharan 
80829bbfb24SSujith Manoharan 	return 0;
80929bbfb24SSujith Manoharan }
81029bbfb24SSujith Manoharan 
81121cb9879SVivek Natarajan static int ath9k_init_device(struct ath9k_htc_priv *priv,
812fa6e15e0SRajkumar Manoharan 			     u16 devid, char *product, u32 drv_info)
813fb9987d0SSujith {
814fb9987d0SSujith 	struct ieee80211_hw *hw = priv->hw;
815fb9987d0SSujith 	struct ath_common *common;
816fb9987d0SSujith 	struct ath_hw *ah;
817fb9987d0SSujith 	int error = 0;
818fb9987d0SSujith 	struct ath_regulatory *reg;
8193e3f1d19SSujith Manoharan 	char hw_name[64];
820fb9987d0SSujith 
821fb9987d0SSujith 	/* Bring up device */
822fa6e15e0SRajkumar Manoharan 	error = ath9k_init_priv(priv, devid, product, drv_info);
823fb9987d0SSujith 	if (error != 0)
824fb9987d0SSujith 		goto err_init;
825fb9987d0SSujith 
826fb9987d0SSujith 	ah = priv->ah;
827fb9987d0SSujith 	common = ath9k_hw_common(ah);
828fb9987d0SSujith 	ath9k_set_hw_capab(priv, hw);
829fb9987d0SSujith 
83029bbfb24SSujith Manoharan 	error = ath9k_init_firmware_version(priv);
83129bbfb24SSujith Manoharan 	if (error != 0)
83229bbfb24SSujith Manoharan 		goto err_fw;
83329bbfb24SSujith Manoharan 
834fb9987d0SSujith 	/* Initialize regulatory */
835fb9987d0SSujith 	error = ath_regd_init(&common->regulatory, priv->hw->wiphy,
836fb9987d0SSujith 			      ath9k_reg_notifier);
837fb9987d0SSujith 	if (error)
838fb9987d0SSujith 		goto err_regd;
839fb9987d0SSujith 
840fb9987d0SSujith 	reg = &common->regulatory;
841fb9987d0SSujith 
842fb9987d0SSujith 	/* Setup TX */
843fb9987d0SSujith 	error = ath9k_tx_init(priv);
844fb9987d0SSujith 	if (error != 0)
845fb9987d0SSujith 		goto err_tx;
846fb9987d0SSujith 
847fb9987d0SSujith 	/* Setup RX */
848fb9987d0SSujith 	error = ath9k_rx_init(priv);
849fb9987d0SSujith 	if (error != 0)
850fb9987d0SSujith 		goto err_rx;
851fb9987d0SSujith 
852d244f21eSSujith Manoharan #ifdef CONFIG_MAC80211_LEDS
853d244f21eSSujith Manoharan 	/* must be initialized before ieee80211_register_hw */
854d244f21eSSujith Manoharan 	priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw,
855d244f21eSSujith Manoharan 		IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_htc_tpt_blink,
856d244f21eSSujith Manoharan 		ARRAY_SIZE(ath9k_htc_tpt_blink));
857d244f21eSSujith Manoharan #endif
858d244f21eSSujith Manoharan 
859fb9987d0SSujith 	/* Register with mac80211 */
860fb9987d0SSujith 	error = ieee80211_register_hw(hw);
861fb9987d0SSujith 	if (error)
862fb9987d0SSujith 		goto err_register;
863fb9987d0SSujith 
864fb9987d0SSujith 	/* Handle world regulatory */
865fb9987d0SSujith 	if (!ath_is_world_regd(reg)) {
866fb9987d0SSujith 		error = regulatory_hint(hw->wiphy, reg->alpha2);
867fb9987d0SSujith 		if (error)
868fb9987d0SSujith 			goto err_world;
869fb9987d0SSujith 	}
870fb9987d0SSujith 
871e5facc75SRajkumar Manoharan 	error = ath9k_htc_init_debug(priv->ah);
872e5facc75SRajkumar Manoharan 	if (error) {
873e5facc75SRajkumar Manoharan 		ath_err(common, "Unable to create debugfs files\n");
874e5facc75SRajkumar Manoharan 		goto err_world;
875e5facc75SRajkumar Manoharan 	}
876e5facc75SRajkumar Manoharan 
877d2182b69SJoe Perches 	ath_dbg(common, CONFIG,
878d2182b69SJoe Perches 		"WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, BE:%d, BK:%d, VI:%d, VO:%d\n",
8793e3f1d19SSujith Manoharan 		priv->wmi_cmd_ep,
8803e3f1d19SSujith Manoharan 		priv->beacon_ep,
8813e3f1d19SSujith Manoharan 		priv->cab_ep,
8823e3f1d19SSujith Manoharan 		priv->uapsd_ep,
8833e3f1d19SSujith Manoharan 		priv->mgmt_ep,
8843e3f1d19SSujith Manoharan 		priv->data_be_ep,
8853e3f1d19SSujith Manoharan 		priv->data_bk_ep,
8863e3f1d19SSujith Manoharan 		priv->data_vi_ep,
8873e3f1d19SSujith Manoharan 		priv->data_vo_ep);
8883e3f1d19SSujith Manoharan 
8893e3f1d19SSujith Manoharan 	ath9k_hw_name(priv->ah, hw_name, sizeof(hw_name));
8903e3f1d19SSujith Manoharan 	wiphy_info(hw->wiphy, "%s\n", hw_name);
8913e3f1d19SSujith Manoharan 
892fb9987d0SSujith 	ath9k_init_leds(priv);
893fb9987d0SSujith 	ath9k_start_rfkill_poll(priv);
894fb9987d0SSujith 
895fb9987d0SSujith 	return 0;
896fb9987d0SSujith 
897fb9987d0SSujith err_world:
898fb9987d0SSujith 	ieee80211_unregister_hw(hw);
899fb9987d0SSujith err_register:
900fb9987d0SSujith 	ath9k_rx_cleanup(priv);
901fb9987d0SSujith err_rx:
902fb9987d0SSujith 	ath9k_tx_cleanup(priv);
903fb9987d0SSujith err_tx:
904fb9987d0SSujith 	/* Nothing */
905fb9987d0SSujith err_regd:
90629bbfb24SSujith Manoharan 	/* Nothing */
90729bbfb24SSujith Manoharan err_fw:
908fb9987d0SSujith 	ath9k_deinit_priv(priv);
909fb9987d0SSujith err_init:
910fb9987d0SSujith 	return error;
911fb9987d0SSujith }
912fb9987d0SSujith 
913fb9987d0SSujith int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
914fa6e15e0SRajkumar Manoharan 			   u16 devid, char *product, u32 drv_info)
915fb9987d0SSujith {
916fb9987d0SSujith 	struct ieee80211_hw *hw;
917fb9987d0SSujith 	struct ath9k_htc_priv *priv;
918fb9987d0SSujith 	int ret;
919fb9987d0SSujith 
920fb9987d0SSujith 	hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops);
921fb9987d0SSujith 	if (!hw)
922fb9987d0SSujith 		return -ENOMEM;
923fb9987d0SSujith 
924fb9987d0SSujith 	priv = hw->priv;
925fb9987d0SSujith 	priv->hw = hw;
926fb9987d0SSujith 	priv->htc = htc_handle;
927fb9987d0SSujith 	priv->dev = dev;
928fb9987d0SSujith 	htc_handle->drv_priv = priv;
929fb9987d0SSujith 	SET_IEEE80211_DEV(hw, priv->dev);
930fb9987d0SSujith 
931fb9987d0SSujith 	ret = ath9k_htc_wait_for_target(priv);
932fb9987d0SSujith 	if (ret)
933fb9987d0SSujith 		goto err_free;
934fb9987d0SSujith 
935fb9987d0SSujith 	priv->wmi = ath9k_init_wmi(priv);
936fb9987d0SSujith 	if (!priv->wmi) {
937fb9987d0SSujith 		ret = -EINVAL;
938fb9987d0SSujith 		goto err_free;
939fb9987d0SSujith 	}
940fb9987d0SSujith 
941fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_htc_services(priv, devid, drv_info);
942fb9987d0SSujith 	if (ret)
943fb9987d0SSujith 		goto err_init;
944fb9987d0SSujith 
945fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_device(priv, devid, product, drv_info);
946fb9987d0SSujith 	if (ret)
947fb9987d0SSujith 		goto err_init;
948fb9987d0SSujith 
949fb9987d0SSujith 	return 0;
950fb9987d0SSujith 
951fb9987d0SSujith err_init:
952fb9987d0SSujith 	ath9k_deinit_wmi(priv);
953fb9987d0SSujith err_free:
954fb9987d0SSujith 	ieee80211_free_hw(hw);
955fb9987d0SSujith 	return ret;
956fb9987d0SSujith }
957fb9987d0SSujith 
958fb9987d0SSujith void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
959fb9987d0SSujith {
960fb9987d0SSujith 	if (htc_handle->drv_priv) {
961a3be14b7SSujith 
962a3be14b7SSujith 		/* Check if the device has been yanked out. */
963a3be14b7SSujith 		if (hotunplug)
96497dcec57SSujith Manoharan 			htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED;
965a3be14b7SSujith 
966fb9987d0SSujith 		ath9k_deinit_device(htc_handle->drv_priv);
967fb9987d0SSujith 		ath9k_deinit_wmi(htc_handle->drv_priv);
968fb9987d0SSujith 		ieee80211_free_hw(htc_handle->drv_priv->hw);
969fb9987d0SSujith 	}
970fb9987d0SSujith }
971fb9987d0SSujith 
972fb9987d0SSujith #ifdef CONFIG_PM
973f933ebedSSujith Manoharan 
974f933ebedSSujith Manoharan void ath9k_htc_suspend(struct htc_target *htc_handle)
975f933ebedSSujith Manoharan {
976f933ebedSSujith Manoharan 	ath9k_htc_setpower(htc_handle->drv_priv, ATH9K_PM_FULL_SLEEP);
977f933ebedSSujith Manoharan }
978f933ebedSSujith Manoharan 
979fb9987d0SSujith int ath9k_htc_resume(struct htc_target *htc_handle)
980fb9987d0SSujith {
981fa6e15e0SRajkumar Manoharan 	struct ath9k_htc_priv *priv = htc_handle->drv_priv;
982fb9987d0SSujith 	int ret;
983fb9987d0SSujith 
984fa6e15e0SRajkumar Manoharan 	ret = ath9k_htc_wait_for_target(priv);
985fb9987d0SSujith 	if (ret)
986fb9987d0SSujith 		return ret;
987fb9987d0SSujith 
988fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid,
9890b5ead91SSujith Manoharan 				      priv->ah->hw_version.usbdev);
990fb9987d0SSujith 	return ret;
991fb9987d0SSujith }
992fb9987d0SSujith #endif
993fb9987d0SSujith 
994fb9987d0SSujith static int __init ath9k_htc_init(void)
995fb9987d0SSujith {
996e5facc75SRajkumar Manoharan 	if (ath9k_hif_usb_init() < 0) {
997516304b0SJoe Perches 		pr_err("No USB devices found, driver not installed\n");
998e5facc75SRajkumar Manoharan 		return -ENODEV;
999fb9987d0SSujith 	}
1000fb9987d0SSujith 
1001fb9987d0SSujith 	return 0;
1002fb9987d0SSujith }
1003fb9987d0SSujith module_init(ath9k_htc_init);
1004fb9987d0SSujith 
1005fb9987d0SSujith static void __exit ath9k_htc_exit(void)
1006fb9987d0SSujith {
1007fb9987d0SSujith 	ath9k_hif_usb_exit();
1008516304b0SJoe Perches 	pr_info("Driver unloaded\n");
1009fb9987d0SSujith }
1010fb9987d0SSujith module_exit(ath9k_htc_exit);
1011