Linux Audio

Check our new training course

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