1fb9987d0SSujith /*
2fb9987d0SSujith  * Copyright (c) 2010 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 
4421cb9879SVivek Natarajan #define ATH_HTC_BTCOEX_PRODUCT_ID "wb193"
4521cb9879SVivek Natarajan 
46fb9987d0SSujith static struct ieee80211_channel ath9k_2ghz_channels[] = {
47fb9987d0SSujith 	CHAN2G(2412, 0), /* Channel 1 */
48fb9987d0SSujith 	CHAN2G(2417, 1), /* Channel 2 */
49fb9987d0SSujith 	CHAN2G(2422, 2), /* Channel 3 */
50fb9987d0SSujith 	CHAN2G(2427, 3), /* Channel 4 */
51fb9987d0SSujith 	CHAN2G(2432, 4), /* Channel 5 */
52fb9987d0SSujith 	CHAN2G(2437, 5), /* Channel 6 */
53fb9987d0SSujith 	CHAN2G(2442, 6), /* Channel 7 */
54fb9987d0SSujith 	CHAN2G(2447, 7), /* Channel 8 */
55fb9987d0SSujith 	CHAN2G(2452, 8), /* Channel 9 */
56fb9987d0SSujith 	CHAN2G(2457, 9), /* Channel 10 */
57fb9987d0SSujith 	CHAN2G(2462, 10), /* Channel 11 */
58fb9987d0SSujith 	CHAN2G(2467, 11), /* Channel 12 */
59fb9987d0SSujith 	CHAN2G(2472, 12), /* Channel 13 */
60fb9987d0SSujith 	CHAN2G(2484, 13), /* Channel 14 */
61fb9987d0SSujith };
62fb9987d0SSujith 
63ea46e644SSujith static struct ieee80211_channel ath9k_5ghz_channels[] = {
64ea46e644SSujith 	/* _We_ call this UNII 1 */
65ea46e644SSujith 	CHAN5G(5180, 14), /* Channel 36 */
66ea46e644SSujith 	CHAN5G(5200, 15), /* Channel 40 */
67ea46e644SSujith 	CHAN5G(5220, 16), /* Channel 44 */
68ea46e644SSujith 	CHAN5G(5240, 17), /* Channel 48 */
69ea46e644SSujith 	/* _We_ call this UNII 2 */
70ea46e644SSujith 	CHAN5G(5260, 18), /* Channel 52 */
71ea46e644SSujith 	CHAN5G(5280, 19), /* Channel 56 */
72ea46e644SSujith 	CHAN5G(5300, 20), /* Channel 60 */
73ea46e644SSujith 	CHAN5G(5320, 21), /* Channel 64 */
74ea46e644SSujith 	/* _We_ call this "Middle band" */
75ea46e644SSujith 	CHAN5G(5500, 22), /* Channel 100 */
76ea46e644SSujith 	CHAN5G(5520, 23), /* Channel 104 */
77ea46e644SSujith 	CHAN5G(5540, 24), /* Channel 108 */
78ea46e644SSujith 	CHAN5G(5560, 25), /* Channel 112 */
79ea46e644SSujith 	CHAN5G(5580, 26), /* Channel 116 */
80ea46e644SSujith 	CHAN5G(5600, 27), /* Channel 120 */
81ea46e644SSujith 	CHAN5G(5620, 28), /* Channel 124 */
82ea46e644SSujith 	CHAN5G(5640, 29), /* Channel 128 */
83ea46e644SSujith 	CHAN5G(5660, 30), /* Channel 132 */
84ea46e644SSujith 	CHAN5G(5680, 31), /* Channel 136 */
85ea46e644SSujith 	CHAN5G(5700, 32), /* Channel 140 */
86ea46e644SSujith 	/* _We_ call this UNII 3 */
87ea46e644SSujith 	CHAN5G(5745, 33), /* Channel 149 */
88ea46e644SSujith 	CHAN5G(5765, 34), /* Channel 153 */
89ea46e644SSujith 	CHAN5G(5785, 35), /* Channel 157 */
90ea46e644SSujith 	CHAN5G(5805, 36), /* Channel 161 */
91ea46e644SSujith 	CHAN5G(5825, 37), /* Channel 165 */
92ea46e644SSujith };
93ea46e644SSujith 
94fb9987d0SSujith /* Atheros hardware rate code addition for short premble */
95fb9987d0SSujith #define SHPCHECK(__hw_rate, __flags) \
96fb9987d0SSujith 	((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0)
97fb9987d0SSujith 
98fb9987d0SSujith #define RATE(_bitrate, _hw_rate, _flags) {		\
99fb9987d0SSujith 	.bitrate	= (_bitrate),			\
100fb9987d0SSujith 	.flags		= (_flags),			\
101fb9987d0SSujith 	.hw_value	= (_hw_rate),			\
102fb9987d0SSujith 	.hw_value_short = (SHPCHECK(_hw_rate, _flags))	\
103fb9987d0SSujith }
104fb9987d0SSujith 
105fb9987d0SSujith static struct ieee80211_rate ath9k_legacy_rates[] = {
106fb9987d0SSujith 	RATE(10, 0x1b, 0),
107fb9987d0SSujith 	RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp : 0x1e */
108fb9987d0SSujith 	RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp: 0x1d */
109fb9987d0SSujith 	RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), /* short: 0x1c */
110fb9987d0SSujith 	RATE(60, 0x0b, 0),
111fb9987d0SSujith 	RATE(90, 0x0f, 0),
112fb9987d0SSujith 	RATE(120, 0x0a, 0),
113fb9987d0SSujith 	RATE(180, 0x0e, 0),
114fb9987d0SSujith 	RATE(240, 0x09, 0),
115fb9987d0SSujith 	RATE(360, 0x0d, 0),
116fb9987d0SSujith 	RATE(480, 0x08, 0),
117fb9987d0SSujith 	RATE(540, 0x0c, 0),
118fb9987d0SSujith };
119fb9987d0SSujith 
120fb9987d0SSujith static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
121fb9987d0SSujith {
122fb9987d0SSujith 	int time_left;
123fb9987d0SSujith 
124d8c49ffbSSujith.Manoharan@atheros.com 	if (atomic_read(&priv->htc->tgt_ready) > 0) {
125d8c49ffbSSujith.Manoharan@atheros.com 		atomic_dec(&priv->htc->tgt_ready);
126d8c49ffbSSujith.Manoharan@atheros.com 		return 0;
127d8c49ffbSSujith.Manoharan@atheros.com 	}
128d8c49ffbSSujith.Manoharan@atheros.com 
129fb9987d0SSujith 	/* Firmware can take up to 50ms to get ready, to be safe use 1 second */
130fb9987d0SSujith 	time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ);
131fb9987d0SSujith 	if (!time_left) {
132fb9987d0SSujith 		dev_err(priv->dev, "ath9k_htc: Target is unresponsive\n");
133fb9987d0SSujith 		return -ETIMEDOUT;
134fb9987d0SSujith 	}
135fb9987d0SSujith 
136d8c49ffbSSujith.Manoharan@atheros.com 	atomic_dec(&priv->htc->tgt_ready);
137d8c49ffbSSujith.Manoharan@atheros.com 
138fb9987d0SSujith 	return 0;
139fb9987d0SSujith }
140fb9987d0SSujith 
141fb9987d0SSujith static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
142fb9987d0SSujith {
143fb9987d0SSujith 	ath9k_hw_deinit(priv->ah);
144fb9987d0SSujith 	kfree(priv->ah);
145fb9987d0SSujith 	priv->ah = NULL;
146fb9987d0SSujith }
147fb9987d0SSujith 
148fb9987d0SSujith static void ath9k_deinit_device(struct ath9k_htc_priv *priv)
149fb9987d0SSujith {
150fb9987d0SSujith 	struct ieee80211_hw *hw = priv->hw;
151fb9987d0SSujith 
152fb9987d0SSujith 	wiphy_rfkill_stop_polling(hw->wiphy);
153fb9987d0SSujith 	ath9k_deinit_leds(priv);
154fb9987d0SSujith 	ieee80211_unregister_hw(hw);
155fb9987d0SSujith 	ath9k_rx_cleanup(priv);
156fb9987d0SSujith 	ath9k_tx_cleanup(priv);
157fb9987d0SSujith 	ath9k_deinit_priv(priv);
158fb9987d0SSujith }
159fb9987d0SSujith 
160fb9987d0SSujith static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv,
161fb9987d0SSujith 					u16 service_id,
162fb9987d0SSujith 					void (*tx) (void *,
163fb9987d0SSujith 						    struct sk_buff *,
164fb9987d0SSujith 						    enum htc_endpoint_id,
165fb9987d0SSujith 						    bool txok),
166fb9987d0SSujith 					enum htc_endpoint_id *ep_id)
167fb9987d0SSujith {
168fb9987d0SSujith 	struct htc_service_connreq req;
169fb9987d0SSujith 
170fb9987d0SSujith 	memset(&req, 0, sizeof(struct htc_service_connreq));
171fb9987d0SSujith 
172fb9987d0SSujith 	req.service_id = service_id;
173fb9987d0SSujith 	req.ep_callbacks.priv = priv;
174fb9987d0SSujith 	req.ep_callbacks.rx = ath9k_htc_rxep;
175fb9987d0SSujith 	req.ep_callbacks.tx = tx;
176fb9987d0SSujith 
177fb9987d0SSujith 	return htc_connect_service(priv->htc, &req, ep_id);
178fb9987d0SSujith }
179fb9987d0SSujith 
180fa6e15e0SRajkumar Manoharan static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid,
181fa6e15e0SRajkumar Manoharan 				   u32 drv_info)
182fb9987d0SSujith {
183fb9987d0SSujith 	int ret;
184fb9987d0SSujith 
185fb9987d0SSujith 	/* WMI CMD*/
186fb9987d0SSujith 	ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep);
187fb9987d0SSujith 	if (ret)
188fb9987d0SSujith 		goto err;
189fb9987d0SSujith 
190fb9987d0SSujith 	/* Beacon */
1919c6dda4eSSujith 	ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, ath9k_htc_beaconep,
192fb9987d0SSujith 				    &priv->beacon_ep);
193fb9987d0SSujith 	if (ret)
194fb9987d0SSujith 		goto err;
195fb9987d0SSujith 
196fb9987d0SSujith 	/* CAB */
197fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep,
198fb9987d0SSujith 				    &priv->cab_ep);
199fb9987d0SSujith 	if (ret)
200fb9987d0SSujith 		goto err;
201fb9987d0SSujith 
202fb9987d0SSujith 
203fb9987d0SSujith 	/* UAPSD */
204fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep,
205fb9987d0SSujith 				    &priv->uapsd_ep);
206fb9987d0SSujith 	if (ret)
207fb9987d0SSujith 		goto err;
208fb9987d0SSujith 
209fb9987d0SSujith 	/* MGMT */
210fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep,
211fb9987d0SSujith 				    &priv->mgmt_ep);
212fb9987d0SSujith 	if (ret)
213fb9987d0SSujith 		goto err;
214fb9987d0SSujith 
215fb9987d0SSujith 	/* DATA BE */
216fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep,
217fb9987d0SSujith 				    &priv->data_be_ep);
218fb9987d0SSujith 	if (ret)
219fb9987d0SSujith 		goto err;
220fb9987d0SSujith 
221fb9987d0SSujith 	/* DATA BK */
222fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep,
223fb9987d0SSujith 				    &priv->data_bk_ep);
224fb9987d0SSujith 	if (ret)
225fb9987d0SSujith 		goto err;
226fb9987d0SSujith 
227fb9987d0SSujith 	/* DATA VI */
228fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep,
229fb9987d0SSujith 				    &priv->data_vi_ep);
230fb9987d0SSujith 	if (ret)
231fb9987d0SSujith 		goto err;
232fb9987d0SSujith 
233fb9987d0SSujith 	/* DATA VO */
234fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep,
235fb9987d0SSujith 				    &priv->data_vo_ep);
236fb9987d0SSujith 	if (ret)
237fb9987d0SSujith 		goto err;
238fb9987d0SSujith 
2396267dc70SSujith 	/*
2406267dc70SSujith 	 * Setup required credits before initializing HTC.
2416267dc70SSujith 	 * This is a bit hacky, but, since queuing is done in
2426267dc70SSujith 	 * the HIF layer, shouldn't matter much.
2436267dc70SSujith 	 */
2446267dc70SSujith 
2450b5ead91SSujith Manoharan 	if (IS_AR7010_DEVICE(drv_info))
2466267dc70SSujith 		priv->htc->credits = 45;
247fa6e15e0SRajkumar Manoharan 	else
2484e63f768SSujith 		priv->htc->credits = 33;
2496267dc70SSujith 
250fb9987d0SSujith 	ret = htc_init(priv->htc);
251fb9987d0SSujith 	if (ret)
252fb9987d0SSujith 		goto err;
253fb9987d0SSujith 
2546267dc70SSujith 	dev_info(priv->dev, "ath9k_htc: HTC initialized with %d credits\n",
2556267dc70SSujith 		 priv->htc->credits);
2566267dc70SSujith 
257fb9987d0SSujith 	return 0;
258fb9987d0SSujith 
259fb9987d0SSujith err:
260fb9987d0SSujith 	dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n");
261fb9987d0SSujith 	return ret;
262fb9987d0SSujith }
263fb9987d0SSujith 
264fb9987d0SSujith static int ath9k_reg_notifier(struct wiphy *wiphy,
265fb9987d0SSujith 			      struct regulatory_request *request)
266fb9987d0SSujith {
267fb9987d0SSujith 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
268fb9987d0SSujith 	struct ath9k_htc_priv *priv = hw->priv;
269fb9987d0SSujith 
270fb9987d0SSujith 	return ath_reg_notifier_apply(wiphy, request,
271fb9987d0SSujith 				      ath9k_hw_regulatory(priv->ah));
272fb9987d0SSujith }
273fb9987d0SSujith 
2744a22fe10SSujith static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
275fb9987d0SSujith {
276fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
277fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(ah);
278fb9987d0SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
279fb9987d0SSujith 	__be32 val, reg = cpu_to_be32(reg_offset);
280fb9987d0SSujith 	int r;
281fb9987d0SSujith 
282fb9987d0SSujith 	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
283fb9987d0SSujith 			  (u8 *) &reg, sizeof(reg),
284fb9987d0SSujith 			  (u8 *) &val, sizeof(val),
285fb9987d0SSujith 			  100);
286fb9987d0SSujith 	if (unlikely(r)) {
287226afe68SJoe Perches 		ath_dbg(common, ATH_DBG_WMI,
288fb9987d0SSujith 			"REGISTER READ FAILED: (0x%04x, %d)\n",
289fb9987d0SSujith 			reg_offset, r);
290fb9987d0SSujith 		return -EIO;
291fb9987d0SSujith 	}
292fb9987d0SSujith 
293fb9987d0SSujith 	return be32_to_cpu(val);
294fb9987d0SSujith }
295fb9987d0SSujith 
29609a525d3SSujith Manoharan static void ath9k_multi_regread(void *hw_priv, u32 *addr,
29709a525d3SSujith Manoharan 				u32 *val, u16 count)
29809a525d3SSujith Manoharan {
29909a525d3SSujith Manoharan 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
30009a525d3SSujith Manoharan 	struct ath_common *common = ath9k_hw_common(ah);
30109a525d3SSujith Manoharan 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
30209a525d3SSujith Manoharan 	__be32 tmpaddr[8];
30309a525d3SSujith Manoharan 	__be32 tmpval[8];
30409a525d3SSujith Manoharan 	int i, ret;
30509a525d3SSujith Manoharan 
30609a525d3SSujith Manoharan        for (i = 0; i < count; i++) {
30709a525d3SSujith Manoharan 	       tmpaddr[i] = cpu_to_be32(addr[i]);
30809a525d3SSujith Manoharan        }
30909a525d3SSujith Manoharan 
31009a525d3SSujith Manoharan        ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
31109a525d3SSujith Manoharan 			   (u8 *)tmpaddr , sizeof(u32) * count,
31209a525d3SSujith Manoharan 			   (u8 *)tmpval, sizeof(u32) * count,
31309a525d3SSujith Manoharan 			   100);
31409a525d3SSujith Manoharan 	if (unlikely(ret)) {
31509a525d3SSujith Manoharan 		ath_dbg(common, ATH_DBG_WMI,
31609a525d3SSujith Manoharan 			"Multiple REGISTER READ FAILED (count: %d)\n", count);
31709a525d3SSujith Manoharan 	}
31809a525d3SSujith Manoharan 
31909a525d3SSujith Manoharan        for (i = 0; i < count; i++) {
32009a525d3SSujith Manoharan 	       val[i] = be32_to_cpu(tmpval[i]);
32109a525d3SSujith Manoharan        }
32209a525d3SSujith Manoharan }
32309a525d3SSujith Manoharan 
3244a22fe10SSujith static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
325fb9987d0SSujith {
326fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
327fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(ah);
328fb9987d0SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
32907b2fa5aSJoe Perches 	const __be32 buf[2] = {
330fb9987d0SSujith 		cpu_to_be32(reg_offset),
331fb9987d0SSujith 		cpu_to_be32(val),
332fb9987d0SSujith 	};
333fb9987d0SSujith 	int r;
334fb9987d0SSujith 
335fb9987d0SSujith 	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
336fb9987d0SSujith 			  (u8 *) &buf, sizeof(buf),
337fb9987d0SSujith 			  (u8 *) &val, sizeof(val),
338fb9987d0SSujith 			  100);
339fb9987d0SSujith 	if (unlikely(r)) {
340226afe68SJoe Perches 		ath_dbg(common, ATH_DBG_WMI,
341fb9987d0SSujith 			"REGISTER WRITE FAILED:(0x%04x, %d)\n",
342fb9987d0SSujith 			reg_offset, r);
343fb9987d0SSujith 	}
344fb9987d0SSujith }
345fb9987d0SSujith 
3464a22fe10SSujith static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset)
3474a22fe10SSujith {
3484a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3494a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3504a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3514a22fe10SSujith 	u32 rsp_status;
3524a22fe10SSujith 	int r;
3534a22fe10SSujith 
3544a22fe10SSujith 	mutex_lock(&priv->wmi->multi_write_mutex);
3554a22fe10SSujith 
3564a22fe10SSujith 	/* Store the register/value */
3574a22fe10SSujith 	priv->wmi->multi_write[priv->wmi->multi_write_idx].reg =
3584a22fe10SSujith 		cpu_to_be32(reg_offset);
3594a22fe10SSujith 	priv->wmi->multi_write[priv->wmi->multi_write_idx].val =
3604a22fe10SSujith 		cpu_to_be32(val);
3614a22fe10SSujith 
3624a22fe10SSujith 	priv->wmi->multi_write_idx++;
3634a22fe10SSujith 
3644a22fe10SSujith 	/* If the buffer is full, send it out. */
3654a22fe10SSujith 	if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) {
3664a22fe10SSujith 		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
3674a22fe10SSujith 			  (u8 *) &priv->wmi->multi_write,
3684a22fe10SSujith 			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
3694a22fe10SSujith 			  (u8 *) &rsp_status, sizeof(rsp_status),
3704a22fe10SSujith 			  100);
3714a22fe10SSujith 		if (unlikely(r)) {
372226afe68SJoe Perches 			ath_dbg(common, ATH_DBG_WMI,
3734a22fe10SSujith 				"REGISTER WRITE FAILED, multi len: %d\n",
3744a22fe10SSujith 				priv->wmi->multi_write_idx);
3754a22fe10SSujith 		}
3764a22fe10SSujith 		priv->wmi->multi_write_idx = 0;
3774a22fe10SSujith 	}
3784a22fe10SSujith 
3794a22fe10SSujith 	mutex_unlock(&priv->wmi->multi_write_mutex);
3804a22fe10SSujith }
3814a22fe10SSujith 
3824a22fe10SSujith static void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset)
3834a22fe10SSujith {
3844a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3854a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3864a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3874a22fe10SSujith 
3884a22fe10SSujith 	if (atomic_read(&priv->wmi->mwrite_cnt))
3894a22fe10SSujith 		ath9k_regwrite_buffer(hw_priv, val, reg_offset);
3904a22fe10SSujith 	else
3914a22fe10SSujith 		ath9k_regwrite_single(hw_priv, val, reg_offset);
3924a22fe10SSujith }
3934a22fe10SSujith 
3944a22fe10SSujith static void ath9k_enable_regwrite_buffer(void *hw_priv)
3954a22fe10SSujith {
3964a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3974a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3984a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3994a22fe10SSujith 
4004a22fe10SSujith 	atomic_inc(&priv->wmi->mwrite_cnt);
4014a22fe10SSujith }
4024a22fe10SSujith 
4034a22fe10SSujith static void ath9k_regwrite_flush(void *hw_priv)
4044a22fe10SSujith {
4054a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
4064a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
4074a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
4084a22fe10SSujith 	u32 rsp_status;
4094a22fe10SSujith 	int r;
4104a22fe10SSujith 
411435c1610SFelix Fietkau 	atomic_dec(&priv->wmi->mwrite_cnt);
412435c1610SFelix Fietkau 
4134a22fe10SSujith 	mutex_lock(&priv->wmi->multi_write_mutex);
4144a22fe10SSujith 
4154a22fe10SSujith 	if (priv->wmi->multi_write_idx) {
4164a22fe10SSujith 		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
4174a22fe10SSujith 			  (u8 *) &priv->wmi->multi_write,
4184a22fe10SSujith 			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
4194a22fe10SSujith 			  (u8 *) &rsp_status, sizeof(rsp_status),
4204a22fe10SSujith 			  100);
4214a22fe10SSujith 		if (unlikely(r)) {
422226afe68SJoe Perches 			ath_dbg(common, ATH_DBG_WMI,
4234a22fe10SSujith 				"REGISTER WRITE FAILED, multi len: %d\n",
4244a22fe10SSujith 				priv->wmi->multi_write_idx);
4254a22fe10SSujith 		}
4264a22fe10SSujith 		priv->wmi->multi_write_idx = 0;
4274a22fe10SSujith 	}
4284a22fe10SSujith 
4294a22fe10SSujith 	mutex_unlock(&priv->wmi->multi_write_mutex);
4304a22fe10SSujith }
4314a22fe10SSujith 
432845e03c9SFelix Fietkau static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
433845e03c9SFelix Fietkau {
434845e03c9SFelix Fietkau 	u32 val;
435845e03c9SFelix Fietkau 
436845e03c9SFelix Fietkau 	val = ath9k_regread(hw_priv, reg_offset);
437845e03c9SFelix Fietkau 	val &= ~clr;
438845e03c9SFelix Fietkau 	val |= set;
439845e03c9SFelix Fietkau 	ath9k_regwrite(hw_priv, val, reg_offset);
440845e03c9SFelix Fietkau 	return val;
441845e03c9SFelix Fietkau }
442845e03c9SFelix Fietkau 
443fb9987d0SSujith static void ath_usb_read_cachesize(struct ath_common *common, int *csz)
444fb9987d0SSujith {
445fb9987d0SSujith 	*csz = L1_CACHE_BYTES >> 2;
446fb9987d0SSujith }
447fb9987d0SSujith 
448fb9987d0SSujith static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
449fb9987d0SSujith {
450fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) common->ah;
451fb9987d0SSujith 
452fb9987d0SSujith 	(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
453fb9987d0SSujith 
454fb9987d0SSujith 	if (!ath9k_hw_wait(ah,
455fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA,
456fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA_BUSY |
457fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
458fb9987d0SSujith 			   AH_WAIT_TIMEOUT))
459fb9987d0SSujith 		return false;
460fb9987d0SSujith 
461fb9987d0SSujith 	*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
462fb9987d0SSujith 		   AR_EEPROM_STATUS_DATA_VAL);
463fb9987d0SSujith 
464fb9987d0SSujith 	return true;
465fb9987d0SSujith }
466fb9987d0SSujith 
467fb9987d0SSujith static const struct ath_bus_ops ath9k_usb_bus_ops = {
468497ad9adSSujith 	.ath_bus_type = ATH_USB,
469fb9987d0SSujith 	.read_cachesize = ath_usb_read_cachesize,
470fb9987d0SSujith 	.eeprom_read = ath_usb_eeprom_read,
471fb9987d0SSujith };
472fb9987d0SSujith 
473fb9987d0SSujith static void setup_ht_cap(struct ath9k_htc_priv *priv,
474fb9987d0SSujith 			 struct ieee80211_sta_ht_cap *ht_info)
475fb9987d0SSujith {
4766debecadSSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
4776debecadSSujith 	u8 tx_streams, rx_streams;
4786debecadSSujith 	int i;
4796debecadSSujith 
480fb9987d0SSujith 	ht_info->ht_supported = true;
481fb9987d0SSujith 	ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
482fb9987d0SSujith 		       IEEE80211_HT_CAP_SM_PS |
483fb9987d0SSujith 		       IEEE80211_HT_CAP_SGI_40 |
484fb9987d0SSujith 		       IEEE80211_HT_CAP_DSSSCCK40;
485fb9987d0SSujith 
486b4dec5e8SSujith 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
487b4dec5e8SSujith 		ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
488b4dec5e8SSujith 
48917525f96SSujith 	ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
49017525f96SSujith 
491fb9987d0SSujith 	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
492fb9987d0SSujith 	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
493fb9987d0SSujith 
494fb9987d0SSujith 	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
4956debecadSSujith 
4966debecadSSujith 	/* ath9k_htc supports only 1 or 2 stream devices */
4976debecadSSujith 	tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2);
4986debecadSSujith 	rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2);
4996debecadSSujith 
500226afe68SJoe Perches 	ath_dbg(common, ATH_DBG_CONFIG,
5016debecadSSujith 		"TX streams %d, RX streams: %d\n",
5026debecadSSujith 		tx_streams, rx_streams);
5036debecadSSujith 
5046debecadSSujith 	if (tx_streams != rx_streams) {
5056debecadSSujith 		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
5066debecadSSujith 		ht_info->mcs.tx_params |= ((tx_streams - 1) <<
5076debecadSSujith 					   IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
5086debecadSSujith 	}
5096debecadSSujith 
5106debecadSSujith 	for (i = 0; i < rx_streams; i++)
5116debecadSSujith 		ht_info->mcs.rx_mask[i] = 0xff;
5126debecadSSujith 
513fb9987d0SSujith 	ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
514fb9987d0SSujith }
515fb9987d0SSujith 
516fb9987d0SSujith static int ath9k_init_queues(struct ath9k_htc_priv *priv)
517fb9987d0SSujith {
518fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
519fb9987d0SSujith 	int i;
520fb9987d0SSujith 
521fb9987d0SSujith 	for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++)
522fb9987d0SSujith 		priv->hwq_map[i] = -1;
523fb9987d0SSujith 
524ca74b83bSSujith 	priv->beaconq = ath9k_hw_beaconq_setup(priv->ah);
525ca74b83bSSujith 	if (priv->beaconq == -1) {
5263800276aSJoe Perches 		ath_err(common, "Unable to setup BEACON xmit queue\n");
527ca74b83bSSujith 		goto err;
528ca74b83bSSujith 	}
529ca74b83bSSujith 
530ca74b83bSSujith 	priv->cabq = ath9k_htc_cabq_setup(priv);
531ca74b83bSSujith 	if (priv->cabq == -1) {
5323800276aSJoe Perches 		ath_err(common, "Unable to setup CAB xmit queue\n");
533ca74b83bSSujith 		goto err;
534ca74b83bSSujith 	}
535ca74b83bSSujith 
536e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) {
5373800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for BE traffic\n");
538fb9987d0SSujith 		goto err;
539fb9987d0SSujith 	}
540fb9987d0SSujith 
541e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) {
5423800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for BK traffic\n");
543fb9987d0SSujith 		goto err;
544fb9987d0SSujith 	}
545e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) {
5463800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for VI traffic\n");
547fb9987d0SSujith 		goto err;
548fb9987d0SSujith 	}
549e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) {
5503800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for VO traffic\n");
551fb9987d0SSujith 		goto err;
552fb9987d0SSujith 	}
553fb9987d0SSujith 
554fb9987d0SSujith 	return 0;
555fb9987d0SSujith 
556fb9987d0SSujith err:
557fb9987d0SSujith 	return -EINVAL;
558fb9987d0SSujith }
559fb9987d0SSujith 
560fb9987d0SSujith static void ath9k_init_crypto(struct ath9k_htc_priv *priv)
561fb9987d0SSujith {
562fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
563fb9987d0SSujith 	int i = 0;
564fb9987d0SSujith 
565fb9987d0SSujith 	/* Get the hardware key cache size. */
5666de12a1bSFelix Fietkau 	common->keymax = AR_KEYTABLE_SIZE;
567fb9987d0SSujith 
568e2b62624SRajkumar Manoharan 	if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
569e2b62624SRajkumar Manoharan 		common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
570e2b62624SRajkumar Manoharan 
571fb9987d0SSujith 	/*
572fb9987d0SSujith 	 * Reset the key cache since some parts do not
573fb9987d0SSujith 	 * reset the contents on initial power up.
574fb9987d0SSujith 	 */
575fb9987d0SSujith 	for (i = 0; i < common->keymax; i++)
576040e539eSBruno Randolf 		ath_hw_keyreset(common, (u16) i);
577fb9987d0SSujith }
578fb9987d0SSujith 
579fb9987d0SSujith static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
580fb9987d0SSujith {
581d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
582fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].channels =
583fb9987d0SSujith 			ath9k_2ghz_channels;
584fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
585fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].n_channels =
586fb9987d0SSujith 			ARRAY_SIZE(ath9k_2ghz_channels);
587fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
588fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
589fb9987d0SSujith 			ARRAY_SIZE(ath9k_legacy_rates);
590fb9987d0SSujith 	}
591ea46e644SSujith 
592d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
593ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels;
594ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
595ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].n_channels =
596ea46e644SSujith 			ARRAY_SIZE(ath9k_5ghz_channels);
597ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].bitrates =
598ea46e644SSujith 			ath9k_legacy_rates + 4;
599ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
600ea46e644SSujith 			ARRAY_SIZE(ath9k_legacy_rates) - 4;
601ea46e644SSujith 	}
602fb9987d0SSujith }
603fb9987d0SSujith 
604fb9987d0SSujith static void ath9k_init_misc(struct ath9k_htc_priv *priv)
605fb9987d0SSujith {
606fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
607fb9987d0SSujith 
608fb9987d0SSujith 	common->tx_chainmask = priv->ah->caps.tx_chainmask;
609fb9987d0SSujith 	common->rx_chainmask = priv->ah->caps.rx_chainmask;
610fb9987d0SSujith 
611fb9987d0SSujith 	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
612fb9987d0SSujith 
6139f01a84eSSujith 	priv->ah->opmode = NL80211_IFTYPE_STATION;
614fb9987d0SSujith }
615fb9987d0SSujith 
61621cb9879SVivek Natarajan static void ath9k_init_btcoex(struct ath9k_htc_priv *priv)
61721cb9879SVivek Natarajan {
61821cb9879SVivek Natarajan 	int qnum;
61921cb9879SVivek Natarajan 
62021cb9879SVivek Natarajan 	switch (priv->ah->btcoex_hw.scheme) {
62121cb9879SVivek Natarajan 	case ATH_BTCOEX_CFG_NONE:
62221cb9879SVivek Natarajan 		break;
62321cb9879SVivek Natarajan 	case ATH_BTCOEX_CFG_3WIRE:
62421cb9879SVivek Natarajan 		priv->ah->btcoex_hw.btactive_gpio = 7;
62521cb9879SVivek Natarajan 		priv->ah->btcoex_hw.btpriority_gpio = 6;
62621cb9879SVivek Natarajan 		priv->ah->btcoex_hw.wlanactive_gpio = 8;
62721cb9879SVivek Natarajan 		priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
62821cb9879SVivek Natarajan 		ath9k_hw_btcoex_init_3wire(priv->ah);
62921cb9879SVivek Natarajan 		ath_htc_init_btcoex_work(priv);
63021cb9879SVivek Natarajan 		qnum = priv->hwq_map[WME_AC_BE];
63121cb9879SVivek Natarajan 		ath9k_hw_init_btcoex_hw(priv->ah, qnum);
63221cb9879SVivek Natarajan 		break;
63321cb9879SVivek Natarajan 	default:
63421cb9879SVivek Natarajan 		WARN_ON(1);
63521cb9879SVivek Natarajan 		break;
63621cb9879SVivek Natarajan 	}
63721cb9879SVivek Natarajan }
63821cb9879SVivek Natarajan 
63921cb9879SVivek Natarajan static int ath9k_init_priv(struct ath9k_htc_priv *priv,
640fa6e15e0SRajkumar Manoharan 			   u16 devid, char *product,
641fa6e15e0SRajkumar Manoharan 			   u32 drv_info)
642fb9987d0SSujith {
643fb9987d0SSujith 	struct ath_hw *ah = NULL;
644fb9987d0SSujith 	struct ath_common *common;
645832f6a18SSujith Manoharan 	int i, ret = 0, csz = 0;
646fb9987d0SSujith 
647fb9987d0SSujith 	priv->op_flags |= OP_INVALID;
648fb9987d0SSujith 
649fb9987d0SSujith 	ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
650fb9987d0SSujith 	if (!ah)
651fb9987d0SSujith 		return -ENOMEM;
652fb9987d0SSujith 
653fb9987d0SSujith 	ah->hw_version.devid = devid;
654fb9987d0SSujith 	ah->hw_version.subsysid = 0; /* FIXME */
6550b5ead91SSujith Manoharan 	ah->hw_version.usbdev = drv_info;
656f8afa42bSFelix Fietkau 	ah->ah_flags |= AH_USE_EEPROM;
657f9f84e96SFelix Fietkau 	ah->reg_ops.read = ath9k_regread;
658f9f84e96SFelix Fietkau 	ah->reg_ops.multi_read = ath9k_multi_regread;
659f9f84e96SFelix Fietkau 	ah->reg_ops.write = ath9k_regwrite;
660f9f84e96SFelix Fietkau 	ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer;
661f9f84e96SFelix Fietkau 	ah->reg_ops.write_flush = ath9k_regwrite_flush;
662845e03c9SFelix Fietkau 	ah->reg_ops.rmw = ath9k_reg_rmw;
663fb9987d0SSujith 	priv->ah = ah;
664fb9987d0SSujith 
665fb9987d0SSujith 	common = ath9k_hw_common(ah);
666f9f84e96SFelix Fietkau 	common->ops = &ah->reg_ops;
667fb9987d0SSujith 	common->bus_ops = &ath9k_usb_bus_ops;
668fb9987d0SSujith 	common->ah = ah;
669fb9987d0SSujith 	common->hw = priv->hw;
670fb9987d0SSujith 	common->priv = priv;
671fb9987d0SSujith 	common->debug_mask = ath9k_debug;
672fb9987d0SSujith 
673fb9987d0SSujith 	spin_lock_init(&priv->beacon_lock);
674658ef04fSSujith Manoharan 	spin_lock_init(&priv->tx.tx_lock);
675fb9987d0SSujith 	mutex_init(&priv->mutex);
676bde748a4SVivek Natarajan 	mutex_init(&priv->htc_pm_lock);
677fb9987d0SSujith 	tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
678fb9987d0SSujith 		     (unsigned long)priv);
67927876a29SSujith Manoharan 	tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet,
68073908674SSujith Manoharan 		     (unsigned long)priv);
681a236254cSSujith Manoharan 	INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
682bde748a4SVivek Natarajan 	INIT_WORK(&priv->ps_work, ath9k_ps_work);
68373908674SSujith Manoharan 	INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
684859c3ca1SSujith Manoharan 	setup_timer(&priv->tx.cleanup_timer, ath9k_htc_tx_cleanup_timer,
685859c3ca1SSujith Manoharan 		    (unsigned long)priv);
686fb9987d0SSujith 
687fb9987d0SSujith 	/*
688fb9987d0SSujith 	 * Cache line size is used to size and align various
689fb9987d0SSujith 	 * structures used to communicate with the hardware.
690fb9987d0SSujith 	 */
691fb9987d0SSujith 	ath_read_cachesize(common, &csz);
692fb9987d0SSujith 	common->cachelsz = csz << 2; /* convert to bytes */
693fb9987d0SSujith 
694fb9987d0SSujith 	ret = ath9k_hw_init(ah);
695fb9987d0SSujith 	if (ret) {
6963800276aSJoe Perches 		ath_err(common,
6973800276aSJoe Perches 			"Unable to initialize hardware; initialization status: %d\n",
6983800276aSJoe Perches 			ret);
699fb9987d0SSujith 		goto err_hw;
700fb9987d0SSujith 	}
701fb9987d0SSujith 
702fb9987d0SSujith 	ret = ath9k_init_queues(priv);
703fb9987d0SSujith 	if (ret)
704fb9987d0SSujith 		goto err_queues;
705fb9987d0SSujith 
706832f6a18SSujith Manoharan 	for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
707832f6a18SSujith Manoharan 		priv->cur_beacon_conf.bslot[i] = NULL;
708832f6a18SSujith Manoharan 
709fb9987d0SSujith 	ath9k_init_crypto(priv);
710fb9987d0SSujith 	ath9k_init_channels_rates(priv);
711fb9987d0SSujith 	ath9k_init_misc(priv);
712fb9987d0SSujith 
71321cb9879SVivek Natarajan 	if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) {
71421cb9879SVivek Natarajan 		ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE;
71521cb9879SVivek Natarajan 		ath9k_init_btcoex(priv);
71621cb9879SVivek Natarajan 	}
71721cb9879SVivek Natarajan 
718fb9987d0SSujith 	return 0;
719fb9987d0SSujith 
720fb9987d0SSujith err_queues:
721fb9987d0SSujith 	ath9k_hw_deinit(ah);
722fb9987d0SSujith err_hw:
723fb9987d0SSujith 
724fb9987d0SSujith 	kfree(ah);
725fb9987d0SSujith 	priv->ah = NULL;
726fb9987d0SSujith 
727fb9987d0SSujith 	return ret;
728fb9987d0SSujith }
729fb9987d0SSujith 
730fb9987d0SSujith static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
731fb9987d0SSujith 			       struct ieee80211_hw *hw)
732fb9987d0SSujith {
733fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
734fb9987d0SSujith 
735fb9987d0SSujith 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
736fb9987d0SSujith 		IEEE80211_HW_AMPDU_AGGREGATION |
737fb9987d0SSujith 		IEEE80211_HW_SPECTRUM_MGMT |
73832fbccafSSujith 		IEEE80211_HW_HAS_RATE_CONTROL |
739bde748a4SVivek Natarajan 		IEEE80211_HW_RX_INCLUDES_FCS |
740bde748a4SVivek Natarajan 		IEEE80211_HW_SUPPORTS_PS |
7417d547eb4SSujith Manoharan 		IEEE80211_HW_PS_NULLFUNC_STACK |
7427d547eb4SSujith Manoharan 		IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
743fb9987d0SSujith 
744fb9987d0SSujith 	hw->wiphy->interface_modes =
745fb9987d0SSujith 		BIT(NL80211_IFTYPE_STATION) |
74609d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_ADHOC) |
74709d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_AP) |
74809d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_P2P_GO) |
74909d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_P2P_CLIENT);
750fb9987d0SSujith 
751bde748a4SVivek Natarajan 	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
752bde748a4SVivek Natarajan 
753fb9987d0SSujith 	hw->queues = 4;
754fb9987d0SSujith 	hw->channel_change_time = 5000;
755fb9987d0SSujith 	hw->max_listen_interval = 10;
7563a0593efSSujith Manoharan 
7573a0593efSSujith Manoharan 	if (AR_SREV_9271(priv->ah))
7583a0593efSSujith Manoharan 		hw->max_tx_aggregation_subframes = MAX_TX_AMPDU_SUBFRAMES_9271;
7593a0593efSSujith Manoharan 	else
7603a0593efSSujith Manoharan 		hw->max_tx_aggregation_subframes = MAX_TX_AMPDU_SUBFRAMES_7010;
7613a0593efSSujith Manoharan 
762fb9987d0SSujith 	hw->vif_data_size = sizeof(struct ath9k_htc_vif);
763fb9987d0SSujith 	hw->sta_data_size = sizeof(struct ath9k_htc_sta);
764fb9987d0SSujith 
765fb9987d0SSujith 	/* tx_frame_hdr is larger than tx_mgmt_hdr anyway */
766fb9987d0SSujith 	hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) +
767fb9987d0SSujith 		sizeof(struct htc_frame_hdr) + 4;
768fb9987d0SSujith 
769d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
770fb9987d0SSujith 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
771fb9987d0SSujith 			&priv->sbands[IEEE80211_BAND_2GHZ];
772d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
773ea46e644SSujith 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
774ea46e644SSujith 			&priv->sbands[IEEE80211_BAND_5GHZ];
775fb9987d0SSujith 
776fb9987d0SSujith 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
777d4659912SFelix Fietkau 		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
778fb9987d0SSujith 			setup_ht_cap(priv,
779fb9987d0SSujith 				     &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap);
780d4659912SFelix Fietkau 		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
781ea46e644SSujith 			setup_ht_cap(priv,
782ea46e644SSujith 				     &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
783fb9987d0SSujith 	}
784fb9987d0SSujith 
785fb9987d0SSujith 	SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
786fb9987d0SSujith }
787fb9987d0SSujith 
78829bbfb24SSujith Manoharan static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv)
78929bbfb24SSujith Manoharan {
79029bbfb24SSujith Manoharan 	struct ieee80211_hw *hw = priv->hw;
79129bbfb24SSujith Manoharan 	struct wmi_fw_version cmd_rsp;
79229bbfb24SSujith Manoharan 	int ret;
79329bbfb24SSujith Manoharan 
79429bbfb24SSujith Manoharan 	memset(&cmd_rsp, 0, sizeof(cmd_rsp));
79529bbfb24SSujith Manoharan 
79629bbfb24SSujith Manoharan 	WMI_CMD(WMI_GET_FW_VERSION);
79729bbfb24SSujith Manoharan 	if (ret)
79829bbfb24SSujith Manoharan 		return -EINVAL;
79929bbfb24SSujith Manoharan 
80029bbfb24SSujith Manoharan 	priv->fw_version_major = be16_to_cpu(cmd_rsp.major);
80129bbfb24SSujith Manoharan 	priv->fw_version_minor = be16_to_cpu(cmd_rsp.minor);
80229bbfb24SSujith Manoharan 
80329bbfb24SSujith Manoharan 	snprintf(hw->wiphy->fw_version, ETHTOOL_BUSINFO_LEN, "%d.%d",
80429bbfb24SSujith Manoharan 		 priv->fw_version_major,
80529bbfb24SSujith Manoharan 		 priv->fw_version_minor);
80629bbfb24SSujith Manoharan 
80729bbfb24SSujith Manoharan 	dev_info(priv->dev, "ath9k_htc: FW Version: %d.%d\n",
80829bbfb24SSujith Manoharan 		 priv->fw_version_major,
80929bbfb24SSujith Manoharan 		 priv->fw_version_minor);
81029bbfb24SSujith Manoharan 
8113a0593efSSujith Manoharan 	/*
8123a0593efSSujith Manoharan 	 * Check if the available FW matches the driver's
8133a0593efSSujith Manoharan 	 * required version.
8143a0593efSSujith Manoharan 	 */
8153a0593efSSujith Manoharan 	if (priv->fw_version_major != MAJOR_VERSION_REQ ||
8163a0593efSSujith Manoharan 	    priv->fw_version_minor != MINOR_VERSION_REQ) {
8173a0593efSSujith Manoharan 		dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n",
8183a0593efSSujith Manoharan 			MAJOR_VERSION_REQ, MINOR_VERSION_REQ);
8193a0593efSSujith Manoharan 		return -EINVAL;
8203a0593efSSujith Manoharan 	}
8213a0593efSSujith Manoharan 
82229bbfb24SSujith Manoharan 	return 0;
82329bbfb24SSujith Manoharan }
82429bbfb24SSujith Manoharan 
82521cb9879SVivek Natarajan static int ath9k_init_device(struct ath9k_htc_priv *priv,
826fa6e15e0SRajkumar Manoharan 			     u16 devid, char *product, u32 drv_info)
827fb9987d0SSujith {
828fb9987d0SSujith 	struct ieee80211_hw *hw = priv->hw;
829fb9987d0SSujith 	struct ath_common *common;
830fb9987d0SSujith 	struct ath_hw *ah;
831fb9987d0SSujith 	int error = 0;
832fb9987d0SSujith 	struct ath_regulatory *reg;
8333e3f1d19SSujith Manoharan 	char hw_name[64];
834fb9987d0SSujith 
835fb9987d0SSujith 	/* Bring up device */
836fa6e15e0SRajkumar Manoharan 	error = ath9k_init_priv(priv, devid, product, drv_info);
837fb9987d0SSujith 	if (error != 0)
838fb9987d0SSujith 		goto err_init;
839fb9987d0SSujith 
840fb9987d0SSujith 	ah = priv->ah;
841fb9987d0SSujith 	common = ath9k_hw_common(ah);
842fb9987d0SSujith 	ath9k_set_hw_capab(priv, hw);
843fb9987d0SSujith 
84429bbfb24SSujith Manoharan 	error = ath9k_init_firmware_version(priv);
84529bbfb24SSujith Manoharan 	if (error != 0)
84629bbfb24SSujith Manoharan 		goto err_fw;
84729bbfb24SSujith Manoharan 
848fb9987d0SSujith 	/* Initialize regulatory */
849fb9987d0SSujith 	error = ath_regd_init(&common->regulatory, priv->hw->wiphy,
850fb9987d0SSujith 			      ath9k_reg_notifier);
851fb9987d0SSujith 	if (error)
852fb9987d0SSujith 		goto err_regd;
853fb9987d0SSujith 
854fb9987d0SSujith 	reg = &common->regulatory;
855fb9987d0SSujith 
856fb9987d0SSujith 	/* Setup TX */
857fb9987d0SSujith 	error = ath9k_tx_init(priv);
858fb9987d0SSujith 	if (error != 0)
859fb9987d0SSujith 		goto err_tx;
860fb9987d0SSujith 
861fb9987d0SSujith 	/* Setup RX */
862fb9987d0SSujith 	error = ath9k_rx_init(priv);
863fb9987d0SSujith 	if (error != 0)
864fb9987d0SSujith 		goto err_rx;
865fb9987d0SSujith 
866fb9987d0SSujith 	/* Register with mac80211 */
867fb9987d0SSujith 	error = ieee80211_register_hw(hw);
868fb9987d0SSujith 	if (error)
869fb9987d0SSujith 		goto err_register;
870fb9987d0SSujith 
871fb9987d0SSujith 	/* Handle world regulatory */
872fb9987d0SSujith 	if (!ath_is_world_regd(reg)) {
873fb9987d0SSujith 		error = regulatory_hint(hw->wiphy, reg->alpha2);
874fb9987d0SSujith 		if (error)
875fb9987d0SSujith 			goto err_world;
876fb9987d0SSujith 	}
877fb9987d0SSujith 
878e5facc75SRajkumar Manoharan 	error = ath9k_htc_init_debug(priv->ah);
879e5facc75SRajkumar Manoharan 	if (error) {
880e5facc75SRajkumar Manoharan 		ath_err(common, "Unable to create debugfs files\n");
881e5facc75SRajkumar Manoharan 		goto err_world;
882e5facc75SRajkumar Manoharan 	}
883e5facc75SRajkumar Manoharan 
8843e3f1d19SSujith Manoharan 	ath_dbg(common, ATH_DBG_CONFIG,
8853e3f1d19SSujith Manoharan 		"WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, "
8863e3f1d19SSujith Manoharan 		"BE:%d, BK:%d, VI:%d, VO:%d\n",
8873e3f1d19SSujith Manoharan 		priv->wmi_cmd_ep,
8883e3f1d19SSujith Manoharan 		priv->beacon_ep,
8893e3f1d19SSujith Manoharan 		priv->cab_ep,
8903e3f1d19SSujith Manoharan 		priv->uapsd_ep,
8913e3f1d19SSujith Manoharan 		priv->mgmt_ep,
8923e3f1d19SSujith Manoharan 		priv->data_be_ep,
8933e3f1d19SSujith Manoharan 		priv->data_bk_ep,
8943e3f1d19SSujith Manoharan 		priv->data_vi_ep,
8953e3f1d19SSujith Manoharan 		priv->data_vo_ep);
8963e3f1d19SSujith Manoharan 
8973e3f1d19SSujith Manoharan 	ath9k_hw_name(priv->ah, hw_name, sizeof(hw_name));
8983e3f1d19SSujith Manoharan 	wiphy_info(hw->wiphy, "%s\n", hw_name);
8993e3f1d19SSujith Manoharan 
900fb9987d0SSujith 	ath9k_init_leds(priv);
901fb9987d0SSujith 	ath9k_start_rfkill_poll(priv);
902fb9987d0SSujith 
903fb9987d0SSujith 	return 0;
904fb9987d0SSujith 
905fb9987d0SSujith err_world:
906fb9987d0SSujith 	ieee80211_unregister_hw(hw);
907fb9987d0SSujith err_register:
908fb9987d0SSujith 	ath9k_rx_cleanup(priv);
909fb9987d0SSujith err_rx:
910fb9987d0SSujith 	ath9k_tx_cleanup(priv);
911fb9987d0SSujith err_tx:
912fb9987d0SSujith 	/* Nothing */
913fb9987d0SSujith err_regd:
91429bbfb24SSujith Manoharan 	/* Nothing */
91529bbfb24SSujith Manoharan err_fw:
916fb9987d0SSujith 	ath9k_deinit_priv(priv);
917fb9987d0SSujith err_init:
918fb9987d0SSujith 	return error;
919fb9987d0SSujith }
920fb9987d0SSujith 
921fb9987d0SSujith int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
922fa6e15e0SRajkumar Manoharan 			   u16 devid, char *product, u32 drv_info)
923fb9987d0SSujith {
924fb9987d0SSujith 	struct ieee80211_hw *hw;
925fb9987d0SSujith 	struct ath9k_htc_priv *priv;
926fb9987d0SSujith 	int ret;
927fb9987d0SSujith 
928fb9987d0SSujith 	hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops);
929fb9987d0SSujith 	if (!hw)
930fb9987d0SSujith 		return -ENOMEM;
931fb9987d0SSujith 
932fb9987d0SSujith 	priv = hw->priv;
933fb9987d0SSujith 	priv->hw = hw;
934fb9987d0SSujith 	priv->htc = htc_handle;
935fb9987d0SSujith 	priv->dev = dev;
936fb9987d0SSujith 	htc_handle->drv_priv = priv;
937fb9987d0SSujith 	SET_IEEE80211_DEV(hw, priv->dev);
938fb9987d0SSujith 
939fb9987d0SSujith 	ret = ath9k_htc_wait_for_target(priv);
940fb9987d0SSujith 	if (ret)
941fb9987d0SSujith 		goto err_free;
942fb9987d0SSujith 
943fb9987d0SSujith 	priv->wmi = ath9k_init_wmi(priv);
944fb9987d0SSujith 	if (!priv->wmi) {
945fb9987d0SSujith 		ret = -EINVAL;
946fb9987d0SSujith 		goto err_free;
947fb9987d0SSujith 	}
948fb9987d0SSujith 
949fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_htc_services(priv, devid, drv_info);
950fb9987d0SSujith 	if (ret)
951fb9987d0SSujith 		goto err_init;
952fb9987d0SSujith 
953fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_device(priv, devid, product, drv_info);
954fb9987d0SSujith 	if (ret)
955fb9987d0SSujith 		goto err_init;
956fb9987d0SSujith 
957fb9987d0SSujith 	return 0;
958fb9987d0SSujith 
959fb9987d0SSujith err_init:
960fb9987d0SSujith 	ath9k_deinit_wmi(priv);
961fb9987d0SSujith err_free:
962fb9987d0SSujith 	ieee80211_free_hw(hw);
963fb9987d0SSujith 	return ret;
964fb9987d0SSujith }
965fb9987d0SSujith 
966fb9987d0SSujith void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
967fb9987d0SSujith {
968fb9987d0SSujith 	if (htc_handle->drv_priv) {
969a3be14b7SSujith 
970a3be14b7SSujith 		/* Check if the device has been yanked out. */
971a3be14b7SSujith 		if (hotunplug)
97297dcec57SSujith Manoharan 			htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED;
973a3be14b7SSujith 
974fb9987d0SSujith 		ath9k_deinit_device(htc_handle->drv_priv);
975fb9987d0SSujith 		ath9k_deinit_wmi(htc_handle->drv_priv);
976fb9987d0SSujith 		ieee80211_free_hw(htc_handle->drv_priv->hw);
977fb9987d0SSujith 	}
978fb9987d0SSujith }
979fb9987d0SSujith 
980fb9987d0SSujith #ifdef CONFIG_PM
981f933ebedSSujith Manoharan 
982f933ebedSSujith Manoharan void ath9k_htc_suspend(struct htc_target *htc_handle)
983f933ebedSSujith Manoharan {
984f933ebedSSujith Manoharan 	ath9k_htc_setpower(htc_handle->drv_priv, ATH9K_PM_FULL_SLEEP);
985f933ebedSSujith Manoharan }
986f933ebedSSujith Manoharan 
987fb9987d0SSujith int ath9k_htc_resume(struct htc_target *htc_handle)
988fb9987d0SSujith {
989fa6e15e0SRajkumar Manoharan 	struct ath9k_htc_priv *priv = htc_handle->drv_priv;
990fb9987d0SSujith 	int ret;
991fb9987d0SSujith 
992fa6e15e0SRajkumar Manoharan 	ret = ath9k_htc_wait_for_target(priv);
993fb9987d0SSujith 	if (ret)
994fb9987d0SSujith 		return ret;
995fb9987d0SSujith 
996fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid,
9970b5ead91SSujith Manoharan 				      priv->ah->hw_version.usbdev);
998fb9987d0SSujith 	return ret;
999fb9987d0SSujith }
1000fb9987d0SSujith #endif
1001fb9987d0SSujith 
1002fb9987d0SSujith static int __init ath9k_htc_init(void)
1003fb9987d0SSujith {
1004e5facc75SRajkumar Manoharan 	if (ath9k_hif_usb_init() < 0) {
1005fb9987d0SSujith 		printk(KERN_ERR
1006fb9987d0SSujith 			"ath9k_htc: No USB devices found,"
1007fb9987d0SSujith 			" driver not installed.\n");
1008e5facc75SRajkumar Manoharan 		return -ENODEV;
1009fb9987d0SSujith 	}
1010fb9987d0SSujith 
1011fb9987d0SSujith 	return 0;
1012fb9987d0SSujith }
1013fb9987d0SSujith module_init(ath9k_htc_init);
1014fb9987d0SSujith 
1015fb9987d0SSujith static void __exit ath9k_htc_exit(void)
1016fb9987d0SSujith {
1017fb9987d0SSujith 	ath9k_hif_usb_exit();
1018fb9987d0SSujith 	printk(KERN_INFO "ath9k_htc: Driver unloaded\n");
1019fb9987d0SSujith }
1020fb9987d0SSujith module_exit(ath9k_htc_exit);
1021