• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * mac80211 glue code for mac80211 ST-Ericsson CW1200 drivers
3  *
4  * Copyright (c) 2010, ST-Ericsson
5  * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
6  *
7  * Based on:
8  * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
9  * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
10  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
11  *
12  * Based on:
13  * - the islsm (softmac prism54) driver, which is:
14  *   Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
15  * - stlc45xx driver
16  *   Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
17  *
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License version 2 as
20  * published by the Free Software Foundation.
21  */
22 
23 #include <linux/module.h>
24 #include <linux/firmware.h>
25 #include <linux/etherdevice.h>
26 #include <linux/vmalloc.h>
27 #include <linux/random.h>
28 #include <linux/sched.h>
29 #include <net/mac80211.h>
30 
31 #include "cw1200.h"
32 #include "txrx.h"
33 #include "hwbus.h"
34 #include "fwio.h"
35 #include "hwio.h"
36 #include "bh.h"
37 #include "sta.h"
38 #include "scan.h"
39 #include "debug.h"
40 #include "pm.h"
41 
42 MODULE_AUTHOR("Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>");
43 MODULE_DESCRIPTION("Softmac ST-Ericsson CW1200 common code");
44 MODULE_LICENSE("GPL");
45 MODULE_ALIAS("cw1200_core");
46 
47 /* Accept MAC address of the form macaddr=0x00,0x80,0xE1,0x30,0x40,0x50 */
48 static u8 cw1200_mac_template[ETH_ALEN] = {0x02, 0x80, 0xe1, 0x00, 0x00, 0x00};
49 module_param_array_named(macaddr, cw1200_mac_template, byte, NULL, S_IRUGO);
50 MODULE_PARM_DESC(macaddr, "Override platform_data MAC address");
51 
52 static char *cw1200_sdd_path;
53 module_param(cw1200_sdd_path, charp, 0644);
54 MODULE_PARM_DESC(cw1200_sdd_path, "Override platform_data SDD file");
55 static int cw1200_refclk;
56 module_param(cw1200_refclk, int, 0644);
57 MODULE_PARM_DESC(cw1200_refclk, "Override platform_data reference clock");
58 
59 int cw1200_power_mode = wsm_power_mode_quiescent;
60 module_param(cw1200_power_mode, int, 0644);
61 MODULE_PARM_DESC(cw1200_power_mode, "WSM power mode.  0 == active, 1 == doze, 2 == quiescent (default)");
62 
63 #define RATETAB_ENT(_rate, _rateid, _flags)		\
64 	{						\
65 		.bitrate	= (_rate),		\
66 		.hw_value	= (_rateid),		\
67 		.flags		= (_flags),		\
68 	}
69 
70 static struct ieee80211_rate cw1200_rates[] = {
71 	RATETAB_ENT(10,  0,   0),
72 	RATETAB_ENT(20,  1,   0),
73 	RATETAB_ENT(55,  2,   0),
74 	RATETAB_ENT(110, 3,   0),
75 	RATETAB_ENT(60,  6,  0),
76 	RATETAB_ENT(90,  7,  0),
77 	RATETAB_ENT(120, 8,  0),
78 	RATETAB_ENT(180, 9,  0),
79 	RATETAB_ENT(240, 10, 0),
80 	RATETAB_ENT(360, 11, 0),
81 	RATETAB_ENT(480, 12, 0),
82 	RATETAB_ENT(540, 13, 0),
83 };
84 
85 static struct ieee80211_rate cw1200_mcs_rates[] = {
86 	RATETAB_ENT(65,  14, IEEE80211_TX_RC_MCS),
87 	RATETAB_ENT(130, 15, IEEE80211_TX_RC_MCS),
88 	RATETAB_ENT(195, 16, IEEE80211_TX_RC_MCS),
89 	RATETAB_ENT(260, 17, IEEE80211_TX_RC_MCS),
90 	RATETAB_ENT(390, 18, IEEE80211_TX_RC_MCS),
91 	RATETAB_ENT(520, 19, IEEE80211_TX_RC_MCS),
92 	RATETAB_ENT(585, 20, IEEE80211_TX_RC_MCS),
93 	RATETAB_ENT(650, 21, IEEE80211_TX_RC_MCS),
94 };
95 
96 #define cw1200_a_rates		(cw1200_rates + 4)
97 #define cw1200_a_rates_size	(ARRAY_SIZE(cw1200_rates) - 4)
98 #define cw1200_g_rates		(cw1200_rates + 0)
99 #define cw1200_g_rates_size	(ARRAY_SIZE(cw1200_rates))
100 #define cw1200_n_rates		(cw1200_mcs_rates)
101 #define cw1200_n_rates_size	(ARRAY_SIZE(cw1200_mcs_rates))
102 
103 
104 #define CHAN2G(_channel, _freq, _flags) {			\
105 	.band			= IEEE80211_BAND_2GHZ,		\
106 	.center_freq		= (_freq),			\
107 	.hw_value		= (_channel),			\
108 	.flags			= (_flags),			\
109 	.max_antenna_gain	= 0,				\
110 	.max_power		= 30,				\
111 }
112 
113 #define CHAN5G(_channel, _flags) {				\
114 	.band			= IEEE80211_BAND_5GHZ,		\
115 	.center_freq	= 5000 + (5 * (_channel)),		\
116 	.hw_value		= (_channel),			\
117 	.flags			= (_flags),			\
118 	.max_antenna_gain	= 0,				\
119 	.max_power		= 30,				\
120 }
121 
122 static struct ieee80211_channel cw1200_2ghz_chantable[] = {
123 	CHAN2G(1, 2412, 0),
124 	CHAN2G(2, 2417, 0),
125 	CHAN2G(3, 2422, 0),
126 	CHAN2G(4, 2427, 0),
127 	CHAN2G(5, 2432, 0),
128 	CHAN2G(6, 2437, 0),
129 	CHAN2G(7, 2442, 0),
130 	CHAN2G(8, 2447, 0),
131 	CHAN2G(9, 2452, 0),
132 	CHAN2G(10, 2457, 0),
133 	CHAN2G(11, 2462, 0),
134 	CHAN2G(12, 2467, 0),
135 	CHAN2G(13, 2472, 0),
136 	CHAN2G(14, 2484, 0),
137 };
138 
139 static struct ieee80211_channel cw1200_5ghz_chantable[] = {
140 	CHAN5G(34, 0),		CHAN5G(36, 0),
141 	CHAN5G(38, 0),		CHAN5G(40, 0),
142 	CHAN5G(42, 0),		CHAN5G(44, 0),
143 	CHAN5G(46, 0),		CHAN5G(48, 0),
144 	CHAN5G(52, 0),		CHAN5G(56, 0),
145 	CHAN5G(60, 0),		CHAN5G(64, 0),
146 	CHAN5G(100, 0),		CHAN5G(104, 0),
147 	CHAN5G(108, 0),		CHAN5G(112, 0),
148 	CHAN5G(116, 0),		CHAN5G(120, 0),
149 	CHAN5G(124, 0),		CHAN5G(128, 0),
150 	CHAN5G(132, 0),		CHAN5G(136, 0),
151 	CHAN5G(140, 0),		CHAN5G(149, 0),
152 	CHAN5G(153, 0),		CHAN5G(157, 0),
153 	CHAN5G(161, 0),		CHAN5G(165, 0),
154 	CHAN5G(184, 0),		CHAN5G(188, 0),
155 	CHAN5G(192, 0),		CHAN5G(196, 0),
156 	CHAN5G(200, 0),		CHAN5G(204, 0),
157 	CHAN5G(208, 0),		CHAN5G(212, 0),
158 	CHAN5G(216, 0),
159 };
160 
161 static struct ieee80211_supported_band cw1200_band_2ghz = {
162 	.channels = cw1200_2ghz_chantable,
163 	.n_channels = ARRAY_SIZE(cw1200_2ghz_chantable),
164 	.bitrates = cw1200_g_rates,
165 	.n_bitrates = cw1200_g_rates_size,
166 	.ht_cap = {
167 		.cap = IEEE80211_HT_CAP_GRN_FLD |
168 			(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) |
169 			IEEE80211_HT_CAP_MAX_AMSDU,
170 		.ht_supported = 1,
171 		.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K,
172 		.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
173 		.mcs = {
174 			.rx_mask[0] = 0xFF,
175 			.rx_highest = __cpu_to_le16(0x41),
176 			.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
177 		},
178 	},
179 };
180 
181 static struct ieee80211_supported_band cw1200_band_5ghz = {
182 	.channels = cw1200_5ghz_chantable,
183 	.n_channels = ARRAY_SIZE(cw1200_5ghz_chantable),
184 	.bitrates = cw1200_a_rates,
185 	.n_bitrates = cw1200_a_rates_size,
186 	.ht_cap = {
187 		.cap = IEEE80211_HT_CAP_GRN_FLD |
188 			(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) |
189 			IEEE80211_HT_CAP_MAX_AMSDU,
190 		.ht_supported = 1,
191 		.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K,
192 		.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
193 		.mcs = {
194 			.rx_mask[0] = 0xFF,
195 			.rx_highest = __cpu_to_le16(0x41),
196 			.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
197 		},
198 	},
199 };
200 
201 static const unsigned long cw1200_ttl[] = {
202 	1 * HZ,	/* VO */
203 	2 * HZ,	/* VI */
204 	5 * HZ, /* BE */
205 	10 * HZ	/* BK */
206 };
207 
208 static const struct ieee80211_ops cw1200_ops = {
209 	.start			= cw1200_start,
210 	.stop			= cw1200_stop,
211 	.add_interface		= cw1200_add_interface,
212 	.remove_interface	= cw1200_remove_interface,
213 	.change_interface	= cw1200_change_interface,
214 	.tx			= cw1200_tx,
215 	.hw_scan		= cw1200_hw_scan,
216 	.set_tim		= cw1200_set_tim,
217 	.sta_notify		= cw1200_sta_notify,
218 	.sta_add		= cw1200_sta_add,
219 	.sta_remove		= cw1200_sta_remove,
220 	.set_key		= cw1200_set_key,
221 	.set_rts_threshold	= cw1200_set_rts_threshold,
222 	.config			= cw1200_config,
223 	.bss_info_changed	= cw1200_bss_info_changed,
224 	.prepare_multicast	= cw1200_prepare_multicast,
225 	.configure_filter	= cw1200_configure_filter,
226 	.conf_tx		= cw1200_conf_tx,
227 	.get_stats		= cw1200_get_stats,
228 	.ampdu_action		= cw1200_ampdu_action,
229 	.flush			= cw1200_flush,
230 #ifdef CONFIG_PM
231 	.suspend		= cw1200_wow_suspend,
232 	.resume			= cw1200_wow_resume,
233 #endif
234 	/* Intentionally not offloaded:					*/
235 	/*.channel_switch	= cw1200_channel_switch,		*/
236 	/*.remain_on_channel	= cw1200_remain_on_channel,		*/
237 	/*.cancel_remain_on_channel = cw1200_cancel_remain_on_channel,	*/
238 };
239 
240 static int cw1200_ba_rx_tids = -1;
241 static int cw1200_ba_tx_tids = -1;
242 module_param(cw1200_ba_rx_tids, int, 0644);
243 module_param(cw1200_ba_tx_tids, int, 0644);
244 MODULE_PARM_DESC(cw1200_ba_rx_tids, "Block ACK RX TIDs");
245 MODULE_PARM_DESC(cw1200_ba_tx_tids, "Block ACK TX TIDs");
246 
247 #ifdef CONFIG_PM
248 static const struct wiphy_wowlan_support cw1200_wowlan_support = {
249 	/* Support only for limited wowlan functionalities */
250 	.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT,
251 };
252 #endif
253 
254 
cw1200_init_common(const u8 * macaddr,const bool have_5ghz)255 static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
256 						const bool have_5ghz)
257 {
258 	int i, band;
259 	struct ieee80211_hw *hw;
260 	struct cw1200_common *priv;
261 
262 	hw = ieee80211_alloc_hw(sizeof(struct cw1200_common), &cw1200_ops);
263 	if (!hw)
264 		return NULL;
265 
266 	priv = hw->priv;
267 	priv->hw = hw;
268 	priv->hw_type = -1;
269 	priv->mode = NL80211_IFTYPE_UNSPECIFIED;
270 	priv->rates = cw1200_rates; /* TODO: fetch from FW */
271 	priv->mcs_rates = cw1200_n_rates;
272 	if (cw1200_ba_rx_tids != -1)
273 		priv->ba_rx_tid_mask = cw1200_ba_rx_tids;
274 	else
275 		priv->ba_rx_tid_mask = 0xFF; /* Enable RX BLKACK for all TIDs */
276 	if (cw1200_ba_tx_tids != -1)
277 		priv->ba_tx_tid_mask = cw1200_ba_tx_tids;
278 	else
279 		priv->ba_tx_tid_mask = 0xff; /* Enable TX BLKACK for all TIDs */
280 
281 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
282 		    IEEE80211_HW_SUPPORTS_PS |
283 		    IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
284 		    IEEE80211_HW_REPORTS_TX_ACK_STATUS |
285 		    IEEE80211_HW_SUPPORTS_UAPSD |
286 		    IEEE80211_HW_CONNECTION_MONITOR |
287 		    IEEE80211_HW_AMPDU_AGGREGATION |
288 		    IEEE80211_HW_TX_AMPDU_SETUP_IN_HW |
289 		    IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC;
290 
291 	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
292 					  BIT(NL80211_IFTYPE_ADHOC) |
293 					  BIT(NL80211_IFTYPE_AP) |
294 					  BIT(NL80211_IFTYPE_MESH_POINT) |
295 					  BIT(NL80211_IFTYPE_P2P_CLIENT) |
296 					  BIT(NL80211_IFTYPE_P2P_GO);
297 
298 #ifdef CONFIG_PM
299 	hw->wiphy->wowlan = &cw1200_wowlan_support;
300 #endif
301 
302 	hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
303 
304 	hw->queues = 4;
305 
306 	priv->rts_threshold = -1;
307 
308 	hw->max_rates = 8;
309 	hw->max_rate_tries = 15;
310 	hw->extra_tx_headroom = WSM_TX_EXTRA_HEADROOM +
311 		8;  /* TKIP IV */
312 
313 	hw->sta_data_size = sizeof(struct cw1200_sta_priv);
314 
315 	hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &cw1200_band_2ghz;
316 	if (have_5ghz)
317 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &cw1200_band_5ghz;
318 
319 	/* Channel params have to be cleared before registering wiphy again */
320 	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
321 		struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
322 		if (!sband)
323 			continue;
324 		for (i = 0; i < sband->n_channels; i++) {
325 			sband->channels[i].flags = 0;
326 			sband->channels[i].max_antenna_gain = 0;
327 			sband->channels[i].max_power = 30;
328 		}
329 	}
330 
331 	hw->wiphy->max_scan_ssids = 2;
332 	hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
333 
334 	if (macaddr)
335 		SET_IEEE80211_PERM_ADDR(hw, (u8 *)macaddr);
336 	else
337 		SET_IEEE80211_PERM_ADDR(hw, cw1200_mac_template);
338 
339 	/* Fix up mac address if necessary */
340 	if (hw->wiphy->perm_addr[3] == 0 &&
341 	    hw->wiphy->perm_addr[4] == 0 &&
342 	    hw->wiphy->perm_addr[5] == 0) {
343 		get_random_bytes(&hw->wiphy->perm_addr[3], 3);
344 	}
345 
346 	mutex_init(&priv->wsm_cmd_mux);
347 	mutex_init(&priv->conf_mutex);
348 	priv->workqueue = create_singlethread_workqueue("cw1200_wq");
349 	sema_init(&priv->scan.lock, 1);
350 	INIT_WORK(&priv->scan.work, cw1200_scan_work);
351 	INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work);
352 	INIT_DELAYED_WORK(&priv->scan.timeout, cw1200_scan_timeout);
353 	INIT_DELAYED_WORK(&priv->clear_recent_scan_work,
354 			  cw1200_clear_recent_scan_work);
355 	INIT_DELAYED_WORK(&priv->join_timeout, cw1200_join_timeout);
356 	INIT_WORK(&priv->unjoin_work, cw1200_unjoin_work);
357 	INIT_WORK(&priv->join_complete_work, cw1200_join_complete_work);
358 	INIT_WORK(&priv->wep_key_work, cw1200_wep_key_work);
359 	INIT_WORK(&priv->tx_policy_upload_work, tx_policy_upload_work);
360 	spin_lock_init(&priv->event_queue_lock);
361 	INIT_LIST_HEAD(&priv->event_queue);
362 	INIT_WORK(&priv->event_handler, cw1200_event_handler);
363 	INIT_DELAYED_WORK(&priv->bss_loss_work, cw1200_bss_loss_work);
364 	INIT_WORK(&priv->bss_params_work, cw1200_bss_params_work);
365 	spin_lock_init(&priv->bss_loss_lock);
366 	spin_lock_init(&priv->ps_state_lock);
367 	INIT_WORK(&priv->set_cts_work, cw1200_set_cts_work);
368 	INIT_WORK(&priv->set_tim_work, cw1200_set_tim_work);
369 	INIT_WORK(&priv->multicast_start_work, cw1200_multicast_start_work);
370 	INIT_WORK(&priv->multicast_stop_work, cw1200_multicast_stop_work);
371 	INIT_WORK(&priv->link_id_work, cw1200_link_id_work);
372 	INIT_DELAYED_WORK(&priv->link_id_gc_work, cw1200_link_id_gc_work);
373 	INIT_WORK(&priv->linkid_reset_work, cw1200_link_id_reset);
374 	INIT_WORK(&priv->update_filtering_work, cw1200_update_filtering_work);
375 	INIT_WORK(&priv->set_beacon_wakeup_period_work,
376 		  cw1200_set_beacon_wakeup_period_work);
377 	init_timer(&priv->mcast_timeout);
378 	priv->mcast_timeout.data = (unsigned long)priv;
379 	priv->mcast_timeout.function = cw1200_mcast_timeout;
380 
381 	if (cw1200_queue_stats_init(&priv->tx_queue_stats,
382 				    CW1200_LINK_ID_MAX,
383 				    cw1200_skb_dtor,
384 				    priv)) {
385 		ieee80211_free_hw(hw);
386 		return NULL;
387 	}
388 
389 	for (i = 0; i < 4; ++i) {
390 		if (cw1200_queue_init(&priv->tx_queue[i],
391 				      &priv->tx_queue_stats, i, 16,
392 				      cw1200_ttl[i])) {
393 			for (; i > 0; i--)
394 				cw1200_queue_deinit(&priv->tx_queue[i - 1]);
395 			cw1200_queue_stats_deinit(&priv->tx_queue_stats);
396 			ieee80211_free_hw(hw);
397 			return NULL;
398 		}
399 	}
400 
401 	init_waitqueue_head(&priv->channel_switch_done);
402 	init_waitqueue_head(&priv->wsm_cmd_wq);
403 	init_waitqueue_head(&priv->wsm_startup_done);
404 	init_waitqueue_head(&priv->ps_mode_switch_done);
405 	wsm_buf_init(&priv->wsm_cmd_buf);
406 	spin_lock_init(&priv->wsm_cmd.lock);
407 	priv->wsm_cmd.done = 1;
408 	tx_policy_init(priv);
409 
410 	return hw;
411 }
412 
cw1200_register_common(struct ieee80211_hw * dev)413 static int cw1200_register_common(struct ieee80211_hw *dev)
414 {
415 	struct cw1200_common *priv = dev->priv;
416 	int err;
417 
418 #ifdef CONFIG_PM
419 	err = cw1200_pm_init(&priv->pm_state, priv);
420 	if (err) {
421 		pr_err("Cannot init PM. (%d).\n",
422 		       err);
423 		return err;
424 	}
425 #endif
426 
427 	err = ieee80211_register_hw(dev);
428 	if (err) {
429 		pr_err("Cannot register device (%d).\n",
430 		       err);
431 #ifdef CONFIG_PM
432 		cw1200_pm_deinit(&priv->pm_state);
433 #endif
434 		return err;
435 	}
436 
437 	cw1200_debug_init(priv);
438 
439 	pr_info("Registered as '%s'\n", wiphy_name(dev->wiphy));
440 	return 0;
441 }
442 
cw1200_free_common(struct ieee80211_hw * dev)443 static void cw1200_free_common(struct ieee80211_hw *dev)
444 {
445 	ieee80211_free_hw(dev);
446 }
447 
cw1200_unregister_common(struct ieee80211_hw * dev)448 static void cw1200_unregister_common(struct ieee80211_hw *dev)
449 {
450 	struct cw1200_common *priv = dev->priv;
451 	int i;
452 
453 	ieee80211_unregister_hw(dev);
454 
455 	del_timer_sync(&priv->mcast_timeout);
456 	cw1200_unregister_bh(priv);
457 
458 	cw1200_debug_release(priv);
459 
460 	mutex_destroy(&priv->conf_mutex);
461 
462 	wsm_buf_deinit(&priv->wsm_cmd_buf);
463 
464 	destroy_workqueue(priv->workqueue);
465 	priv->workqueue = NULL;
466 
467 	if (priv->sdd) {
468 		release_firmware(priv->sdd);
469 		priv->sdd = NULL;
470 	}
471 
472 	for (i = 0; i < 4; ++i)
473 		cw1200_queue_deinit(&priv->tx_queue[i]);
474 
475 	cw1200_queue_stats_deinit(&priv->tx_queue_stats);
476 #ifdef CONFIG_PM
477 	cw1200_pm_deinit(&priv->pm_state);
478 #endif
479 }
480 
481 /* Clock is in KHz */
cw1200_dpll_from_clk(u16 clk_khz)482 u32 cw1200_dpll_from_clk(u16 clk_khz)
483 {
484 	switch (clk_khz) {
485 	case 0x32C8: /* 13000 KHz */
486 		return 0x1D89D241;
487 	case 0x3E80: /* 16000 KHz */
488 		return 0x000001E1;
489 	case 0x41A0: /* 16800 KHz */
490 		return 0x124931C1;
491 	case 0x4B00: /* 19200 KHz */
492 		return 0x00000191;
493 	case 0x5DC0: /* 24000 KHz */
494 		return 0x00000141;
495 	case 0x6590: /* 26000 KHz */
496 		return 0x0EC4F121;
497 	case 0x8340: /* 33600 KHz */
498 		return 0x092490E1;
499 	case 0x9600: /* 38400 KHz */
500 		return 0x100010C1;
501 	case 0x9C40: /* 40000 KHz */
502 		return 0x000000C1;
503 	case 0xBB80: /* 48000 KHz */
504 		return 0x000000A1;
505 	case 0xCB20: /* 52000 KHz */
506 		return 0x07627091;
507 	default:
508 		pr_err("Unknown Refclk freq (0x%04x), using 26000KHz\n",
509 		       clk_khz);
510 		return 0x0EC4F121;
511 	}
512 }
513 
cw1200_core_probe(const struct hwbus_ops * hwbus_ops,struct hwbus_priv * hwbus,struct device * pdev,struct cw1200_common ** core,int ref_clk,const u8 * macaddr,const char * sdd_path,bool have_5ghz)514 int cw1200_core_probe(const struct hwbus_ops *hwbus_ops,
515 		      struct hwbus_priv *hwbus,
516 		      struct device *pdev,
517 		      struct cw1200_common **core,
518 		      int ref_clk, const u8 *macaddr,
519 		      const char *sdd_path, bool have_5ghz)
520 {
521 	int err = -EINVAL;
522 	struct ieee80211_hw *dev;
523 	struct cw1200_common *priv;
524 	struct wsm_operational_mode mode = {
525 		.power_mode = cw1200_power_mode,
526 		.disable_more_flag_usage = true,
527 	};
528 
529 	dev = cw1200_init_common(macaddr, have_5ghz);
530 	if (!dev)
531 		goto err;
532 
533 	priv = dev->priv;
534 	priv->hw_refclk = ref_clk;
535 	if (cw1200_refclk)
536 		priv->hw_refclk = cw1200_refclk;
537 
538 	priv->sdd_path = (char *)sdd_path;
539 	if (cw1200_sdd_path)
540 		priv->sdd_path = cw1200_sdd_path;
541 
542 	priv->hwbus_ops = hwbus_ops;
543 	priv->hwbus_priv = hwbus;
544 	priv->pdev = pdev;
545 	SET_IEEE80211_DEV(priv->hw, pdev);
546 
547 	/* Pass struct cw1200_common back up */
548 	*core = priv;
549 
550 	err = cw1200_register_bh(priv);
551 	if (err)
552 		goto err1;
553 
554 	err = cw1200_load_firmware(priv);
555 	if (err)
556 		goto err2;
557 
558 	if (wait_event_interruptible_timeout(priv->wsm_startup_done,
559 					     priv->firmware_ready,
560 					     3*HZ) <= 0) {
561 		/* TODO: Need to find how to reset device
562 		   in QUEUE mode properly.
563 		*/
564 		pr_err("Timeout waiting on device startup\n");
565 		err = -ETIMEDOUT;
566 		goto err2;
567 	}
568 
569 	/* Set low-power mode. */
570 	wsm_set_operational_mode(priv, &mode);
571 
572 	/* Enable multi-TX confirmation */
573 	wsm_use_multi_tx_conf(priv, true);
574 
575 	err = cw1200_register_common(dev);
576 	if (err)
577 		goto err2;
578 
579 	return err;
580 
581 err2:
582 	cw1200_unregister_bh(priv);
583 err1:
584 	cw1200_free_common(dev);
585 err:
586 	*core = NULL;
587 	return err;
588 }
589 EXPORT_SYMBOL_GPL(cw1200_core_probe);
590 
cw1200_core_release(struct cw1200_common * self)591 void cw1200_core_release(struct cw1200_common *self)
592 {
593 	/* Disable device interrupts */
594 	self->hwbus_ops->lock(self->hwbus_priv);
595 	__cw1200_irq_enable(self, 0);
596 	self->hwbus_ops->unlock(self->hwbus_priv);
597 
598 	/* And then clean up */
599 	cw1200_unregister_common(self->hw);
600 	cw1200_free_common(self->hw);
601 	return;
602 }
603 EXPORT_SYMBOL_GPL(cw1200_core_release);
604