• 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 	ieee80211_hw_set(hw, NEED_DTIM_BEFORE_ASSOC);
282 	ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
283 	ieee80211_hw_set(hw, AMPDU_AGGREGATION);
284 	ieee80211_hw_set(hw, CONNECTION_MONITOR);
285 	ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
286 	ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
287 	ieee80211_hw_set(hw, SIGNAL_DBM);
288 	ieee80211_hw_set(hw, SUPPORTS_PS);
289 
290 	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
291 					  BIT(NL80211_IFTYPE_ADHOC) |
292 					  BIT(NL80211_IFTYPE_AP) |
293 					  BIT(NL80211_IFTYPE_MESH_POINT) |
294 					  BIT(NL80211_IFTYPE_P2P_CLIENT) |
295 					  BIT(NL80211_IFTYPE_P2P_GO);
296 
297 #ifdef CONFIG_PM
298 	hw->wiphy->wowlan = &cw1200_wowlan_support;
299 #endif
300 
301 	hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
302 
303 	hw->queues = 4;
304 
305 	priv->rts_threshold = -1;
306 
307 	hw->max_rates = 8;
308 	hw->max_rate_tries = 15;
309 	hw->extra_tx_headroom = WSM_TX_EXTRA_HEADROOM +
310 		8;  /* TKIP IV */
311 
312 	hw->sta_data_size = sizeof(struct cw1200_sta_priv);
313 
314 	hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &cw1200_band_2ghz;
315 	if (have_5ghz)
316 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &cw1200_band_5ghz;
317 
318 	/* Channel params have to be cleared before registering wiphy again */
319 	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
320 		struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
321 		if (!sband)
322 			continue;
323 		for (i = 0; i < sband->n_channels; i++) {
324 			sband->channels[i].flags = 0;
325 			sband->channels[i].max_antenna_gain = 0;
326 			sband->channels[i].max_power = 30;
327 		}
328 	}
329 
330 	hw->wiphy->max_scan_ssids = 2;
331 	hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
332 
333 	if (macaddr)
334 		SET_IEEE80211_PERM_ADDR(hw, (u8 *)macaddr);
335 	else
336 		SET_IEEE80211_PERM_ADDR(hw, cw1200_mac_template);
337 
338 	/* Fix up mac address if necessary */
339 	if (hw->wiphy->perm_addr[3] == 0 &&
340 	    hw->wiphy->perm_addr[4] == 0 &&
341 	    hw->wiphy->perm_addr[5] == 0) {
342 		get_random_bytes(&hw->wiphy->perm_addr[3], 3);
343 	}
344 
345 	mutex_init(&priv->wsm_cmd_mux);
346 	mutex_init(&priv->conf_mutex);
347 	priv->workqueue = create_singlethread_workqueue("cw1200_wq");
348 	if (!priv->workqueue) {
349 		ieee80211_free_hw(hw);
350 		return NULL;
351 	}
352 
353 	sema_init(&priv->scan.lock, 1);
354 	INIT_WORK(&priv->scan.work, cw1200_scan_work);
355 	INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work);
356 	INIT_DELAYED_WORK(&priv->scan.timeout, cw1200_scan_timeout);
357 	INIT_DELAYED_WORK(&priv->clear_recent_scan_work,
358 			  cw1200_clear_recent_scan_work);
359 	INIT_DELAYED_WORK(&priv->join_timeout, cw1200_join_timeout);
360 	INIT_WORK(&priv->unjoin_work, cw1200_unjoin_work);
361 	INIT_WORK(&priv->join_complete_work, cw1200_join_complete_work);
362 	INIT_WORK(&priv->wep_key_work, cw1200_wep_key_work);
363 	INIT_WORK(&priv->tx_policy_upload_work, tx_policy_upload_work);
364 	spin_lock_init(&priv->event_queue_lock);
365 	INIT_LIST_HEAD(&priv->event_queue);
366 	INIT_WORK(&priv->event_handler, cw1200_event_handler);
367 	INIT_DELAYED_WORK(&priv->bss_loss_work, cw1200_bss_loss_work);
368 	INIT_WORK(&priv->bss_params_work, cw1200_bss_params_work);
369 	spin_lock_init(&priv->bss_loss_lock);
370 	spin_lock_init(&priv->ps_state_lock);
371 	INIT_WORK(&priv->set_cts_work, cw1200_set_cts_work);
372 	INIT_WORK(&priv->set_tim_work, cw1200_set_tim_work);
373 	INIT_WORK(&priv->multicast_start_work, cw1200_multicast_start_work);
374 	INIT_WORK(&priv->multicast_stop_work, cw1200_multicast_stop_work);
375 	INIT_WORK(&priv->link_id_work, cw1200_link_id_work);
376 	INIT_DELAYED_WORK(&priv->link_id_gc_work, cw1200_link_id_gc_work);
377 	INIT_WORK(&priv->linkid_reset_work, cw1200_link_id_reset);
378 	INIT_WORK(&priv->update_filtering_work, cw1200_update_filtering_work);
379 	INIT_WORK(&priv->set_beacon_wakeup_period_work,
380 		  cw1200_set_beacon_wakeup_period_work);
381 	setup_timer(&priv->mcast_timeout, cw1200_mcast_timeout,
382 		    (unsigned long)priv);
383 
384 	if (cw1200_queue_stats_init(&priv->tx_queue_stats,
385 				    CW1200_LINK_ID_MAX,
386 				    cw1200_skb_dtor,
387 				    priv)) {
388 		destroy_workqueue(priv->workqueue);
389 		ieee80211_free_hw(hw);
390 		return NULL;
391 	}
392 
393 	for (i = 0; i < 4; ++i) {
394 		if (cw1200_queue_init(&priv->tx_queue[i],
395 				      &priv->tx_queue_stats, i, 16,
396 				      cw1200_ttl[i])) {
397 			for (; i > 0; i--)
398 				cw1200_queue_deinit(&priv->tx_queue[i - 1]);
399 			cw1200_queue_stats_deinit(&priv->tx_queue_stats);
400 			destroy_workqueue(priv->workqueue);
401 			ieee80211_free_hw(hw);
402 			return NULL;
403 		}
404 	}
405 
406 	init_waitqueue_head(&priv->channel_switch_done);
407 	init_waitqueue_head(&priv->wsm_cmd_wq);
408 	init_waitqueue_head(&priv->wsm_startup_done);
409 	init_waitqueue_head(&priv->ps_mode_switch_done);
410 	wsm_buf_init(&priv->wsm_cmd_buf);
411 	spin_lock_init(&priv->wsm_cmd.lock);
412 	priv->wsm_cmd.done = 1;
413 	tx_policy_init(priv);
414 
415 	return hw;
416 }
417 
cw1200_register_common(struct ieee80211_hw * dev)418 static int cw1200_register_common(struct ieee80211_hw *dev)
419 {
420 	struct cw1200_common *priv = dev->priv;
421 	int err;
422 
423 #ifdef CONFIG_PM
424 	err = cw1200_pm_init(&priv->pm_state, priv);
425 	if (err) {
426 		pr_err("Cannot init PM. (%d).\n",
427 		       err);
428 		return err;
429 	}
430 #endif
431 
432 	err = ieee80211_register_hw(dev);
433 	if (err) {
434 		pr_err("Cannot register device (%d).\n",
435 		       err);
436 #ifdef CONFIG_PM
437 		cw1200_pm_deinit(&priv->pm_state);
438 #endif
439 		return err;
440 	}
441 
442 	cw1200_debug_init(priv);
443 
444 	pr_info("Registered as '%s'\n", wiphy_name(dev->wiphy));
445 	return 0;
446 }
447 
cw1200_free_common(struct ieee80211_hw * dev)448 static void cw1200_free_common(struct ieee80211_hw *dev)
449 {
450 	ieee80211_free_hw(dev);
451 }
452 
cw1200_unregister_common(struct ieee80211_hw * dev)453 static void cw1200_unregister_common(struct ieee80211_hw *dev)
454 {
455 	struct cw1200_common *priv = dev->priv;
456 	int i;
457 
458 	ieee80211_unregister_hw(dev);
459 
460 	del_timer_sync(&priv->mcast_timeout);
461 	cw1200_unregister_bh(priv);
462 
463 	cw1200_debug_release(priv);
464 
465 	mutex_destroy(&priv->conf_mutex);
466 
467 	wsm_buf_deinit(&priv->wsm_cmd_buf);
468 
469 	destroy_workqueue(priv->workqueue);
470 	priv->workqueue = NULL;
471 
472 	if (priv->sdd) {
473 		release_firmware(priv->sdd);
474 		priv->sdd = NULL;
475 	}
476 
477 	for (i = 0; i < 4; ++i)
478 		cw1200_queue_deinit(&priv->tx_queue[i]);
479 
480 	cw1200_queue_stats_deinit(&priv->tx_queue_stats);
481 #ifdef CONFIG_PM
482 	cw1200_pm_deinit(&priv->pm_state);
483 #endif
484 }
485 
486 /* Clock is in KHz */
cw1200_dpll_from_clk(u16 clk_khz)487 u32 cw1200_dpll_from_clk(u16 clk_khz)
488 {
489 	switch (clk_khz) {
490 	case 0x32C8: /* 13000 KHz */
491 		return 0x1D89D241;
492 	case 0x3E80: /* 16000 KHz */
493 		return 0x000001E1;
494 	case 0x41A0: /* 16800 KHz */
495 		return 0x124931C1;
496 	case 0x4B00: /* 19200 KHz */
497 		return 0x00000191;
498 	case 0x5DC0: /* 24000 KHz */
499 		return 0x00000141;
500 	case 0x6590: /* 26000 KHz */
501 		return 0x0EC4F121;
502 	case 0x8340: /* 33600 KHz */
503 		return 0x092490E1;
504 	case 0x9600: /* 38400 KHz */
505 		return 0x100010C1;
506 	case 0x9C40: /* 40000 KHz */
507 		return 0x000000C1;
508 	case 0xBB80: /* 48000 KHz */
509 		return 0x000000A1;
510 	case 0xCB20: /* 52000 KHz */
511 		return 0x07627091;
512 	default:
513 		pr_err("Unknown Refclk freq (0x%04x), using 26000KHz\n",
514 		       clk_khz);
515 		return 0x0EC4F121;
516 	}
517 }
518 
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)519 int cw1200_core_probe(const struct hwbus_ops *hwbus_ops,
520 		      struct hwbus_priv *hwbus,
521 		      struct device *pdev,
522 		      struct cw1200_common **core,
523 		      int ref_clk, const u8 *macaddr,
524 		      const char *sdd_path, bool have_5ghz)
525 {
526 	int err = -EINVAL;
527 	struct ieee80211_hw *dev;
528 	struct cw1200_common *priv;
529 	struct wsm_operational_mode mode = {
530 		.power_mode = cw1200_power_mode,
531 		.disable_more_flag_usage = true,
532 	};
533 
534 	dev = cw1200_init_common(macaddr, have_5ghz);
535 	if (!dev)
536 		goto err;
537 
538 	priv = dev->priv;
539 	priv->hw_refclk = ref_clk;
540 	if (cw1200_refclk)
541 		priv->hw_refclk = cw1200_refclk;
542 
543 	priv->sdd_path = (char *)sdd_path;
544 	if (cw1200_sdd_path)
545 		priv->sdd_path = cw1200_sdd_path;
546 
547 	priv->hwbus_ops = hwbus_ops;
548 	priv->hwbus_priv = hwbus;
549 	priv->pdev = pdev;
550 	SET_IEEE80211_DEV(priv->hw, pdev);
551 
552 	/* Pass struct cw1200_common back up */
553 	*core = priv;
554 
555 	err = cw1200_register_bh(priv);
556 	if (err)
557 		goto err1;
558 
559 	err = cw1200_load_firmware(priv);
560 	if (err)
561 		goto err2;
562 
563 	if (wait_event_interruptible_timeout(priv->wsm_startup_done,
564 					     priv->firmware_ready,
565 					     3*HZ) <= 0) {
566 		/* TODO: Need to find how to reset device
567 		   in QUEUE mode properly.
568 		*/
569 		pr_err("Timeout waiting on device startup\n");
570 		err = -ETIMEDOUT;
571 		goto err2;
572 	}
573 
574 	/* Set low-power mode. */
575 	wsm_set_operational_mode(priv, &mode);
576 
577 	/* Enable multi-TX confirmation */
578 	wsm_use_multi_tx_conf(priv, true);
579 
580 	err = cw1200_register_common(dev);
581 	if (err)
582 		goto err2;
583 
584 	return err;
585 
586 err2:
587 	cw1200_unregister_bh(priv);
588 err1:
589 	cw1200_free_common(dev);
590 err:
591 	*core = NULL;
592 	return err;
593 }
594 EXPORT_SYMBOL_GPL(cw1200_core_probe);
595 
cw1200_core_release(struct cw1200_common * self)596 void cw1200_core_release(struct cw1200_common *self)
597 {
598 	/* Disable device interrupts */
599 	self->hwbus_ops->lock(self->hwbus_priv);
600 	__cw1200_irq_enable(self, 0);
601 	self->hwbus_ops->unlock(self->hwbus_priv);
602 
603 	/* And then clean up */
604 	cw1200_unregister_common(self->hw);
605 	cw1200_free_common(self->hw);
606 	return;
607 }
608 EXPORT_SYMBOL_GPL(cw1200_core_release);
609