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 {
143e1572c5eSSujith 	ath9k_htc_exit_debug(priv->ah);
144fb9987d0SSujith 	ath9k_hw_deinit(priv->ah);
145fb9987d0SSujith 	kfree(priv->ah);
146fb9987d0SSujith 	priv->ah = NULL;
147fb9987d0SSujith }
148fb9987d0SSujith 
149fb9987d0SSujith static void ath9k_deinit_device(struct ath9k_htc_priv *priv)
150fb9987d0SSujith {
151fb9987d0SSujith 	struct ieee80211_hw *hw = priv->hw;
152fb9987d0SSujith 
153fb9987d0SSujith 	wiphy_rfkill_stop_polling(hw->wiphy);
154fb9987d0SSujith 	ath9k_deinit_leds(priv);
155fb9987d0SSujith 	ieee80211_unregister_hw(hw);
156fb9987d0SSujith 	ath9k_rx_cleanup(priv);
157fb9987d0SSujith 	ath9k_tx_cleanup(priv);
158fb9987d0SSujith 	ath9k_deinit_priv(priv);
159fb9987d0SSujith }
160fb9987d0SSujith 
161fb9987d0SSujith static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv,
162fb9987d0SSujith 					u16 service_id,
163fb9987d0SSujith 					void (*tx) (void *,
164fb9987d0SSujith 						    struct sk_buff *,
165fb9987d0SSujith 						    enum htc_endpoint_id,
166fb9987d0SSujith 						    bool txok),
167fb9987d0SSujith 					enum htc_endpoint_id *ep_id)
168fb9987d0SSujith {
169fb9987d0SSujith 	struct htc_service_connreq req;
170fb9987d0SSujith 
171fb9987d0SSujith 	memset(&req, 0, sizeof(struct htc_service_connreq));
172fb9987d0SSujith 
173fb9987d0SSujith 	req.service_id = service_id;
174fb9987d0SSujith 	req.ep_callbacks.priv = priv;
175fb9987d0SSujith 	req.ep_callbacks.rx = ath9k_htc_rxep;
176fb9987d0SSujith 	req.ep_callbacks.tx = tx;
177fb9987d0SSujith 
178fb9987d0SSujith 	return htc_connect_service(priv->htc, &req, ep_id);
179fb9987d0SSujith }
180fb9987d0SSujith 
181fa6e15e0SRajkumar Manoharan static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid,
182fa6e15e0SRajkumar Manoharan 				   u32 drv_info)
183fb9987d0SSujith {
184fb9987d0SSujith 	int ret;
185fb9987d0SSujith 
186fb9987d0SSujith 	/* WMI CMD*/
187fb9987d0SSujith 	ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep);
188fb9987d0SSujith 	if (ret)
189fb9987d0SSujith 		goto err;
190fb9987d0SSujith 
191fb9987d0SSujith 	/* Beacon */
1929c6dda4eSSujith 	ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, ath9k_htc_beaconep,
193fb9987d0SSujith 				    &priv->beacon_ep);
194fb9987d0SSujith 	if (ret)
195fb9987d0SSujith 		goto err;
196fb9987d0SSujith 
197fb9987d0SSujith 	/* CAB */
198fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep,
199fb9987d0SSujith 				    &priv->cab_ep);
200fb9987d0SSujith 	if (ret)
201fb9987d0SSujith 		goto err;
202fb9987d0SSujith 
203fb9987d0SSujith 
204fb9987d0SSujith 	/* UAPSD */
205fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep,
206fb9987d0SSujith 				    &priv->uapsd_ep);
207fb9987d0SSujith 	if (ret)
208fb9987d0SSujith 		goto err;
209fb9987d0SSujith 
210fb9987d0SSujith 	/* MGMT */
211fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep,
212fb9987d0SSujith 				    &priv->mgmt_ep);
213fb9987d0SSujith 	if (ret)
214fb9987d0SSujith 		goto err;
215fb9987d0SSujith 
216fb9987d0SSujith 	/* DATA BE */
217fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep,
218fb9987d0SSujith 				    &priv->data_be_ep);
219fb9987d0SSujith 	if (ret)
220fb9987d0SSujith 		goto err;
221fb9987d0SSujith 
222fb9987d0SSujith 	/* DATA BK */
223fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep,
224fb9987d0SSujith 				    &priv->data_bk_ep);
225fb9987d0SSujith 	if (ret)
226fb9987d0SSujith 		goto err;
227fb9987d0SSujith 
228fb9987d0SSujith 	/* DATA VI */
229fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep,
230fb9987d0SSujith 				    &priv->data_vi_ep);
231fb9987d0SSujith 	if (ret)
232fb9987d0SSujith 		goto err;
233fb9987d0SSujith 
234fb9987d0SSujith 	/* DATA VO */
235fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep,
236fb9987d0SSujith 				    &priv->data_vo_ep);
237fb9987d0SSujith 	if (ret)
238fb9987d0SSujith 		goto err;
239fb9987d0SSujith 
2406267dc70SSujith 	/*
2416267dc70SSujith 	 * Setup required credits before initializing HTC.
2426267dc70SSujith 	 * This is a bit hacky, but, since queuing is done in
2436267dc70SSujith 	 * the HIF layer, shouldn't matter much.
2446267dc70SSujith 	 */
2456267dc70SSujith 
2460b5ead91SSujith Manoharan 	if (IS_AR7010_DEVICE(drv_info))
2476267dc70SSujith 		priv->htc->credits = 45;
248fa6e15e0SRajkumar Manoharan 	else
2494e63f768SSujith 		priv->htc->credits = 33;
2506267dc70SSujith 
251fb9987d0SSujith 	ret = htc_init(priv->htc);
252fb9987d0SSujith 	if (ret)
253fb9987d0SSujith 		goto err;
254fb9987d0SSujith 
2556267dc70SSujith 	dev_info(priv->dev, "ath9k_htc: HTC initialized with %d credits\n",
2566267dc70SSujith 		 priv->htc->credits);
2576267dc70SSujith 
258fb9987d0SSujith 	return 0;
259fb9987d0SSujith 
260fb9987d0SSujith err:
261fb9987d0SSujith 	dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n");
262fb9987d0SSujith 	return ret;
263fb9987d0SSujith }
264fb9987d0SSujith 
265fb9987d0SSujith static int ath9k_reg_notifier(struct wiphy *wiphy,
266fb9987d0SSujith 			      struct regulatory_request *request)
267fb9987d0SSujith {
268fb9987d0SSujith 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
269fb9987d0SSujith 	struct ath9k_htc_priv *priv = hw->priv;
270fb9987d0SSujith 
271fb9987d0SSujith 	return ath_reg_notifier_apply(wiphy, request,
272fb9987d0SSujith 				      ath9k_hw_regulatory(priv->ah));
273fb9987d0SSujith }
274fb9987d0SSujith 
2754a22fe10SSujith static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
276fb9987d0SSujith {
277fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
278fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(ah);
279fb9987d0SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
280fb9987d0SSujith 	__be32 val, reg = cpu_to_be32(reg_offset);
281fb9987d0SSujith 	int r;
282fb9987d0SSujith 
283fb9987d0SSujith 	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
284fb9987d0SSujith 			  (u8 *) &reg, sizeof(reg),
285fb9987d0SSujith 			  (u8 *) &val, sizeof(val),
286fb9987d0SSujith 			  100);
287fb9987d0SSujith 	if (unlikely(r)) {
288226afe68SJoe Perches 		ath_dbg(common, ATH_DBG_WMI,
289fb9987d0SSujith 			"REGISTER READ FAILED: (0x%04x, %d)\n",
290fb9987d0SSujith 			reg_offset, r);
291fb9987d0SSujith 		return -EIO;
292fb9987d0SSujith 	}
293fb9987d0SSujith 
294fb9987d0SSujith 	return be32_to_cpu(val);
295fb9987d0SSujith }
296fb9987d0SSujith 
29709a525d3SSujith Manoharan static void ath9k_multi_regread(void *hw_priv, u32 *addr,
29809a525d3SSujith Manoharan 				u32 *val, u16 count)
29909a525d3SSujith Manoharan {
30009a525d3SSujith Manoharan 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
30109a525d3SSujith Manoharan 	struct ath_common *common = ath9k_hw_common(ah);
30209a525d3SSujith Manoharan 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
30309a525d3SSujith Manoharan 	__be32 tmpaddr[8];
30409a525d3SSujith Manoharan 	__be32 tmpval[8];
30509a525d3SSujith Manoharan 	int i, ret;
30609a525d3SSujith Manoharan 
30709a525d3SSujith Manoharan        for (i = 0; i < count; i++) {
30809a525d3SSujith Manoharan 	       tmpaddr[i] = cpu_to_be32(addr[i]);
30909a525d3SSujith Manoharan        }
31009a525d3SSujith Manoharan 
31109a525d3SSujith Manoharan        ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
31209a525d3SSujith Manoharan 			   (u8 *)tmpaddr , sizeof(u32) * count,
31309a525d3SSujith Manoharan 			   (u8 *)tmpval, sizeof(u32) * count,
31409a525d3SSujith Manoharan 			   100);
31509a525d3SSujith Manoharan 	if (unlikely(ret)) {
31609a525d3SSujith Manoharan 		ath_dbg(common, ATH_DBG_WMI,
31709a525d3SSujith Manoharan 			"Multiple REGISTER READ FAILED (count: %d)\n", count);
31809a525d3SSujith Manoharan 	}
31909a525d3SSujith Manoharan 
32009a525d3SSujith Manoharan        for (i = 0; i < count; i++) {
32109a525d3SSujith Manoharan 	       val[i] = be32_to_cpu(tmpval[i]);
32209a525d3SSujith Manoharan        }
32309a525d3SSujith Manoharan }
32409a525d3SSujith Manoharan 
3254a22fe10SSujith static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
326fb9987d0SSujith {
327fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
328fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(ah);
329fb9987d0SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
33007b2fa5aSJoe Perches 	const __be32 buf[2] = {
331fb9987d0SSujith 		cpu_to_be32(reg_offset),
332fb9987d0SSujith 		cpu_to_be32(val),
333fb9987d0SSujith 	};
334fb9987d0SSujith 	int r;
335fb9987d0SSujith 
336fb9987d0SSujith 	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
337fb9987d0SSujith 			  (u8 *) &buf, sizeof(buf),
338fb9987d0SSujith 			  (u8 *) &val, sizeof(val),
339fb9987d0SSujith 			  100);
340fb9987d0SSujith 	if (unlikely(r)) {
341226afe68SJoe Perches 		ath_dbg(common, ATH_DBG_WMI,
342fb9987d0SSujith 			"REGISTER WRITE FAILED:(0x%04x, %d)\n",
343fb9987d0SSujith 			reg_offset, r);
344fb9987d0SSujith 	}
345fb9987d0SSujith }
346fb9987d0SSujith 
3474a22fe10SSujith static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset)
3484a22fe10SSujith {
3494a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3504a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3514a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3524a22fe10SSujith 	u32 rsp_status;
3534a22fe10SSujith 	int r;
3544a22fe10SSujith 
3554a22fe10SSujith 	mutex_lock(&priv->wmi->multi_write_mutex);
3564a22fe10SSujith 
3574a22fe10SSujith 	/* Store the register/value */
3584a22fe10SSujith 	priv->wmi->multi_write[priv->wmi->multi_write_idx].reg =
3594a22fe10SSujith 		cpu_to_be32(reg_offset);
3604a22fe10SSujith 	priv->wmi->multi_write[priv->wmi->multi_write_idx].val =
3614a22fe10SSujith 		cpu_to_be32(val);
3624a22fe10SSujith 
3634a22fe10SSujith 	priv->wmi->multi_write_idx++;
3644a22fe10SSujith 
3654a22fe10SSujith 	/* If the buffer is full, send it out. */
3664a22fe10SSujith 	if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) {
3674a22fe10SSujith 		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
3684a22fe10SSujith 			  (u8 *) &priv->wmi->multi_write,
3694a22fe10SSujith 			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
3704a22fe10SSujith 			  (u8 *) &rsp_status, sizeof(rsp_status),
3714a22fe10SSujith 			  100);
3724a22fe10SSujith 		if (unlikely(r)) {
373226afe68SJoe Perches 			ath_dbg(common, ATH_DBG_WMI,
3744a22fe10SSujith 				"REGISTER WRITE FAILED, multi len: %d\n",
3754a22fe10SSujith 				priv->wmi->multi_write_idx);
3764a22fe10SSujith 		}
3774a22fe10SSujith 		priv->wmi->multi_write_idx = 0;
3784a22fe10SSujith 	}
3794a22fe10SSujith 
3804a22fe10SSujith 	mutex_unlock(&priv->wmi->multi_write_mutex);
3814a22fe10SSujith }
3824a22fe10SSujith 
3834a22fe10SSujith static void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset)
3844a22fe10SSujith {
3854a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3864a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3874a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3884a22fe10SSujith 
3894a22fe10SSujith 	if (atomic_read(&priv->wmi->mwrite_cnt))
3904a22fe10SSujith 		ath9k_regwrite_buffer(hw_priv, val, reg_offset);
3914a22fe10SSujith 	else
3924a22fe10SSujith 		ath9k_regwrite_single(hw_priv, val, reg_offset);
3934a22fe10SSujith }
3944a22fe10SSujith 
3954a22fe10SSujith static void ath9k_enable_regwrite_buffer(void *hw_priv)
3964a22fe10SSujith {
3974a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3984a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3994a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
4004a22fe10SSujith 
4014a22fe10SSujith 	atomic_inc(&priv->wmi->mwrite_cnt);
4024a22fe10SSujith }
4034a22fe10SSujith 
4044a22fe10SSujith static void ath9k_regwrite_flush(void *hw_priv)
4054a22fe10SSujith {
4064a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
4074a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
4084a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
4094a22fe10SSujith 	u32 rsp_status;
4104a22fe10SSujith 	int r;
4114a22fe10SSujith 
412435c1610SFelix Fietkau 	atomic_dec(&priv->wmi->mwrite_cnt);
413435c1610SFelix Fietkau 
4144a22fe10SSujith 	mutex_lock(&priv->wmi->multi_write_mutex);
4154a22fe10SSujith 
4164a22fe10SSujith 	if (priv->wmi->multi_write_idx) {
4174a22fe10SSujith 		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
4184a22fe10SSujith 			  (u8 *) &priv->wmi->multi_write,
4194a22fe10SSujith 			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
4204a22fe10SSujith 			  (u8 *) &rsp_status, sizeof(rsp_status),
4214a22fe10SSujith 			  100);
4224a22fe10SSujith 		if (unlikely(r)) {
423226afe68SJoe Perches 			ath_dbg(common, ATH_DBG_WMI,
4244a22fe10SSujith 				"REGISTER WRITE FAILED, multi len: %d\n",
4254a22fe10SSujith 				priv->wmi->multi_write_idx);
4264a22fe10SSujith 		}
4274a22fe10SSujith 		priv->wmi->multi_write_idx = 0;
4284a22fe10SSujith 	}
4294a22fe10SSujith 
4304a22fe10SSujith 	mutex_unlock(&priv->wmi->multi_write_mutex);
4314a22fe10SSujith }
4324a22fe10SSujith 
433fb9987d0SSujith static const struct ath_ops ath9k_common_ops = {
4344a22fe10SSujith 	.read = ath9k_regread,
43509a525d3SSujith Manoharan 	.multi_read = ath9k_multi_regread,
4364a22fe10SSujith 	.write = ath9k_regwrite,
4374a22fe10SSujith 	.enable_write_buffer = ath9k_enable_regwrite_buffer,
4384a22fe10SSujith 	.write_flush = ath9k_regwrite_flush,
439fb9987d0SSujith };
440fb9987d0SSujith 
441fb9987d0SSujith static void ath_usb_read_cachesize(struct ath_common *common, int *csz)
442fb9987d0SSujith {
443fb9987d0SSujith 	*csz = L1_CACHE_BYTES >> 2;
444fb9987d0SSujith }
445fb9987d0SSujith 
446fb9987d0SSujith static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
447fb9987d0SSujith {
448fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) common->ah;
449fb9987d0SSujith 
450fb9987d0SSujith 	(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
451fb9987d0SSujith 
452fb9987d0SSujith 	if (!ath9k_hw_wait(ah,
453fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA,
454fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA_BUSY |
455fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
456fb9987d0SSujith 			   AH_WAIT_TIMEOUT))
457fb9987d0SSujith 		return false;
458fb9987d0SSujith 
459fb9987d0SSujith 	*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
460fb9987d0SSujith 		   AR_EEPROM_STATUS_DATA_VAL);
461fb9987d0SSujith 
462fb9987d0SSujith 	return true;
463fb9987d0SSujith }
464fb9987d0SSujith 
465fb9987d0SSujith static const struct ath_bus_ops ath9k_usb_bus_ops = {
466497ad9adSSujith 	.ath_bus_type = ATH_USB,
467fb9987d0SSujith 	.read_cachesize = ath_usb_read_cachesize,
468fb9987d0SSujith 	.eeprom_read = ath_usb_eeprom_read,
469fb9987d0SSujith };
470fb9987d0SSujith 
471fb9987d0SSujith static void setup_ht_cap(struct ath9k_htc_priv *priv,
472fb9987d0SSujith 			 struct ieee80211_sta_ht_cap *ht_info)
473fb9987d0SSujith {
4746debecadSSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
4756debecadSSujith 	u8 tx_streams, rx_streams;
4766debecadSSujith 	int i;
4776debecadSSujith 
478fb9987d0SSujith 	ht_info->ht_supported = true;
479fb9987d0SSujith 	ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
480fb9987d0SSujith 		       IEEE80211_HT_CAP_SM_PS |
481fb9987d0SSujith 		       IEEE80211_HT_CAP_SGI_40 |
482fb9987d0SSujith 		       IEEE80211_HT_CAP_DSSSCCK40;
483fb9987d0SSujith 
484b4dec5e8SSujith 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
485b4dec5e8SSujith 		ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
486b4dec5e8SSujith 
48717525f96SSujith 	ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
48817525f96SSujith 
489fb9987d0SSujith 	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
490fb9987d0SSujith 	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
491fb9987d0SSujith 
492fb9987d0SSujith 	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
4936debecadSSujith 
4946debecadSSujith 	/* ath9k_htc supports only 1 or 2 stream devices */
4956debecadSSujith 	tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2);
4966debecadSSujith 	rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2);
4976debecadSSujith 
498226afe68SJoe Perches 	ath_dbg(common, ATH_DBG_CONFIG,
4996debecadSSujith 		"TX streams %d, RX streams: %d\n",
5006debecadSSujith 		tx_streams, rx_streams);
5016debecadSSujith 
5026debecadSSujith 	if (tx_streams != rx_streams) {
5036debecadSSujith 		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
5046debecadSSujith 		ht_info->mcs.tx_params |= ((tx_streams - 1) <<
5056debecadSSujith 					   IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
5066debecadSSujith 	}
5076debecadSSujith 
5086debecadSSujith 	for (i = 0; i < rx_streams; i++)
5096debecadSSujith 		ht_info->mcs.rx_mask[i] = 0xff;
5106debecadSSujith 
511fb9987d0SSujith 	ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
512fb9987d0SSujith }
513fb9987d0SSujith 
514fb9987d0SSujith static int ath9k_init_queues(struct ath9k_htc_priv *priv)
515fb9987d0SSujith {
516fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
517fb9987d0SSujith 	int i;
518fb9987d0SSujith 
519fb9987d0SSujith 	for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++)
520fb9987d0SSujith 		priv->hwq_map[i] = -1;
521fb9987d0SSujith 
522ca74b83bSSujith 	priv->beaconq = ath9k_hw_beaconq_setup(priv->ah);
523ca74b83bSSujith 	if (priv->beaconq == -1) {
5243800276aSJoe Perches 		ath_err(common, "Unable to setup BEACON xmit queue\n");
525ca74b83bSSujith 		goto err;
526ca74b83bSSujith 	}
527ca74b83bSSujith 
528ca74b83bSSujith 	priv->cabq = ath9k_htc_cabq_setup(priv);
529ca74b83bSSujith 	if (priv->cabq == -1) {
5303800276aSJoe Perches 		ath_err(common, "Unable to setup CAB xmit queue\n");
531ca74b83bSSujith 		goto err;
532ca74b83bSSujith 	}
533ca74b83bSSujith 
534e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) {
5353800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for BE traffic\n");
536fb9987d0SSujith 		goto err;
537fb9987d0SSujith 	}
538fb9987d0SSujith 
539e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) {
5403800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for BK traffic\n");
541fb9987d0SSujith 		goto err;
542fb9987d0SSujith 	}
543e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) {
5443800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for VI traffic\n");
545fb9987d0SSujith 		goto err;
546fb9987d0SSujith 	}
547e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) {
5483800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for VO traffic\n");
549fb9987d0SSujith 		goto err;
550fb9987d0SSujith 	}
551fb9987d0SSujith 
552fb9987d0SSujith 	return 0;
553fb9987d0SSujith 
554fb9987d0SSujith err:
555fb9987d0SSujith 	return -EINVAL;
556fb9987d0SSujith }
557fb9987d0SSujith 
558fb9987d0SSujith static void ath9k_init_crypto(struct ath9k_htc_priv *priv)
559fb9987d0SSujith {
560fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
561fb9987d0SSujith 	int i = 0;
562fb9987d0SSujith 
563fb9987d0SSujith 	/* Get the hardware key cache size. */
564fb9987d0SSujith 	common->keymax = priv->ah->caps.keycache_size;
565fb9987d0SSujith 	if (common->keymax > ATH_KEYMAX) {
566226afe68SJoe Perches 		ath_dbg(common, ATH_DBG_ANY,
567fb9987d0SSujith 			"Warning, using only %u entries in %u key cache\n",
568fb9987d0SSujith 			ATH_KEYMAX, common->keymax);
569fb9987d0SSujith 		common->keymax = ATH_KEYMAX;
570fb9987d0SSujith 	}
571fb9987d0SSujith 
572e2b62624SRajkumar Manoharan 	if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
573e2b62624SRajkumar Manoharan 		common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
574e2b62624SRajkumar Manoharan 
575fb9987d0SSujith 	/*
576fb9987d0SSujith 	 * Reset the key cache since some parts do not
577fb9987d0SSujith 	 * reset the contents on initial power up.
578fb9987d0SSujith 	 */
579fb9987d0SSujith 	for (i = 0; i < common->keymax; i++)
580040e539eSBruno Randolf 		ath_hw_keyreset(common, (u16) i);
581fb9987d0SSujith }
582fb9987d0SSujith 
583fb9987d0SSujith static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
584fb9987d0SSujith {
585d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
586fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].channels =
587fb9987d0SSujith 			ath9k_2ghz_channels;
588fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
589fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].n_channels =
590fb9987d0SSujith 			ARRAY_SIZE(ath9k_2ghz_channels);
591fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
592fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
593fb9987d0SSujith 			ARRAY_SIZE(ath9k_legacy_rates);
594fb9987d0SSujith 	}
595ea46e644SSujith 
596d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
597ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels;
598ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
599ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].n_channels =
600ea46e644SSujith 			ARRAY_SIZE(ath9k_5ghz_channels);
601ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].bitrates =
602ea46e644SSujith 			ath9k_legacy_rates + 4;
603ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
604ea46e644SSujith 			ARRAY_SIZE(ath9k_legacy_rates) - 4;
605ea46e644SSujith 	}
606fb9987d0SSujith }
607fb9987d0SSujith 
608fb9987d0SSujith static void ath9k_init_misc(struct ath9k_htc_priv *priv)
609fb9987d0SSujith {
610fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
611fb9987d0SSujith 
612fb9987d0SSujith 	common->tx_chainmask = priv->ah->caps.tx_chainmask;
613fb9987d0SSujith 	common->rx_chainmask = priv->ah->caps.rx_chainmask;
614fb9987d0SSujith 
615fb9987d0SSujith 	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
616fb9987d0SSujith 
6179f01a84eSSujith 	priv->ah->opmode = NL80211_IFTYPE_STATION;
618fb9987d0SSujith }
619fb9987d0SSujith 
62021cb9879SVivek Natarajan static void ath9k_init_btcoex(struct ath9k_htc_priv *priv)
62121cb9879SVivek Natarajan {
62221cb9879SVivek Natarajan 	int qnum;
62321cb9879SVivek Natarajan 
62421cb9879SVivek Natarajan 	switch (priv->ah->btcoex_hw.scheme) {
62521cb9879SVivek Natarajan 	case ATH_BTCOEX_CFG_NONE:
62621cb9879SVivek Natarajan 		break;
62721cb9879SVivek Natarajan 	case ATH_BTCOEX_CFG_3WIRE:
62821cb9879SVivek Natarajan 		priv->ah->btcoex_hw.btactive_gpio = 7;
62921cb9879SVivek Natarajan 		priv->ah->btcoex_hw.btpriority_gpio = 6;
63021cb9879SVivek Natarajan 		priv->ah->btcoex_hw.wlanactive_gpio = 8;
63121cb9879SVivek Natarajan 		priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
63221cb9879SVivek Natarajan 		ath9k_hw_btcoex_init_3wire(priv->ah);
63321cb9879SVivek Natarajan 		ath_htc_init_btcoex_work(priv);
63421cb9879SVivek Natarajan 		qnum = priv->hwq_map[WME_AC_BE];
63521cb9879SVivek Natarajan 		ath9k_hw_init_btcoex_hw(priv->ah, qnum);
63621cb9879SVivek Natarajan 		break;
63721cb9879SVivek Natarajan 	default:
63821cb9879SVivek Natarajan 		WARN_ON(1);
63921cb9879SVivek Natarajan 		break;
64021cb9879SVivek Natarajan 	}
64121cb9879SVivek Natarajan }
64221cb9879SVivek Natarajan 
64321cb9879SVivek Natarajan static int ath9k_init_priv(struct ath9k_htc_priv *priv,
644fa6e15e0SRajkumar Manoharan 			   u16 devid, char *product,
645fa6e15e0SRajkumar Manoharan 			   u32 drv_info)
646fb9987d0SSujith {
647fb9987d0SSujith 	struct ath_hw *ah = NULL;
648fb9987d0SSujith 	struct ath_common *common;
649fb9987d0SSujith 	int ret = 0, csz = 0;
650fb9987d0SSujith 
651fb9987d0SSujith 	priv->op_flags |= OP_INVALID;
652fb9987d0SSujith 
653fb9987d0SSujith 	ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
654fb9987d0SSujith 	if (!ah)
655fb9987d0SSujith 		return -ENOMEM;
656fb9987d0SSujith 
657fb9987d0SSujith 	ah->hw_version.devid = devid;
658fb9987d0SSujith 	ah->hw_version.subsysid = 0; /* FIXME */
6590b5ead91SSujith Manoharan 	ah->hw_version.usbdev = drv_info;
660f8afa42bSFelix Fietkau 	ah->ah_flags |= AH_USE_EEPROM;
661fb9987d0SSujith 	priv->ah = ah;
662fb9987d0SSujith 
663fb9987d0SSujith 	common = ath9k_hw_common(ah);
664fb9987d0SSujith 	common->ops = &ath9k_common_ops;
665fb9987d0SSujith 	common->bus_ops = &ath9k_usb_bus_ops;
666fb9987d0SSujith 	common->ah = ah;
667fb9987d0SSujith 	common->hw = priv->hw;
668fb9987d0SSujith 	common->priv = priv;
669fb9987d0SSujith 	common->debug_mask = ath9k_debug;
670fb9987d0SSujith 
671fb9987d0SSujith 	spin_lock_init(&priv->wmi->wmi_lock);
672fb9987d0SSujith 	spin_lock_init(&priv->beacon_lock);
6737757dfedSSujith 	spin_lock_init(&priv->tx_lock);
674fb9987d0SSujith 	mutex_init(&priv->mutex);
675bde748a4SVivek Natarajan 	mutex_init(&priv->htc_pm_lock);
67673908674SSujith Manoharan 	tasklet_init(&priv->swba_tasklet, ath9k_swba_tasklet,
677fb9987d0SSujith 		     (unsigned long)priv);
678fb9987d0SSujith 	tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
679fb9987d0SSujith 		     (unsigned long)priv);
68073908674SSujith Manoharan 	tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet,
68173908674SSujith Manoharan 		     (unsigned long)priv);
682a236254cSSujith Manoharan 	INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
683bde748a4SVivek Natarajan 	INIT_WORK(&priv->ps_work, ath9k_ps_work);
68473908674SSujith Manoharan 	INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
685fb9987d0SSujith 
686fb9987d0SSujith 	/*
687fb9987d0SSujith 	 * Cache line size is used to size and align various
688fb9987d0SSujith 	 * structures used to communicate with the hardware.
689fb9987d0SSujith 	 */
690fb9987d0SSujith 	ath_read_cachesize(common, &csz);
691fb9987d0SSujith 	common->cachelsz = csz << 2; /* convert to bytes */
692fb9987d0SSujith 
693fb9987d0SSujith 	ret = ath9k_hw_init(ah);
694fb9987d0SSujith 	if (ret) {
6953800276aSJoe Perches 		ath_err(common,
6963800276aSJoe Perches 			"Unable to initialize hardware; initialization status: %d\n",
6973800276aSJoe Perches 			ret);
698fb9987d0SSujith 		goto err_hw;
699fb9987d0SSujith 	}
700fb9987d0SSujith 
701e1572c5eSSujith 	ret = ath9k_htc_init_debug(ah);
702fb9987d0SSujith 	if (ret) {
7033800276aSJoe Perches 		ath_err(common, "Unable to create debugfs files\n");
704fb9987d0SSujith 		goto err_debug;
705fb9987d0SSujith 	}
706fb9987d0SSujith 
707fb9987d0SSujith 	ret = ath9k_init_queues(priv);
708fb9987d0SSujith 	if (ret)
709fb9987d0SSujith 		goto err_queues;
710fb9987d0SSujith 
711fb9987d0SSujith 	ath9k_init_crypto(priv);
712fb9987d0SSujith 	ath9k_init_channels_rates(priv);
713fb9987d0SSujith 	ath9k_init_misc(priv);
714fb9987d0SSujith 
71521cb9879SVivek Natarajan 	if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) {
71621cb9879SVivek Natarajan 		ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE;
71721cb9879SVivek Natarajan 		ath9k_init_btcoex(priv);
71821cb9879SVivek Natarajan 	}
71921cb9879SVivek Natarajan 
720fb9987d0SSujith 	return 0;
721fb9987d0SSujith 
722fb9987d0SSujith err_queues:
723e1572c5eSSujith 	ath9k_htc_exit_debug(ah);
724fb9987d0SSujith err_debug:
725fb9987d0SSujith 	ath9k_hw_deinit(ah);
726fb9987d0SSujith err_hw:
727fb9987d0SSujith 
728fb9987d0SSujith 	kfree(ah);
729fb9987d0SSujith 	priv->ah = NULL;
730fb9987d0SSujith 
731fb9987d0SSujith 	return ret;
732fb9987d0SSujith }
733fb9987d0SSujith 
734fb9987d0SSujith static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
735fb9987d0SSujith 			       struct ieee80211_hw *hw)
736fb9987d0SSujith {
737fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
738fb9987d0SSujith 
739fb9987d0SSujith 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
740fb9987d0SSujith 		IEEE80211_HW_AMPDU_AGGREGATION |
741fb9987d0SSujith 		IEEE80211_HW_SPECTRUM_MGMT |
74232fbccafSSujith 		IEEE80211_HW_HAS_RATE_CONTROL |
743bde748a4SVivek Natarajan 		IEEE80211_HW_RX_INCLUDES_FCS |
744bde748a4SVivek Natarajan 		IEEE80211_HW_SUPPORTS_PS |
745bd8027a7SMohammed Shafi Shajakhan 		IEEE80211_HW_PS_NULLFUNC_STACK;
746fb9987d0SSujith 
747fb9987d0SSujith 	hw->wiphy->interface_modes =
748fb9987d0SSujith 		BIT(NL80211_IFTYPE_STATION) |
749fb9987d0SSujith 		BIT(NL80211_IFTYPE_ADHOC);
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;
756fb9987d0SSujith 	hw->vif_data_size = sizeof(struct ath9k_htc_vif);
757fb9987d0SSujith 	hw->sta_data_size = sizeof(struct ath9k_htc_sta);
758fb9987d0SSujith 
759fb9987d0SSujith 	/* tx_frame_hdr is larger than tx_mgmt_hdr anyway */
760fb9987d0SSujith 	hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) +
761fb9987d0SSujith 		sizeof(struct htc_frame_hdr) + 4;
762fb9987d0SSujith 
763d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
764fb9987d0SSujith 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
765fb9987d0SSujith 			&priv->sbands[IEEE80211_BAND_2GHZ];
766d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
767ea46e644SSujith 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
768ea46e644SSujith 			&priv->sbands[IEEE80211_BAND_5GHZ];
769fb9987d0SSujith 
770fb9987d0SSujith 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
771d4659912SFelix Fietkau 		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
772fb9987d0SSujith 			setup_ht_cap(priv,
773fb9987d0SSujith 				     &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap);
774d4659912SFelix Fietkau 		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
775ea46e644SSujith 			setup_ht_cap(priv,
776ea46e644SSujith 				     &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
777fb9987d0SSujith 	}
778fb9987d0SSujith 
779fb9987d0SSujith 	SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
780fb9987d0SSujith }
781fb9987d0SSujith 
78221cb9879SVivek Natarajan static int ath9k_init_device(struct ath9k_htc_priv *priv,
783fa6e15e0SRajkumar Manoharan 			     u16 devid, char *product, u32 drv_info)
784fb9987d0SSujith {
785fb9987d0SSujith 	struct ieee80211_hw *hw = priv->hw;
786fb9987d0SSujith 	struct ath_common *common;
787fb9987d0SSujith 	struct ath_hw *ah;
788fb9987d0SSujith 	int error = 0;
789fb9987d0SSujith 	struct ath_regulatory *reg;
7903e3f1d19SSujith Manoharan 	char hw_name[64];
791fb9987d0SSujith 
792fb9987d0SSujith 	/* Bring up device */
793fa6e15e0SRajkumar Manoharan 	error = ath9k_init_priv(priv, devid, product, drv_info);
794fb9987d0SSujith 	if (error != 0)
795fb9987d0SSujith 		goto err_init;
796fb9987d0SSujith 
797fb9987d0SSujith 	ah = priv->ah;
798fb9987d0SSujith 	common = ath9k_hw_common(ah);
799fb9987d0SSujith 	ath9k_set_hw_capab(priv, hw);
800fb9987d0SSujith 
801fb9987d0SSujith 	/* Initialize regulatory */
802fb9987d0SSujith 	error = ath_regd_init(&common->regulatory, priv->hw->wiphy,
803fb9987d0SSujith 			      ath9k_reg_notifier);
804fb9987d0SSujith 	if (error)
805fb9987d0SSujith 		goto err_regd;
806fb9987d0SSujith 
807fb9987d0SSujith 	reg = &common->regulatory;
808fb9987d0SSujith 
809fb9987d0SSujith 	/* Setup TX */
810fb9987d0SSujith 	error = ath9k_tx_init(priv);
811fb9987d0SSujith 	if (error != 0)
812fb9987d0SSujith 		goto err_tx;
813fb9987d0SSujith 
814fb9987d0SSujith 	/* Setup RX */
815fb9987d0SSujith 	error = ath9k_rx_init(priv);
816fb9987d0SSujith 	if (error != 0)
817fb9987d0SSujith 		goto err_rx;
818fb9987d0SSujith 
819fb9987d0SSujith 	/* Register with mac80211 */
820fb9987d0SSujith 	error = ieee80211_register_hw(hw);
821fb9987d0SSujith 	if (error)
822fb9987d0SSujith 		goto err_register;
823fb9987d0SSujith 
824fb9987d0SSujith 	/* Handle world regulatory */
825fb9987d0SSujith 	if (!ath_is_world_regd(reg)) {
826fb9987d0SSujith 		error = regulatory_hint(hw->wiphy, reg->alpha2);
827fb9987d0SSujith 		if (error)
828fb9987d0SSujith 			goto err_world;
829fb9987d0SSujith 	}
830fb9987d0SSujith 
8313e3f1d19SSujith Manoharan 	ath_dbg(common, ATH_DBG_CONFIG,
8323e3f1d19SSujith Manoharan 		"WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, "
8333e3f1d19SSujith Manoharan 		"BE:%d, BK:%d, VI:%d, VO:%d\n",
8343e3f1d19SSujith Manoharan 		priv->wmi_cmd_ep,
8353e3f1d19SSujith Manoharan 		priv->beacon_ep,
8363e3f1d19SSujith Manoharan 		priv->cab_ep,
8373e3f1d19SSujith Manoharan 		priv->uapsd_ep,
8383e3f1d19SSujith Manoharan 		priv->mgmt_ep,
8393e3f1d19SSujith Manoharan 		priv->data_be_ep,
8403e3f1d19SSujith Manoharan 		priv->data_bk_ep,
8413e3f1d19SSujith Manoharan 		priv->data_vi_ep,
8423e3f1d19SSujith Manoharan 		priv->data_vo_ep);
8433e3f1d19SSujith Manoharan 
8443e3f1d19SSujith Manoharan 	ath9k_hw_name(priv->ah, hw_name, sizeof(hw_name));
8453e3f1d19SSujith Manoharan 	wiphy_info(hw->wiphy, "%s\n", hw_name);
8463e3f1d19SSujith Manoharan 
847fb9987d0SSujith 	ath9k_init_leds(priv);
848fb9987d0SSujith 	ath9k_start_rfkill_poll(priv);
849fb9987d0SSujith 
850fb9987d0SSujith 	return 0;
851fb9987d0SSujith 
852fb9987d0SSujith err_world:
853fb9987d0SSujith 	ieee80211_unregister_hw(hw);
854fb9987d0SSujith err_register:
855fb9987d0SSujith 	ath9k_rx_cleanup(priv);
856fb9987d0SSujith err_rx:
857fb9987d0SSujith 	ath9k_tx_cleanup(priv);
858fb9987d0SSujith err_tx:
859fb9987d0SSujith 	/* Nothing */
860fb9987d0SSujith err_regd:
861fb9987d0SSujith 	ath9k_deinit_priv(priv);
862fb9987d0SSujith err_init:
863fb9987d0SSujith 	return error;
864fb9987d0SSujith }
865fb9987d0SSujith 
866fb9987d0SSujith int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
867fa6e15e0SRajkumar Manoharan 			   u16 devid, char *product, u32 drv_info)
868fb9987d0SSujith {
869fb9987d0SSujith 	struct ieee80211_hw *hw;
870fb9987d0SSujith 	struct ath9k_htc_priv *priv;
871fb9987d0SSujith 	int ret;
872fb9987d0SSujith 
873fb9987d0SSujith 	hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops);
874fb9987d0SSujith 	if (!hw)
875fb9987d0SSujith 		return -ENOMEM;
876fb9987d0SSujith 
877fb9987d0SSujith 	priv = hw->priv;
878fb9987d0SSujith 	priv->hw = hw;
879fb9987d0SSujith 	priv->htc = htc_handle;
880fb9987d0SSujith 	priv->dev = dev;
881fb9987d0SSujith 	htc_handle->drv_priv = priv;
882fb9987d0SSujith 	SET_IEEE80211_DEV(hw, priv->dev);
883fb9987d0SSujith 
884fb9987d0SSujith 	ret = ath9k_htc_wait_for_target(priv);
885fb9987d0SSujith 	if (ret)
886fb9987d0SSujith 		goto err_free;
887fb9987d0SSujith 
888fb9987d0SSujith 	priv->wmi = ath9k_init_wmi(priv);
889fb9987d0SSujith 	if (!priv->wmi) {
890fb9987d0SSujith 		ret = -EINVAL;
891fb9987d0SSujith 		goto err_free;
892fb9987d0SSujith 	}
893fb9987d0SSujith 
894fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_htc_services(priv, devid, drv_info);
895fb9987d0SSujith 	if (ret)
896fb9987d0SSujith 		goto err_init;
897fb9987d0SSujith 
898fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_device(priv, devid, product, drv_info);
899fb9987d0SSujith 	if (ret)
900fb9987d0SSujith 		goto err_init;
901fb9987d0SSujith 
902fb9987d0SSujith 	return 0;
903fb9987d0SSujith 
904fb9987d0SSujith err_init:
905fb9987d0SSujith 	ath9k_deinit_wmi(priv);
906fb9987d0SSujith err_free:
907fb9987d0SSujith 	ieee80211_free_hw(hw);
908fb9987d0SSujith 	return ret;
909fb9987d0SSujith }
910fb9987d0SSujith 
911fb9987d0SSujith void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
912fb9987d0SSujith {
913fb9987d0SSujith 	if (htc_handle->drv_priv) {
914a3be14b7SSujith 
915a3be14b7SSujith 		/* Check if the device has been yanked out. */
916a3be14b7SSujith 		if (hotunplug)
91797dcec57SSujith Manoharan 			htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED;
918a3be14b7SSujith 
919fb9987d0SSujith 		ath9k_deinit_device(htc_handle->drv_priv);
920fb9987d0SSujith 		ath9k_deinit_wmi(htc_handle->drv_priv);
921fb9987d0SSujith 		ieee80211_free_hw(htc_handle->drv_priv->hw);
922fb9987d0SSujith 	}
923fb9987d0SSujith }
924fb9987d0SSujith 
925fb9987d0SSujith #ifdef CONFIG_PM
926f933ebedSSujith Manoharan 
927f933ebedSSujith Manoharan void ath9k_htc_suspend(struct htc_target *htc_handle)
928f933ebedSSujith Manoharan {
929f933ebedSSujith Manoharan 	ath9k_htc_setpower(htc_handle->drv_priv, ATH9K_PM_FULL_SLEEP);
930f933ebedSSujith Manoharan }
931f933ebedSSujith Manoharan 
932fb9987d0SSujith int ath9k_htc_resume(struct htc_target *htc_handle)
933fb9987d0SSujith {
934fa6e15e0SRajkumar Manoharan 	struct ath9k_htc_priv *priv = htc_handle->drv_priv;
935fb9987d0SSujith 	int ret;
936fb9987d0SSujith 
937fa6e15e0SRajkumar Manoharan 	ret = ath9k_htc_wait_for_target(priv);
938fb9987d0SSujith 	if (ret)
939fb9987d0SSujith 		return ret;
940fb9987d0SSujith 
941fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid,
9420b5ead91SSujith Manoharan 				      priv->ah->hw_version.usbdev);
943fb9987d0SSujith 	return ret;
944fb9987d0SSujith }
945fb9987d0SSujith #endif
946fb9987d0SSujith 
947fb9987d0SSujith static int __init ath9k_htc_init(void)
948fb9987d0SSujith {
949fb9987d0SSujith 	int error;
950fb9987d0SSujith 
951e1572c5eSSujith 	error = ath9k_htc_debug_create_root();
952fb9987d0SSujith 	if (error < 0) {
953fb9987d0SSujith 		printk(KERN_ERR
954fb9987d0SSujith 			"ath9k_htc: Unable to create debugfs root: %d\n",
955fb9987d0SSujith 			error);
956fb9987d0SSujith 		goto err_dbg;
957fb9987d0SSujith 	}
958fb9987d0SSujith 
959fb9987d0SSujith 	error = ath9k_hif_usb_init();
960fb9987d0SSujith 	if (error < 0) {
961fb9987d0SSujith 		printk(KERN_ERR
962fb9987d0SSujith 			"ath9k_htc: No USB devices found,"
963fb9987d0SSujith 			" driver not installed.\n");
964fb9987d0SSujith 		error = -ENODEV;
965fb9987d0SSujith 		goto err_usb;
966fb9987d0SSujith 	}
967fb9987d0SSujith 
968fb9987d0SSujith 	return 0;
969fb9987d0SSujith 
970fb9987d0SSujith err_usb:
971e1572c5eSSujith 	ath9k_htc_debug_remove_root();
972fb9987d0SSujith err_dbg:
973fb9987d0SSujith 	return error;
974fb9987d0SSujith }
975fb9987d0SSujith module_init(ath9k_htc_init);
976fb9987d0SSujith 
977fb9987d0SSujith static void __exit ath9k_htc_exit(void)
978fb9987d0SSujith {
979fb9987d0SSujith 	ath9k_hif_usb_exit();
980e1572c5eSSujith 	ath9k_htc_debug_remove_root();
981fb9987d0SSujith 	printk(KERN_INFO "ath9k_htc: Driver unloaded\n");
982fb9987d0SSujith }
983fb9987d0SSujith module_exit(ath9k_htc_exit);
984