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 	tasklet_kill(&priv->wmi_tasklet);
146fb9987d0SSujith 	tasklet_kill(&priv->rx_tasklet);
147fb9987d0SSujith 	tasklet_kill(&priv->tx_tasklet);
148fb9987d0SSujith 	kfree(priv->ah);
149fb9987d0SSujith 	priv->ah = NULL;
150fb9987d0SSujith }
151fb9987d0SSujith 
152fb9987d0SSujith static void ath9k_deinit_device(struct ath9k_htc_priv *priv)
153fb9987d0SSujith {
154fb9987d0SSujith 	struct ieee80211_hw *hw = priv->hw;
155fb9987d0SSujith 
156fb9987d0SSujith 	wiphy_rfkill_stop_polling(hw->wiphy);
157fb9987d0SSujith 	ath9k_deinit_leds(priv);
158fb9987d0SSujith 	ieee80211_unregister_hw(hw);
159fb9987d0SSujith 	ath9k_rx_cleanup(priv);
160fb9987d0SSujith 	ath9k_tx_cleanup(priv);
161fb9987d0SSujith 	ath9k_deinit_priv(priv);
162fb9987d0SSujith }
163fb9987d0SSujith 
164fb9987d0SSujith static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv,
165fb9987d0SSujith 					u16 service_id,
166fb9987d0SSujith 					void (*tx) (void *,
167fb9987d0SSujith 						    struct sk_buff *,
168fb9987d0SSujith 						    enum htc_endpoint_id,
169fb9987d0SSujith 						    bool txok),
170fb9987d0SSujith 					enum htc_endpoint_id *ep_id)
171fb9987d0SSujith {
172fb9987d0SSujith 	struct htc_service_connreq req;
173fb9987d0SSujith 
174fb9987d0SSujith 	memset(&req, 0, sizeof(struct htc_service_connreq));
175fb9987d0SSujith 
176fb9987d0SSujith 	req.service_id = service_id;
177fb9987d0SSujith 	req.ep_callbacks.priv = priv;
178fb9987d0SSujith 	req.ep_callbacks.rx = ath9k_htc_rxep;
179fb9987d0SSujith 	req.ep_callbacks.tx = tx;
180fb9987d0SSujith 
181fb9987d0SSujith 	return htc_connect_service(priv->htc, &req, ep_id);
182fb9987d0SSujith }
183fb9987d0SSujith 
184fa6e15e0SRajkumar Manoharan static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid,
185fa6e15e0SRajkumar Manoharan 				   u32 drv_info)
186fb9987d0SSujith {
187fb9987d0SSujith 	int ret;
188fb9987d0SSujith 
189fb9987d0SSujith 	/* WMI CMD*/
190fb9987d0SSujith 	ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep);
191fb9987d0SSujith 	if (ret)
192fb9987d0SSujith 		goto err;
193fb9987d0SSujith 
194fb9987d0SSujith 	/* Beacon */
1959c6dda4eSSujith 	ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, ath9k_htc_beaconep,
196fb9987d0SSujith 				    &priv->beacon_ep);
197fb9987d0SSujith 	if (ret)
198fb9987d0SSujith 		goto err;
199fb9987d0SSujith 
200fb9987d0SSujith 	/* CAB */
201fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep,
202fb9987d0SSujith 				    &priv->cab_ep);
203fb9987d0SSujith 	if (ret)
204fb9987d0SSujith 		goto err;
205fb9987d0SSujith 
206fb9987d0SSujith 
207fb9987d0SSujith 	/* UAPSD */
208fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep,
209fb9987d0SSujith 				    &priv->uapsd_ep);
210fb9987d0SSujith 	if (ret)
211fb9987d0SSujith 		goto err;
212fb9987d0SSujith 
213fb9987d0SSujith 	/* MGMT */
214fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep,
215fb9987d0SSujith 				    &priv->mgmt_ep);
216fb9987d0SSujith 	if (ret)
217fb9987d0SSujith 		goto err;
218fb9987d0SSujith 
219fb9987d0SSujith 	/* DATA BE */
220fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep,
221fb9987d0SSujith 				    &priv->data_be_ep);
222fb9987d0SSujith 	if (ret)
223fb9987d0SSujith 		goto err;
224fb9987d0SSujith 
225fb9987d0SSujith 	/* DATA BK */
226fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep,
227fb9987d0SSujith 				    &priv->data_bk_ep);
228fb9987d0SSujith 	if (ret)
229fb9987d0SSujith 		goto err;
230fb9987d0SSujith 
231fb9987d0SSujith 	/* DATA VI */
232fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep,
233fb9987d0SSujith 				    &priv->data_vi_ep);
234fb9987d0SSujith 	if (ret)
235fb9987d0SSujith 		goto err;
236fb9987d0SSujith 
237fb9987d0SSujith 	/* DATA VO */
238fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep,
239fb9987d0SSujith 				    &priv->data_vo_ep);
240fb9987d0SSujith 	if (ret)
241fb9987d0SSujith 		goto err;
242fb9987d0SSujith 
2436267dc70SSujith 	/*
2446267dc70SSujith 	 * Setup required credits before initializing HTC.
2456267dc70SSujith 	 * This is a bit hacky, but, since queuing is done in
2466267dc70SSujith 	 * the HIF layer, shouldn't matter much.
2476267dc70SSujith 	 */
2486267dc70SSujith 
249fa6e15e0SRajkumar Manoharan 	if (drv_info & AR7010_DEVICE)
2506267dc70SSujith 		priv->htc->credits = 45;
251fa6e15e0SRajkumar Manoharan 	else
2524e63f768SSujith 		priv->htc->credits = 33;
2536267dc70SSujith 
254fb9987d0SSujith 	ret = htc_init(priv->htc);
255fb9987d0SSujith 	if (ret)
256fb9987d0SSujith 		goto err;
257fb9987d0SSujith 
2586267dc70SSujith 	dev_info(priv->dev, "ath9k_htc: HTC initialized with %d credits\n",
2596267dc70SSujith 		 priv->htc->credits);
2606267dc70SSujith 
261fb9987d0SSujith 	return 0;
262fb9987d0SSujith 
263fb9987d0SSujith err:
264fb9987d0SSujith 	dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n");
265fb9987d0SSujith 	return ret;
266fb9987d0SSujith }
267fb9987d0SSujith 
268fb9987d0SSujith static int ath9k_reg_notifier(struct wiphy *wiphy,
269fb9987d0SSujith 			      struct regulatory_request *request)
270fb9987d0SSujith {
271fb9987d0SSujith 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
272fb9987d0SSujith 	struct ath9k_htc_priv *priv = hw->priv;
273fb9987d0SSujith 
274fb9987d0SSujith 	return ath_reg_notifier_apply(wiphy, request,
275fb9987d0SSujith 				      ath9k_hw_regulatory(priv->ah));
276fb9987d0SSujith }
277fb9987d0SSujith 
2784a22fe10SSujith static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
279fb9987d0SSujith {
280fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
281fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(ah);
282fb9987d0SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
283fb9987d0SSujith 	__be32 val, reg = cpu_to_be32(reg_offset);
284fb9987d0SSujith 	int r;
285fb9987d0SSujith 
286fb9987d0SSujith 	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
287fb9987d0SSujith 			  (u8 *) &reg, sizeof(reg),
288fb9987d0SSujith 			  (u8 *) &val, sizeof(val),
289fb9987d0SSujith 			  100);
290fb9987d0SSujith 	if (unlikely(r)) {
291226afe68SJoe Perches 		ath_dbg(common, ATH_DBG_WMI,
292fb9987d0SSujith 			"REGISTER READ FAILED: (0x%04x, %d)\n",
293fb9987d0SSujith 			reg_offset, r);
294fb9987d0SSujith 		return -EIO;
295fb9987d0SSujith 	}
296fb9987d0SSujith 
297fb9987d0SSujith 	return be32_to_cpu(val);
298fb9987d0SSujith }
299fb9987d0SSujith 
3004a22fe10SSujith static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
301fb9987d0SSujith {
302fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
303fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(ah);
304fb9987d0SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
30507b2fa5aSJoe Perches 	const __be32 buf[2] = {
306fb9987d0SSujith 		cpu_to_be32(reg_offset),
307fb9987d0SSujith 		cpu_to_be32(val),
308fb9987d0SSujith 	};
309fb9987d0SSujith 	int r;
310fb9987d0SSujith 
311fb9987d0SSujith 	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
312fb9987d0SSujith 			  (u8 *) &buf, sizeof(buf),
313fb9987d0SSujith 			  (u8 *) &val, sizeof(val),
314fb9987d0SSujith 			  100);
315fb9987d0SSujith 	if (unlikely(r)) {
316226afe68SJoe Perches 		ath_dbg(common, ATH_DBG_WMI,
317fb9987d0SSujith 			"REGISTER WRITE FAILED:(0x%04x, %d)\n",
318fb9987d0SSujith 			reg_offset, r);
319fb9987d0SSujith 	}
320fb9987d0SSujith }
321fb9987d0SSujith 
3224a22fe10SSujith static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset)
3234a22fe10SSujith {
3244a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3254a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3264a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3274a22fe10SSujith 	u32 rsp_status;
3284a22fe10SSujith 	int r;
3294a22fe10SSujith 
3304a22fe10SSujith 	mutex_lock(&priv->wmi->multi_write_mutex);
3314a22fe10SSujith 
3324a22fe10SSujith 	/* Store the register/value */
3334a22fe10SSujith 	priv->wmi->multi_write[priv->wmi->multi_write_idx].reg =
3344a22fe10SSujith 		cpu_to_be32(reg_offset);
3354a22fe10SSujith 	priv->wmi->multi_write[priv->wmi->multi_write_idx].val =
3364a22fe10SSujith 		cpu_to_be32(val);
3374a22fe10SSujith 
3384a22fe10SSujith 	priv->wmi->multi_write_idx++;
3394a22fe10SSujith 
3404a22fe10SSujith 	/* If the buffer is full, send it out. */
3414a22fe10SSujith 	if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) {
3424a22fe10SSujith 		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
3434a22fe10SSujith 			  (u8 *) &priv->wmi->multi_write,
3444a22fe10SSujith 			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
3454a22fe10SSujith 			  (u8 *) &rsp_status, sizeof(rsp_status),
3464a22fe10SSujith 			  100);
3474a22fe10SSujith 		if (unlikely(r)) {
348226afe68SJoe Perches 			ath_dbg(common, ATH_DBG_WMI,
3494a22fe10SSujith 				"REGISTER WRITE FAILED, multi len: %d\n",
3504a22fe10SSujith 				priv->wmi->multi_write_idx);
3514a22fe10SSujith 		}
3524a22fe10SSujith 		priv->wmi->multi_write_idx = 0;
3534a22fe10SSujith 	}
3544a22fe10SSujith 
3554a22fe10SSujith 	mutex_unlock(&priv->wmi->multi_write_mutex);
3564a22fe10SSujith }
3574a22fe10SSujith 
3584a22fe10SSujith static void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset)
3594a22fe10SSujith {
3604a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3614a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3624a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3634a22fe10SSujith 
3644a22fe10SSujith 	if (atomic_read(&priv->wmi->mwrite_cnt))
3654a22fe10SSujith 		ath9k_regwrite_buffer(hw_priv, val, reg_offset);
3664a22fe10SSujith 	else
3674a22fe10SSujith 		ath9k_regwrite_single(hw_priv, val, reg_offset);
3684a22fe10SSujith }
3694a22fe10SSujith 
3704a22fe10SSujith static void ath9k_enable_regwrite_buffer(void *hw_priv)
3714a22fe10SSujith {
3724a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3734a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3744a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3754a22fe10SSujith 
3764a22fe10SSujith 	atomic_inc(&priv->wmi->mwrite_cnt);
3774a22fe10SSujith }
3784a22fe10SSujith 
3794a22fe10SSujith static void ath9k_regwrite_flush(void *hw_priv)
3804a22fe10SSujith {
3814a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3824a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3834a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3844a22fe10SSujith 	u32 rsp_status;
3854a22fe10SSujith 	int r;
3864a22fe10SSujith 
387435c1610SFelix Fietkau 	atomic_dec(&priv->wmi->mwrite_cnt);
388435c1610SFelix Fietkau 
3894a22fe10SSujith 	mutex_lock(&priv->wmi->multi_write_mutex);
3904a22fe10SSujith 
3914a22fe10SSujith 	if (priv->wmi->multi_write_idx) {
3924a22fe10SSujith 		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
3934a22fe10SSujith 			  (u8 *) &priv->wmi->multi_write,
3944a22fe10SSujith 			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
3954a22fe10SSujith 			  (u8 *) &rsp_status, sizeof(rsp_status),
3964a22fe10SSujith 			  100);
3974a22fe10SSujith 		if (unlikely(r)) {
398226afe68SJoe Perches 			ath_dbg(common, ATH_DBG_WMI,
3994a22fe10SSujith 				"REGISTER WRITE FAILED, multi len: %d\n",
4004a22fe10SSujith 				priv->wmi->multi_write_idx);
4014a22fe10SSujith 		}
4024a22fe10SSujith 		priv->wmi->multi_write_idx = 0;
4034a22fe10SSujith 	}
4044a22fe10SSujith 
4054a22fe10SSujith 	mutex_unlock(&priv->wmi->multi_write_mutex);
4064a22fe10SSujith }
4074a22fe10SSujith 
408fb9987d0SSujith static const struct ath_ops ath9k_common_ops = {
4094a22fe10SSujith 	.read = ath9k_regread,
4104a22fe10SSujith 	.write = ath9k_regwrite,
4114a22fe10SSujith 	.enable_write_buffer = ath9k_enable_regwrite_buffer,
4124a22fe10SSujith 	.write_flush = ath9k_regwrite_flush,
413fb9987d0SSujith };
414fb9987d0SSujith 
415fb9987d0SSujith static void ath_usb_read_cachesize(struct ath_common *common, int *csz)
416fb9987d0SSujith {
417fb9987d0SSujith 	*csz = L1_CACHE_BYTES >> 2;
418fb9987d0SSujith }
419fb9987d0SSujith 
420fb9987d0SSujith static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
421fb9987d0SSujith {
422fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) common->ah;
423fb9987d0SSujith 
424fb9987d0SSujith 	(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
425fb9987d0SSujith 
426fb9987d0SSujith 	if (!ath9k_hw_wait(ah,
427fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA,
428fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA_BUSY |
429fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
430fb9987d0SSujith 			   AH_WAIT_TIMEOUT))
431fb9987d0SSujith 		return false;
432fb9987d0SSujith 
433fb9987d0SSujith 	*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
434fb9987d0SSujith 		   AR_EEPROM_STATUS_DATA_VAL);
435fb9987d0SSujith 
436fb9987d0SSujith 	return true;
437fb9987d0SSujith }
438fb9987d0SSujith 
439fb9987d0SSujith static const struct ath_bus_ops ath9k_usb_bus_ops = {
440497ad9adSSujith 	.ath_bus_type = ATH_USB,
441fb9987d0SSujith 	.read_cachesize = ath_usb_read_cachesize,
442fb9987d0SSujith 	.eeprom_read = ath_usb_eeprom_read,
443fb9987d0SSujith };
444fb9987d0SSujith 
445fb9987d0SSujith static void setup_ht_cap(struct ath9k_htc_priv *priv,
446fb9987d0SSujith 			 struct ieee80211_sta_ht_cap *ht_info)
447fb9987d0SSujith {
4486debecadSSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
4496debecadSSujith 	u8 tx_streams, rx_streams;
4506debecadSSujith 	int i;
4516debecadSSujith 
452fb9987d0SSujith 	ht_info->ht_supported = true;
453fb9987d0SSujith 	ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
454fb9987d0SSujith 		       IEEE80211_HT_CAP_SM_PS |
455fb9987d0SSujith 		       IEEE80211_HT_CAP_SGI_40 |
456fb9987d0SSujith 		       IEEE80211_HT_CAP_DSSSCCK40;
457fb9987d0SSujith 
458b4dec5e8SSujith 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
459b4dec5e8SSujith 		ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
460b4dec5e8SSujith 
46117525f96SSujith 	ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
46217525f96SSujith 
463fb9987d0SSujith 	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
464fb9987d0SSujith 	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
465fb9987d0SSujith 
466fb9987d0SSujith 	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
4676debecadSSujith 
4686debecadSSujith 	/* ath9k_htc supports only 1 or 2 stream devices */
4696debecadSSujith 	tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2);
4706debecadSSujith 	rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2);
4716debecadSSujith 
472226afe68SJoe Perches 	ath_dbg(common, ATH_DBG_CONFIG,
4736debecadSSujith 		"TX streams %d, RX streams: %d\n",
4746debecadSSujith 		tx_streams, rx_streams);
4756debecadSSujith 
4766debecadSSujith 	if (tx_streams != rx_streams) {
4776debecadSSujith 		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
4786debecadSSujith 		ht_info->mcs.tx_params |= ((tx_streams - 1) <<
4796debecadSSujith 					   IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
4806debecadSSujith 	}
4816debecadSSujith 
4826debecadSSujith 	for (i = 0; i < rx_streams; i++)
4836debecadSSujith 		ht_info->mcs.rx_mask[i] = 0xff;
4846debecadSSujith 
485fb9987d0SSujith 	ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
486fb9987d0SSujith }
487fb9987d0SSujith 
488fb9987d0SSujith static int ath9k_init_queues(struct ath9k_htc_priv *priv)
489fb9987d0SSujith {
490fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
491fb9987d0SSujith 	int i;
492fb9987d0SSujith 
493fb9987d0SSujith 	for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++)
494fb9987d0SSujith 		priv->hwq_map[i] = -1;
495fb9987d0SSujith 
496ca74b83bSSujith 	priv->beaconq = ath9k_hw_beaconq_setup(priv->ah);
497ca74b83bSSujith 	if (priv->beaconq == -1) {
4983800276aSJoe Perches 		ath_err(common, "Unable to setup BEACON xmit queue\n");
499ca74b83bSSujith 		goto err;
500ca74b83bSSujith 	}
501ca74b83bSSujith 
502ca74b83bSSujith 	priv->cabq = ath9k_htc_cabq_setup(priv);
503ca74b83bSSujith 	if (priv->cabq == -1) {
5043800276aSJoe Perches 		ath_err(common, "Unable to setup CAB xmit queue\n");
505ca74b83bSSujith 		goto err;
506ca74b83bSSujith 	}
507ca74b83bSSujith 
508e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) {
5093800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for BE traffic\n");
510fb9987d0SSujith 		goto err;
511fb9987d0SSujith 	}
512fb9987d0SSujith 
513e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) {
5143800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for BK traffic\n");
515fb9987d0SSujith 		goto err;
516fb9987d0SSujith 	}
517e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) {
5183800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for VI traffic\n");
519fb9987d0SSujith 		goto err;
520fb9987d0SSujith 	}
521e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) {
5223800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for VO traffic\n");
523fb9987d0SSujith 		goto err;
524fb9987d0SSujith 	}
525fb9987d0SSujith 
526fb9987d0SSujith 	return 0;
527fb9987d0SSujith 
528fb9987d0SSujith err:
529fb9987d0SSujith 	return -EINVAL;
530fb9987d0SSujith }
531fb9987d0SSujith 
532fb9987d0SSujith static void ath9k_init_crypto(struct ath9k_htc_priv *priv)
533fb9987d0SSujith {
534fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
535fb9987d0SSujith 	int i = 0;
536fb9987d0SSujith 
537fb9987d0SSujith 	/* Get the hardware key cache size. */
538fb9987d0SSujith 	common->keymax = priv->ah->caps.keycache_size;
539fb9987d0SSujith 	if (common->keymax > ATH_KEYMAX) {
540226afe68SJoe Perches 		ath_dbg(common, ATH_DBG_ANY,
541fb9987d0SSujith 			"Warning, using only %u entries in %u key cache\n",
542fb9987d0SSujith 			ATH_KEYMAX, common->keymax);
543fb9987d0SSujith 		common->keymax = ATH_KEYMAX;
544fb9987d0SSujith 	}
545fb9987d0SSujith 
546e2b62624SRajkumar Manoharan 	if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
547e2b62624SRajkumar Manoharan 		common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
548e2b62624SRajkumar Manoharan 
549fb9987d0SSujith 	/*
550fb9987d0SSujith 	 * Reset the key cache since some parts do not
551fb9987d0SSujith 	 * reset the contents on initial power up.
552fb9987d0SSujith 	 */
553fb9987d0SSujith 	for (i = 0; i < common->keymax; i++)
554040e539eSBruno Randolf 		ath_hw_keyreset(common, (u16) i);
555fb9987d0SSujith }
556fb9987d0SSujith 
557fb9987d0SSujith static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
558fb9987d0SSujith {
559d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
560fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].channels =
561fb9987d0SSujith 			ath9k_2ghz_channels;
562fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
563fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].n_channels =
564fb9987d0SSujith 			ARRAY_SIZE(ath9k_2ghz_channels);
565fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
566fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
567fb9987d0SSujith 			ARRAY_SIZE(ath9k_legacy_rates);
568fb9987d0SSujith 	}
569ea46e644SSujith 
570d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
571ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels;
572ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
573ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].n_channels =
574ea46e644SSujith 			ARRAY_SIZE(ath9k_5ghz_channels);
575ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].bitrates =
576ea46e644SSujith 			ath9k_legacy_rates + 4;
577ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
578ea46e644SSujith 			ARRAY_SIZE(ath9k_legacy_rates) - 4;
579ea46e644SSujith 	}
580fb9987d0SSujith }
581fb9987d0SSujith 
582fb9987d0SSujith static void ath9k_init_misc(struct ath9k_htc_priv *priv)
583fb9987d0SSujith {
584fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
585fb9987d0SSujith 
586fb9987d0SSujith 	common->tx_chainmask = priv->ah->caps.tx_chainmask;
587fb9987d0SSujith 	common->rx_chainmask = priv->ah->caps.rx_chainmask;
588fb9987d0SSujith 
589fb9987d0SSujith 	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
590fb9987d0SSujith 
5919f01a84eSSujith 	priv->ah->opmode = NL80211_IFTYPE_STATION;
592fb9987d0SSujith }
593fb9987d0SSujith 
59421cb9879SVivek Natarajan static void ath9k_init_btcoex(struct ath9k_htc_priv *priv)
59521cb9879SVivek Natarajan {
59621cb9879SVivek Natarajan 	int qnum;
59721cb9879SVivek Natarajan 
59821cb9879SVivek Natarajan 	switch (priv->ah->btcoex_hw.scheme) {
59921cb9879SVivek Natarajan 	case ATH_BTCOEX_CFG_NONE:
60021cb9879SVivek Natarajan 		break;
60121cb9879SVivek Natarajan 	case ATH_BTCOEX_CFG_3WIRE:
60221cb9879SVivek Natarajan 		priv->ah->btcoex_hw.btactive_gpio = 7;
60321cb9879SVivek Natarajan 		priv->ah->btcoex_hw.btpriority_gpio = 6;
60421cb9879SVivek Natarajan 		priv->ah->btcoex_hw.wlanactive_gpio = 8;
60521cb9879SVivek Natarajan 		priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
60621cb9879SVivek Natarajan 		ath9k_hw_btcoex_init_3wire(priv->ah);
60721cb9879SVivek Natarajan 		ath_htc_init_btcoex_work(priv);
60821cb9879SVivek Natarajan 		qnum = priv->hwq_map[WME_AC_BE];
60921cb9879SVivek Natarajan 		ath9k_hw_init_btcoex_hw(priv->ah, qnum);
61021cb9879SVivek Natarajan 		break;
61121cb9879SVivek Natarajan 	default:
61221cb9879SVivek Natarajan 		WARN_ON(1);
61321cb9879SVivek Natarajan 		break;
61421cb9879SVivek Natarajan 	}
61521cb9879SVivek Natarajan }
61621cb9879SVivek Natarajan 
61721cb9879SVivek Natarajan static int ath9k_init_priv(struct ath9k_htc_priv *priv,
618fa6e15e0SRajkumar Manoharan 			   u16 devid, char *product,
619fa6e15e0SRajkumar Manoharan 			   u32 drv_info)
620fb9987d0SSujith {
621fb9987d0SSujith 	struct ath_hw *ah = NULL;
622fb9987d0SSujith 	struct ath_common *common;
623fb9987d0SSujith 	int ret = 0, csz = 0;
624fb9987d0SSujith 
625fb9987d0SSujith 	priv->op_flags |= OP_INVALID;
626fb9987d0SSujith 
627fb9987d0SSujith 	ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
628fb9987d0SSujith 	if (!ah)
629fb9987d0SSujith 		return -ENOMEM;
630fb9987d0SSujith 
631fb9987d0SSujith 	ah->hw_version.devid = devid;
632fb9987d0SSujith 	ah->hw_version.subsysid = 0; /* FIXME */
633f8afa42bSFelix Fietkau 	ah->ah_flags |= AH_USE_EEPROM;
634fb9987d0SSujith 	priv->ah = ah;
635fb9987d0SSujith 
636fb9987d0SSujith 	common = ath9k_hw_common(ah);
637fb9987d0SSujith 	common->ops = &ath9k_common_ops;
638fb9987d0SSujith 	common->bus_ops = &ath9k_usb_bus_ops;
639fb9987d0SSujith 	common->ah = ah;
640fb9987d0SSujith 	common->hw = priv->hw;
641fb9987d0SSujith 	common->priv = priv;
642fb9987d0SSujith 	common->debug_mask = ath9k_debug;
643fa6e15e0SRajkumar Manoharan 	common->driver_info = drv_info;
644fb9987d0SSujith 
645fb9987d0SSujith 	spin_lock_init(&priv->wmi->wmi_lock);
646fb9987d0SSujith 	spin_lock_init(&priv->beacon_lock);
6477757dfedSSujith 	spin_lock_init(&priv->tx_lock);
648fb9987d0SSujith 	mutex_init(&priv->mutex);
649bde748a4SVivek Natarajan 	mutex_init(&priv->htc_pm_lock);
650fb9987d0SSujith 	tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet,
651fb9987d0SSujith 		     (unsigned long)priv);
652fb9987d0SSujith 	tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
653fb9987d0SSujith 		     (unsigned long)priv);
654fb9987d0SSujith 	tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv);
655fb9987d0SSujith 	INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work);
656bde748a4SVivek Natarajan 	INIT_WORK(&priv->ps_work, ath9k_ps_work);
657fb9987d0SSujith 
658fb9987d0SSujith 	/*
659fb9987d0SSujith 	 * Cache line size is used to size and align various
660fb9987d0SSujith 	 * structures used to communicate with the hardware.
661fb9987d0SSujith 	 */
662fb9987d0SSujith 	ath_read_cachesize(common, &csz);
663fb9987d0SSujith 	common->cachelsz = csz << 2; /* convert to bytes */
664fb9987d0SSujith 
665fb9987d0SSujith 	ret = ath9k_hw_init(ah);
666fb9987d0SSujith 	if (ret) {
6673800276aSJoe Perches 		ath_err(common,
6683800276aSJoe Perches 			"Unable to initialize hardware; initialization status: %d\n",
6693800276aSJoe Perches 			ret);
670fb9987d0SSujith 		goto err_hw;
671fb9987d0SSujith 	}
672fb9987d0SSujith 
673e1572c5eSSujith 	ret = ath9k_htc_init_debug(ah);
674fb9987d0SSujith 	if (ret) {
6753800276aSJoe Perches 		ath_err(common, "Unable to create debugfs files\n");
676fb9987d0SSujith 		goto err_debug;
677fb9987d0SSujith 	}
678fb9987d0SSujith 
679fb9987d0SSujith 	ret = ath9k_init_queues(priv);
680fb9987d0SSujith 	if (ret)
681fb9987d0SSujith 		goto err_queues;
682fb9987d0SSujith 
683fb9987d0SSujith 	ath9k_init_crypto(priv);
684fb9987d0SSujith 	ath9k_init_channels_rates(priv);
685fb9987d0SSujith 	ath9k_init_misc(priv);
686fb9987d0SSujith 
68721cb9879SVivek Natarajan 	if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) {
68821cb9879SVivek Natarajan 		ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE;
68921cb9879SVivek Natarajan 		ath9k_init_btcoex(priv);
69021cb9879SVivek Natarajan 	}
69121cb9879SVivek Natarajan 
692fb9987d0SSujith 	return 0;
693fb9987d0SSujith 
694fb9987d0SSujith err_queues:
695e1572c5eSSujith 	ath9k_htc_exit_debug(ah);
696fb9987d0SSujith err_debug:
697fb9987d0SSujith 	ath9k_hw_deinit(ah);
698fb9987d0SSujith err_hw:
699fb9987d0SSujith 
700fb9987d0SSujith 	kfree(ah);
701fb9987d0SSujith 	priv->ah = NULL;
702fb9987d0SSujith 
703fb9987d0SSujith 	return ret;
704fb9987d0SSujith }
705fb9987d0SSujith 
706fb9987d0SSujith static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
707fb9987d0SSujith 			       struct ieee80211_hw *hw)
708fb9987d0SSujith {
709fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
710fb9987d0SSujith 
711fb9987d0SSujith 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
712fb9987d0SSujith 		IEEE80211_HW_AMPDU_AGGREGATION |
713fb9987d0SSujith 		IEEE80211_HW_SPECTRUM_MGMT |
71432fbccafSSujith 		IEEE80211_HW_HAS_RATE_CONTROL |
715bde748a4SVivek Natarajan 		IEEE80211_HW_RX_INCLUDES_FCS |
716bde748a4SVivek Natarajan 		IEEE80211_HW_SUPPORTS_PS |
717bde748a4SVivek Natarajan 		IEEE80211_HW_PS_NULLFUNC_STACK;
718fb9987d0SSujith 
719fb9987d0SSujith 	hw->wiphy->interface_modes =
720fb9987d0SSujith 		BIT(NL80211_IFTYPE_STATION) |
721fb9987d0SSujith 		BIT(NL80211_IFTYPE_ADHOC);
722fb9987d0SSujith 
723bde748a4SVivek Natarajan 	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
724bde748a4SVivek Natarajan 
725fb9987d0SSujith 	hw->queues = 4;
726fb9987d0SSujith 	hw->channel_change_time = 5000;
727fb9987d0SSujith 	hw->max_listen_interval = 10;
728fb9987d0SSujith 	hw->vif_data_size = sizeof(struct ath9k_htc_vif);
729fb9987d0SSujith 	hw->sta_data_size = sizeof(struct ath9k_htc_sta);
730fb9987d0SSujith 
731fb9987d0SSujith 	/* tx_frame_hdr is larger than tx_mgmt_hdr anyway */
732fb9987d0SSujith 	hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) +
733fb9987d0SSujith 		sizeof(struct htc_frame_hdr) + 4;
734fb9987d0SSujith 
735d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
736fb9987d0SSujith 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
737fb9987d0SSujith 			&priv->sbands[IEEE80211_BAND_2GHZ];
738d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
739ea46e644SSujith 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
740ea46e644SSujith 			&priv->sbands[IEEE80211_BAND_5GHZ];
741fb9987d0SSujith 
742fb9987d0SSujith 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
743d4659912SFelix Fietkau 		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
744fb9987d0SSujith 			setup_ht_cap(priv,
745fb9987d0SSujith 				     &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap);
746d4659912SFelix Fietkau 		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
747ea46e644SSujith 			setup_ht_cap(priv,
748ea46e644SSujith 				     &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
749fb9987d0SSujith 	}
750fb9987d0SSujith 
751fb9987d0SSujith 	SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
752fb9987d0SSujith }
753fb9987d0SSujith 
75421cb9879SVivek Natarajan static int ath9k_init_device(struct ath9k_htc_priv *priv,
755fa6e15e0SRajkumar Manoharan 			     u16 devid, char *product, u32 drv_info)
756fb9987d0SSujith {
757fb9987d0SSujith 	struct ieee80211_hw *hw = priv->hw;
758fb9987d0SSujith 	struct ath_common *common;
759fb9987d0SSujith 	struct ath_hw *ah;
760fb9987d0SSujith 	int error = 0;
761fb9987d0SSujith 	struct ath_regulatory *reg;
762fb9987d0SSujith 
763fb9987d0SSujith 	/* Bring up device */
764fa6e15e0SRajkumar Manoharan 	error = ath9k_init_priv(priv, devid, product, drv_info);
765fb9987d0SSujith 	if (error != 0)
766fb9987d0SSujith 		goto err_init;
767fb9987d0SSujith 
768fb9987d0SSujith 	ah = priv->ah;
769fb9987d0SSujith 	common = ath9k_hw_common(ah);
770fb9987d0SSujith 	ath9k_set_hw_capab(priv, hw);
771fb9987d0SSujith 
772fb9987d0SSujith 	/* Initialize regulatory */
773fb9987d0SSujith 	error = ath_regd_init(&common->regulatory, priv->hw->wiphy,
774fb9987d0SSujith 			      ath9k_reg_notifier);
775fb9987d0SSujith 	if (error)
776fb9987d0SSujith 		goto err_regd;
777fb9987d0SSujith 
778fb9987d0SSujith 	reg = &common->regulatory;
779fb9987d0SSujith 
780fb9987d0SSujith 	/* Setup TX */
781fb9987d0SSujith 	error = ath9k_tx_init(priv);
782fb9987d0SSujith 	if (error != 0)
783fb9987d0SSujith 		goto err_tx;
784fb9987d0SSujith 
785fb9987d0SSujith 	/* Setup RX */
786fb9987d0SSujith 	error = ath9k_rx_init(priv);
787fb9987d0SSujith 	if (error != 0)
788fb9987d0SSujith 		goto err_rx;
789fb9987d0SSujith 
790fb9987d0SSujith 	/* Register with mac80211 */
791fb9987d0SSujith 	error = ieee80211_register_hw(hw);
792fb9987d0SSujith 	if (error)
793fb9987d0SSujith 		goto err_register;
794fb9987d0SSujith 
795fb9987d0SSujith 	/* Handle world regulatory */
796fb9987d0SSujith 	if (!ath_is_world_regd(reg)) {
797fb9987d0SSujith 		error = regulatory_hint(hw->wiphy, reg->alpha2);
798fb9987d0SSujith 		if (error)
799fb9987d0SSujith 			goto err_world;
800fb9987d0SSujith 	}
801fb9987d0SSujith 
802fb9987d0SSujith 	ath9k_init_leds(priv);
803fb9987d0SSujith 	ath9k_start_rfkill_poll(priv);
804fb9987d0SSujith 
805fb9987d0SSujith 	return 0;
806fb9987d0SSujith 
807fb9987d0SSujith err_world:
808fb9987d0SSujith 	ieee80211_unregister_hw(hw);
809fb9987d0SSujith err_register:
810fb9987d0SSujith 	ath9k_rx_cleanup(priv);
811fb9987d0SSujith err_rx:
812fb9987d0SSujith 	ath9k_tx_cleanup(priv);
813fb9987d0SSujith err_tx:
814fb9987d0SSujith 	/* Nothing */
815fb9987d0SSujith err_regd:
816fb9987d0SSujith 	ath9k_deinit_priv(priv);
817fb9987d0SSujith err_init:
818fb9987d0SSujith 	return error;
819fb9987d0SSujith }
820fb9987d0SSujith 
821fb9987d0SSujith int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
822fa6e15e0SRajkumar Manoharan 			   u16 devid, char *product, u32 drv_info)
823fb9987d0SSujith {
824fb9987d0SSujith 	struct ieee80211_hw *hw;
825fb9987d0SSujith 	struct ath9k_htc_priv *priv;
826fb9987d0SSujith 	int ret;
827fb9987d0SSujith 
828fb9987d0SSujith 	hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops);
829fb9987d0SSujith 	if (!hw)
830fb9987d0SSujith 		return -ENOMEM;
831fb9987d0SSujith 
832fb9987d0SSujith 	priv = hw->priv;
833fb9987d0SSujith 	priv->hw = hw;
834fb9987d0SSujith 	priv->htc = htc_handle;
835fb9987d0SSujith 	priv->dev = dev;
836fb9987d0SSujith 	htc_handle->drv_priv = priv;
837fb9987d0SSujith 	SET_IEEE80211_DEV(hw, priv->dev);
838fb9987d0SSujith 
839fb9987d0SSujith 	ret = ath9k_htc_wait_for_target(priv);
840fb9987d0SSujith 	if (ret)
841fb9987d0SSujith 		goto err_free;
842fb9987d0SSujith 
843fb9987d0SSujith 	priv->wmi = ath9k_init_wmi(priv);
844fb9987d0SSujith 	if (!priv->wmi) {
845fb9987d0SSujith 		ret = -EINVAL;
846fb9987d0SSujith 		goto err_free;
847fb9987d0SSujith 	}
848fb9987d0SSujith 
849fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_htc_services(priv, devid, drv_info);
850fb9987d0SSujith 	if (ret)
851fb9987d0SSujith 		goto err_init;
852fb9987d0SSujith 
853a3be14b7SSujith 	/* The device may have been unplugged earlier. */
854a3be14b7SSujith 	priv->op_flags &= ~OP_UNPLUGGED;
855a3be14b7SSujith 
856fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_device(priv, devid, product, drv_info);
857fb9987d0SSujith 	if (ret)
858fb9987d0SSujith 		goto err_init;
859fb9987d0SSujith 
860fb9987d0SSujith 	return 0;
861fb9987d0SSujith 
862fb9987d0SSujith err_init:
863fb9987d0SSujith 	ath9k_deinit_wmi(priv);
864fb9987d0SSujith err_free:
865fb9987d0SSujith 	ieee80211_free_hw(hw);
866fb9987d0SSujith 	return ret;
867fb9987d0SSujith }
868fb9987d0SSujith 
869fb9987d0SSujith void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
870fb9987d0SSujith {
871fb9987d0SSujith 	if (htc_handle->drv_priv) {
872a3be14b7SSujith 
873a3be14b7SSujith 		/* Check if the device has been yanked out. */
874a3be14b7SSujith 		if (hotunplug)
875a3be14b7SSujith 			htc_handle->drv_priv->op_flags |= OP_UNPLUGGED;
876a3be14b7SSujith 
877fb9987d0SSujith 		ath9k_deinit_device(htc_handle->drv_priv);
878fb9987d0SSujith 		ath9k_deinit_wmi(htc_handle->drv_priv);
879fb9987d0SSujith 		ieee80211_free_hw(htc_handle->drv_priv->hw);
880fb9987d0SSujith 	}
881fb9987d0SSujith }
882fb9987d0SSujith 
883fb9987d0SSujith #ifdef CONFIG_PM
884fb9987d0SSujith int ath9k_htc_resume(struct htc_target *htc_handle)
885fb9987d0SSujith {
886fa6e15e0SRajkumar Manoharan 	struct ath9k_htc_priv *priv = htc_handle->drv_priv;
887fb9987d0SSujith 	int ret;
888fb9987d0SSujith 
889fa6e15e0SRajkumar Manoharan 	ret = ath9k_htc_wait_for_target(priv);
890fb9987d0SSujith 	if (ret)
891fb9987d0SSujith 		return ret;
892fb9987d0SSujith 
893fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid,
894fa6e15e0SRajkumar Manoharan 				      priv->ah->common.driver_info);
895fb9987d0SSujith 	return ret;
896fb9987d0SSujith }
897fb9987d0SSujith #endif
898fb9987d0SSujith 
899fb9987d0SSujith static int __init ath9k_htc_init(void)
900fb9987d0SSujith {
901fb9987d0SSujith 	int error;
902fb9987d0SSujith 
903e1572c5eSSujith 	error = ath9k_htc_debug_create_root();
904fb9987d0SSujith 	if (error < 0) {
905fb9987d0SSujith 		printk(KERN_ERR
906fb9987d0SSujith 			"ath9k_htc: Unable to create debugfs root: %d\n",
907fb9987d0SSujith 			error);
908fb9987d0SSujith 		goto err_dbg;
909fb9987d0SSujith 	}
910fb9987d0SSujith 
911fb9987d0SSujith 	error = ath9k_hif_usb_init();
912fb9987d0SSujith 	if (error < 0) {
913fb9987d0SSujith 		printk(KERN_ERR
914fb9987d0SSujith 			"ath9k_htc: No USB devices found,"
915fb9987d0SSujith 			" driver not installed.\n");
916fb9987d0SSujith 		error = -ENODEV;
917fb9987d0SSujith 		goto err_usb;
918fb9987d0SSujith 	}
919fb9987d0SSujith 
920fb9987d0SSujith 	return 0;
921fb9987d0SSujith 
922fb9987d0SSujith err_usb:
923e1572c5eSSujith 	ath9k_htc_debug_remove_root();
924fb9987d0SSujith err_dbg:
925fb9987d0SSujith 	return error;
926fb9987d0SSujith }
927fb9987d0SSujith module_init(ath9k_htc_init);
928fb9987d0SSujith 
929fb9987d0SSujith static void __exit ath9k_htc_exit(void)
930fb9987d0SSujith {
931fb9987d0SSujith 	ath9k_hif_usb_exit();
932e1572c5eSSujith 	ath9k_htc_debug_remove_root();
933fb9987d0SSujith 	printk(KERN_INFO "ath9k_htc: Driver unloaded\n");
934fb9987d0SSujith }
935fb9987d0SSujith module_exit(ath9k_htc_exit);
936