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 
1846267dc70SSujith static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid)
185fb9987d0SSujith {
186fb9987d0SSujith 	int ret;
187fb9987d0SSujith 
188fb9987d0SSujith 	/* WMI CMD*/
189fb9987d0SSujith 	ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep);
190fb9987d0SSujith 	if (ret)
191fb9987d0SSujith 		goto err;
192fb9987d0SSujith 
193fb9987d0SSujith 	/* Beacon */
1949c6dda4eSSujith 	ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, ath9k_htc_beaconep,
195fb9987d0SSujith 				    &priv->beacon_ep);
196fb9987d0SSujith 	if (ret)
197fb9987d0SSujith 		goto err;
198fb9987d0SSujith 
199fb9987d0SSujith 	/* CAB */
200fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep,
201fb9987d0SSujith 				    &priv->cab_ep);
202fb9987d0SSujith 	if (ret)
203fb9987d0SSujith 		goto err;
204fb9987d0SSujith 
205fb9987d0SSujith 
206fb9987d0SSujith 	/* UAPSD */
207fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep,
208fb9987d0SSujith 				    &priv->uapsd_ep);
209fb9987d0SSujith 	if (ret)
210fb9987d0SSujith 		goto err;
211fb9987d0SSujith 
212fb9987d0SSujith 	/* MGMT */
213fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep,
214fb9987d0SSujith 				    &priv->mgmt_ep);
215fb9987d0SSujith 	if (ret)
216fb9987d0SSujith 		goto err;
217fb9987d0SSujith 
218fb9987d0SSujith 	/* DATA BE */
219fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep,
220fb9987d0SSujith 				    &priv->data_be_ep);
221fb9987d0SSujith 	if (ret)
222fb9987d0SSujith 		goto err;
223fb9987d0SSujith 
224fb9987d0SSujith 	/* DATA BK */
225fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep,
226fb9987d0SSujith 				    &priv->data_bk_ep);
227fb9987d0SSujith 	if (ret)
228fb9987d0SSujith 		goto err;
229fb9987d0SSujith 
230fb9987d0SSujith 	/* DATA VI */
231fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep,
232fb9987d0SSujith 				    &priv->data_vi_ep);
233fb9987d0SSujith 	if (ret)
234fb9987d0SSujith 		goto err;
235fb9987d0SSujith 
236fb9987d0SSujith 	/* DATA VO */
237fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep,
238fb9987d0SSujith 				    &priv->data_vo_ep);
239fb9987d0SSujith 	if (ret)
240fb9987d0SSujith 		goto err;
241fb9987d0SSujith 
2426267dc70SSujith 	/*
2436267dc70SSujith 	 * Setup required credits before initializing HTC.
2446267dc70SSujith 	 * This is a bit hacky, but, since queuing is done in
2456267dc70SSujith 	 * the HIF layer, shouldn't matter much.
2466267dc70SSujith 	 */
2476267dc70SSujith 
2486267dc70SSujith 	switch(devid) {
2496267dc70SSujith 	case 0x7010:
250ca6cff1fSRajkumar Manoharan 	case 0x7015:
2514e63f768SSujith 	case 0x9018:
2526267dc70SSujith 		priv->htc->credits = 45;
2536267dc70SSujith 		break;
2546267dc70SSujith 	default:
2554e63f768SSujith 		priv->htc->credits = 33;
2566267dc70SSujith 	}
2576267dc70SSujith 
258fb9987d0SSujith 	ret = htc_init(priv->htc);
259fb9987d0SSujith 	if (ret)
260fb9987d0SSujith 		goto err;
261fb9987d0SSujith 
2626267dc70SSujith 	dev_info(priv->dev, "ath9k_htc: HTC initialized with %d credits\n",
2636267dc70SSujith 		 priv->htc->credits);
2646267dc70SSujith 
265fb9987d0SSujith 	return 0;
266fb9987d0SSujith 
267fb9987d0SSujith err:
268fb9987d0SSujith 	dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n");
269fb9987d0SSujith 	return ret;
270fb9987d0SSujith }
271fb9987d0SSujith 
272fb9987d0SSujith static int ath9k_reg_notifier(struct wiphy *wiphy,
273fb9987d0SSujith 			      struct regulatory_request *request)
274fb9987d0SSujith {
275fb9987d0SSujith 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
276fb9987d0SSujith 	struct ath9k_htc_priv *priv = hw->priv;
277fb9987d0SSujith 
278fb9987d0SSujith 	return ath_reg_notifier_apply(wiphy, request,
279fb9987d0SSujith 				      ath9k_hw_regulatory(priv->ah));
280fb9987d0SSujith }
281fb9987d0SSujith 
2824a22fe10SSujith static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
283fb9987d0SSujith {
284fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
285fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(ah);
286fb9987d0SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
287fb9987d0SSujith 	__be32 val, reg = cpu_to_be32(reg_offset);
288fb9987d0SSujith 	int r;
289fb9987d0SSujith 
290fb9987d0SSujith 	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
291fb9987d0SSujith 			  (u8 *) &reg, sizeof(reg),
292fb9987d0SSujith 			  (u8 *) &val, sizeof(val),
293fb9987d0SSujith 			  100);
294fb9987d0SSujith 	if (unlikely(r)) {
295fb9987d0SSujith 		ath_print(common, ATH_DBG_WMI,
296fb9987d0SSujith 			  "REGISTER READ FAILED: (0x%04x, %d)\n",
297fb9987d0SSujith 			   reg_offset, r);
298fb9987d0SSujith 		return -EIO;
299fb9987d0SSujith 	}
300fb9987d0SSujith 
301fb9987d0SSujith 	return be32_to_cpu(val);
302fb9987d0SSujith }
303fb9987d0SSujith 
3044a22fe10SSujith static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
305fb9987d0SSujith {
306fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
307fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(ah);
308fb9987d0SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
309fb9987d0SSujith 	__be32 buf[2] = {
310fb9987d0SSujith 		cpu_to_be32(reg_offset),
311fb9987d0SSujith 		cpu_to_be32(val),
312fb9987d0SSujith 	};
313fb9987d0SSujith 	int r;
314fb9987d0SSujith 
315fb9987d0SSujith 	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
316fb9987d0SSujith 			  (u8 *) &buf, sizeof(buf),
317fb9987d0SSujith 			  (u8 *) &val, sizeof(val),
318fb9987d0SSujith 			  100);
319fb9987d0SSujith 	if (unlikely(r)) {
320fb9987d0SSujith 		ath_print(common, ATH_DBG_WMI,
321fb9987d0SSujith 			  "REGISTER WRITE FAILED:(0x%04x, %d)\n",
322fb9987d0SSujith 			  reg_offset, r);
323fb9987d0SSujith 	}
324fb9987d0SSujith }
325fb9987d0SSujith 
3264a22fe10SSujith static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset)
3274a22fe10SSujith {
3284a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3294a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3304a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3314a22fe10SSujith 	u32 rsp_status;
3324a22fe10SSujith 	int r;
3334a22fe10SSujith 
3344a22fe10SSujith 	mutex_lock(&priv->wmi->multi_write_mutex);
3354a22fe10SSujith 
3364a22fe10SSujith 	/* Store the register/value */
3374a22fe10SSujith 	priv->wmi->multi_write[priv->wmi->multi_write_idx].reg =
3384a22fe10SSujith 		cpu_to_be32(reg_offset);
3394a22fe10SSujith 	priv->wmi->multi_write[priv->wmi->multi_write_idx].val =
3404a22fe10SSujith 		cpu_to_be32(val);
3414a22fe10SSujith 
3424a22fe10SSujith 	priv->wmi->multi_write_idx++;
3434a22fe10SSujith 
3444a22fe10SSujith 	/* If the buffer is full, send it out. */
3454a22fe10SSujith 	if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) {
3464a22fe10SSujith 		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
3474a22fe10SSujith 			  (u8 *) &priv->wmi->multi_write,
3484a22fe10SSujith 			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
3494a22fe10SSujith 			  (u8 *) &rsp_status, sizeof(rsp_status),
3504a22fe10SSujith 			  100);
3514a22fe10SSujith 		if (unlikely(r)) {
3524a22fe10SSujith 			ath_print(common, ATH_DBG_WMI,
3534a22fe10SSujith 				  "REGISTER WRITE FAILED, multi len: %d\n",
3544a22fe10SSujith 				  priv->wmi->multi_write_idx);
3554a22fe10SSujith 		}
3564a22fe10SSujith 		priv->wmi->multi_write_idx = 0;
3574a22fe10SSujith 	}
3584a22fe10SSujith 
3594a22fe10SSujith 	mutex_unlock(&priv->wmi->multi_write_mutex);
3604a22fe10SSujith }
3614a22fe10SSujith 
3624a22fe10SSujith static void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset)
3634a22fe10SSujith {
3644a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3654a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3664a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3674a22fe10SSujith 
3684a22fe10SSujith 	if (atomic_read(&priv->wmi->mwrite_cnt))
3694a22fe10SSujith 		ath9k_regwrite_buffer(hw_priv, val, reg_offset);
3704a22fe10SSujith 	else
3714a22fe10SSujith 		ath9k_regwrite_single(hw_priv, val, reg_offset);
3724a22fe10SSujith }
3734a22fe10SSujith 
3744a22fe10SSujith static void ath9k_enable_regwrite_buffer(void *hw_priv)
3754a22fe10SSujith {
3764a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3774a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3784a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3794a22fe10SSujith 
3804a22fe10SSujith 	atomic_inc(&priv->wmi->mwrite_cnt);
3814a22fe10SSujith }
3824a22fe10SSujith 
3834a22fe10SSujith static void ath9k_disable_regwrite_buffer(void *hw_priv)
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 	atomic_dec(&priv->wmi->mwrite_cnt);
3904a22fe10SSujith }
3914a22fe10SSujith 
3924a22fe10SSujith static void ath9k_regwrite_flush(void *hw_priv)
3934a22fe10SSujith {
3944a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3954a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3964a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3974a22fe10SSujith 	u32 rsp_status;
3984a22fe10SSujith 	int r;
3994a22fe10SSujith 
4004a22fe10SSujith 	mutex_lock(&priv->wmi->multi_write_mutex);
4014a22fe10SSujith 
4024a22fe10SSujith 	if (priv->wmi->multi_write_idx) {
4034a22fe10SSujith 		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
4044a22fe10SSujith 			  (u8 *) &priv->wmi->multi_write,
4054a22fe10SSujith 			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
4064a22fe10SSujith 			  (u8 *) &rsp_status, sizeof(rsp_status),
4074a22fe10SSujith 			  100);
4084a22fe10SSujith 		if (unlikely(r)) {
4094a22fe10SSujith 			ath_print(common, ATH_DBG_WMI,
4104a22fe10SSujith 				  "REGISTER WRITE FAILED, multi len: %d\n",
4114a22fe10SSujith 				  priv->wmi->multi_write_idx);
4124a22fe10SSujith 		}
4134a22fe10SSujith 		priv->wmi->multi_write_idx = 0;
4144a22fe10SSujith 	}
4154a22fe10SSujith 
4164a22fe10SSujith 	mutex_unlock(&priv->wmi->multi_write_mutex);
4174a22fe10SSujith }
4184a22fe10SSujith 
419fb9987d0SSujith static const struct ath_ops ath9k_common_ops = {
4204a22fe10SSujith 	.read = ath9k_regread,
4214a22fe10SSujith 	.write = ath9k_regwrite,
4224a22fe10SSujith 	.enable_write_buffer = ath9k_enable_regwrite_buffer,
4234a22fe10SSujith 	.disable_write_buffer = ath9k_disable_regwrite_buffer,
4244a22fe10SSujith 	.write_flush = ath9k_regwrite_flush,
425fb9987d0SSujith };
426fb9987d0SSujith 
427fb9987d0SSujith static void ath_usb_read_cachesize(struct ath_common *common, int *csz)
428fb9987d0SSujith {
429fb9987d0SSujith 	*csz = L1_CACHE_BYTES >> 2;
430fb9987d0SSujith }
431fb9987d0SSujith 
432fb9987d0SSujith static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
433fb9987d0SSujith {
434fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) common->ah;
435fb9987d0SSujith 
436fb9987d0SSujith 	(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
437fb9987d0SSujith 
438fb9987d0SSujith 	if (!ath9k_hw_wait(ah,
439fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA,
440fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA_BUSY |
441fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
442fb9987d0SSujith 			   AH_WAIT_TIMEOUT))
443fb9987d0SSujith 		return false;
444fb9987d0SSujith 
445fb9987d0SSujith 	*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
446fb9987d0SSujith 		   AR_EEPROM_STATUS_DATA_VAL);
447fb9987d0SSujith 
448fb9987d0SSujith 	return true;
449fb9987d0SSujith }
450fb9987d0SSujith 
451fb9987d0SSujith static const struct ath_bus_ops ath9k_usb_bus_ops = {
452497ad9adSSujith 	.ath_bus_type = ATH_USB,
453fb9987d0SSujith 	.read_cachesize = ath_usb_read_cachesize,
454fb9987d0SSujith 	.eeprom_read = ath_usb_eeprom_read,
455fb9987d0SSujith };
456fb9987d0SSujith 
457fb9987d0SSujith static void setup_ht_cap(struct ath9k_htc_priv *priv,
458fb9987d0SSujith 			 struct ieee80211_sta_ht_cap *ht_info)
459fb9987d0SSujith {
4606debecadSSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
4616debecadSSujith 	u8 tx_streams, rx_streams;
4626debecadSSujith 	int i;
4636debecadSSujith 
464fb9987d0SSujith 	ht_info->ht_supported = true;
465fb9987d0SSujith 	ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
466fb9987d0SSujith 		       IEEE80211_HT_CAP_SM_PS |
467fb9987d0SSujith 		       IEEE80211_HT_CAP_SGI_40 |
468fb9987d0SSujith 		       IEEE80211_HT_CAP_DSSSCCK40;
469fb9987d0SSujith 
470b4dec5e8SSujith 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
471b4dec5e8SSujith 		ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
472b4dec5e8SSujith 
47317525f96SSujith 	ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
47417525f96SSujith 
475fb9987d0SSujith 	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
476fb9987d0SSujith 	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
477fb9987d0SSujith 
478fb9987d0SSujith 	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
4796debecadSSujith 
4806debecadSSujith 	/* ath9k_htc supports only 1 or 2 stream devices */
4816debecadSSujith 	tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2);
4826debecadSSujith 	rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2);
4836debecadSSujith 
4846debecadSSujith 	ath_print(common, ATH_DBG_CONFIG,
4856debecadSSujith 		  "TX streams %d, RX streams: %d\n",
4866debecadSSujith 		  tx_streams, rx_streams);
4876debecadSSujith 
4886debecadSSujith 	if (tx_streams != rx_streams) {
4896debecadSSujith 		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
4906debecadSSujith 		ht_info->mcs.tx_params |= ((tx_streams - 1) <<
4916debecadSSujith 					   IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
4926debecadSSujith 	}
4936debecadSSujith 
4946debecadSSujith 	for (i = 0; i < rx_streams; i++)
4956debecadSSujith 		ht_info->mcs.rx_mask[i] = 0xff;
4966debecadSSujith 
497fb9987d0SSujith 	ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
498fb9987d0SSujith }
499fb9987d0SSujith 
500fb9987d0SSujith static int ath9k_init_queues(struct ath9k_htc_priv *priv)
501fb9987d0SSujith {
502fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
503fb9987d0SSujith 	int i;
504fb9987d0SSujith 
505fb9987d0SSujith 	for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++)
506fb9987d0SSujith 		priv->hwq_map[i] = -1;
507fb9987d0SSujith 
508ca74b83bSSujith 	priv->beaconq = ath9k_hw_beaconq_setup(priv->ah);
509ca74b83bSSujith 	if (priv->beaconq == -1) {
510ca74b83bSSujith 		ath_print(common, ATH_DBG_FATAL,
511ca74b83bSSujith 			  "Unable to setup BEACON xmit queue\n");
512ca74b83bSSujith 		goto err;
513ca74b83bSSujith 	}
514ca74b83bSSujith 
515ca74b83bSSujith 	priv->cabq = ath9k_htc_cabq_setup(priv);
516ca74b83bSSujith 	if (priv->cabq == -1) {
517ca74b83bSSujith 		ath_print(common, ATH_DBG_FATAL,
518ca74b83bSSujith 			  "Unable to setup CAB xmit queue\n");
519ca74b83bSSujith 		goto err;
520ca74b83bSSujith 	}
521ca74b83bSSujith 
522e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) {
523fb9987d0SSujith 		ath_print(common, ATH_DBG_FATAL,
524fb9987d0SSujith 			  "Unable to setup xmit queue for BE traffic\n");
525fb9987d0SSujith 		goto err;
526fb9987d0SSujith 	}
527fb9987d0SSujith 
528e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) {
529fb9987d0SSujith 		ath_print(common, ATH_DBG_FATAL,
530fb9987d0SSujith 			  "Unable to setup xmit queue for BK traffic\n");
531fb9987d0SSujith 		goto err;
532fb9987d0SSujith 	}
533e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) {
534fb9987d0SSujith 		ath_print(common, ATH_DBG_FATAL,
535fb9987d0SSujith 			  "Unable to setup xmit queue for VI traffic\n");
536fb9987d0SSujith 		goto err;
537fb9987d0SSujith 	}
538e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) {
539fb9987d0SSujith 		ath_print(common, ATH_DBG_FATAL,
540fb9987d0SSujith 			  "Unable to setup xmit queue for VO traffic\n");
541fb9987d0SSujith 		goto err;
542fb9987d0SSujith 	}
543fb9987d0SSujith 
544fb9987d0SSujith 	return 0;
545fb9987d0SSujith 
546fb9987d0SSujith err:
547fb9987d0SSujith 	return -EINVAL;
548fb9987d0SSujith }
549fb9987d0SSujith 
550fb9987d0SSujith static void ath9k_init_crypto(struct ath9k_htc_priv *priv)
551fb9987d0SSujith {
552fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
553fb9987d0SSujith 	int i = 0;
554fb9987d0SSujith 
555fb9987d0SSujith 	/* Get the hardware key cache size. */
556fb9987d0SSujith 	common->keymax = priv->ah->caps.keycache_size;
557fb9987d0SSujith 	if (common->keymax > ATH_KEYMAX) {
558fb9987d0SSujith 		ath_print(common, ATH_DBG_ANY,
559fb9987d0SSujith 			  "Warning, using only %u entries in %u key cache\n",
560fb9987d0SSujith 			  ATH_KEYMAX, common->keymax);
561fb9987d0SSujith 		common->keymax = ATH_KEYMAX;
562fb9987d0SSujith 	}
563fb9987d0SSujith 
564e2b62624SRajkumar Manoharan 	if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
565e2b62624SRajkumar Manoharan 		common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
566e2b62624SRajkumar Manoharan 
567fb9987d0SSujith 	/*
568fb9987d0SSujith 	 * Reset the key cache since some parts do not
569fb9987d0SSujith 	 * reset the contents on initial power up.
570fb9987d0SSujith 	 */
571fb9987d0SSujith 	for (i = 0; i < common->keymax; i++)
572040e539eSBruno Randolf 		ath_hw_keyreset(common, (u16) i);
573fb9987d0SSujith }
574fb9987d0SSujith 
575fb9987d0SSujith static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
576fb9987d0SSujith {
577fb9987d0SSujith 	if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) {
578fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].channels =
579fb9987d0SSujith 			ath9k_2ghz_channels;
580fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
581fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].n_channels =
582fb9987d0SSujith 			ARRAY_SIZE(ath9k_2ghz_channels);
583fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
584fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
585fb9987d0SSujith 			ARRAY_SIZE(ath9k_legacy_rates);
586fb9987d0SSujith 	}
587ea46e644SSujith 
588ea46e644SSujith 	if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) {
589ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels;
590ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
591ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].n_channels =
592ea46e644SSujith 			ARRAY_SIZE(ath9k_5ghz_channels);
593ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].bitrates =
594ea46e644SSujith 			ath9k_legacy_rates + 4;
595ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
596ea46e644SSujith 			ARRAY_SIZE(ath9k_legacy_rates) - 4;
597ea46e644SSujith 	}
598fb9987d0SSujith }
599fb9987d0SSujith 
600fb9987d0SSujith static void ath9k_init_misc(struct ath9k_htc_priv *priv)
601fb9987d0SSujith {
602fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
603fb9987d0SSujith 
604fb9987d0SSujith 	common->tx_chainmask = priv->ah->caps.tx_chainmask;
605fb9987d0SSujith 	common->rx_chainmask = priv->ah->caps.rx_chainmask;
606fb9987d0SSujith 
607fb9987d0SSujith 	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
608fb9987d0SSujith 
6099f01a84eSSujith 	priv->ah->opmode = NL80211_IFTYPE_STATION;
610fb9987d0SSujith }
611fb9987d0SSujith 
61221cb9879SVivek Natarajan static void ath9k_init_btcoex(struct ath9k_htc_priv *priv)
61321cb9879SVivek Natarajan {
61421cb9879SVivek Natarajan 	int qnum;
61521cb9879SVivek Natarajan 
61621cb9879SVivek Natarajan 	switch (priv->ah->btcoex_hw.scheme) {
61721cb9879SVivek Natarajan 	case ATH_BTCOEX_CFG_NONE:
61821cb9879SVivek Natarajan 		break;
61921cb9879SVivek Natarajan 	case ATH_BTCOEX_CFG_3WIRE:
62021cb9879SVivek Natarajan 		priv->ah->btcoex_hw.btactive_gpio = 7;
62121cb9879SVivek Natarajan 		priv->ah->btcoex_hw.btpriority_gpio = 6;
62221cb9879SVivek Natarajan 		priv->ah->btcoex_hw.wlanactive_gpio = 8;
62321cb9879SVivek Natarajan 		priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
62421cb9879SVivek Natarajan 		ath9k_hw_btcoex_init_3wire(priv->ah);
62521cb9879SVivek Natarajan 		ath_htc_init_btcoex_work(priv);
62621cb9879SVivek Natarajan 		qnum = priv->hwq_map[WME_AC_BE];
62721cb9879SVivek Natarajan 		ath9k_hw_init_btcoex_hw(priv->ah, qnum);
62821cb9879SVivek Natarajan 		break;
62921cb9879SVivek Natarajan 	default:
63021cb9879SVivek Natarajan 		WARN_ON(1);
63121cb9879SVivek Natarajan 		break;
63221cb9879SVivek Natarajan 	}
63321cb9879SVivek Natarajan }
63421cb9879SVivek Natarajan 
63521cb9879SVivek Natarajan static int ath9k_init_priv(struct ath9k_htc_priv *priv,
63621cb9879SVivek Natarajan 			   u16 devid, char *product)
637fb9987d0SSujith {
638fb9987d0SSujith 	struct ath_hw *ah = NULL;
639fb9987d0SSujith 	struct ath_common *common;
640fb9987d0SSujith 	int ret = 0, csz = 0;
641fb9987d0SSujith 
642fb9987d0SSujith 	priv->op_flags |= OP_INVALID;
643fb9987d0SSujith 
644fb9987d0SSujith 	ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
645fb9987d0SSujith 	if (!ah)
646fb9987d0SSujith 		return -ENOMEM;
647fb9987d0SSujith 
648fb9987d0SSujith 	ah->hw_version.devid = devid;
649fb9987d0SSujith 	ah->hw_version.subsysid = 0; /* FIXME */
650fb9987d0SSujith 	priv->ah = ah;
651fb9987d0SSujith 
652fb9987d0SSujith 	common = ath9k_hw_common(ah);
653fb9987d0SSujith 	common->ops = &ath9k_common_ops;
654fb9987d0SSujith 	common->bus_ops = &ath9k_usb_bus_ops;
655fb9987d0SSujith 	common->ah = ah;
656fb9987d0SSujith 	common->hw = priv->hw;
657fb9987d0SSujith 	common->priv = priv;
658fb9987d0SSujith 	common->debug_mask = ath9k_debug;
659fb9987d0SSujith 
660fb9987d0SSujith 	spin_lock_init(&priv->wmi->wmi_lock);
661fb9987d0SSujith 	spin_lock_init(&priv->beacon_lock);
6627757dfedSSujith 	spin_lock_init(&priv->tx_lock);
663fb9987d0SSujith 	mutex_init(&priv->mutex);
664bde748a4SVivek Natarajan 	mutex_init(&priv->htc_pm_lock);
665fb9987d0SSujith 	tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet,
666fb9987d0SSujith 		     (unsigned long)priv);
667fb9987d0SSujith 	tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
668fb9987d0SSujith 		     (unsigned long)priv);
669fb9987d0SSujith 	tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv);
670fb9987d0SSujith 	INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work);
671bde748a4SVivek Natarajan 	INIT_WORK(&priv->ps_work, ath9k_ps_work);
672fb9987d0SSujith 
673fb9987d0SSujith 	/*
674fb9987d0SSujith 	 * Cache line size is used to size and align various
675fb9987d0SSujith 	 * structures used to communicate with the hardware.
676fb9987d0SSujith 	 */
677fb9987d0SSujith 	ath_read_cachesize(common, &csz);
678fb9987d0SSujith 	common->cachelsz = csz << 2; /* convert to bytes */
679fb9987d0SSujith 
680fb9987d0SSujith 	ret = ath9k_hw_init(ah);
681fb9987d0SSujith 	if (ret) {
682fb9987d0SSujith 		ath_print(common, ATH_DBG_FATAL,
683fb9987d0SSujith 			  "Unable to initialize hardware; "
684fb9987d0SSujith 			  "initialization status: %d\n", ret);
685fb9987d0SSujith 		goto err_hw;
686fb9987d0SSujith 	}
687fb9987d0SSujith 
688e1572c5eSSujith 	ret = ath9k_htc_init_debug(ah);
689fb9987d0SSujith 	if (ret) {
690fb9987d0SSujith 		ath_print(common, ATH_DBG_FATAL,
691fb9987d0SSujith 			  "Unable to create debugfs files\n");
692fb9987d0SSujith 		goto err_debug;
693fb9987d0SSujith 	}
694fb9987d0SSujith 
695fb9987d0SSujith 	ret = ath9k_init_queues(priv);
696fb9987d0SSujith 	if (ret)
697fb9987d0SSujith 		goto err_queues;
698fb9987d0SSujith 
699fb9987d0SSujith 	ath9k_init_crypto(priv);
700fb9987d0SSujith 	ath9k_init_channels_rates(priv);
701fb9987d0SSujith 	ath9k_init_misc(priv);
702fb9987d0SSujith 
70321cb9879SVivek Natarajan 	if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) {
70421cb9879SVivek Natarajan 		ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE;
70521cb9879SVivek Natarajan 		ath9k_init_btcoex(priv);
70621cb9879SVivek Natarajan 	}
70721cb9879SVivek Natarajan 
708fb9987d0SSujith 	return 0;
709fb9987d0SSujith 
710fb9987d0SSujith err_queues:
711e1572c5eSSujith 	ath9k_htc_exit_debug(ah);
712fb9987d0SSujith err_debug:
713fb9987d0SSujith 	ath9k_hw_deinit(ah);
714fb9987d0SSujith err_hw:
715fb9987d0SSujith 
716fb9987d0SSujith 	kfree(ah);
717fb9987d0SSujith 	priv->ah = NULL;
718fb9987d0SSujith 
719fb9987d0SSujith 	return ret;
720fb9987d0SSujith }
721fb9987d0SSujith 
722fb9987d0SSujith static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
723fb9987d0SSujith 			       struct ieee80211_hw *hw)
724fb9987d0SSujith {
725fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
726fb9987d0SSujith 
727fb9987d0SSujith 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
728fb9987d0SSujith 		IEEE80211_HW_AMPDU_AGGREGATION |
729fb9987d0SSujith 		IEEE80211_HW_SPECTRUM_MGMT |
73032fbccafSSujith 		IEEE80211_HW_HAS_RATE_CONTROL |
731bde748a4SVivek Natarajan 		IEEE80211_HW_RX_INCLUDES_FCS |
732bde748a4SVivek Natarajan 		IEEE80211_HW_SUPPORTS_PS |
733bde748a4SVivek Natarajan 		IEEE80211_HW_PS_NULLFUNC_STACK;
734fb9987d0SSujith 
735fb9987d0SSujith 	hw->wiphy->interface_modes =
736fb9987d0SSujith 		BIT(NL80211_IFTYPE_STATION) |
737fb9987d0SSujith 		BIT(NL80211_IFTYPE_ADHOC);
738fb9987d0SSujith 
739bde748a4SVivek Natarajan 	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
740bde748a4SVivek Natarajan 
741fb9987d0SSujith 	hw->queues = 4;
742fb9987d0SSujith 	hw->channel_change_time = 5000;
743fb9987d0SSujith 	hw->max_listen_interval = 10;
744fb9987d0SSujith 	hw->vif_data_size = sizeof(struct ath9k_htc_vif);
745fb9987d0SSujith 	hw->sta_data_size = sizeof(struct ath9k_htc_sta);
746fb9987d0SSujith 
747fb9987d0SSujith 	/* tx_frame_hdr is larger than tx_mgmt_hdr anyway */
748fb9987d0SSujith 	hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) +
749fb9987d0SSujith 		sizeof(struct htc_frame_hdr) + 4;
750fb9987d0SSujith 
751fb9987d0SSujith 	if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes))
752fb9987d0SSujith 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
753fb9987d0SSujith 			&priv->sbands[IEEE80211_BAND_2GHZ];
754ea46e644SSujith 	if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes))
755ea46e644SSujith 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
756ea46e644SSujith 			&priv->sbands[IEEE80211_BAND_5GHZ];
757fb9987d0SSujith 
758fb9987d0SSujith 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
759fb9987d0SSujith 		if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes))
760fb9987d0SSujith 			setup_ht_cap(priv,
761fb9987d0SSujith 				     &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap);
762ea46e644SSujith 		if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes))
763ea46e644SSujith 			setup_ht_cap(priv,
764ea46e644SSujith 				     &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
765fb9987d0SSujith 	}
766fb9987d0SSujith 
767fb9987d0SSujith 	SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
768fb9987d0SSujith }
769fb9987d0SSujith 
77021cb9879SVivek Natarajan static int ath9k_init_device(struct ath9k_htc_priv *priv,
77121cb9879SVivek Natarajan 			     u16 devid, char *product)
772fb9987d0SSujith {
773fb9987d0SSujith 	struct ieee80211_hw *hw = priv->hw;
774fb9987d0SSujith 	struct ath_common *common;
775fb9987d0SSujith 	struct ath_hw *ah;
776fb9987d0SSujith 	int error = 0;
777fb9987d0SSujith 	struct ath_regulatory *reg;
778fb9987d0SSujith 
779fb9987d0SSujith 	/* Bring up device */
78021cb9879SVivek Natarajan 	error = ath9k_init_priv(priv, devid, product);
781fb9987d0SSujith 	if (error != 0)
782fb9987d0SSujith 		goto err_init;
783fb9987d0SSujith 
784fb9987d0SSujith 	ah = priv->ah;
785fb9987d0SSujith 	common = ath9k_hw_common(ah);
786fb9987d0SSujith 	ath9k_set_hw_capab(priv, hw);
787fb9987d0SSujith 
788fb9987d0SSujith 	/* Initialize regulatory */
789fb9987d0SSujith 	error = ath_regd_init(&common->regulatory, priv->hw->wiphy,
790fb9987d0SSujith 			      ath9k_reg_notifier);
791fb9987d0SSujith 	if (error)
792fb9987d0SSujith 		goto err_regd;
793fb9987d0SSujith 
794fb9987d0SSujith 	reg = &common->regulatory;
795fb9987d0SSujith 
796fb9987d0SSujith 	/* Setup TX */
797fb9987d0SSujith 	error = ath9k_tx_init(priv);
798fb9987d0SSujith 	if (error != 0)
799fb9987d0SSujith 		goto err_tx;
800fb9987d0SSujith 
801fb9987d0SSujith 	/* Setup RX */
802fb9987d0SSujith 	error = ath9k_rx_init(priv);
803fb9987d0SSujith 	if (error != 0)
804fb9987d0SSujith 		goto err_rx;
805fb9987d0SSujith 
806fb9987d0SSujith 	/* Register with mac80211 */
807fb9987d0SSujith 	error = ieee80211_register_hw(hw);
808fb9987d0SSujith 	if (error)
809fb9987d0SSujith 		goto err_register;
810fb9987d0SSujith 
811fb9987d0SSujith 	/* Handle world regulatory */
812fb9987d0SSujith 	if (!ath_is_world_regd(reg)) {
813fb9987d0SSujith 		error = regulatory_hint(hw->wiphy, reg->alpha2);
814fb9987d0SSujith 		if (error)
815fb9987d0SSujith 			goto err_world;
816fb9987d0SSujith 	}
817fb9987d0SSujith 
818fb9987d0SSujith 	ath9k_init_leds(priv);
819fb9987d0SSujith 	ath9k_start_rfkill_poll(priv);
820fb9987d0SSujith 
821fb9987d0SSujith 	return 0;
822fb9987d0SSujith 
823fb9987d0SSujith err_world:
824fb9987d0SSujith 	ieee80211_unregister_hw(hw);
825fb9987d0SSujith err_register:
826fb9987d0SSujith 	ath9k_rx_cleanup(priv);
827fb9987d0SSujith err_rx:
828fb9987d0SSujith 	ath9k_tx_cleanup(priv);
829fb9987d0SSujith err_tx:
830fb9987d0SSujith 	/* Nothing */
831fb9987d0SSujith err_regd:
832fb9987d0SSujith 	ath9k_deinit_priv(priv);
833fb9987d0SSujith err_init:
834fb9987d0SSujith 	return error;
835fb9987d0SSujith }
836fb9987d0SSujith 
837fb9987d0SSujith int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
83821cb9879SVivek Natarajan 			   u16 devid, char *product)
839fb9987d0SSujith {
840fb9987d0SSujith 	struct ieee80211_hw *hw;
841fb9987d0SSujith 	struct ath9k_htc_priv *priv;
842fb9987d0SSujith 	int ret;
843fb9987d0SSujith 
844fb9987d0SSujith 	hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops);
845fb9987d0SSujith 	if (!hw)
846fb9987d0SSujith 		return -ENOMEM;
847fb9987d0SSujith 
848fb9987d0SSujith 	priv = hw->priv;
849fb9987d0SSujith 	priv->hw = hw;
850fb9987d0SSujith 	priv->htc = htc_handle;
851fb9987d0SSujith 	priv->dev = dev;
852fb9987d0SSujith 	htc_handle->drv_priv = priv;
853fb9987d0SSujith 	SET_IEEE80211_DEV(hw, priv->dev);
854fb9987d0SSujith 
855fb9987d0SSujith 	ret = ath9k_htc_wait_for_target(priv);
856fb9987d0SSujith 	if (ret)
857fb9987d0SSujith 		goto err_free;
858fb9987d0SSujith 
859fb9987d0SSujith 	priv->wmi = ath9k_init_wmi(priv);
860fb9987d0SSujith 	if (!priv->wmi) {
861fb9987d0SSujith 		ret = -EINVAL;
862fb9987d0SSujith 		goto err_free;
863fb9987d0SSujith 	}
864fb9987d0SSujith 
8656267dc70SSujith 	ret = ath9k_init_htc_services(priv, devid);
866fb9987d0SSujith 	if (ret)
867fb9987d0SSujith 		goto err_init;
868fb9987d0SSujith 
869a3be14b7SSujith 	/* The device may have been unplugged earlier. */
870a3be14b7SSujith 	priv->op_flags &= ~OP_UNPLUGGED;
871a3be14b7SSujith 
87221cb9879SVivek Natarajan 	ret = ath9k_init_device(priv, devid, product);
873fb9987d0SSujith 	if (ret)
874fb9987d0SSujith 		goto err_init;
875fb9987d0SSujith 
876fb9987d0SSujith 	return 0;
877fb9987d0SSujith 
878fb9987d0SSujith err_init:
879fb9987d0SSujith 	ath9k_deinit_wmi(priv);
880fb9987d0SSujith err_free:
881fb9987d0SSujith 	ieee80211_free_hw(hw);
882fb9987d0SSujith 	return ret;
883fb9987d0SSujith }
884fb9987d0SSujith 
885fb9987d0SSujith void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
886fb9987d0SSujith {
887fb9987d0SSujith 	if (htc_handle->drv_priv) {
888a3be14b7SSujith 
889a3be14b7SSujith 		/* Check if the device has been yanked out. */
890a3be14b7SSujith 		if (hotunplug)
891a3be14b7SSujith 			htc_handle->drv_priv->op_flags |= OP_UNPLUGGED;
892a3be14b7SSujith 
893fb9987d0SSujith 		ath9k_deinit_device(htc_handle->drv_priv);
894fb9987d0SSujith 		ath9k_deinit_wmi(htc_handle->drv_priv);
895fb9987d0SSujith 		ieee80211_free_hw(htc_handle->drv_priv->hw);
896fb9987d0SSujith 	}
897fb9987d0SSujith }
898fb9987d0SSujith 
899fb9987d0SSujith #ifdef CONFIG_PM
900fb9987d0SSujith int ath9k_htc_resume(struct htc_target *htc_handle)
901fb9987d0SSujith {
902fb9987d0SSujith 	int ret;
903fb9987d0SSujith 
904fb9987d0SSujith 	ret = ath9k_htc_wait_for_target(htc_handle->drv_priv);
905fb9987d0SSujith 	if (ret)
906fb9987d0SSujith 		return ret;
907fb9987d0SSujith 
9086267dc70SSujith 	ret = ath9k_init_htc_services(htc_handle->drv_priv,
9096267dc70SSujith 			      htc_handle->drv_priv->ah->hw_version.devid);
910fb9987d0SSujith 	return ret;
911fb9987d0SSujith }
912fb9987d0SSujith #endif
913fb9987d0SSujith 
914fb9987d0SSujith static int __init ath9k_htc_init(void)
915fb9987d0SSujith {
916fb9987d0SSujith 	int error;
917fb9987d0SSujith 
918e1572c5eSSujith 	error = ath9k_htc_debug_create_root();
919fb9987d0SSujith 	if (error < 0) {
920fb9987d0SSujith 		printk(KERN_ERR
921fb9987d0SSujith 			"ath9k_htc: Unable to create debugfs root: %d\n",
922fb9987d0SSujith 			error);
923fb9987d0SSujith 		goto err_dbg;
924fb9987d0SSujith 	}
925fb9987d0SSujith 
926fb9987d0SSujith 	error = ath9k_hif_usb_init();
927fb9987d0SSujith 	if (error < 0) {
928fb9987d0SSujith 		printk(KERN_ERR
929fb9987d0SSujith 			"ath9k_htc: No USB devices found,"
930fb9987d0SSujith 			" driver not installed.\n");
931fb9987d0SSujith 		error = -ENODEV;
932fb9987d0SSujith 		goto err_usb;
933fb9987d0SSujith 	}
934fb9987d0SSujith 
935fb9987d0SSujith 	return 0;
936fb9987d0SSujith 
937fb9987d0SSujith err_usb:
938e1572c5eSSujith 	ath9k_htc_debug_remove_root();
939fb9987d0SSujith err_dbg:
940fb9987d0SSujith 	return error;
941fb9987d0SSujith }
942fb9987d0SSujith module_init(ath9k_htc_init);
943fb9987d0SSujith 
944fb9987d0SSujith static void __exit ath9k_htc_exit(void)
945fb9987d0SSujith {
946fb9987d0SSujith 	ath9k_hif_usb_exit();
947e1572c5eSSujith 	ath9k_htc_debug_remove_root();
948fb9987d0SSujith 	printk(KERN_INFO "ath9k_htc: Driver unloaded\n");
949fb9987d0SSujith }
950fb9987d0SSujith module_exit(ath9k_htc_exit);
951