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