xref: /openbmc/linux/drivers/net/wireless/st/cw1200/main.c (revision 7effbd18)
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 	.wake_tx_queue		= ieee80211_handle_wake_tx_queue,
213 	.hw_scan		= cw1200_hw_scan,
214 	.set_tim		= cw1200_set_tim,
215 	.sta_notify		= cw1200_sta_notify,
216 	.sta_add		= cw1200_sta_add,
217 	.sta_remove		= cw1200_sta_remove,
218 	.set_key		= cw1200_set_key,
219 	.set_rts_threshold	= cw1200_set_rts_threshold,
220 	.config			= cw1200_config,
221 	.bss_info_changed	= cw1200_bss_info_changed,
222 	.prepare_multicast	= cw1200_prepare_multicast,
223 	.configure_filter	= cw1200_configure_filter,
224 	.conf_tx		= cw1200_conf_tx,
225 	.get_stats		= cw1200_get_stats,
226 	.ampdu_action		= cw1200_ampdu_action,
227 	.flush			= cw1200_flush,
228 #ifdef CONFIG_PM
229 	.suspend		= cw1200_wow_suspend,
230 	.resume			= cw1200_wow_resume,
231 #endif
232 	/* Intentionally not offloaded:					*/
233 	/*.channel_switch	= cw1200_channel_switch,		*/
234 	/*.remain_on_channel	= cw1200_remain_on_channel,		*/
235 	/*.cancel_remain_on_channel = cw1200_cancel_remain_on_channel,	*/
236 };
237 
238 static int cw1200_ba_rx_tids = -1;
239 static int cw1200_ba_tx_tids = -1;
240 module_param(cw1200_ba_rx_tids, int, 0644);
241 module_param(cw1200_ba_tx_tids, int, 0644);
242 MODULE_PARM_DESC(cw1200_ba_rx_tids, "Block ACK RX TIDs");
243 MODULE_PARM_DESC(cw1200_ba_tx_tids, "Block ACK TX TIDs");
244 
245 #ifdef CONFIG_PM
246 static const struct wiphy_wowlan_support cw1200_wowlan_support = {
247 	/* Support only for limited wowlan functionalities */
248 	.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT,
249 };
250 #endif
251 
252 
253 static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
254 						const bool have_5ghz)
255 {
256 	int i, band;
257 	struct ieee80211_hw *hw;
258 	struct cw1200_common *priv;
259 
260 	hw = ieee80211_alloc_hw(sizeof(struct cw1200_common), &cw1200_ops);
261 	if (!hw)
262 		return NULL;
263 
264 	priv = hw->priv;
265 	priv->hw = hw;
266 	priv->hw_type = -1;
267 	priv->mode = NL80211_IFTYPE_UNSPECIFIED;
268 	priv->rates = cw1200_rates; /* TODO: fetch from FW */
269 	priv->mcs_rates = cw1200_n_rates;
270 	if (cw1200_ba_rx_tids != -1)
271 		priv->ba_rx_tid_mask = cw1200_ba_rx_tids;
272 	else
273 		priv->ba_rx_tid_mask = 0xFF; /* Enable RX BLKACK for all TIDs */
274 	if (cw1200_ba_tx_tids != -1)
275 		priv->ba_tx_tid_mask = cw1200_ba_tx_tids;
276 	else
277 		priv->ba_tx_tid_mask = 0xff; /* Enable TX BLKACK for all TIDs */
278 
279 	ieee80211_hw_set(hw, NEED_DTIM_BEFORE_ASSOC);
280 	ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
281 	ieee80211_hw_set(hw, AMPDU_AGGREGATION);
282 	ieee80211_hw_set(hw, CONNECTION_MONITOR);
283 	ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
284 	ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
285 	ieee80211_hw_set(hw, SIGNAL_DBM);
286 	ieee80211_hw_set(hw, SUPPORTS_PS);
287 
288 	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
289 					  BIT(NL80211_IFTYPE_ADHOC) |
290 					  BIT(NL80211_IFTYPE_AP) |
291 					  BIT(NL80211_IFTYPE_MESH_POINT) |
292 					  BIT(NL80211_IFTYPE_P2P_CLIENT) |
293 					  BIT(NL80211_IFTYPE_P2P_GO);
294 
295 #ifdef CONFIG_PM
296 	hw->wiphy->wowlan = &cw1200_wowlan_support;
297 #endif
298 
299 	hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
300 
301 	hw->queues = 4;
302 
303 	priv->rts_threshold = -1;
304 
305 	hw->max_rates = 8;
306 	hw->max_rate_tries = 15;
307 	hw->extra_tx_headroom = WSM_TX_EXTRA_HEADROOM +
308 		8;  /* TKIP IV */
309 
310 	hw->sta_data_size = sizeof(struct cw1200_sta_priv);
311 
312 	hw->wiphy->bands[NL80211_BAND_2GHZ] = &cw1200_band_2ghz;
313 	if (have_5ghz)
314 		hw->wiphy->bands[NL80211_BAND_5GHZ] = &cw1200_band_5ghz;
315 
316 	/* Channel params have to be cleared before registering wiphy again */
317 	for (band = 0; band < NUM_NL80211_BANDS; band++) {
318 		struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
319 		if (!sband)
320 			continue;
321 		for (i = 0; i < sband->n_channels; i++) {
322 			sband->channels[i].flags = 0;
323 			sband->channels[i].max_antenna_gain = 0;
324 			sband->channels[i].max_power = 30;
325 		}
326 	}
327 
328 	hw->wiphy->max_scan_ssids = 2;
329 	hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
330 
331 	if (macaddr)
332 		SET_IEEE80211_PERM_ADDR(hw, (u8 *)macaddr);
333 	else
334 		SET_IEEE80211_PERM_ADDR(hw, cw1200_mac_template);
335 
336 	/* Fix up mac address if necessary */
337 	if (hw->wiphy->perm_addr[3] == 0 &&
338 	    hw->wiphy->perm_addr[4] == 0 &&
339 	    hw->wiphy->perm_addr[5] == 0) {
340 		get_random_bytes(&hw->wiphy->perm_addr[3], 3);
341 	}
342 
343 	mutex_init(&priv->wsm_cmd_mux);
344 	mutex_init(&priv->conf_mutex);
345 	priv->workqueue = create_singlethread_workqueue("cw1200_wq");
346 	if (!priv->workqueue) {
347 		ieee80211_free_hw(hw);
348 		return NULL;
349 	}
350 
351 	sema_init(&priv->scan.lock, 1);
352 	INIT_WORK(&priv->scan.work, cw1200_scan_work);
353 	INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work);
354 	INIT_DELAYED_WORK(&priv->scan.timeout, cw1200_scan_timeout);
355 	INIT_DELAYED_WORK(&priv->clear_recent_scan_work,
356 			  cw1200_clear_recent_scan_work);
357 	INIT_DELAYED_WORK(&priv->join_timeout, cw1200_join_timeout);
358 	INIT_WORK(&priv->unjoin_work, cw1200_unjoin_work);
359 	INIT_WORK(&priv->join_complete_work, cw1200_join_complete_work);
360 	INIT_WORK(&priv->wep_key_work, cw1200_wep_key_work);
361 	INIT_WORK(&priv->tx_policy_upload_work, tx_policy_upload_work);
362 	spin_lock_init(&priv->event_queue_lock);
363 	INIT_LIST_HEAD(&priv->event_queue);
364 	INIT_WORK(&priv->event_handler, cw1200_event_handler);
365 	INIT_DELAYED_WORK(&priv->bss_loss_work, cw1200_bss_loss_work);
366 	INIT_WORK(&priv->bss_params_work, cw1200_bss_params_work);
367 	spin_lock_init(&priv->bss_loss_lock);
368 	spin_lock_init(&priv->ps_state_lock);
369 	INIT_WORK(&priv->set_cts_work, cw1200_set_cts_work);
370 	INIT_WORK(&priv->set_tim_work, cw1200_set_tim_work);
371 	INIT_WORK(&priv->multicast_start_work, cw1200_multicast_start_work);
372 	INIT_WORK(&priv->multicast_stop_work, cw1200_multicast_stop_work);
373 	INIT_WORK(&priv->link_id_work, cw1200_link_id_work);
374 	INIT_DELAYED_WORK(&priv->link_id_gc_work, cw1200_link_id_gc_work);
375 	INIT_WORK(&priv->linkid_reset_work, cw1200_link_id_reset);
376 	INIT_WORK(&priv->update_filtering_work, cw1200_update_filtering_work);
377 	INIT_WORK(&priv->set_beacon_wakeup_period_work,
378 		  cw1200_set_beacon_wakeup_period_work);
379 	timer_setup(&priv->mcast_timeout, cw1200_mcast_timeout, 0);
380 
381 	if (cw1200_queue_stats_init(&priv->tx_queue_stats,
382 				    CW1200_LINK_ID_MAX,
383 				    cw1200_skb_dtor,
384 				    priv)) {
385 		destroy_workqueue(priv->workqueue);
386 		ieee80211_free_hw(hw);
387 		return NULL;
388 	}
389 
390 	for (i = 0; i < 4; ++i) {
391 		if (cw1200_queue_init(&priv->tx_queue[i],
392 				      &priv->tx_queue_stats, i, 16,
393 				      cw1200_ttl[i])) {
394 			for (; i > 0; i--)
395 				cw1200_queue_deinit(&priv->tx_queue[i - 1]);
396 			cw1200_queue_stats_deinit(&priv->tx_queue_stats);
397 			destroy_workqueue(priv->workqueue);
398 			ieee80211_free_hw(hw);
399 			return NULL;
400 		}
401 	}
402 
403 	init_waitqueue_head(&priv->channel_switch_done);
404 	init_waitqueue_head(&priv->wsm_cmd_wq);
405 	init_waitqueue_head(&priv->wsm_startup_done);
406 	init_waitqueue_head(&priv->ps_mode_switch_done);
407 	wsm_buf_init(&priv->wsm_cmd_buf);
408 	spin_lock_init(&priv->wsm_cmd.lock);
409 	priv->wsm_cmd.done = 1;
410 	tx_policy_init(priv);
411 
412 	return hw;
413 }
414 
415 static int cw1200_register_common(struct ieee80211_hw *dev)
416 {
417 	struct cw1200_common *priv = dev->priv;
418 	int err;
419 
420 #ifdef CONFIG_PM
421 	err = cw1200_pm_init(&priv->pm_state, priv);
422 	if (err) {
423 		pr_err("Cannot init PM. (%d).\n",
424 		       err);
425 		return err;
426 	}
427 #endif
428 
429 	err = ieee80211_register_hw(dev);
430 	if (err) {
431 		pr_err("Cannot register device (%d).\n",
432 		       err);
433 #ifdef CONFIG_PM
434 		cw1200_pm_deinit(&priv->pm_state);
435 #endif
436 		return err;
437 	}
438 
439 	cw1200_debug_init(priv);
440 
441 	pr_info("Registered as '%s'\n", wiphy_name(dev->wiphy));
442 	return 0;
443 }
444 
445 static void cw1200_free_common(struct ieee80211_hw *dev)
446 {
447 	ieee80211_free_hw(dev);
448 }
449 
450 static void cw1200_unregister_common(struct ieee80211_hw *dev)
451 {
452 	struct cw1200_common *priv = dev->priv;
453 	int i;
454 
455 	ieee80211_unregister_hw(dev);
456 
457 	del_timer_sync(&priv->mcast_timeout);
458 	cw1200_unregister_bh(priv);
459 
460 	cw1200_debug_release(priv);
461 
462 	mutex_destroy(&priv->conf_mutex);
463 
464 	wsm_buf_deinit(&priv->wsm_cmd_buf);
465 
466 	destroy_workqueue(priv->workqueue);
467 	priv->workqueue = NULL;
468 
469 	if (priv->sdd) {
470 		release_firmware(priv->sdd);
471 		priv->sdd = NULL;
472 	}
473 
474 	for (i = 0; i < 4; ++i)
475 		cw1200_queue_deinit(&priv->tx_queue[i]);
476 
477 	cw1200_queue_stats_deinit(&priv->tx_queue_stats);
478 #ifdef CONFIG_PM
479 	cw1200_pm_deinit(&priv->pm_state);
480 #endif
481 }
482 
483 /* Clock is in KHz */
484 u32 cw1200_dpll_from_clk(u16 clk_khz)
485 {
486 	switch (clk_khz) {
487 	case 0x32C8: /* 13000 KHz */
488 		return 0x1D89D241;
489 	case 0x3E80: /* 16000 KHz */
490 		return 0x000001E1;
491 	case 0x41A0: /* 16800 KHz */
492 		return 0x124931C1;
493 	case 0x4B00: /* 19200 KHz */
494 		return 0x00000191;
495 	case 0x5DC0: /* 24000 KHz */
496 		return 0x00000141;
497 	case 0x6590: /* 26000 KHz */
498 		return 0x0EC4F121;
499 	case 0x8340: /* 33600 KHz */
500 		return 0x092490E1;
501 	case 0x9600: /* 38400 KHz */
502 		return 0x100010C1;
503 	case 0x9C40: /* 40000 KHz */
504 		return 0x000000C1;
505 	case 0xBB80: /* 48000 KHz */
506 		return 0x000000A1;
507 	case 0xCB20: /* 52000 KHz */
508 		return 0x07627091;
509 	default:
510 		pr_err("Unknown Refclk freq (0x%04x), using 26000KHz\n",
511 		       clk_khz);
512 		return 0x0EC4F121;
513 	}
514 }
515 
516 int cw1200_core_probe(const struct hwbus_ops *hwbus_ops,
517 		      struct hwbus_priv *hwbus,
518 		      struct device *pdev,
519 		      struct cw1200_common **core,
520 		      int ref_clk, const u8 *macaddr,
521 		      const char *sdd_path, bool have_5ghz)
522 {
523 	int err = -EINVAL;
524 	struct ieee80211_hw *dev;
525 	struct cw1200_common *priv;
526 	struct wsm_operational_mode mode = {
527 		.power_mode = cw1200_power_mode,
528 		.disable_more_flag_usage = true,
529 	};
530 
531 	dev = cw1200_init_common(macaddr, have_5ghz);
532 	if (!dev)
533 		goto err;
534 
535 	priv = dev->priv;
536 	priv->hw_refclk = ref_clk;
537 	if (cw1200_refclk)
538 		priv->hw_refclk = cw1200_refclk;
539 
540 	priv->sdd_path = (char *)sdd_path;
541 	if (cw1200_sdd_path)
542 		priv->sdd_path = cw1200_sdd_path;
543 
544 	priv->hwbus_ops = hwbus_ops;
545 	priv->hwbus_priv = hwbus;
546 	priv->pdev = pdev;
547 	SET_IEEE80211_DEV(priv->hw, pdev);
548 
549 	/* Pass struct cw1200_common back up */
550 	*core = priv;
551 
552 	err = cw1200_register_bh(priv);
553 	if (err)
554 		goto err1;
555 
556 	err = cw1200_load_firmware(priv);
557 	if (err)
558 		goto err2;
559 
560 	if (wait_event_interruptible_timeout(priv->wsm_startup_done,
561 					     priv->firmware_ready,
562 					     3*HZ) <= 0) {
563 		/* TODO: Need to find how to reset device
564 		   in QUEUE mode properly.
565 		*/
566 		pr_err("Timeout waiting on device startup\n");
567 		err = -ETIMEDOUT;
568 		goto err2;
569 	}
570 
571 	/* Set low-power mode. */
572 	wsm_set_operational_mode(priv, &mode);
573 
574 	/* Enable multi-TX confirmation */
575 	wsm_use_multi_tx_conf(priv, true);
576 
577 	err = cw1200_register_common(dev);
578 	if (err)
579 		goto err2;
580 
581 	return err;
582 
583 err2:
584 	cw1200_unregister_bh(priv);
585 err1:
586 	cw1200_free_common(dev);
587 err:
588 	*core = NULL;
589 	return err;
590 }
591 EXPORT_SYMBOL_GPL(cw1200_core_probe);
592 
593 void cw1200_core_release(struct cw1200_common *self)
594 {
595 	/* Disable device interrupts */
596 	self->hwbus_ops->lock(self->hwbus_priv);
597 	__cw1200_irq_enable(self, 0);
598 	self->hwbus_ops->unlock(self->hwbus_priv);
599 
600 	/* And then clean up */
601 	cw1200_unregister_common(self->hw);
602 	cw1200_free_common(self->hw);
603 	return;
604 }
605 EXPORT_SYMBOL_GPL(cw1200_core_release);
606