xref: /openbmc/linux/drivers/net/wireless/st/cw1200/main.c (revision 57fbcce37be7c1d2622b56587c10ade00e96afa3)
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) {			\
105*57fbcce3SJohannes 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) {				\
114*57fbcce3SJohannes 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 
314*57fbcce3SJohannes Berg 	hw->wiphy->bands[NL80211_BAND_2GHZ] = &cw1200_band_2ghz;
315560424e9SKalle Valo 	if (have_5ghz)
316*57fbcce3SJohannes Berg 		hw->wiphy->bands[NL80211_BAND_5GHZ] = &cw1200_band_5ghz;
317560424e9SKalle Valo 
318560424e9SKalle Valo 	/* Channel params have to be cleared before registering wiphy again */
319*57fbcce3SJohannes 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);
376560424e9SKalle Valo 	setup_timer(&priv->mcast_timeout, cw1200_mcast_timeout,
377560424e9SKalle Valo 		    (unsigned long)priv);
378560424e9SKalle Valo 
379560424e9SKalle Valo 	if (cw1200_queue_stats_init(&priv->tx_queue_stats,
380560424e9SKalle Valo 				    CW1200_LINK_ID_MAX,
381560424e9SKalle Valo 				    cw1200_skb_dtor,
382560424e9SKalle Valo 				    priv)) {
383560424e9SKalle Valo 		ieee80211_free_hw(hw);
384560424e9SKalle Valo 		return NULL;
385560424e9SKalle Valo 	}
386560424e9SKalle Valo 
387560424e9SKalle Valo 	for (i = 0; i < 4; ++i) {
388560424e9SKalle Valo 		if (cw1200_queue_init(&priv->tx_queue[i],
389560424e9SKalle Valo 				      &priv->tx_queue_stats, i, 16,
390560424e9SKalle Valo 				      cw1200_ttl[i])) {
391560424e9SKalle Valo 			for (; i > 0; i--)
392560424e9SKalle Valo 				cw1200_queue_deinit(&priv->tx_queue[i - 1]);
393560424e9SKalle Valo 			cw1200_queue_stats_deinit(&priv->tx_queue_stats);
394560424e9SKalle Valo 			ieee80211_free_hw(hw);
395560424e9SKalle Valo 			return NULL;
396560424e9SKalle Valo 		}
397560424e9SKalle Valo 	}
398560424e9SKalle Valo 
399560424e9SKalle Valo 	init_waitqueue_head(&priv->channel_switch_done);
400560424e9SKalle Valo 	init_waitqueue_head(&priv->wsm_cmd_wq);
401560424e9SKalle Valo 	init_waitqueue_head(&priv->wsm_startup_done);
402560424e9SKalle Valo 	init_waitqueue_head(&priv->ps_mode_switch_done);
403560424e9SKalle Valo 	wsm_buf_init(&priv->wsm_cmd_buf);
404560424e9SKalle Valo 	spin_lock_init(&priv->wsm_cmd.lock);
405560424e9SKalle Valo 	priv->wsm_cmd.done = 1;
406560424e9SKalle Valo 	tx_policy_init(priv);
407560424e9SKalle Valo 
408560424e9SKalle Valo 	return hw;
409560424e9SKalle Valo }
410560424e9SKalle Valo 
411560424e9SKalle Valo static int cw1200_register_common(struct ieee80211_hw *dev)
412560424e9SKalle Valo {
413560424e9SKalle Valo 	struct cw1200_common *priv = dev->priv;
414560424e9SKalle Valo 	int err;
415560424e9SKalle Valo 
416560424e9SKalle Valo #ifdef CONFIG_PM
417560424e9SKalle Valo 	err = cw1200_pm_init(&priv->pm_state, priv);
418560424e9SKalle Valo 	if (err) {
419560424e9SKalle Valo 		pr_err("Cannot init PM. (%d).\n",
420560424e9SKalle Valo 		       err);
421560424e9SKalle Valo 		return err;
422560424e9SKalle Valo 	}
423560424e9SKalle Valo #endif
424560424e9SKalle Valo 
425560424e9SKalle Valo 	err = ieee80211_register_hw(dev);
426560424e9SKalle Valo 	if (err) {
427560424e9SKalle Valo 		pr_err("Cannot register device (%d).\n",
428560424e9SKalle Valo 		       err);
429560424e9SKalle Valo #ifdef CONFIG_PM
430560424e9SKalle Valo 		cw1200_pm_deinit(&priv->pm_state);
431560424e9SKalle Valo #endif
432560424e9SKalle Valo 		return err;
433560424e9SKalle Valo 	}
434560424e9SKalle Valo 
435560424e9SKalle Valo 	cw1200_debug_init(priv);
436560424e9SKalle Valo 
437560424e9SKalle Valo 	pr_info("Registered as '%s'\n", wiphy_name(dev->wiphy));
438560424e9SKalle Valo 	return 0;
439560424e9SKalle Valo }
440560424e9SKalle Valo 
441560424e9SKalle Valo static void cw1200_free_common(struct ieee80211_hw *dev)
442560424e9SKalle Valo {
443560424e9SKalle Valo 	ieee80211_free_hw(dev);
444560424e9SKalle Valo }
445560424e9SKalle Valo 
446560424e9SKalle Valo static void cw1200_unregister_common(struct ieee80211_hw *dev)
447560424e9SKalle Valo {
448560424e9SKalle Valo 	struct cw1200_common *priv = dev->priv;
449560424e9SKalle Valo 	int i;
450560424e9SKalle Valo 
451560424e9SKalle Valo 	ieee80211_unregister_hw(dev);
452560424e9SKalle Valo 
453560424e9SKalle Valo 	del_timer_sync(&priv->mcast_timeout);
454560424e9SKalle Valo 	cw1200_unregister_bh(priv);
455560424e9SKalle Valo 
456560424e9SKalle Valo 	cw1200_debug_release(priv);
457560424e9SKalle Valo 
458560424e9SKalle Valo 	mutex_destroy(&priv->conf_mutex);
459560424e9SKalle Valo 
460560424e9SKalle Valo 	wsm_buf_deinit(&priv->wsm_cmd_buf);
461560424e9SKalle Valo 
462560424e9SKalle Valo 	destroy_workqueue(priv->workqueue);
463560424e9SKalle Valo 	priv->workqueue = NULL;
464560424e9SKalle Valo 
465560424e9SKalle Valo 	if (priv->sdd) {
466560424e9SKalle Valo 		release_firmware(priv->sdd);
467560424e9SKalle Valo 		priv->sdd = NULL;
468560424e9SKalle Valo 	}
469560424e9SKalle Valo 
470560424e9SKalle Valo 	for (i = 0; i < 4; ++i)
471560424e9SKalle Valo 		cw1200_queue_deinit(&priv->tx_queue[i]);
472560424e9SKalle Valo 
473560424e9SKalle Valo 	cw1200_queue_stats_deinit(&priv->tx_queue_stats);
474560424e9SKalle Valo #ifdef CONFIG_PM
475560424e9SKalle Valo 	cw1200_pm_deinit(&priv->pm_state);
476560424e9SKalle Valo #endif
477560424e9SKalle Valo }
478560424e9SKalle Valo 
479560424e9SKalle Valo /* Clock is in KHz */
480560424e9SKalle Valo u32 cw1200_dpll_from_clk(u16 clk_khz)
481560424e9SKalle Valo {
482560424e9SKalle Valo 	switch (clk_khz) {
483560424e9SKalle Valo 	case 0x32C8: /* 13000 KHz */
484560424e9SKalle Valo 		return 0x1D89D241;
485560424e9SKalle Valo 	case 0x3E80: /* 16000 KHz */
486560424e9SKalle Valo 		return 0x000001E1;
487560424e9SKalle Valo 	case 0x41A0: /* 16800 KHz */
488560424e9SKalle Valo 		return 0x124931C1;
489560424e9SKalle Valo 	case 0x4B00: /* 19200 KHz */
490560424e9SKalle Valo 		return 0x00000191;
491560424e9SKalle Valo 	case 0x5DC0: /* 24000 KHz */
492560424e9SKalle Valo 		return 0x00000141;
493560424e9SKalle Valo 	case 0x6590: /* 26000 KHz */
494560424e9SKalle Valo 		return 0x0EC4F121;
495560424e9SKalle Valo 	case 0x8340: /* 33600 KHz */
496560424e9SKalle Valo 		return 0x092490E1;
497560424e9SKalle Valo 	case 0x9600: /* 38400 KHz */
498560424e9SKalle Valo 		return 0x100010C1;
499560424e9SKalle Valo 	case 0x9C40: /* 40000 KHz */
500560424e9SKalle Valo 		return 0x000000C1;
501560424e9SKalle Valo 	case 0xBB80: /* 48000 KHz */
502560424e9SKalle Valo 		return 0x000000A1;
503560424e9SKalle Valo 	case 0xCB20: /* 52000 KHz */
504560424e9SKalle Valo 		return 0x07627091;
505560424e9SKalle Valo 	default:
506560424e9SKalle Valo 		pr_err("Unknown Refclk freq (0x%04x), using 26000KHz\n",
507560424e9SKalle Valo 		       clk_khz);
508560424e9SKalle Valo 		return 0x0EC4F121;
509560424e9SKalle Valo 	}
510560424e9SKalle Valo }
511560424e9SKalle Valo 
512560424e9SKalle Valo int cw1200_core_probe(const struct hwbus_ops *hwbus_ops,
513560424e9SKalle Valo 		      struct hwbus_priv *hwbus,
514560424e9SKalle Valo 		      struct device *pdev,
515560424e9SKalle Valo 		      struct cw1200_common **core,
516560424e9SKalle Valo 		      int ref_clk, const u8 *macaddr,
517560424e9SKalle Valo 		      const char *sdd_path, bool have_5ghz)
518560424e9SKalle Valo {
519560424e9SKalle Valo 	int err = -EINVAL;
520560424e9SKalle Valo 	struct ieee80211_hw *dev;
521560424e9SKalle Valo 	struct cw1200_common *priv;
522560424e9SKalle Valo 	struct wsm_operational_mode mode = {
523560424e9SKalle Valo 		.power_mode = cw1200_power_mode,
524560424e9SKalle Valo 		.disable_more_flag_usage = true,
525560424e9SKalle Valo 	};
526560424e9SKalle Valo 
527560424e9SKalle Valo 	dev = cw1200_init_common(macaddr, have_5ghz);
528560424e9SKalle Valo 	if (!dev)
529560424e9SKalle Valo 		goto err;
530560424e9SKalle Valo 
531560424e9SKalle Valo 	priv = dev->priv;
532560424e9SKalle Valo 	priv->hw_refclk = ref_clk;
533560424e9SKalle Valo 	if (cw1200_refclk)
534560424e9SKalle Valo 		priv->hw_refclk = cw1200_refclk;
535560424e9SKalle Valo 
536560424e9SKalle Valo 	priv->sdd_path = (char *)sdd_path;
537560424e9SKalle Valo 	if (cw1200_sdd_path)
538560424e9SKalle Valo 		priv->sdd_path = cw1200_sdd_path;
539560424e9SKalle Valo 
540560424e9SKalle Valo 	priv->hwbus_ops = hwbus_ops;
541560424e9SKalle Valo 	priv->hwbus_priv = hwbus;
542560424e9SKalle Valo 	priv->pdev = pdev;
543560424e9SKalle Valo 	SET_IEEE80211_DEV(priv->hw, pdev);
544560424e9SKalle Valo 
545560424e9SKalle Valo 	/* Pass struct cw1200_common back up */
546560424e9SKalle Valo 	*core = priv;
547560424e9SKalle Valo 
548560424e9SKalle Valo 	err = cw1200_register_bh(priv);
549560424e9SKalle Valo 	if (err)
550560424e9SKalle Valo 		goto err1;
551560424e9SKalle Valo 
552560424e9SKalle Valo 	err = cw1200_load_firmware(priv);
553560424e9SKalle Valo 	if (err)
554560424e9SKalle Valo 		goto err2;
555560424e9SKalle Valo 
556560424e9SKalle Valo 	if (wait_event_interruptible_timeout(priv->wsm_startup_done,
557560424e9SKalle Valo 					     priv->firmware_ready,
558560424e9SKalle Valo 					     3*HZ) <= 0) {
559560424e9SKalle Valo 		/* TODO: Need to find how to reset device
560560424e9SKalle Valo 		   in QUEUE mode properly.
561560424e9SKalle Valo 		*/
562560424e9SKalle Valo 		pr_err("Timeout waiting on device startup\n");
563560424e9SKalle Valo 		err = -ETIMEDOUT;
564560424e9SKalle Valo 		goto err2;
565560424e9SKalle Valo 	}
566560424e9SKalle Valo 
567560424e9SKalle Valo 	/* Set low-power mode. */
568560424e9SKalle Valo 	wsm_set_operational_mode(priv, &mode);
569560424e9SKalle Valo 
570560424e9SKalle Valo 	/* Enable multi-TX confirmation */
571560424e9SKalle Valo 	wsm_use_multi_tx_conf(priv, true);
572560424e9SKalle Valo 
573560424e9SKalle Valo 	err = cw1200_register_common(dev);
574560424e9SKalle Valo 	if (err)
575560424e9SKalle Valo 		goto err2;
576560424e9SKalle Valo 
577560424e9SKalle Valo 	return err;
578560424e9SKalle Valo 
579560424e9SKalle Valo err2:
580560424e9SKalle Valo 	cw1200_unregister_bh(priv);
581560424e9SKalle Valo err1:
582560424e9SKalle Valo 	cw1200_free_common(dev);
583560424e9SKalle Valo err:
584560424e9SKalle Valo 	*core = NULL;
585560424e9SKalle Valo 	return err;
586560424e9SKalle Valo }
587560424e9SKalle Valo EXPORT_SYMBOL_GPL(cw1200_core_probe);
588560424e9SKalle Valo 
589560424e9SKalle Valo void cw1200_core_release(struct cw1200_common *self)
590560424e9SKalle Valo {
591560424e9SKalle Valo 	/* Disable device interrupts */
592560424e9SKalle Valo 	self->hwbus_ops->lock(self->hwbus_priv);
593560424e9SKalle Valo 	__cw1200_irq_enable(self, 0);
594560424e9SKalle Valo 	self->hwbus_ops->unlock(self->hwbus_priv);
595560424e9SKalle Valo 
596560424e9SKalle Valo 	/* And then clean up */
597560424e9SKalle Valo 	cw1200_unregister_common(self->hw);
598560424e9SKalle Valo 	cw1200_free_common(self->hw);
599560424e9SKalle Valo 	return;
600560424e9SKalle Valo }
601560424e9SKalle Valo EXPORT_SYMBOL_GPL(cw1200_core_release);
602