xref: /openbmc/linux/drivers/net/wireless/st/cw1200/main.c (revision e3dcf8bbeb0c58df475cad58e2dc267a5c02ae20)
1560424e9SKalle Valo /*
2560424e9SKalle Valo  * mac80211 glue code for mac80211 ST-Ericsson CW1200 drivers
3560424e9SKalle Valo  *
4560424e9SKalle Valo  * Copyright (c) 2010, ST-Ericsson
5560424e9SKalle Valo  * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
6560424e9SKalle Valo  *
7560424e9SKalle Valo  * Based on:
8560424e9SKalle Valo  * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
9560424e9SKalle Valo  * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
10560424e9SKalle Valo  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
11560424e9SKalle Valo  *
12560424e9SKalle Valo  * Based on:
13560424e9SKalle Valo  * - the islsm (softmac prism54) driver, which is:
14560424e9SKalle Valo  *   Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
15560424e9SKalle Valo  * - stlc45xx driver
16560424e9SKalle Valo  *   Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
17560424e9SKalle Valo  *
18560424e9SKalle Valo  * This program is free software; you can redistribute it and/or modify
19560424e9SKalle Valo  * it under the terms of the GNU General Public License version 2 as
20560424e9SKalle Valo  * published by the Free Software Foundation.
21560424e9SKalle Valo  */
22560424e9SKalle Valo 
23560424e9SKalle Valo #include <linux/module.h>
24560424e9SKalle Valo #include <linux/firmware.h>
25560424e9SKalle Valo #include <linux/etherdevice.h>
26560424e9SKalle Valo #include <linux/vmalloc.h>
27560424e9SKalle Valo #include <linux/random.h>
28560424e9SKalle Valo #include <linux/sched.h>
29560424e9SKalle Valo #include <net/mac80211.h>
30560424e9SKalle Valo 
31560424e9SKalle Valo #include "cw1200.h"
32560424e9SKalle Valo #include "txrx.h"
33560424e9SKalle Valo #include "hwbus.h"
34560424e9SKalle Valo #include "fwio.h"
35560424e9SKalle Valo #include "hwio.h"
36560424e9SKalle Valo #include "bh.h"
37560424e9SKalle Valo #include "sta.h"
38560424e9SKalle Valo #include "scan.h"
39560424e9SKalle Valo #include "debug.h"
40560424e9SKalle Valo #include "pm.h"
41560424e9SKalle Valo 
42560424e9SKalle Valo MODULE_AUTHOR("Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>");
43560424e9SKalle Valo MODULE_DESCRIPTION("Softmac ST-Ericsson CW1200 common code");
44560424e9SKalle Valo MODULE_LICENSE("GPL");
45560424e9SKalle Valo MODULE_ALIAS("cw1200_core");
46560424e9SKalle Valo 
47560424e9SKalle Valo /* Accept MAC address of the form macaddr=0x00,0x80,0xE1,0x30,0x40,0x50 */
48560424e9SKalle Valo static u8 cw1200_mac_template[ETH_ALEN] = {0x02, 0x80, 0xe1, 0x00, 0x00, 0x00};
49560424e9SKalle Valo module_param_array_named(macaddr, cw1200_mac_template, byte, NULL, S_IRUGO);
50560424e9SKalle Valo MODULE_PARM_DESC(macaddr, "Override platform_data MAC address");
51560424e9SKalle Valo 
52560424e9SKalle Valo static char *cw1200_sdd_path;
53560424e9SKalle Valo module_param(cw1200_sdd_path, charp, 0644);
54560424e9SKalle Valo MODULE_PARM_DESC(cw1200_sdd_path, "Override platform_data SDD file");
55560424e9SKalle Valo static int cw1200_refclk;
56560424e9SKalle Valo module_param(cw1200_refclk, int, 0644);
57560424e9SKalle Valo MODULE_PARM_DESC(cw1200_refclk, "Override platform_data reference clock");
58560424e9SKalle Valo 
59560424e9SKalle Valo int cw1200_power_mode = wsm_power_mode_quiescent;
60560424e9SKalle Valo module_param(cw1200_power_mode, int, 0644);
61560424e9SKalle Valo MODULE_PARM_DESC(cw1200_power_mode, "WSM power mode.  0 == active, 1 == doze, 2 == quiescent (default)");
62560424e9SKalle Valo 
63560424e9SKalle Valo #define RATETAB_ENT(_rate, _rateid, _flags)		\
64560424e9SKalle Valo 	{						\
65560424e9SKalle Valo 		.bitrate	= (_rate),		\
66560424e9SKalle Valo 		.hw_value	= (_rateid),		\
67560424e9SKalle Valo 		.flags		= (_flags),		\
68560424e9SKalle Valo 	}
69560424e9SKalle Valo 
70560424e9SKalle Valo static struct ieee80211_rate cw1200_rates[] = {
71560424e9SKalle Valo 	RATETAB_ENT(10,  0,   0),
72560424e9SKalle Valo 	RATETAB_ENT(20,  1,   0),
73560424e9SKalle Valo 	RATETAB_ENT(55,  2,   0),
74560424e9SKalle Valo 	RATETAB_ENT(110, 3,   0),
75560424e9SKalle Valo 	RATETAB_ENT(60,  6,  0),
76560424e9SKalle Valo 	RATETAB_ENT(90,  7,  0),
77560424e9SKalle Valo 	RATETAB_ENT(120, 8,  0),
78560424e9SKalle Valo 	RATETAB_ENT(180, 9,  0),
79560424e9SKalle Valo 	RATETAB_ENT(240, 10, 0),
80560424e9SKalle Valo 	RATETAB_ENT(360, 11, 0),
81560424e9SKalle Valo 	RATETAB_ENT(480, 12, 0),
82560424e9SKalle Valo 	RATETAB_ENT(540, 13, 0),
83560424e9SKalle Valo };
84560424e9SKalle Valo 
85560424e9SKalle Valo static struct ieee80211_rate cw1200_mcs_rates[] = {
86560424e9SKalle Valo 	RATETAB_ENT(65,  14, IEEE80211_TX_RC_MCS),
87560424e9SKalle Valo 	RATETAB_ENT(130, 15, IEEE80211_TX_RC_MCS),
88560424e9SKalle Valo 	RATETAB_ENT(195, 16, IEEE80211_TX_RC_MCS),
89560424e9SKalle Valo 	RATETAB_ENT(260, 17, IEEE80211_TX_RC_MCS),
90560424e9SKalle Valo 	RATETAB_ENT(390, 18, IEEE80211_TX_RC_MCS),
91560424e9SKalle Valo 	RATETAB_ENT(520, 19, IEEE80211_TX_RC_MCS),
92560424e9SKalle Valo 	RATETAB_ENT(585, 20, IEEE80211_TX_RC_MCS),
93560424e9SKalle Valo 	RATETAB_ENT(650, 21, IEEE80211_TX_RC_MCS),
94560424e9SKalle Valo };
95560424e9SKalle Valo 
96560424e9SKalle Valo #define cw1200_a_rates		(cw1200_rates + 4)
97560424e9SKalle Valo #define cw1200_a_rates_size	(ARRAY_SIZE(cw1200_rates) - 4)
98560424e9SKalle Valo #define cw1200_g_rates		(cw1200_rates + 0)
99560424e9SKalle Valo #define cw1200_g_rates_size	(ARRAY_SIZE(cw1200_rates))
100560424e9SKalle Valo #define cw1200_n_rates		(cw1200_mcs_rates)
101560424e9SKalle Valo #define cw1200_n_rates_size	(ARRAY_SIZE(cw1200_mcs_rates))
102560424e9SKalle Valo 
103560424e9SKalle Valo 
104560424e9SKalle Valo #define CHAN2G(_channel, _freq, _flags) {			\
10557fbcce3SJohannes Berg 	.band			= NL80211_BAND_2GHZ,		\
106560424e9SKalle Valo 	.center_freq		= (_freq),			\
107560424e9SKalle Valo 	.hw_value		= (_channel),			\
108560424e9SKalle Valo 	.flags			= (_flags),			\
109560424e9SKalle Valo 	.max_antenna_gain	= 0,				\
110560424e9SKalle Valo 	.max_power		= 30,				\
111560424e9SKalle Valo }
112560424e9SKalle Valo 
113560424e9SKalle Valo #define CHAN5G(_channel, _flags) {				\
11457fbcce3SJohannes Berg 	.band			= NL80211_BAND_5GHZ,		\
115560424e9SKalle Valo 	.center_freq	= 5000 + (5 * (_channel)),		\
116560424e9SKalle Valo 	.hw_value		= (_channel),			\
117560424e9SKalle Valo 	.flags			= (_flags),			\
118560424e9SKalle Valo 	.max_antenna_gain	= 0,				\
119560424e9SKalle Valo 	.max_power		= 30,				\
120560424e9SKalle Valo }
121560424e9SKalle Valo 
122560424e9SKalle Valo static struct ieee80211_channel cw1200_2ghz_chantable[] = {
123560424e9SKalle Valo 	CHAN2G(1, 2412, 0),
124560424e9SKalle Valo 	CHAN2G(2, 2417, 0),
125560424e9SKalle Valo 	CHAN2G(3, 2422, 0),
126560424e9SKalle Valo 	CHAN2G(4, 2427, 0),
127560424e9SKalle Valo 	CHAN2G(5, 2432, 0),
128560424e9SKalle Valo 	CHAN2G(6, 2437, 0),
129560424e9SKalle Valo 	CHAN2G(7, 2442, 0),
130560424e9SKalle Valo 	CHAN2G(8, 2447, 0),
131560424e9SKalle Valo 	CHAN2G(9, 2452, 0),
132560424e9SKalle Valo 	CHAN2G(10, 2457, 0),
133560424e9SKalle Valo 	CHAN2G(11, 2462, 0),
134560424e9SKalle Valo 	CHAN2G(12, 2467, 0),
135560424e9SKalle Valo 	CHAN2G(13, 2472, 0),
136560424e9SKalle Valo 	CHAN2G(14, 2484, 0),
137560424e9SKalle Valo };
138560424e9SKalle Valo 
139560424e9SKalle Valo static struct ieee80211_channel cw1200_5ghz_chantable[] = {
140560424e9SKalle Valo 	CHAN5G(34, 0),		CHAN5G(36, 0),
141560424e9SKalle Valo 	CHAN5G(38, 0),		CHAN5G(40, 0),
142560424e9SKalle Valo 	CHAN5G(42, 0),		CHAN5G(44, 0),
143560424e9SKalle Valo 	CHAN5G(46, 0),		CHAN5G(48, 0),
144560424e9SKalle Valo 	CHAN5G(52, 0),		CHAN5G(56, 0),
145560424e9SKalle Valo 	CHAN5G(60, 0),		CHAN5G(64, 0),
146560424e9SKalle Valo 	CHAN5G(100, 0),		CHAN5G(104, 0),
147560424e9SKalle Valo 	CHAN5G(108, 0),		CHAN5G(112, 0),
148560424e9SKalle Valo 	CHAN5G(116, 0),		CHAN5G(120, 0),
149560424e9SKalle Valo 	CHAN5G(124, 0),		CHAN5G(128, 0),
150560424e9SKalle Valo 	CHAN5G(132, 0),		CHAN5G(136, 0),
151560424e9SKalle Valo 	CHAN5G(140, 0),		CHAN5G(149, 0),
152560424e9SKalle Valo 	CHAN5G(153, 0),		CHAN5G(157, 0),
153560424e9SKalle Valo 	CHAN5G(161, 0),		CHAN5G(165, 0),
154560424e9SKalle Valo 	CHAN5G(184, 0),		CHAN5G(188, 0),
155560424e9SKalle Valo 	CHAN5G(192, 0),		CHAN5G(196, 0),
156560424e9SKalle Valo 	CHAN5G(200, 0),		CHAN5G(204, 0),
157560424e9SKalle Valo 	CHAN5G(208, 0),		CHAN5G(212, 0),
158560424e9SKalle Valo 	CHAN5G(216, 0),
159560424e9SKalle Valo };
160560424e9SKalle Valo 
161560424e9SKalle Valo static struct ieee80211_supported_band cw1200_band_2ghz = {
162560424e9SKalle Valo 	.channels = cw1200_2ghz_chantable,
163560424e9SKalle Valo 	.n_channels = ARRAY_SIZE(cw1200_2ghz_chantable),
164560424e9SKalle Valo 	.bitrates = cw1200_g_rates,
165560424e9SKalle Valo 	.n_bitrates = cw1200_g_rates_size,
166560424e9SKalle Valo 	.ht_cap = {
167560424e9SKalle Valo 		.cap = IEEE80211_HT_CAP_GRN_FLD |
168560424e9SKalle Valo 			(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) |
169560424e9SKalle Valo 			IEEE80211_HT_CAP_MAX_AMSDU,
170560424e9SKalle Valo 		.ht_supported = 1,
171560424e9SKalle Valo 		.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K,
172560424e9SKalle Valo 		.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
173560424e9SKalle Valo 		.mcs = {
174560424e9SKalle Valo 			.rx_mask[0] = 0xFF,
175560424e9SKalle Valo 			.rx_highest = __cpu_to_le16(0x41),
176560424e9SKalle Valo 			.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
177560424e9SKalle Valo 		},
178560424e9SKalle Valo 	},
179560424e9SKalle Valo };
180560424e9SKalle Valo 
181560424e9SKalle Valo static struct ieee80211_supported_band cw1200_band_5ghz = {
182560424e9SKalle Valo 	.channels = cw1200_5ghz_chantable,
183560424e9SKalle Valo 	.n_channels = ARRAY_SIZE(cw1200_5ghz_chantable),
184560424e9SKalle Valo 	.bitrates = cw1200_a_rates,
185560424e9SKalle Valo 	.n_bitrates = cw1200_a_rates_size,
186560424e9SKalle Valo 	.ht_cap = {
187560424e9SKalle Valo 		.cap = IEEE80211_HT_CAP_GRN_FLD |
188560424e9SKalle Valo 			(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) |
189560424e9SKalle Valo 			IEEE80211_HT_CAP_MAX_AMSDU,
190560424e9SKalle Valo 		.ht_supported = 1,
191560424e9SKalle Valo 		.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K,
192560424e9SKalle Valo 		.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
193560424e9SKalle Valo 		.mcs = {
194560424e9SKalle Valo 			.rx_mask[0] = 0xFF,
195560424e9SKalle Valo 			.rx_highest = __cpu_to_le16(0x41),
196560424e9SKalle Valo 			.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
197560424e9SKalle Valo 		},
198560424e9SKalle Valo 	},
199560424e9SKalle Valo };
200560424e9SKalle Valo 
201560424e9SKalle Valo static const unsigned long cw1200_ttl[] = {
202560424e9SKalle Valo 	1 * HZ,	/* VO */
203560424e9SKalle Valo 	2 * HZ,	/* VI */
204560424e9SKalle Valo 	5 * HZ, /* BE */
205560424e9SKalle Valo 	10 * HZ	/* BK */
206560424e9SKalle Valo };
207560424e9SKalle Valo 
208560424e9SKalle Valo static const struct ieee80211_ops cw1200_ops = {
209560424e9SKalle Valo 	.start			= cw1200_start,
210560424e9SKalle Valo 	.stop			= cw1200_stop,
211560424e9SKalle Valo 	.add_interface		= cw1200_add_interface,
212560424e9SKalle Valo 	.remove_interface	= cw1200_remove_interface,
213560424e9SKalle Valo 	.change_interface	= cw1200_change_interface,
214560424e9SKalle Valo 	.tx			= cw1200_tx,
215560424e9SKalle Valo 	.hw_scan		= cw1200_hw_scan,
216560424e9SKalle Valo 	.set_tim		= cw1200_set_tim,
217560424e9SKalle Valo 	.sta_notify		= cw1200_sta_notify,
218560424e9SKalle Valo 	.sta_add		= cw1200_sta_add,
219560424e9SKalle Valo 	.sta_remove		= cw1200_sta_remove,
220560424e9SKalle Valo 	.set_key		= cw1200_set_key,
221560424e9SKalle Valo 	.set_rts_threshold	= cw1200_set_rts_threshold,
222560424e9SKalle Valo 	.config			= cw1200_config,
223560424e9SKalle Valo 	.bss_info_changed	= cw1200_bss_info_changed,
224560424e9SKalle Valo 	.prepare_multicast	= cw1200_prepare_multicast,
225560424e9SKalle Valo 	.configure_filter	= cw1200_configure_filter,
226560424e9SKalle Valo 	.conf_tx		= cw1200_conf_tx,
227560424e9SKalle Valo 	.get_stats		= cw1200_get_stats,
228560424e9SKalle Valo 	.ampdu_action		= cw1200_ampdu_action,
229560424e9SKalle Valo 	.flush			= cw1200_flush,
230560424e9SKalle Valo #ifdef CONFIG_PM
231560424e9SKalle Valo 	.suspend		= cw1200_wow_suspend,
232560424e9SKalle Valo 	.resume			= cw1200_wow_resume,
233560424e9SKalle Valo #endif
234560424e9SKalle Valo 	/* Intentionally not offloaded:					*/
235560424e9SKalle Valo 	/*.channel_switch	= cw1200_channel_switch,		*/
236560424e9SKalle Valo 	/*.remain_on_channel	= cw1200_remain_on_channel,		*/
237560424e9SKalle Valo 	/*.cancel_remain_on_channel = cw1200_cancel_remain_on_channel,	*/
238560424e9SKalle Valo };
239560424e9SKalle Valo 
240560424e9SKalle Valo static int cw1200_ba_rx_tids = -1;
241560424e9SKalle Valo static int cw1200_ba_tx_tids = -1;
242560424e9SKalle Valo module_param(cw1200_ba_rx_tids, int, 0644);
243560424e9SKalle Valo module_param(cw1200_ba_tx_tids, int, 0644);
244560424e9SKalle Valo MODULE_PARM_DESC(cw1200_ba_rx_tids, "Block ACK RX TIDs");
245560424e9SKalle Valo MODULE_PARM_DESC(cw1200_ba_tx_tids, "Block ACK TX TIDs");
246560424e9SKalle Valo 
247560424e9SKalle Valo #ifdef CONFIG_PM
248560424e9SKalle Valo static const struct wiphy_wowlan_support cw1200_wowlan_support = {
249560424e9SKalle Valo 	/* Support only for limited wowlan functionalities */
250560424e9SKalle Valo 	.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT,
251560424e9SKalle Valo };
252560424e9SKalle Valo #endif
253560424e9SKalle Valo 
254560424e9SKalle Valo 
255560424e9SKalle Valo static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
256560424e9SKalle Valo 						const bool have_5ghz)
257560424e9SKalle Valo {
258560424e9SKalle Valo 	int i, band;
259560424e9SKalle Valo 	struct ieee80211_hw *hw;
260560424e9SKalle Valo 	struct cw1200_common *priv;
261560424e9SKalle Valo 
262560424e9SKalle Valo 	hw = ieee80211_alloc_hw(sizeof(struct cw1200_common), &cw1200_ops);
263560424e9SKalle Valo 	if (!hw)
264560424e9SKalle Valo 		return NULL;
265560424e9SKalle Valo 
266560424e9SKalle Valo 	priv = hw->priv;
267560424e9SKalle Valo 	priv->hw = hw;
268560424e9SKalle Valo 	priv->hw_type = -1;
269560424e9SKalle Valo 	priv->mode = NL80211_IFTYPE_UNSPECIFIED;
270560424e9SKalle Valo 	priv->rates = cw1200_rates; /* TODO: fetch from FW */
271560424e9SKalle Valo 	priv->mcs_rates = cw1200_n_rates;
272560424e9SKalle Valo 	if (cw1200_ba_rx_tids != -1)
273560424e9SKalle Valo 		priv->ba_rx_tid_mask = cw1200_ba_rx_tids;
274560424e9SKalle Valo 	else
275560424e9SKalle Valo 		priv->ba_rx_tid_mask = 0xFF; /* Enable RX BLKACK for all TIDs */
276560424e9SKalle Valo 	if (cw1200_ba_tx_tids != -1)
277560424e9SKalle Valo 		priv->ba_tx_tid_mask = cw1200_ba_tx_tids;
278560424e9SKalle Valo 	else
279560424e9SKalle Valo 		priv->ba_tx_tid_mask = 0xff; /* Enable TX BLKACK for all TIDs */
280560424e9SKalle Valo 
281560424e9SKalle Valo 	ieee80211_hw_set(hw, NEED_DTIM_BEFORE_ASSOC);
282560424e9SKalle Valo 	ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
283560424e9SKalle Valo 	ieee80211_hw_set(hw, AMPDU_AGGREGATION);
284560424e9SKalle Valo 	ieee80211_hw_set(hw, CONNECTION_MONITOR);
285560424e9SKalle Valo 	ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
286560424e9SKalle Valo 	ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
287560424e9SKalle Valo 	ieee80211_hw_set(hw, SIGNAL_DBM);
288560424e9SKalle Valo 	ieee80211_hw_set(hw, SUPPORTS_PS);
289560424e9SKalle Valo 
290560424e9SKalle Valo 	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
291560424e9SKalle Valo 					  BIT(NL80211_IFTYPE_ADHOC) |
292560424e9SKalle Valo 					  BIT(NL80211_IFTYPE_AP) |
293560424e9SKalle Valo 					  BIT(NL80211_IFTYPE_MESH_POINT) |
294560424e9SKalle Valo 					  BIT(NL80211_IFTYPE_P2P_CLIENT) |
295560424e9SKalle Valo 					  BIT(NL80211_IFTYPE_P2P_GO);
296560424e9SKalle Valo 
297560424e9SKalle Valo #ifdef CONFIG_PM
298560424e9SKalle Valo 	hw->wiphy->wowlan = &cw1200_wowlan_support;
299560424e9SKalle Valo #endif
300560424e9SKalle Valo 
301560424e9SKalle Valo 	hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
302560424e9SKalle Valo 
303560424e9SKalle Valo 	hw->queues = 4;
304560424e9SKalle Valo 
305560424e9SKalle Valo 	priv->rts_threshold = -1;
306560424e9SKalle Valo 
307560424e9SKalle Valo 	hw->max_rates = 8;
308560424e9SKalle Valo 	hw->max_rate_tries = 15;
309560424e9SKalle Valo 	hw->extra_tx_headroom = WSM_TX_EXTRA_HEADROOM +
310560424e9SKalle Valo 		8;  /* TKIP IV */
311560424e9SKalle Valo 
312560424e9SKalle Valo 	hw->sta_data_size = sizeof(struct cw1200_sta_priv);
313560424e9SKalle Valo 
31457fbcce3SJohannes Berg 	hw->wiphy->bands[NL80211_BAND_2GHZ] = &cw1200_band_2ghz;
315560424e9SKalle Valo 	if (have_5ghz)
31657fbcce3SJohannes Berg 		hw->wiphy->bands[NL80211_BAND_5GHZ] = &cw1200_band_5ghz;
317560424e9SKalle Valo 
318560424e9SKalle Valo 	/* Channel params have to be cleared before registering wiphy again */
31957fbcce3SJohannes Berg 	for (band = 0; band < NUM_NL80211_BANDS; band++) {
320560424e9SKalle Valo 		struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
321560424e9SKalle Valo 		if (!sband)
322560424e9SKalle Valo 			continue;
323560424e9SKalle Valo 		for (i = 0; i < sband->n_channels; i++) {
324560424e9SKalle Valo 			sband->channels[i].flags = 0;
325560424e9SKalle Valo 			sband->channels[i].max_antenna_gain = 0;
326560424e9SKalle Valo 			sband->channels[i].max_power = 30;
327560424e9SKalle Valo 		}
328560424e9SKalle Valo 	}
329560424e9SKalle Valo 
330560424e9SKalle Valo 	hw->wiphy->max_scan_ssids = 2;
331560424e9SKalle Valo 	hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
332560424e9SKalle Valo 
333560424e9SKalle Valo 	if (macaddr)
334560424e9SKalle Valo 		SET_IEEE80211_PERM_ADDR(hw, (u8 *)macaddr);
335560424e9SKalle Valo 	else
336560424e9SKalle Valo 		SET_IEEE80211_PERM_ADDR(hw, cw1200_mac_template);
337560424e9SKalle Valo 
338560424e9SKalle Valo 	/* Fix up mac address if necessary */
339560424e9SKalle Valo 	if (hw->wiphy->perm_addr[3] == 0 &&
340560424e9SKalle Valo 	    hw->wiphy->perm_addr[4] == 0 &&
341560424e9SKalle Valo 	    hw->wiphy->perm_addr[5] == 0) {
342560424e9SKalle Valo 		get_random_bytes(&hw->wiphy->perm_addr[3], 3);
343560424e9SKalle Valo 	}
344560424e9SKalle Valo 
345560424e9SKalle Valo 	mutex_init(&priv->wsm_cmd_mux);
346560424e9SKalle Valo 	mutex_init(&priv->conf_mutex);
347560424e9SKalle Valo 	priv->workqueue = create_singlethread_workqueue("cw1200_wq");
348560424e9SKalle Valo 	sema_init(&priv->scan.lock, 1);
349560424e9SKalle Valo 	INIT_WORK(&priv->scan.work, cw1200_scan_work);
350560424e9SKalle Valo 	INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work);
351560424e9SKalle Valo 	INIT_DELAYED_WORK(&priv->scan.timeout, cw1200_scan_timeout);
352560424e9SKalle Valo 	INIT_DELAYED_WORK(&priv->clear_recent_scan_work,
353560424e9SKalle Valo 			  cw1200_clear_recent_scan_work);
354560424e9SKalle Valo 	INIT_DELAYED_WORK(&priv->join_timeout, cw1200_join_timeout);
355560424e9SKalle Valo 	INIT_WORK(&priv->unjoin_work, cw1200_unjoin_work);
356560424e9SKalle Valo 	INIT_WORK(&priv->join_complete_work, cw1200_join_complete_work);
357560424e9SKalle Valo 	INIT_WORK(&priv->wep_key_work, cw1200_wep_key_work);
358560424e9SKalle Valo 	INIT_WORK(&priv->tx_policy_upload_work, tx_policy_upload_work);
359560424e9SKalle Valo 	spin_lock_init(&priv->event_queue_lock);
360560424e9SKalle Valo 	INIT_LIST_HEAD(&priv->event_queue);
361560424e9SKalle Valo 	INIT_WORK(&priv->event_handler, cw1200_event_handler);
362560424e9SKalle Valo 	INIT_DELAYED_WORK(&priv->bss_loss_work, cw1200_bss_loss_work);
363560424e9SKalle Valo 	INIT_WORK(&priv->bss_params_work, cw1200_bss_params_work);
364560424e9SKalle Valo 	spin_lock_init(&priv->bss_loss_lock);
365560424e9SKalle Valo 	spin_lock_init(&priv->ps_state_lock);
366560424e9SKalle Valo 	INIT_WORK(&priv->set_cts_work, cw1200_set_cts_work);
367560424e9SKalle Valo 	INIT_WORK(&priv->set_tim_work, cw1200_set_tim_work);
368560424e9SKalle Valo 	INIT_WORK(&priv->multicast_start_work, cw1200_multicast_start_work);
369560424e9SKalle Valo 	INIT_WORK(&priv->multicast_stop_work, cw1200_multicast_stop_work);
370560424e9SKalle Valo 	INIT_WORK(&priv->link_id_work, cw1200_link_id_work);
371560424e9SKalle Valo 	INIT_DELAYED_WORK(&priv->link_id_gc_work, cw1200_link_id_gc_work);
372560424e9SKalle Valo 	INIT_WORK(&priv->linkid_reset_work, cw1200_link_id_reset);
373560424e9SKalle Valo 	INIT_WORK(&priv->update_filtering_work, cw1200_update_filtering_work);
374560424e9SKalle Valo 	INIT_WORK(&priv->set_beacon_wakeup_period_work,
375560424e9SKalle Valo 		  cw1200_set_beacon_wakeup_period_work);
376*e3dcf8bbSKees Cook 	timer_setup(&priv->mcast_timeout, cw1200_mcast_timeout, 0);
377560424e9SKalle Valo 
378560424e9SKalle Valo 	if (cw1200_queue_stats_init(&priv->tx_queue_stats,
379560424e9SKalle Valo 				    CW1200_LINK_ID_MAX,
380560424e9SKalle Valo 				    cw1200_skb_dtor,
381560424e9SKalle Valo 				    priv)) {
382560424e9SKalle Valo 		ieee80211_free_hw(hw);
383560424e9SKalle Valo 		return NULL;
384560424e9SKalle Valo 	}
385560424e9SKalle Valo 
386560424e9SKalle Valo 	for (i = 0; i < 4; ++i) {
387560424e9SKalle Valo 		if (cw1200_queue_init(&priv->tx_queue[i],
388560424e9SKalle Valo 				      &priv->tx_queue_stats, i, 16,
389560424e9SKalle Valo 				      cw1200_ttl[i])) {
390560424e9SKalle Valo 			for (; i > 0; i--)
391560424e9SKalle Valo 				cw1200_queue_deinit(&priv->tx_queue[i - 1]);
392560424e9SKalle Valo 			cw1200_queue_stats_deinit(&priv->tx_queue_stats);
393560424e9SKalle Valo 			ieee80211_free_hw(hw);
394560424e9SKalle Valo 			return NULL;
395560424e9SKalle Valo 		}
396560424e9SKalle Valo 	}
397560424e9SKalle Valo 
398560424e9SKalle Valo 	init_waitqueue_head(&priv->channel_switch_done);
399560424e9SKalle Valo 	init_waitqueue_head(&priv->wsm_cmd_wq);
400560424e9SKalle Valo 	init_waitqueue_head(&priv->wsm_startup_done);
401560424e9SKalle Valo 	init_waitqueue_head(&priv->ps_mode_switch_done);
402560424e9SKalle Valo 	wsm_buf_init(&priv->wsm_cmd_buf);
403560424e9SKalle Valo 	spin_lock_init(&priv->wsm_cmd.lock);
404560424e9SKalle Valo 	priv->wsm_cmd.done = 1;
405560424e9SKalle Valo 	tx_policy_init(priv);
406560424e9SKalle Valo 
407560424e9SKalle Valo 	return hw;
408560424e9SKalle Valo }
409560424e9SKalle Valo 
410560424e9SKalle Valo static int cw1200_register_common(struct ieee80211_hw *dev)
411560424e9SKalle Valo {
412560424e9SKalle Valo 	struct cw1200_common *priv = dev->priv;
413560424e9SKalle Valo 	int err;
414560424e9SKalle Valo 
415560424e9SKalle Valo #ifdef CONFIG_PM
416560424e9SKalle Valo 	err = cw1200_pm_init(&priv->pm_state, priv);
417560424e9SKalle Valo 	if (err) {
418560424e9SKalle Valo 		pr_err("Cannot init PM. (%d).\n",
419560424e9SKalle Valo 		       err);
420560424e9SKalle Valo 		return err;
421560424e9SKalle Valo 	}
422560424e9SKalle Valo #endif
423560424e9SKalle Valo 
424560424e9SKalle Valo 	err = ieee80211_register_hw(dev);
425560424e9SKalle Valo 	if (err) {
426560424e9SKalle Valo 		pr_err("Cannot register device (%d).\n",
427560424e9SKalle Valo 		       err);
428560424e9SKalle Valo #ifdef CONFIG_PM
429560424e9SKalle Valo 		cw1200_pm_deinit(&priv->pm_state);
430560424e9SKalle Valo #endif
431560424e9SKalle Valo 		return err;
432560424e9SKalle Valo 	}
433560424e9SKalle Valo 
434560424e9SKalle Valo 	cw1200_debug_init(priv);
435560424e9SKalle Valo 
436560424e9SKalle Valo 	pr_info("Registered as '%s'\n", wiphy_name(dev->wiphy));
437560424e9SKalle Valo 	return 0;
438560424e9SKalle Valo }
439560424e9SKalle Valo 
440560424e9SKalle Valo static void cw1200_free_common(struct ieee80211_hw *dev)
441560424e9SKalle Valo {
442560424e9SKalle Valo 	ieee80211_free_hw(dev);
443560424e9SKalle Valo }
444560424e9SKalle Valo 
445560424e9SKalle Valo static void cw1200_unregister_common(struct ieee80211_hw *dev)
446560424e9SKalle Valo {
447560424e9SKalle Valo 	struct cw1200_common *priv = dev->priv;
448560424e9SKalle Valo 	int i;
449560424e9SKalle Valo 
450560424e9SKalle Valo 	ieee80211_unregister_hw(dev);
451560424e9SKalle Valo 
452560424e9SKalle Valo 	del_timer_sync(&priv->mcast_timeout);
453560424e9SKalle Valo 	cw1200_unregister_bh(priv);
454560424e9SKalle Valo 
455560424e9SKalle Valo 	cw1200_debug_release(priv);
456560424e9SKalle Valo 
457560424e9SKalle Valo 	mutex_destroy(&priv->conf_mutex);
458560424e9SKalle Valo 
459560424e9SKalle Valo 	wsm_buf_deinit(&priv->wsm_cmd_buf);
460560424e9SKalle Valo 
461560424e9SKalle Valo 	destroy_workqueue(priv->workqueue);
462560424e9SKalle Valo 	priv->workqueue = NULL;
463560424e9SKalle Valo 
464560424e9SKalle Valo 	if (priv->sdd) {
465560424e9SKalle Valo 		release_firmware(priv->sdd);
466560424e9SKalle Valo 		priv->sdd = NULL;
467560424e9SKalle Valo 	}
468560424e9SKalle Valo 
469560424e9SKalle Valo 	for (i = 0; i < 4; ++i)
470560424e9SKalle Valo 		cw1200_queue_deinit(&priv->tx_queue[i]);
471560424e9SKalle Valo 
472560424e9SKalle Valo 	cw1200_queue_stats_deinit(&priv->tx_queue_stats);
473560424e9SKalle Valo #ifdef CONFIG_PM
474560424e9SKalle Valo 	cw1200_pm_deinit(&priv->pm_state);
475560424e9SKalle Valo #endif
476560424e9SKalle Valo }
477560424e9SKalle Valo 
478560424e9SKalle Valo /* Clock is in KHz */
479560424e9SKalle Valo u32 cw1200_dpll_from_clk(u16 clk_khz)
480560424e9SKalle Valo {
481560424e9SKalle Valo 	switch (clk_khz) {
482560424e9SKalle Valo 	case 0x32C8: /* 13000 KHz */
483560424e9SKalle Valo 		return 0x1D89D241;
484560424e9SKalle Valo 	case 0x3E80: /* 16000 KHz */
485560424e9SKalle Valo 		return 0x000001E1;
486560424e9SKalle Valo 	case 0x41A0: /* 16800 KHz */
487560424e9SKalle Valo 		return 0x124931C1;
488560424e9SKalle Valo 	case 0x4B00: /* 19200 KHz */
489560424e9SKalle Valo 		return 0x00000191;
490560424e9SKalle Valo 	case 0x5DC0: /* 24000 KHz */
491560424e9SKalle Valo 		return 0x00000141;
492560424e9SKalle Valo 	case 0x6590: /* 26000 KHz */
493560424e9SKalle Valo 		return 0x0EC4F121;
494560424e9SKalle Valo 	case 0x8340: /* 33600 KHz */
495560424e9SKalle Valo 		return 0x092490E1;
496560424e9SKalle Valo 	case 0x9600: /* 38400 KHz */
497560424e9SKalle Valo 		return 0x100010C1;
498560424e9SKalle Valo 	case 0x9C40: /* 40000 KHz */
499560424e9SKalle Valo 		return 0x000000C1;
500560424e9SKalle Valo 	case 0xBB80: /* 48000 KHz */
501560424e9SKalle Valo 		return 0x000000A1;
502560424e9SKalle Valo 	case 0xCB20: /* 52000 KHz */
503560424e9SKalle Valo 		return 0x07627091;
504560424e9SKalle Valo 	default:
505560424e9SKalle Valo 		pr_err("Unknown Refclk freq (0x%04x), using 26000KHz\n",
506560424e9SKalle Valo 		       clk_khz);
507560424e9SKalle Valo 		return 0x0EC4F121;
508560424e9SKalle Valo 	}
509560424e9SKalle Valo }
510560424e9SKalle Valo 
511560424e9SKalle Valo int cw1200_core_probe(const struct hwbus_ops *hwbus_ops,
512560424e9SKalle Valo 		      struct hwbus_priv *hwbus,
513560424e9SKalle Valo 		      struct device *pdev,
514560424e9SKalle Valo 		      struct cw1200_common **core,
515560424e9SKalle Valo 		      int ref_clk, const u8 *macaddr,
516560424e9SKalle Valo 		      const char *sdd_path, bool have_5ghz)
517560424e9SKalle Valo {
518560424e9SKalle Valo 	int err = -EINVAL;
519560424e9SKalle Valo 	struct ieee80211_hw *dev;
520560424e9SKalle Valo 	struct cw1200_common *priv;
521560424e9SKalle Valo 	struct wsm_operational_mode mode = {
522560424e9SKalle Valo 		.power_mode = cw1200_power_mode,
523560424e9SKalle Valo 		.disable_more_flag_usage = true,
524560424e9SKalle Valo 	};
525560424e9SKalle Valo 
526560424e9SKalle Valo 	dev = cw1200_init_common(macaddr, have_5ghz);
527560424e9SKalle Valo 	if (!dev)
528560424e9SKalle Valo 		goto err;
529560424e9SKalle Valo 
530560424e9SKalle Valo 	priv = dev->priv;
531560424e9SKalle Valo 	priv->hw_refclk = ref_clk;
532560424e9SKalle Valo 	if (cw1200_refclk)
533560424e9SKalle Valo 		priv->hw_refclk = cw1200_refclk;
534560424e9SKalle Valo 
535560424e9SKalle Valo 	priv->sdd_path = (char *)sdd_path;
536560424e9SKalle Valo 	if (cw1200_sdd_path)
537560424e9SKalle Valo 		priv->sdd_path = cw1200_sdd_path;
538560424e9SKalle Valo 
539560424e9SKalle Valo 	priv->hwbus_ops = hwbus_ops;
540560424e9SKalle Valo 	priv->hwbus_priv = hwbus;
541560424e9SKalle Valo 	priv->pdev = pdev;
542560424e9SKalle Valo 	SET_IEEE80211_DEV(priv->hw, pdev);
543560424e9SKalle Valo 
544560424e9SKalle Valo 	/* Pass struct cw1200_common back up */
545560424e9SKalle Valo 	*core = priv;
546560424e9SKalle Valo 
547560424e9SKalle Valo 	err = cw1200_register_bh(priv);
548560424e9SKalle Valo 	if (err)
549560424e9SKalle Valo 		goto err1;
550560424e9SKalle Valo 
551560424e9SKalle Valo 	err = cw1200_load_firmware(priv);
552560424e9SKalle Valo 	if (err)
553560424e9SKalle Valo 		goto err2;
554560424e9SKalle Valo 
555560424e9SKalle Valo 	if (wait_event_interruptible_timeout(priv->wsm_startup_done,
556560424e9SKalle Valo 					     priv->firmware_ready,
557560424e9SKalle Valo 					     3*HZ) <= 0) {
558560424e9SKalle Valo 		/* TODO: Need to find how to reset device
559560424e9SKalle Valo 		   in QUEUE mode properly.
560560424e9SKalle Valo 		*/
561560424e9SKalle Valo 		pr_err("Timeout waiting on device startup\n");
562560424e9SKalle Valo 		err = -ETIMEDOUT;
563560424e9SKalle Valo 		goto err2;
564560424e9SKalle Valo 	}
565560424e9SKalle Valo 
566560424e9SKalle Valo 	/* Set low-power mode. */
567560424e9SKalle Valo 	wsm_set_operational_mode(priv, &mode);
568560424e9SKalle Valo 
569560424e9SKalle Valo 	/* Enable multi-TX confirmation */
570560424e9SKalle Valo 	wsm_use_multi_tx_conf(priv, true);
571560424e9SKalle Valo 
572560424e9SKalle Valo 	err = cw1200_register_common(dev);
573560424e9SKalle Valo 	if (err)
574560424e9SKalle Valo 		goto err2;
575560424e9SKalle Valo 
576560424e9SKalle Valo 	return err;
577560424e9SKalle Valo 
578560424e9SKalle Valo err2:
579560424e9SKalle Valo 	cw1200_unregister_bh(priv);
580560424e9SKalle Valo err1:
581560424e9SKalle Valo 	cw1200_free_common(dev);
582560424e9SKalle Valo err:
583560424e9SKalle Valo 	*core = NULL;
584560424e9SKalle Valo 	return err;
585560424e9SKalle Valo }
586560424e9SKalle Valo EXPORT_SYMBOL_GPL(cw1200_core_probe);
587560424e9SKalle Valo 
588560424e9SKalle Valo void cw1200_core_release(struct cw1200_common *self)
589560424e9SKalle Valo {
590560424e9SKalle Valo 	/* Disable device interrupts */
591560424e9SKalle Valo 	self->hwbus_ops->lock(self->hwbus_priv);
592560424e9SKalle Valo 	__cw1200_irq_enable(self, 0);
593560424e9SKalle Valo 	self->hwbus_ops->unlock(self->hwbus_priv);
594560424e9SKalle Valo 
595560424e9SKalle Valo 	/* And then clean up */
596560424e9SKalle Valo 	cw1200_unregister_common(self->hw);
597560424e9SKalle Valo 	cw1200_free_common(self->hw);
598560424e9SKalle Valo 	return;
599560424e9SKalle Valo }
600560424e9SKalle Valo EXPORT_SYMBOL_GPL(cw1200_core_release);
601