1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * This file is part of wl18xx
4 *
5 * Copyright (C) 2011 Texas Instruments
6 */
7
8#include <linux/module.h>
9#include <linux/mod_devicetable.h>
10#include <linux/platform_device.h>
11#include <linux/ip.h>
12#include <linux/firmware.h>
13#include <linux/etherdevice.h>
14#include <linux/irq.h>
15
16#include "../wlcore/wlcore.h"
17#include "../wlcore/debug.h"
18#include "../wlcore/io.h"
19#include "../wlcore/acx.h"
20#include "../wlcore/tx.h"
21#include "../wlcore/rx.h"
22#include "../wlcore/boot.h"
23
24#include "reg.h"
25#include "conf.h"
26#include "cmd.h"
27#include "acx.h"
28#include "tx.h"
29#include "wl18xx.h"
30#include "io.h"
31#include "scan.h"
32#include "event.h"
33#include "debugfs.h"
34
35#define WL18XX_RX_CHECKSUM_MASK      0x40
36
37static char *ht_mode_param = NULL;
38static char *board_type_param = NULL;
39static bool checksum_param = false;
40static int num_rx_desc_param = -1;
41
42/* phy paramters */
43static int dc2dc_param = -1;
44static int n_antennas_2_param = -1;
45static int n_antennas_5_param = -1;
46static int low_band_component_param = -1;
47static int low_band_component_type_param = -1;
48static int high_band_component_param = -1;
49static int high_band_component_type_param = -1;
50static int pwr_limit_reference_11_abg_param = -1;
51
52static const u8 wl18xx_rate_to_idx_2ghz[] = {
53	/* MCS rates are used only with 11n */
54	15,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS15 */
55	14,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS14 */
56	13,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS13 */
57	12,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS12 */
58	11,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS11 */
59	10,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS10 */
60	9,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS9 */
61	8,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS8 */
62	7,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS7 */
63	6,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS6 */
64	5,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS5 */
65	4,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS4 */
66	3,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS3 */
67	2,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS2 */
68	1,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS1 */
69	0,                             /* WL18XX_CONF_HW_RXTX_RATE_MCS0 */
70
71	11,                            /* WL18XX_CONF_HW_RXTX_RATE_54   */
72	10,                            /* WL18XX_CONF_HW_RXTX_RATE_48   */
73	9,                             /* WL18XX_CONF_HW_RXTX_RATE_36   */
74	8,                             /* WL18XX_CONF_HW_RXTX_RATE_24   */
75
76	/* TI-specific rate */
77	CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_22   */
78
79	7,                             /* WL18XX_CONF_HW_RXTX_RATE_18   */
80	6,                             /* WL18XX_CONF_HW_RXTX_RATE_12   */
81	3,                             /* WL18XX_CONF_HW_RXTX_RATE_11   */
82	5,                             /* WL18XX_CONF_HW_RXTX_RATE_9    */
83	4,                             /* WL18XX_CONF_HW_RXTX_RATE_6    */
84	2,                             /* WL18XX_CONF_HW_RXTX_RATE_5_5  */
85	1,                             /* WL18XX_CONF_HW_RXTX_RATE_2    */
86	0                              /* WL18XX_CONF_HW_RXTX_RATE_1    */
87};
88
89static const u8 wl18xx_rate_to_idx_5ghz[] = {
90	/* MCS rates are used only with 11n */
91	15,                           /* WL18XX_CONF_HW_RXTX_RATE_MCS15 */
92	14,                           /* WL18XX_CONF_HW_RXTX_RATE_MCS14 */
93	13,                           /* WL18XX_CONF_HW_RXTX_RATE_MCS13 */
94	12,                           /* WL18XX_CONF_HW_RXTX_RATE_MCS12 */
95	11,                           /* WL18XX_CONF_HW_RXTX_RATE_MCS11 */
96	10,                           /* WL18XX_CONF_HW_RXTX_RATE_MCS10 */
97	9,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS9 */
98	8,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS8 */
99	7,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS7 */
100	6,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS6 */
101	5,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS5 */
102	4,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS4 */
103	3,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS3 */
104	2,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS2 */
105	1,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS1 */
106	0,                            /* WL18XX_CONF_HW_RXTX_RATE_MCS0 */
107
108	7,                             /* WL18XX_CONF_HW_RXTX_RATE_54   */
109	6,                             /* WL18XX_CONF_HW_RXTX_RATE_48   */
110	5,                             /* WL18XX_CONF_HW_RXTX_RATE_36   */
111	4,                             /* WL18XX_CONF_HW_RXTX_RATE_24   */
112
113	/* TI-specific rate */
114	CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_22   */
115
116	3,                             /* WL18XX_CONF_HW_RXTX_RATE_18   */
117	2,                             /* WL18XX_CONF_HW_RXTX_RATE_12   */
118	CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_11   */
119	1,                             /* WL18XX_CONF_HW_RXTX_RATE_9    */
120	0,                             /* WL18XX_CONF_HW_RXTX_RATE_6    */
121	CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_5_5  */
122	CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_2    */
123	CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_1    */
124};
125
126static const u8 *wl18xx_band_rate_to_idx[] = {
127	[NL80211_BAND_2GHZ] = wl18xx_rate_to_idx_2ghz,
128	[NL80211_BAND_5GHZ] = wl18xx_rate_to_idx_5ghz
129};
130
131enum wl18xx_hw_rates {
132	WL18XX_CONF_HW_RXTX_RATE_MCS15 = 0,
133	WL18XX_CONF_HW_RXTX_RATE_MCS14,
134	WL18XX_CONF_HW_RXTX_RATE_MCS13,
135	WL18XX_CONF_HW_RXTX_RATE_MCS12,
136	WL18XX_CONF_HW_RXTX_RATE_MCS11,
137	WL18XX_CONF_HW_RXTX_RATE_MCS10,
138	WL18XX_CONF_HW_RXTX_RATE_MCS9,
139	WL18XX_CONF_HW_RXTX_RATE_MCS8,
140	WL18XX_CONF_HW_RXTX_RATE_MCS7,
141	WL18XX_CONF_HW_RXTX_RATE_MCS6,
142	WL18XX_CONF_HW_RXTX_RATE_MCS5,
143	WL18XX_CONF_HW_RXTX_RATE_MCS4,
144	WL18XX_CONF_HW_RXTX_RATE_MCS3,
145	WL18XX_CONF_HW_RXTX_RATE_MCS2,
146	WL18XX_CONF_HW_RXTX_RATE_MCS1,
147	WL18XX_CONF_HW_RXTX_RATE_MCS0,
148	WL18XX_CONF_HW_RXTX_RATE_54,
149	WL18XX_CONF_HW_RXTX_RATE_48,
150	WL18XX_CONF_HW_RXTX_RATE_36,
151	WL18XX_CONF_HW_RXTX_RATE_24,
152	WL18XX_CONF_HW_RXTX_RATE_22,
153	WL18XX_CONF_HW_RXTX_RATE_18,
154	WL18XX_CONF_HW_RXTX_RATE_12,
155	WL18XX_CONF_HW_RXTX_RATE_11,
156	WL18XX_CONF_HW_RXTX_RATE_9,
157	WL18XX_CONF_HW_RXTX_RATE_6,
158	WL18XX_CONF_HW_RXTX_RATE_5_5,
159	WL18XX_CONF_HW_RXTX_RATE_2,
160	WL18XX_CONF_HW_RXTX_RATE_1,
161	WL18XX_CONF_HW_RXTX_RATE_MAX,
162};
163
164static struct wlcore_conf wl18xx_conf = {
165	.sg = {
166		.params = {
167			[WL18XX_CONF_SG_PARAM_0] = 0,
168			/* Configuration Parameters */
169			[WL18XX_CONF_SG_ANTENNA_CONFIGURATION] = 0,
170			[WL18XX_CONF_SG_ZIGBEE_COEX] = 0,
171			[WL18XX_CONF_SG_TIME_SYNC] = 0,
172			[WL18XX_CONF_SG_PARAM_4] = 0,
173			[WL18XX_CONF_SG_PARAM_5] = 0,
174			[WL18XX_CONF_SG_PARAM_6] = 0,
175			[WL18XX_CONF_SG_PARAM_7] = 0,
176			[WL18XX_CONF_SG_PARAM_8] = 0,
177			[WL18XX_CONF_SG_PARAM_9] = 0,
178			[WL18XX_CONF_SG_PARAM_10] = 0,
179			[WL18XX_CONF_SG_PARAM_11] = 0,
180			[WL18XX_CONF_SG_PARAM_12] = 0,
181			[WL18XX_CONF_SG_PARAM_13] = 0,
182			[WL18XX_CONF_SG_PARAM_14] = 0,
183			[WL18XX_CONF_SG_PARAM_15] = 0,
184			[WL18XX_CONF_SG_PARAM_16] = 0,
185			[WL18XX_CONF_SG_PARAM_17] = 0,
186			[WL18XX_CONF_SG_PARAM_18] = 0,
187			[WL18XX_CONF_SG_PARAM_19] = 0,
188			[WL18XX_CONF_SG_PARAM_20] = 0,
189			[WL18XX_CONF_SG_PARAM_21] = 0,
190			[WL18XX_CONF_SG_PARAM_22] = 0,
191			[WL18XX_CONF_SG_PARAM_23] = 0,
192			[WL18XX_CONF_SG_PARAM_24] = 0,
193			[WL18XX_CONF_SG_PARAM_25] = 0,
194			/* Active Scan Parameters */
195			[WL18XX_CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
196			[WL18XX_CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
197			[WL18XX_CONF_SG_PARAM_28] = 0,
198			/* Passive Scan Parameters */
199			[WL18XX_CONF_SG_PARAM_29] = 0,
200			[WL18XX_CONF_SG_PARAM_30] = 0,
201			[WL18XX_CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
202			/* Passive Scan in Dual Antenna Parameters */
203			[WL18XX_CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0,
204			[WL18XX_CONF_SG_BEACON_HV3_COLL_TH_IN_PASSIVE_SCAN] = 0,
205			[WL18XX_CONF_SG_TX_RX_PROTECT_BW_IN_PASSIVE_SCAN] = 0,
206			/* General Parameters */
207			[WL18XX_CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1,
208			[WL18XX_CONF_SG_PARAM_36] = 0,
209			[WL18XX_CONF_SG_BEACON_MISS_PERCENT] = 60,
210			[WL18XX_CONF_SG_PARAM_38] = 0,
211			[WL18XX_CONF_SG_RXT] = 1200,
212			[WL18XX_CONF_SG_UNUSED] = 0,
213			[WL18XX_CONF_SG_ADAPTIVE_RXT_TXT] = 1,
214			[WL18XX_CONF_SG_GENERAL_USAGE_BIT_MAP] = 3,
215			[WL18XX_CONF_SG_HV3_MAX_SERVED] = 6,
216			[WL18XX_CONF_SG_PARAM_44] = 0,
217			[WL18XX_CONF_SG_PARAM_45] = 0,
218			[WL18XX_CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2,
219			[WL18XX_CONF_SG_GEMINI_PARAM_47] = 0,
220			[WL18XX_CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 0,
221			/* AP Parameters */
222			[WL18XX_CONF_SG_AP_BEACON_MISS_TX] = 3,
223			[WL18XX_CONF_SG_PARAM_50] = 0,
224			[WL18XX_CONF_SG_AP_BEACON_WINDOW_INTERVAL] = 2,
225			[WL18XX_CONF_SG_AP_CONNECTION_PROTECTION_TIME] = 30,
226			[WL18XX_CONF_SG_PARAM_53] = 0,
227			[WL18XX_CONF_SG_PARAM_54] = 0,
228			/* CTS Diluting Parameters */
229			[WL18XX_CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0,
230			[WL18XX_CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0,
231			[WL18XX_CONF_SG_TEMP_PARAM_1] = 0,
232			[WL18XX_CONF_SG_TEMP_PARAM_2] = 0,
233			[WL18XX_CONF_SG_TEMP_PARAM_3] = 0,
234			[WL18XX_CONF_SG_TEMP_PARAM_4] = 0,
235			[WL18XX_CONF_SG_TEMP_PARAM_5] = 0,
236			[WL18XX_CONF_SG_TEMP_PARAM_6] = 0,
237			[WL18XX_CONF_SG_TEMP_PARAM_7] = 0,
238			[WL18XX_CONF_SG_TEMP_PARAM_8] = 0,
239			[WL18XX_CONF_SG_TEMP_PARAM_9] = 0,
240			[WL18XX_CONF_SG_TEMP_PARAM_10] = 0,
241		},
242		.state = CONF_SG_PROTECTIVE,
243	},
244	.rx = {
245		.rx_msdu_life_time           = 512000,
246		.packet_detection_threshold  = 0,
247		.ps_poll_timeout             = 15,
248		.upsd_timeout                = 15,
249		.rts_threshold               = IEEE80211_MAX_RTS_THRESHOLD,
250		.rx_cca_threshold            = 0,
251		.irq_blk_threshold           = 0xFFFF,
252		.irq_pkt_threshold           = 0,
253		.irq_timeout                 = 600,
254		.queue_type                  = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
255	},
256	.tx = {
257		.tx_energy_detection         = 0,
258		.sta_rc_conf                 = {
259			.enabled_rates       = 0,
260			.short_retry_limit   = 10,
261			.long_retry_limit    = 10,
262			.aflags              = 0,
263		},
264		.ac_conf_count               = 4,
265		.ac_conf                     = {
266			[CONF_TX_AC_BE] = {
267				.ac          = CONF_TX_AC_BE,
268				.cw_min      = 15,
269				.cw_max      = 63,
270				.aifsn       = 3,
271				.tx_op_limit = 0,
272			},
273			[CONF_TX_AC_BK] = {
274				.ac          = CONF_TX_AC_BK,
275				.cw_min      = 15,
276				.cw_max      = 63,
277				.aifsn       = 7,
278				.tx_op_limit = 0,
279			},
280			[CONF_TX_AC_VI] = {
281				.ac          = CONF_TX_AC_VI,
282				.cw_min      = 15,
283				.cw_max      = 63,
284				.aifsn       = CONF_TX_AIFS_PIFS,
285				.tx_op_limit = 3008,
286			},
287			[CONF_TX_AC_VO] = {
288				.ac          = CONF_TX_AC_VO,
289				.cw_min      = 15,
290				.cw_max      = 63,
291				.aifsn       = CONF_TX_AIFS_PIFS,
292				.tx_op_limit = 1504,
293			},
294		},
295		.max_tx_retries = 100,
296		.ap_aging_period = 300,
297		.tid_conf_count = 4,
298		.tid_conf = {
299			[CONF_TX_AC_BE] = {
300				.queue_id    = CONF_TX_AC_BE,
301				.channel_type = CONF_CHANNEL_TYPE_EDCF,
302				.tsid        = CONF_TX_AC_BE,
303				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
304				.ack_policy  = CONF_ACK_POLICY_LEGACY,
305				.apsd_conf   = {0, 0},
306			},
307			[CONF_TX_AC_BK] = {
308				.queue_id    = CONF_TX_AC_BK,
309				.channel_type = CONF_CHANNEL_TYPE_EDCF,
310				.tsid        = CONF_TX_AC_BK,
311				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
312				.ack_policy  = CONF_ACK_POLICY_LEGACY,
313				.apsd_conf   = {0, 0},
314			},
315			[CONF_TX_AC_VI] = {
316				.queue_id    = CONF_TX_AC_VI,
317				.channel_type = CONF_CHANNEL_TYPE_EDCF,
318				.tsid        = CONF_TX_AC_VI,
319				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
320				.ack_policy  = CONF_ACK_POLICY_LEGACY,
321				.apsd_conf   = {0, 0},
322			},
323			[CONF_TX_AC_VO] = {
324				.queue_id    = CONF_TX_AC_VO,
325				.channel_type = CONF_CHANNEL_TYPE_EDCF,
326				.tsid        = CONF_TX_AC_VO,
327				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
328				.ack_policy  = CONF_ACK_POLICY_LEGACY,
329				.apsd_conf   = {0, 0},
330			},
331		},
332		.frag_threshold              = IEEE80211_MAX_FRAG_THRESHOLD,
333		.tx_compl_timeout            = 350,
334		.tx_compl_threshold          = 10,
335		.basic_rate                  = CONF_HW_BIT_RATE_1MBPS,
336		.basic_rate_5                = CONF_HW_BIT_RATE_6MBPS,
337		.tmpl_short_retry_limit      = 10,
338		.tmpl_long_retry_limit       = 10,
339		.tx_watchdog_timeout         = 5000,
340		.slow_link_thold             = 3,
341		.fast_link_thold             = 30,
342	},
343	.conn = {
344		.wake_up_event               = CONF_WAKE_UP_EVENT_DTIM,
345		.listen_interval             = 1,
346		.suspend_wake_up_event       = CONF_WAKE_UP_EVENT_N_DTIM,
347		.suspend_listen_interval     = 3,
348		.bcn_filt_mode               = CONF_BCN_FILT_MODE_ENABLED,
349		.bcn_filt_ie_count           = 3,
350		.bcn_filt_ie = {
351			[0] = {
352				.ie          = WLAN_EID_CHANNEL_SWITCH,
353				.rule        = CONF_BCN_RULE_PASS_ON_APPEARANCE,
354			},
355			[1] = {
356				.ie          = WLAN_EID_HT_OPERATION,
357				.rule        = CONF_BCN_RULE_PASS_ON_CHANGE,
358			},
359			[2] = {
360				.ie	     = WLAN_EID_ERP_INFO,
361				.rule	     = CONF_BCN_RULE_PASS_ON_CHANGE,
362			},
363		},
364		.synch_fail_thold            = 12,
365		.bss_lose_timeout            = 400,
366		.beacon_rx_timeout           = 10000,
367		.broadcast_timeout           = 20000,
368		.rx_broadcast_in_ps          = 1,
369		.ps_poll_threshold           = 10,
370		.bet_enable                  = CONF_BET_MODE_ENABLE,
371		.bet_max_consecutive         = 50,
372		.psm_entry_retries           = 8,
373		.psm_exit_retries            = 16,
374		.psm_entry_nullfunc_retries  = 3,
375		.dynamic_ps_timeout          = 1500,
376		.forced_ps                   = false,
377		.keep_alive_interval         = 55000,
378		.max_listen_interval         = 20,
379		.sta_sleep_auth              = WL1271_PSM_ILLEGAL,
380		.suspend_rx_ba_activity      = 0,
381	},
382	.itrim = {
383		.enable = false,
384		.timeout = 50000,
385	},
386	.pm_config = {
387		.host_clk_settling_time = 5000,
388		.host_fast_wakeup_support = CONF_FAST_WAKEUP_DISABLE,
389	},
390	.roam_trigger = {
391		.trigger_pacing               = 1,
392		.avg_weight_rssi_beacon       = 20,
393		.avg_weight_rssi_data         = 10,
394		.avg_weight_snr_beacon        = 20,
395		.avg_weight_snr_data          = 10,
396	},
397	.scan = {
398		.min_dwell_time_active        = 7500,
399		.max_dwell_time_active        = 30000,
400		.min_dwell_time_active_long   = 25000,
401		.max_dwell_time_active_long   = 50000,
402		.dwell_time_passive           = 100000,
403		.dwell_time_dfs               = 150000,
404		.num_probe_reqs               = 2,
405		.split_scan_timeout           = 50000,
406	},
407	.sched_scan = {
408		/*
409		 * Values are in TU/1000 but since sched scan FW command
410		 * params are in TUs rounding up may occur.
411		 */
412		.base_dwell_time		= 7500,
413		.max_dwell_time_delta		= 22500,
414		/* based on 250bits per probe @1Mbps */
415		.dwell_time_delta_per_probe	= 2000,
416		/* based on 250bits per probe @6Mbps (plus a bit more) */
417		.dwell_time_delta_per_probe_5	= 350,
418		.dwell_time_passive		= 100000,
419		.dwell_time_dfs			= 150000,
420		.num_probe_reqs			= 2,
421		.rssi_threshold			= -90,
422		.snr_threshold			= 0,
423		.num_short_intervals		= SCAN_MAX_SHORT_INTERVALS,
424		.long_interval			= 30000,
425	},
426	.ht = {
427		.rx_ba_win_size = 32,
428		.tx_ba_win_size = 64,
429		.inactivity_timeout = 10000,
430		.tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
431	},
432	.mem = {
433		.num_stations                 = 1,
434		.ssid_profiles                = 1,
435		.rx_block_num                 = 40,
436		.tx_min_block_num             = 40,
437		.dynamic_memory               = 1,
438		.min_req_tx_blocks            = 45,
439		.min_req_rx_blocks            = 22,
440		.tx_min                       = 27,
441	},
442	.fm_coex = {
443		.enable                       = true,
444		.swallow_period               = 5,
445		.n_divider_fref_set_1         = 0xff,       /* default */
446		.n_divider_fref_set_2         = 12,
447		.m_divider_fref_set_1         = 0xffff,
448		.m_divider_fref_set_2         = 148,        /* default */
449		.coex_pll_stabilization_time  = 0xffffffff, /* default */
450		.ldo_stabilization_time       = 0xffff,     /* default */
451		.fm_disturbed_band_margin     = 0xff,       /* default */
452		.swallow_clk_diff             = 0xff,       /* default */
453	},
454	.rx_streaming = {
455		.duration                      = 150,
456		.queues                        = 0x1,
457		.interval                      = 20,
458		.always                        = 0,
459	},
460	.fwlog = {
461		.mode                         = WL12XX_FWLOG_CONTINUOUS,
462		.mem_blocks                   = 0,
463		.severity                     = 0,
464		.timestamp                    = WL12XX_FWLOG_TIMESTAMP_DISABLED,
465		.output                       = WL12XX_FWLOG_OUTPUT_DBG_PINS,
466		.threshold                    = 0,
467	},
468	.rate = {
469		.rate_retry_score = 32000,
470		.per_add = 8192,
471		.per_th1 = 2048,
472		.per_th2 = 4096,
473		.max_per = 8100,
474		.inverse_curiosity_factor = 5,
475		.tx_fail_low_th = 4,
476		.tx_fail_high_th = 10,
477		.per_alpha_shift = 4,
478		.per_add_shift = 13,
479		.per_beta1_shift = 10,
480		.per_beta2_shift = 8,
481		.rate_check_up = 2,
482		.rate_check_down = 12,
483		.rate_retry_policy = {
484			0x00, 0x00, 0x00, 0x00, 0x00,
485			0x00, 0x00, 0x00, 0x00, 0x00,
486			0x00, 0x00, 0x00,
487		},
488	},
489	.hangover = {
490		.recover_time               = 0,
491		.hangover_period            = 20,
492		.dynamic_mode               = 1,
493		.early_termination_mode     = 1,
494		.max_period                 = 20,
495		.min_period                 = 1,
496		.increase_delta             = 1,
497		.decrease_delta             = 2,
498		.quiet_time                 = 4,
499		.increase_time              = 1,
500		.window_size                = 16,
501	},
502	.recovery = {
503		.bug_on_recovery	    = 0,
504		.no_recovery		    = 0,
505	},
506};
507
508static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
509	.ht = {
510		.mode				= HT_MODE_WIDE,
511	},
512	.phy = {
513		.phy_standalone			= 0x00,
514		.primary_clock_setting_time	= 0x05,
515		.clock_valid_on_wake_up		= 0x00,
516		.secondary_clock_setting_time	= 0x05,
517		.board_type 			= BOARD_TYPE_HDK_18XX,
518		.auto_detect			= 0x00,
519		.dedicated_fem			= FEM_NONE,
520		.low_band_component		= COMPONENT_3_WAY_SWITCH,
521		.low_band_component_type	= 0x05,
522		.high_band_component		= COMPONENT_2_WAY_SWITCH,
523		.high_band_component_type	= 0x09,
524		.tcxo_ldo_voltage		= 0x00,
525		.xtal_itrim_val			= 0x04,
526		.srf_state			= 0x00,
527		.io_configuration		= 0x01,
528		.sdio_configuration		= 0x00,
529		.settings			= 0x00,
530		.enable_clpc			= 0x00,
531		.enable_tx_low_pwr_on_siso_rdl	= 0x00,
532		.rx_profile			= 0x00,
533		.pwr_limit_reference_11_abg	= 0x64,
534		.per_chan_pwr_limit_arr_11abg	= {
535			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
536			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
537			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
538			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
539			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
540			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
541			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
542			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
543			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
544			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
545			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
546			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
547			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
548			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
549			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
550			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
551			0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
552		.pwr_limit_reference_11p	= 0x64,
553		.per_chan_bo_mode_11_abg	= { 0x00, 0x00, 0x00, 0x00,
554						    0x00, 0x00, 0x00, 0x00,
555						    0x00, 0x00, 0x00, 0x00,
556						    0x00 },
557		.per_chan_bo_mode_11_p		= { 0x00, 0x00, 0x00, 0x00 },
558		.per_chan_pwr_limit_arr_11p	= { 0xff, 0xff, 0xff, 0xff,
559						    0xff, 0xff, 0xff },
560		.psat				= 0,
561		.external_pa_dc2dc		= 0,
562		.number_of_assembled_ant2_4	= 2,
563		.number_of_assembled_ant5	= 1,
564		.low_power_val			= 0xff,
565		.med_power_val			= 0xff,
566		.high_power_val			= 0xff,
567		.low_power_val_2nd		= 0xff,
568		.med_power_val_2nd		= 0xff,
569		.high_power_val_2nd		= 0xff,
570		.tx_rf_margin			= 1,
571	},
572	.ap_sleep = {               /* disabled by default */
573		.idle_duty_cycle        = 0,
574		.connected_duty_cycle   = 0,
575		.max_stations_thresh    = 0,
576		.idle_conn_thresh       = 0,
577	},
578};
579
580static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = {
581	[PART_TOP_PRCM_ELP_SOC] = {
582		.mem  = { .start = 0x00A00000, .size  = 0x00012000 },
583		.reg  = { .start = 0x00807000, .size  = 0x00005000 },
584		.mem2 = { .start = 0x00800000, .size  = 0x0000B000 },
585		.mem3 = { .start = 0x00401594, .size  = 0x00001020 },
586	},
587	[PART_DOWN] = {
588		.mem  = { .start = 0x00000000, .size  = 0x00014000 },
589		.reg  = { .start = 0x00810000, .size  = 0x0000BFFF },
590		.mem2 = { .start = 0x00000000, .size  = 0x00000000 },
591		.mem3 = { .start = 0x00000000, .size  = 0x00000000 },
592	},
593	[PART_BOOT] = {
594		.mem  = { .start = 0x00700000, .size = 0x0000030c },
595		.reg  = { .start = 0x00802000, .size = 0x00014578 },
596		.mem2 = { .start = 0x00B00404, .size = 0x00001000 },
597		.mem3 = { .start = 0x00C00000, .size = 0x00000400 },
598	},
599	[PART_WORK] = {
600		.mem  = { .start = 0x00800000, .size  = 0x000050FC },
601		.reg  = { .start = 0x00B00404, .size  = 0x00001000 },
602		.mem2 = { .start = 0x00C00000, .size  = 0x00000400 },
603		.mem3 = { .start = 0x00401594, .size  = 0x00001020 },
604	},
605	[PART_PHY_INIT] = {
606		.mem  = { .start = WL18XX_PHY_INIT_MEM_ADDR,
607			  .size  = WL18XX_PHY_INIT_MEM_SIZE },
608		.reg  = { .start = 0x00000000, .size = 0x00000000 },
609		.mem2 = { .start = 0x00000000, .size = 0x00000000 },
610		.mem3 = { .start = 0x00000000, .size = 0x00000000 },
611	},
612};
613
614static const int wl18xx_rtable[REG_TABLE_LEN] = {
615	[REG_ECPU_CONTROL]		= WL18XX_REG_ECPU_CONTROL,
616	[REG_INTERRUPT_NO_CLEAR]	= WL18XX_REG_INTERRUPT_NO_CLEAR,
617	[REG_INTERRUPT_ACK]		= WL18XX_REG_INTERRUPT_ACK,
618	[REG_COMMAND_MAILBOX_PTR]	= WL18XX_REG_COMMAND_MAILBOX_PTR,
619	[REG_EVENT_MAILBOX_PTR]		= WL18XX_REG_EVENT_MAILBOX_PTR,
620	[REG_INTERRUPT_TRIG]		= WL18XX_REG_INTERRUPT_TRIG_H,
621	[REG_INTERRUPT_MASK]		= WL18XX_REG_INTERRUPT_MASK,
622	[REG_PC_ON_RECOVERY]		= WL18XX_SCR_PAD4,
623	[REG_CHIP_ID_B]			= WL18XX_REG_CHIP_ID_B,
624	[REG_CMD_MBOX_ADDRESS]		= WL18XX_CMD_MBOX_ADDRESS,
625
626	/* data access memory addresses, used with partition translation */
627	[REG_SLV_MEM_DATA]		= WL18XX_SLV_MEM_DATA,
628	[REG_SLV_REG_DATA]		= WL18XX_SLV_REG_DATA,
629
630	/* raw data access memory addresses */
631	[REG_RAW_FW_STATUS_ADDR]	= WL18XX_FW_STATUS_ADDR,
632};
633
634static const struct wl18xx_clk_cfg wl18xx_clk_table_coex[NUM_CLOCK_CONFIGS] = {
635	[CLOCK_CONFIG_16_2_M]	= { 8,  121, 0, 0, false },
636	[CLOCK_CONFIG_16_368_M]	= { 8,  120, 0, 0, false },
637	[CLOCK_CONFIG_16_8_M]	= { 8,  117, 0, 0, false },
638	[CLOCK_CONFIG_19_2_M]	= { 10, 128, 0, 0, false },
639	[CLOCK_CONFIG_26_M]	= { 11, 104, 0, 0, false },
640	[CLOCK_CONFIG_32_736_M]	= { 8,  120, 0, 0, false },
641	[CLOCK_CONFIG_33_6_M]	= { 8,  117, 0, 0, false },
642	[CLOCK_CONFIG_38_468_M]	= { 10, 128, 0, 0, false },
643	[CLOCK_CONFIG_52_M]	= { 11, 104, 0, 0, false },
644};
645
646static const struct wl18xx_clk_cfg wl18xx_clk_table[NUM_CLOCK_CONFIGS] = {
647	[CLOCK_CONFIG_16_2_M]	= { 7,  104,  801, 4,  true },
648	[CLOCK_CONFIG_16_368_M]	= { 9,  132, 3751, 4,  true },
649	[CLOCK_CONFIG_16_8_M]	= { 7,  100,    0, 0, false },
650	[CLOCK_CONFIG_19_2_M]	= { 8,  100,    0, 0, false },
651	[CLOCK_CONFIG_26_M]	= { 13, 120,    0, 0, false },
652	[CLOCK_CONFIG_32_736_M]	= { 9,  132, 3751, 4,  true },
653	[CLOCK_CONFIG_33_6_M]	= { 7,  100,    0, 0, false },
654	[CLOCK_CONFIG_38_468_M]	= { 8,  100,    0, 0, false },
655	[CLOCK_CONFIG_52_M]	= { 13, 120,    0, 0, false },
656};
657
658/* TODO: maybe move to a new header file? */
659#define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw-4.bin"
660
661static int wl18xx_identify_chip(struct wl1271 *wl)
662{
663	int ret = 0;
664
665	switch (wl->chip.id) {
666	case CHIP_ID_185x_PG20:
667		wl1271_debug(DEBUG_BOOT, "chip id 0x%x (185x PG20)",
668				 wl->chip.id);
669		wl->sr_fw_name = WL18XX_FW_NAME;
670		/* wl18xx uses the same firmware for PLT */
671		wl->plt_fw_name = WL18XX_FW_NAME;
672		wl->quirks |= WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN |
673			      WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN |
674			      WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN |
675			      WLCORE_QUIRK_TX_PAD_LAST_FRAME |
676			      WLCORE_QUIRK_REGDOMAIN_CONF |
677			      WLCORE_QUIRK_DUAL_PROBE_TMPL;
678
679		wlcore_set_min_fw_ver(wl, WL18XX_CHIP_VER,
680				      WL18XX_IFTYPE_VER,  WL18XX_MAJOR_VER,
681				      WL18XX_SUBTYPE_VER, WL18XX_MINOR_VER,
682				      /* there's no separate multi-role FW */
683				      0, 0, 0, 0);
684		break;
685	case CHIP_ID_185x_PG10:
686		wl1271_warning("chip id 0x%x (185x PG10) is deprecated",
687			       wl->chip.id);
688		ret = -ENODEV;
689		goto out;
690
691	default:
692		wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
693		ret = -ENODEV;
694		goto out;
695	}
696
697	wl->fw_mem_block_size = 272;
698	wl->fwlog_end = 0x40000000;
699
700	wl->scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4;
701	wl->scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5;
702	wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC;
703	wl->sched_scan_templ_id_5 = CMD_TEMPL_PROBE_REQ_5_PERIODIC;
704	wl->max_channels_5 = WL18XX_MAX_CHANNELS_5GHZ;
705	wl->ba_rx_session_count_max = WL18XX_RX_BA_MAX_SESSIONS;
706out:
707	return ret;
708}
709
710static int wl18xx_set_clk(struct wl1271 *wl)
711{
712	u16 clk_freq;
713	int ret;
714
715	ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
716	if (ret < 0)
717		goto out;
718
719	/* TODO: PG2: apparently we need to read the clk type */
720
721	ret = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT, &clk_freq);
722	if (ret < 0)
723		goto out;
724
725	wl1271_debug(DEBUG_BOOT, "clock freq %d (%d, %d, %d, %d, %s)", clk_freq,
726		     wl18xx_clk_table[clk_freq].n, wl18xx_clk_table[clk_freq].m,
727		     wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q,
728		     wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit");
729
730	/* coex PLL configuration */
731	ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_N,
732				   wl18xx_clk_table_coex[clk_freq].n);
733	if (ret < 0)
734		goto out;
735
736	ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_M,
737				   wl18xx_clk_table_coex[clk_freq].m);
738	if (ret < 0)
739		goto out;
740
741	/* bypass the swallowing logic */
742	ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_SWALLOW_EN,
743				   PLLSH_COEX_PLL_SWALLOW_EN_VAL1);
744	if (ret < 0)
745		goto out;
746
747	ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N,
748				   wl18xx_clk_table[clk_freq].n);
749	if (ret < 0)
750		goto out;
751
752	ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M,
753				   wl18xx_clk_table[clk_freq].m);
754	if (ret < 0)
755		goto out;
756
757	if (wl18xx_clk_table[clk_freq].swallow) {
758		/* first the 16 lower bits */
759		ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1,
760					   wl18xx_clk_table[clk_freq].q &
761					   PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK);
762		if (ret < 0)
763			goto out;
764
765		/* then the 16 higher bits, masked out */
766		ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2,
767					(wl18xx_clk_table[clk_freq].q >> 16) &
768					PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK);
769		if (ret < 0)
770			goto out;
771
772		/* first the 16 lower bits */
773		ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1,
774					   wl18xx_clk_table[clk_freq].p &
775					   PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK);
776		if (ret < 0)
777			goto out;
778
779		/* then the 16 higher bits, masked out */
780		ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2,
781					(wl18xx_clk_table[clk_freq].p >> 16) &
782					PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK);
783		if (ret < 0)
784			goto out;
785	} else {
786		ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN,
787					   PLLSH_WCS_PLL_SWALLOW_EN_VAL2);
788		if (ret < 0)
789			goto out;
790	}
791
792	/* choose WCS PLL */
793	ret = wl18xx_top_reg_write(wl, PLLSH_WL_PLL_SEL,
794				   PLLSH_WL_PLL_SEL_WCS_PLL);
795	if (ret < 0)
796		goto out;
797
798	/* enable both PLLs */
799	ret = wl18xx_top_reg_write(wl, PLLSH_WL_PLL_EN, PLLSH_WL_PLL_EN_VAL1);
800	if (ret < 0)
801		goto out;
802
803	udelay(1000);
804
805	/* disable coex PLL */
806	ret = wl18xx_top_reg_write(wl, PLLSH_WL_PLL_EN, PLLSH_WL_PLL_EN_VAL2);
807	if (ret < 0)
808		goto out;
809
810	/* reset the swallowing logic */
811	ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_SWALLOW_EN,
812				   PLLSH_COEX_PLL_SWALLOW_EN_VAL2);
813
814out:
815	return ret;
816}
817
818static int wl18xx_boot_soft_reset(struct wl1271 *wl)
819{
820	int ret;
821
822	/* disable Rx/Tx */
823	ret = wlcore_write32(wl, WL18XX_ENABLE, 0x0);
824	if (ret < 0)
825		goto out;
826
827	/* disable auto calibration on start*/
828	ret = wlcore_write32(wl, WL18XX_SPARE_A2, 0xffff);
829
830out:
831	return ret;
832}
833
834static int wl18xx_pre_boot(struct wl1271 *wl)
835{
836	int ret;
837
838	ret = wl18xx_set_clk(wl);
839	if (ret < 0)
840		goto out;
841
842	/* Continue the ELP wake up sequence */
843	ret = wlcore_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
844	if (ret < 0)
845		goto out;
846
847	udelay(500);
848
849	ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
850	if (ret < 0)
851		goto out;
852
853	/* Disable interrupts */
854	ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
855	if (ret < 0)
856		goto out;
857
858	ret = wl18xx_boot_soft_reset(wl);
859
860out:
861	return ret;
862}
863
864static int wl18xx_pre_upload(struct wl1271 *wl)
865{
866	u32 tmp;
867	int ret;
868	u16 irq_invert;
869
870	BUILD_BUG_ON(sizeof(struct wl18xx_mac_and_phy_params) >
871		WL18XX_PHY_INIT_MEM_SIZE);
872
873	ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
874	if (ret < 0)
875		goto out;
876
877	/* TODO: check if this is all needed */
878	ret = wlcore_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND);
879	if (ret < 0)
880		goto out;
881
882	ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp);
883	if (ret < 0)
884		goto out;
885
886	wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
887
888	ret = wlcore_read32(wl, WL18XX_SCR_PAD2, &tmp);
889	if (ret < 0)
890		goto out;
891
892	/*
893	 * Workaround for FDSP code RAM corruption (needed for PG2.1
894	 * and newer; for older chips it's a NOP).  Change FDSP clock
895	 * settings so that it's muxed to the ATGP clock instead of
896	 * its own clock.
897	 */
898
899	ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
900	if (ret < 0)
901		goto out;
902
903	/* disable FDSP clock */
904	ret = wlcore_write32(wl, WL18XX_PHY_FPGA_SPARE_1,
905			     MEM_FDSP_CLK_120_DISABLE);
906	if (ret < 0)
907		goto out;
908
909	/* set ATPG clock toward FDSP Code RAM rather than its own clock */
910	ret = wlcore_write32(wl, WL18XX_PHY_FPGA_SPARE_1,
911			     MEM_FDSP_CODERAM_FUNC_CLK_SEL);
912	if (ret < 0)
913		goto out;
914
915	/* re-enable FDSP clock */
916	ret = wlcore_write32(wl, WL18XX_PHY_FPGA_SPARE_1,
917			     MEM_FDSP_CLK_120_ENABLE);
918	if (ret < 0)
919		goto out;
920
921	ret = irq_get_trigger_type(wl->irq);
922	if ((ret == IRQ_TYPE_LEVEL_LOW) || (ret == IRQ_TYPE_EDGE_FALLING)) {
923		wl1271_info("using inverted interrupt logic: %d", ret);
924		ret = wlcore_set_partition(wl,
925					   &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
926		if (ret < 0)
927			goto out;
928
929		ret = wl18xx_top_reg_read(wl, TOP_FN0_CCCR_REG_32, &irq_invert);
930		if (ret < 0)
931			goto out;
932
933		irq_invert |= BIT(1);
934		ret = wl18xx_top_reg_write(wl, TOP_FN0_CCCR_REG_32, irq_invert);
935		if (ret < 0)
936			goto out;
937
938		ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
939	}
940
941out:
942	return ret;
943}
944
945static int wl18xx_set_mac_and_phy(struct wl1271 *wl)
946{
947	struct wl18xx_priv *priv = wl->priv;
948	struct wl18xx_mac_and_phy_params *params;
949	int ret;
950
951	params = kmemdup(&priv->conf.phy, sizeof(*params), GFP_KERNEL);
952	if (!params) {
953		ret = -ENOMEM;
954		goto out;
955	}
956
957	ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
958	if (ret < 0)
959		goto out;
960
961	ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, params,
962			   sizeof(*params), false);
963
964out:
965	kfree(params);
966	return ret;
967}
968
969static int wl18xx_enable_interrupts(struct wl1271 *wl)
970{
971	u32 event_mask, intr_mask;
972	int ret;
973
974	event_mask = WL18XX_ACX_EVENTS_VECTOR;
975	intr_mask = WL18XX_INTR_MASK;
976
977	ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask);
978	if (ret < 0)
979		goto out;
980
981	wlcore_enable_interrupts(wl);
982
983	ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK,
984			       WL1271_ACX_INTR_ALL & ~intr_mask);
985	if (ret < 0)
986		goto disable_interrupts;
987
988	return ret;
989
990disable_interrupts:
991	wlcore_disable_interrupts(wl);
992
993out:
994	return ret;
995}
996
997static int wl18xx_boot(struct wl1271 *wl)
998{
999	int ret;
1000
1001	ret = wl18xx_pre_boot(wl);
1002	if (ret < 0)
1003		goto out;
1004
1005	ret = wl18xx_pre_upload(wl);
1006	if (ret < 0)
1007		goto out;
1008
1009	ret = wlcore_boot_upload_firmware(wl);
1010	if (ret < 0)
1011		goto out;
1012
1013	ret = wl18xx_set_mac_and_phy(wl);
1014	if (ret < 0)
1015		goto out;
1016
1017	wl->event_mask = BSS_LOSS_EVENT_ID |
1018		SCAN_COMPLETE_EVENT_ID |
1019		RADAR_DETECTED_EVENT_ID |
1020		RSSI_SNR_TRIGGER_0_EVENT_ID |
1021		PERIODIC_SCAN_COMPLETE_EVENT_ID |
1022		PERIODIC_SCAN_REPORT_EVENT_ID |
1023		DUMMY_PACKET_EVENT_ID |
1024		PEER_REMOVE_COMPLETE_EVENT_ID |
1025		BA_SESSION_RX_CONSTRAINT_EVENT_ID |
1026		REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
1027		INACTIVE_STA_EVENT_ID |
1028		CHANNEL_SWITCH_COMPLETE_EVENT_ID |
1029		DFS_CHANNELS_CONFIG_COMPLETE_EVENT |
1030		SMART_CONFIG_SYNC_EVENT_ID |
1031		SMART_CONFIG_DECODE_EVENT_ID |
1032		TIME_SYNC_EVENT_ID |
1033		FW_LOGGER_INDICATION |
1034		RX_BA_WIN_SIZE_CHANGE_EVENT_ID;
1035
1036	wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID;
1037
1038	ret = wlcore_boot_run_firmware(wl);
1039	if (ret < 0)
1040		goto out;
1041
1042	ret = wl18xx_enable_interrupts(wl);
1043
1044out:
1045	return ret;
1046}
1047
1048static int wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
1049			       void *buf, size_t len)
1050{
1051	struct wl18xx_priv *priv = wl->priv;
1052
1053	memcpy(priv->cmd_buf, buf, len);
1054	memset(priv->cmd_buf + len, 0, WL18XX_CMD_MAX_SIZE - len);
1055
1056	return wlcore_write(wl, cmd_box_addr, priv->cmd_buf,
1057			    WL18XX_CMD_MAX_SIZE, false);
1058}
1059
1060static int wl18xx_ack_event(struct wl1271 *wl)
1061{
1062	return wlcore_write_reg(wl, REG_INTERRUPT_TRIG,
1063				WL18XX_INTR_TRIG_EVENT_ACK);
1064}
1065
1066static u32 wl18xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
1067{
1068	u32 blk_size = WL18XX_TX_HW_BLOCK_SIZE;
1069	return (len + blk_size - 1) / blk_size + spare_blks;
1070}
1071
1072static void
1073wl18xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
1074			  u32 blks, u32 spare_blks)
1075{
1076	desc->wl18xx_mem.total_mem_blocks = blks;
1077}
1078
1079static void
1080wl18xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
1081			    struct sk_buff *skb)
1082{
1083	desc->length = cpu_to_le16(skb->len);
1084
1085	/* if only the last frame is to be padded, we unset this bit on Tx */
1086	if (wl->quirks & WLCORE_QUIRK_TX_PAD_LAST_FRAME)
1087		desc->wl18xx_mem.ctrl = WL18XX_TX_CTRL_NOT_PADDED;
1088	else
1089		desc->wl18xx_mem.ctrl = 0;
1090
1091	wl1271_debug(DEBUG_TX, "tx_fill_hdr: hlid: %d "
1092		     "len: %d life: %d mem: %d", desc->hlid,
1093		     le16_to_cpu(desc->length),
1094		     le16_to_cpu(desc->life_time),
1095		     desc->wl18xx_mem.total_mem_blocks);
1096}
1097
1098static enum wl_rx_buf_align
1099wl18xx_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
1100{
1101	if (rx_desc & RX_BUF_PADDED_PAYLOAD)
1102		return WLCORE_RX_BUF_PADDED;
1103
1104	return WLCORE_RX_BUF_ALIGNED;
1105}
1106
1107static u32 wl18xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
1108				    u32 data_len)
1109{
1110	struct wl1271_rx_descriptor *desc = rx_data;
1111
1112	/* invalid packet */
1113	if (data_len < sizeof(*desc))
1114		return 0;
1115
1116	return data_len - sizeof(*desc);
1117}
1118
1119static void wl18xx_tx_immediate_completion(struct wl1271 *wl)
1120{
1121	wl18xx_tx_immediate_complete(wl);
1122}
1123
1124static int wl18xx_set_host_cfg_bitmap(struct wl1271 *wl, u32 extra_mem_blk)
1125{
1126	int ret;
1127	u32 sdio_align_size = 0;
1128	u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE |
1129			      HOST_IF_CFG_ADD_RX_ALIGNMENT;
1130
1131	/* Enable Tx SDIO padding */
1132	if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN) {
1133		host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK;
1134		sdio_align_size = WL12XX_BUS_BLOCK_SIZE;
1135	}
1136
1137	/* Enable Rx SDIO padding */
1138	if (wl->quirks & WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN) {
1139		host_cfg_bitmap |= HOST_IF_CFG_RX_PAD_TO_SDIO_BLK;
1140		sdio_align_size = WL12XX_BUS_BLOCK_SIZE;
1141	}
1142
1143	ret = wl18xx_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap,
1144					    sdio_align_size, extra_mem_blk,
1145					    WL18XX_HOST_IF_LEN_SIZE_FIELD);
1146	if (ret < 0)
1147		return ret;
1148
1149	return 0;
1150}
1151
1152static int wl18xx_hw_init(struct wl1271 *wl)
1153{
1154	int ret;
1155	struct wl18xx_priv *priv = wl->priv;
1156
1157	/* (re)init private structures. Relevant on recovery as well. */
1158	priv->last_fw_rls_idx = 0;
1159	priv->extra_spare_key_count = 0;
1160
1161	/* set the default amount of spare blocks in the bitmap */
1162	ret = wl18xx_set_host_cfg_bitmap(wl, WL18XX_TX_HW_BLOCK_SPARE);
1163	if (ret < 0)
1164		return ret;
1165
1166	/* set the dynamic fw traces bitmap */
1167	ret = wl18xx_acx_dynamic_fw_traces(wl);
1168	if (ret < 0)
1169		return ret;
1170
1171	if (checksum_param) {
1172		ret = wl18xx_acx_set_checksum_state(wl);
1173		if (ret != 0)
1174			return ret;
1175	}
1176
1177	return ret;
1178}
1179
1180static void wl18xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
1181				     struct wl_fw_status *fw_status)
1182{
1183	struct wl18xx_fw_status *int_fw_status = raw_fw_status;
1184
1185	fw_status->intr = le32_to_cpu(int_fw_status->intr);
1186	fw_status->fw_rx_counter = int_fw_status->fw_rx_counter;
1187	fw_status->drv_rx_counter = int_fw_status->drv_rx_counter;
1188	fw_status->tx_results_counter = int_fw_status->tx_results_counter;
1189	fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs;
1190
1191	fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime);
1192	fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap);
1193	fw_status->link_fast_bitmap =
1194			le32_to_cpu(int_fw_status->link_fast_bitmap);
1195	fw_status->total_released_blks =
1196			le32_to_cpu(int_fw_status->total_released_blks);
1197	fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total);
1198
1199	fw_status->counters.tx_released_pkts =
1200			int_fw_status->counters.tx_released_pkts;
1201	fw_status->counters.tx_lnk_free_pkts =
1202			int_fw_status->counters.tx_lnk_free_pkts;
1203	fw_status->counters.tx_voice_released_blks =
1204			int_fw_status->counters.tx_voice_released_blks;
1205	fw_status->counters.tx_last_rate =
1206			int_fw_status->counters.tx_last_rate;
1207	fw_status->counters.tx_last_rate_mbps =
1208			int_fw_status->counters.tx_last_rate_mbps;
1209	fw_status->counters.hlid =
1210			int_fw_status->counters.hlid;
1211
1212	fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr);
1213
1214	fw_status->priv = &int_fw_status->priv;
1215}
1216
1217static void wl18xx_set_tx_desc_csum(struct wl1271 *wl,
1218				    struct wl1271_tx_hw_descr *desc,
1219				    struct sk_buff *skb)
1220{
1221	u32 ip_hdr_offset;
1222	struct iphdr *ip_hdr;
1223
1224	if (!checksum_param) {
1225		desc->wl18xx_checksum_data = 0;
1226		return;
1227	}
1228
1229	if (skb->ip_summed != CHECKSUM_PARTIAL) {
1230		desc->wl18xx_checksum_data = 0;
1231		return;
1232	}
1233
1234	ip_hdr_offset = skb_network_header(skb) - skb_mac_header(skb);
1235	if (WARN_ON(ip_hdr_offset >= (1<<7))) {
1236		desc->wl18xx_checksum_data = 0;
1237		return;
1238	}
1239
1240	desc->wl18xx_checksum_data = ip_hdr_offset << 1;
1241
1242	/* FW is interested only in the LSB of the protocol  TCP=0 UDP=1 */
1243	ip_hdr = (void *)skb_network_header(skb);
1244	desc->wl18xx_checksum_data |= (ip_hdr->protocol & 0x01);
1245}
1246
1247static void wl18xx_set_rx_csum(struct wl1271 *wl,
1248			       struct wl1271_rx_descriptor *desc,
1249			       struct sk_buff *skb)
1250{
1251	if (desc->status & WL18XX_RX_CHECKSUM_MASK)
1252		skb->ip_summed = CHECKSUM_UNNECESSARY;
1253}
1254
1255static bool wl18xx_is_mimo_supported(struct wl1271 *wl)
1256{
1257	struct wl18xx_priv *priv = wl->priv;
1258
1259	/* only support MIMO with multiple antennas, and when SISO
1260	 * is not forced through config
1261	 */
1262	return (priv->conf.phy.number_of_assembled_ant2_4 >= 2) &&
1263	       (priv->conf.ht.mode != HT_MODE_WIDE) &&
1264	       (priv->conf.ht.mode != HT_MODE_SISO20);
1265}
1266
1267/*
1268 * TODO: instead of having these two functions to get the rate mask,
1269 * we should modify the wlvif->rate_set instead
1270 */
1271static u32 wl18xx_sta_get_ap_rate_mask(struct wl1271 *wl,
1272				       struct wl12xx_vif *wlvif)
1273{
1274	u32 hw_rate_set = wlvif->rate_set;
1275
1276	if (wlvif->channel_type == NL80211_CHAN_HT40MINUS ||
1277	    wlvif->channel_type == NL80211_CHAN_HT40PLUS) {
1278		wl1271_debug(DEBUG_ACX, "using wide channel rate mask");
1279		hw_rate_set |= CONF_TX_RATE_USE_WIDE_CHAN;
1280
1281		/* we don't support MIMO in wide-channel mode */
1282		hw_rate_set &= ~CONF_TX_MIMO_RATES;
1283	} else if (wl18xx_is_mimo_supported(wl)) {
1284		wl1271_debug(DEBUG_ACX, "using MIMO channel rate mask");
1285		hw_rate_set |= CONF_TX_MIMO_RATES;
1286	}
1287
1288	return hw_rate_set;
1289}
1290
1291static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
1292					     struct wl12xx_vif *wlvif)
1293{
1294	if (wlvif->channel_type == NL80211_CHAN_HT40MINUS ||
1295	    wlvif->channel_type == NL80211_CHAN_HT40PLUS) {
1296		wl1271_debug(DEBUG_ACX, "using wide channel rate mask");
1297
1298		/* sanity check - we don't support this */
1299		if (WARN_ON(wlvif->band != NL80211_BAND_5GHZ))
1300			return 0;
1301
1302		return CONF_TX_RATE_USE_WIDE_CHAN;
1303	} else if (wl18xx_is_mimo_supported(wl) &&
1304		   wlvif->band == NL80211_BAND_2GHZ) {
1305		wl1271_debug(DEBUG_ACX, "using MIMO rate mask");
1306		/*
1307		 * we don't care about HT channel here - if a peer doesn't
1308		 * support MIMO, we won't enable it in its rates
1309		 */
1310		return CONF_TX_MIMO_RATES;
1311	} else {
1312		return 0;
1313	}
1314}
1315
1316static const char *wl18xx_rdl_name(enum wl18xx_rdl_num rdl_num)
1317{
1318	switch (rdl_num) {
1319	case RDL_1_HP:
1320		return "183xH";
1321	case RDL_2_SP:
1322		return "183x or 180x";
1323	case RDL_3_HP:
1324		return "187xH";
1325	case RDL_4_SP:
1326		return "187x";
1327	case RDL_5_SP:
1328		return "RDL11 - Not Supported";
1329	case RDL_6_SP:
1330		return "180xD";
1331	case RDL_7_SP:
1332		return "RDL13 - Not Supported (1893Q)";
1333	case RDL_8_SP:
1334		return "18xxQ";
1335	case RDL_NONE:
1336		return "UNTRIMMED";
1337	default:
1338		return "UNKNOWN";
1339	}
1340}
1341
1342static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
1343{
1344	u32 fuse;
1345	s8 rom = 0, metal = 0, pg_ver = 0, rdl_ver = 0, package_type = 0;
1346	int ret;
1347
1348	ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
1349	if (ret < 0)
1350		goto out;
1351
1352	ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_2_3, &fuse);
1353	if (ret < 0)
1354		goto out;
1355
1356	package_type = (fuse >> WL18XX_PACKAGE_TYPE_OFFSET) & 1;
1357
1358	ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_1_3, &fuse);
1359	if (ret < 0)
1360		goto out;
1361
1362	pg_ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET;
1363	rom = (fuse & WL18XX_ROM_VER_MASK) >> WL18XX_ROM_VER_OFFSET;
1364
1365	if ((rom <= 0xE) && (package_type == WL18XX_PACKAGE_TYPE_WSP))
1366		metal = (fuse & WL18XX_METAL_VER_MASK) >>
1367			WL18XX_METAL_VER_OFFSET;
1368	else
1369		metal = (fuse & WL18XX_NEW_METAL_VER_MASK) >>
1370			WL18XX_NEW_METAL_VER_OFFSET;
1371
1372	ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_2_3, &fuse);
1373	if (ret < 0)
1374		goto out;
1375
1376	rdl_ver = (fuse & WL18XX_RDL_VER_MASK) >> WL18XX_RDL_VER_OFFSET;
1377
1378	wl1271_info("wl18xx HW: %s, PG %d.%d (ROM 0x%x)",
1379		    wl18xx_rdl_name(rdl_ver), pg_ver, metal, rom);
1380
1381	if (ver)
1382		*ver = pg_ver;
1383
1384	ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
1385
1386out:
1387	return ret;
1388}
1389
1390static int wl18xx_load_conf_file(struct device *dev, struct wlcore_conf *conf,
1391				 struct wl18xx_priv_conf *priv_conf,
1392				 const char *file)
1393{
1394	struct wlcore_conf_file *conf_file;
1395	const struct firmware *fw;
1396	int ret;
1397
1398	ret = request_firmware(&fw, file, dev);
1399	if (ret < 0) {
1400		wl1271_error("could not get configuration binary %s: %d",
1401			     file, ret);
1402		return ret;
1403	}
1404
1405	if (fw->size != WL18XX_CONF_SIZE) {
1406		wl1271_error("%s configuration binary size is wrong, expected %zu got %zu",
1407			     file, WL18XX_CONF_SIZE, fw->size);
1408		ret = -EINVAL;
1409		goto out_release;
1410	}
1411
1412	conf_file = (struct wlcore_conf_file *) fw->data;
1413
1414	if (conf_file->header.magic != cpu_to_le32(WL18XX_CONF_MAGIC)) {
1415		wl1271_error("configuration binary file magic number mismatch, "
1416			     "expected 0x%0x got 0x%0x", WL18XX_CONF_MAGIC,
1417			     conf_file->header.magic);
1418		ret = -EINVAL;
1419		goto out_release;
1420	}
1421
1422	if (conf_file->header.version != cpu_to_le32(WL18XX_CONF_VERSION)) {
1423		wl1271_error("configuration binary file version not supported, "
1424			     "expected 0x%08x got 0x%08x",
1425			     WL18XX_CONF_VERSION, conf_file->header.version);
1426		ret = -EINVAL;
1427		goto out_release;
1428	}
1429
1430	memcpy(conf, &conf_file->core, sizeof(*conf));
1431	memcpy(priv_conf, &conf_file->priv, sizeof(*priv_conf));
1432
1433out_release:
1434	release_firmware(fw);
1435	return ret;
1436}
1437
1438static int wl18xx_conf_init(struct wl1271 *wl, struct device *dev)
1439{
1440	struct platform_device *pdev = wl->pdev;
1441	struct wlcore_platdev_data *pdata = dev_get_platdata(&pdev->dev);
1442	struct wl18xx_priv *priv = wl->priv;
1443
1444	if (wl18xx_load_conf_file(dev, &wl->conf, &priv->conf,
1445				  pdata->family->cfg_name) < 0) {
1446		wl1271_warning("falling back to default config");
1447
1448		/* apply driver default configuration */
1449		memcpy(&wl->conf, &wl18xx_conf, sizeof(wl->conf));
1450		/* apply default private configuration */
1451		memcpy(&priv->conf, &wl18xx_default_priv_conf,
1452		       sizeof(priv->conf));
1453	}
1454
1455	return 0;
1456}
1457
1458static int wl18xx_plt_init(struct wl1271 *wl)
1459{
1460	int ret;
1461
1462	/* calibrator based auto/fem detect not supported for 18xx */
1463	if (wl->plt_mode == PLT_FEM_DETECT) {
1464		wl1271_error("wl18xx_plt_init: PLT FEM_DETECT not supported");
1465		return -EINVAL;
1466	}
1467
1468	ret = wlcore_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT);
1469	if (ret < 0)
1470		return ret;
1471
1472	return wl->ops->boot(wl);
1473}
1474
1475static int wl18xx_get_mac(struct wl1271 *wl)
1476{
1477	u32 mac1, mac2;
1478	int ret;
1479
1480	ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
1481	if (ret < 0)
1482		goto out;
1483
1484	ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1, &mac1);
1485	if (ret < 0)
1486		goto out;
1487
1488	ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2, &mac2);
1489	if (ret < 0)
1490		goto out;
1491
1492	/* these are the two parts of the BD_ADDR */
1493	wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
1494		((mac1 & 0xff000000) >> 24);
1495	wl->fuse_nic_addr = (mac1 & 0xffffff);
1496
1497	if (!wl->fuse_oui_addr && !wl->fuse_nic_addr) {
1498		u8 mac[ETH_ALEN];
1499
1500		eth_random_addr(mac);
1501
1502		wl->fuse_oui_addr = (mac[0] << 16) + (mac[1] << 8) + mac[2];
1503		wl->fuse_nic_addr = (mac[3] << 16) + (mac[4] << 8) + mac[5];
1504		wl1271_warning("MAC address from fuse not available, using random locally administered addresses.");
1505	}
1506
1507	ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
1508
1509out:
1510	return ret;
1511}
1512
1513static int wl18xx_handle_static_data(struct wl1271 *wl,
1514				     struct wl1271_static_data *static_data)
1515{
1516	struct wl18xx_static_data_priv *static_data_priv =
1517		(struct wl18xx_static_data_priv *) static_data->priv;
1518
1519	strscpy(wl->chip.phy_fw_ver_str, static_data_priv->phy_version,
1520		sizeof(wl->chip.phy_fw_ver_str));
1521
1522	wl1271_info("PHY firmware version: %s", static_data_priv->phy_version);
1523
1524	return 0;
1525}
1526
1527static int wl18xx_get_spare_blocks(struct wl1271 *wl, bool is_gem)
1528{
1529	struct wl18xx_priv *priv = wl->priv;
1530
1531	/* If we have keys requiring extra spare, indulge them */
1532	if (priv->extra_spare_key_count)
1533		return WL18XX_TX_HW_EXTRA_BLOCK_SPARE;
1534
1535	return WL18XX_TX_HW_BLOCK_SPARE;
1536}
1537
1538static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
1539			  struct ieee80211_vif *vif,
1540			  struct ieee80211_sta *sta,
1541			  struct ieee80211_key_conf *key_conf)
1542{
1543	struct wl18xx_priv *priv = wl->priv;
1544	bool change_spare = false, special_enc;
1545	int ret;
1546
1547	wl1271_debug(DEBUG_CRYPT, "extra spare keys before: %d",
1548		     priv->extra_spare_key_count);
1549
1550	special_enc = key_conf->cipher == WL1271_CIPHER_SUITE_GEM ||
1551		      key_conf->cipher == WLAN_CIPHER_SUITE_TKIP;
1552
1553	ret = wlcore_set_key(wl, cmd, vif, sta, key_conf);
1554	if (ret < 0)
1555		goto out;
1556
1557	/*
1558	 * when adding the first or removing the last GEM/TKIP key,
1559	 * we have to adjust the number of spare blocks.
1560	 */
1561	if (special_enc) {
1562		if (cmd == SET_KEY) {
1563			/* first key */
1564			change_spare = (priv->extra_spare_key_count == 0);
1565			priv->extra_spare_key_count++;
1566		} else if (cmd == DISABLE_KEY) {
1567			/* last key */
1568			change_spare = (priv->extra_spare_key_count == 1);
1569			priv->extra_spare_key_count--;
1570		}
1571	}
1572
1573	wl1271_debug(DEBUG_CRYPT, "extra spare keys after: %d",
1574		     priv->extra_spare_key_count);
1575
1576	if (!change_spare)
1577		goto out;
1578
1579	/* key is now set, change the spare blocks */
1580	if (priv->extra_spare_key_count)
1581		ret = wl18xx_set_host_cfg_bitmap(wl,
1582					WL18XX_TX_HW_EXTRA_BLOCK_SPARE);
1583	else
1584		ret = wl18xx_set_host_cfg_bitmap(wl,
1585					WL18XX_TX_HW_BLOCK_SPARE);
1586
1587out:
1588	return ret;
1589}
1590
1591static u32 wl18xx_pre_pkt_send(struct wl1271 *wl,
1592			       u32 buf_offset, u32 last_len)
1593{
1594	if (wl->quirks & WLCORE_QUIRK_TX_PAD_LAST_FRAME) {
1595		struct wl1271_tx_hw_descr *last_desc;
1596
1597		/* get the last TX HW descriptor written to the aggr buf */
1598		last_desc = (struct wl1271_tx_hw_descr *)(wl->aggr_buf +
1599							buf_offset - last_len);
1600
1601		/* the last frame is padded up to an SDIO block */
1602		last_desc->wl18xx_mem.ctrl &= ~WL18XX_TX_CTRL_NOT_PADDED;
1603		return ALIGN(buf_offset, WL12XX_BUS_BLOCK_SIZE);
1604	}
1605
1606	/* no modifications */
1607	return buf_offset;
1608}
1609
1610static void wl18xx_sta_rc_update(struct wl1271 *wl,
1611				 struct wl12xx_vif *wlvif)
1612{
1613	bool wide = wlvif->rc_update_bw >= IEEE80211_STA_RX_BW_40;
1614
1615	wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update wide %d", wide);
1616
1617	/* sanity */
1618	if (WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS))
1619		return;
1620
1621	/* ignore the change before association */
1622	if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
1623		return;
1624
1625	/*
1626	 * If we started out as wide, we can change the operation mode. If we
1627	 * thought this was a 20mhz AP, we have to reconnect
1628	 */
1629	if (wlvif->sta.role_chan_type == NL80211_CHAN_HT40MINUS ||
1630	    wlvif->sta.role_chan_type == NL80211_CHAN_HT40PLUS)
1631		wl18xx_acx_peer_ht_operation_mode(wl, wlvif->sta.hlid, wide);
1632	else
1633		ieee80211_connection_loss(wl12xx_wlvif_to_vif(wlvif));
1634}
1635
1636static int wl18xx_set_peer_cap(struct wl1271 *wl,
1637			       struct ieee80211_sta_ht_cap *ht_cap,
1638			       bool allow_ht_operation,
1639			       u32 rate_set, u8 hlid)
1640{
1641	return wl18xx_acx_set_peer_cap(wl, ht_cap, allow_ht_operation,
1642				       rate_set, hlid);
1643}
1644
1645static bool wl18xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
1646				 struct wl1271_link *lnk)
1647{
1648	u8 thold;
1649	struct wl18xx_fw_status_priv *status_priv =
1650		(struct wl18xx_fw_status_priv *)wl->fw_status->priv;
1651	unsigned long suspend_bitmap;
1652
1653	/* if we don't have the link map yet, assume they all low prio */
1654	if (!status_priv)
1655		return false;
1656
1657	/* suspended links are never high priority */
1658	suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
1659	if (test_bit(hlid, &suspend_bitmap))
1660		return false;
1661
1662	/* the priority thresholds are taken from FW */
1663	if (test_bit(hlid, &wl->fw_fast_lnk_map) &&
1664	    !test_bit(hlid, &wl->ap_fw_ps_map))
1665		thold = status_priv->tx_fast_link_prio_threshold;
1666	else
1667		thold = status_priv->tx_slow_link_prio_threshold;
1668
1669	return lnk->allocated_pkts < thold;
1670}
1671
1672static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
1673				struct wl1271_link *lnk)
1674{
1675	u8 thold;
1676	struct wl18xx_fw_status_priv *status_priv =
1677		(struct wl18xx_fw_status_priv *)wl->fw_status->priv;
1678	unsigned long suspend_bitmap;
1679
1680	/* if we don't have the link map yet, assume they all low prio */
1681	if (!status_priv)
1682		return true;
1683
1684	suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
1685	if (test_bit(hlid, &suspend_bitmap))
1686		thold = status_priv->tx_suspend_threshold;
1687	else if (test_bit(hlid, &wl->fw_fast_lnk_map) &&
1688		 !test_bit(hlid, &wl->ap_fw_ps_map))
1689		thold = status_priv->tx_fast_stop_threshold;
1690	else
1691		thold = status_priv->tx_slow_stop_threshold;
1692
1693	return lnk->allocated_pkts < thold;
1694}
1695
1696static u32 wl18xx_convert_hwaddr(struct wl1271 *wl, u32 hwaddr)
1697{
1698	return hwaddr & ~0x80000000;
1699}
1700
1701static int wl18xx_setup(struct wl1271 *wl);
1702
1703static struct wlcore_ops wl18xx_ops = {
1704	.setup		= wl18xx_setup,
1705	.identify_chip	= wl18xx_identify_chip,
1706	.boot		= wl18xx_boot,
1707	.plt_init	= wl18xx_plt_init,
1708	.trigger_cmd	= wl18xx_trigger_cmd,
1709	.ack_event	= wl18xx_ack_event,
1710	.wait_for_event	= wl18xx_wait_for_event,
1711	.process_mailbox_events = wl18xx_process_mailbox_events,
1712	.calc_tx_blocks = wl18xx_calc_tx_blocks,
1713	.set_tx_desc_blocks = wl18xx_set_tx_desc_blocks,
1714	.set_tx_desc_data_len = wl18xx_set_tx_desc_data_len,
1715	.get_rx_buf_align = wl18xx_get_rx_buf_align,
1716	.get_rx_packet_len = wl18xx_get_rx_packet_len,
1717	.tx_immediate_compl = wl18xx_tx_immediate_completion,
1718	.tx_delayed_compl = NULL,
1719	.hw_init	= wl18xx_hw_init,
1720	.convert_fw_status = wl18xx_convert_fw_status,
1721	.set_tx_desc_csum = wl18xx_set_tx_desc_csum,
1722	.get_pg_ver	= wl18xx_get_pg_ver,
1723	.set_rx_csum = wl18xx_set_rx_csum,
1724	.sta_get_ap_rate_mask = wl18xx_sta_get_ap_rate_mask,
1725	.ap_get_mimo_wide_rate_mask = wl18xx_ap_get_mimo_wide_rate_mask,
1726	.get_mac	= wl18xx_get_mac,
1727	.debugfs_init	= wl18xx_debugfs_add_files,
1728	.scan_start	= wl18xx_scan_start,
1729	.scan_stop	= wl18xx_scan_stop,
1730	.sched_scan_start	= wl18xx_sched_scan_start,
1731	.sched_scan_stop	= wl18xx_scan_sched_scan_stop,
1732	.handle_static_data	= wl18xx_handle_static_data,
1733	.get_spare_blocks = wl18xx_get_spare_blocks,
1734	.set_key	= wl18xx_set_key,
1735	.channel_switch	= wl18xx_cmd_channel_switch,
1736	.pre_pkt_send	= wl18xx_pre_pkt_send,
1737	.sta_rc_update	= wl18xx_sta_rc_update,
1738	.set_peer_cap	= wl18xx_set_peer_cap,
1739	.convert_hwaddr = wl18xx_convert_hwaddr,
1740	.lnk_high_prio	= wl18xx_lnk_high_prio,
1741	.lnk_low_prio	= wl18xx_lnk_low_prio,
1742	.smart_config_start = wl18xx_cmd_smart_config_start,
1743	.smart_config_stop  = wl18xx_cmd_smart_config_stop,
1744	.smart_config_set_group_key = wl18xx_cmd_smart_config_set_group_key,
1745	.interrupt_notify = wl18xx_acx_interrupt_notify_config,
1746	.rx_ba_filter	= wl18xx_acx_rx_ba_filter,
1747	.ap_sleep	= wl18xx_acx_ap_sleep,
1748	.set_cac	= wl18xx_cmd_set_cac,
1749	.dfs_master_restart	= wl18xx_cmd_dfs_master_restart,
1750};
1751
1752/* HT cap appropriate for wide channels in 2Ghz */
1753static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_2ghz = {
1754	.cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
1755	       IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40 |
1756	       IEEE80211_HT_CAP_GRN_FLD,
1757	.ht_supported = true,
1758	.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
1759	.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
1760	.mcs = {
1761		.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
1762		.rx_highest = cpu_to_le16(150),
1763		.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
1764		},
1765};
1766
1767/* HT cap appropriate for wide channels in 5Ghz */
1768static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_5ghz = {
1769	.cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
1770	       IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
1771	       IEEE80211_HT_CAP_GRN_FLD,
1772	.ht_supported = true,
1773	.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
1774	.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
1775	.mcs = {
1776		.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
1777		.rx_highest = cpu_to_le16(150),
1778		.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
1779		},
1780};
1781
1782/* HT cap appropriate for SISO 20 */
1783static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = {
1784	.cap = IEEE80211_HT_CAP_SGI_20 |
1785	       IEEE80211_HT_CAP_GRN_FLD,
1786	.ht_supported = true,
1787	.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
1788	.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
1789	.mcs = {
1790		.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
1791		.rx_highest = cpu_to_le16(72),
1792		.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
1793		},
1794};
1795
1796/* HT cap appropriate for MIMO rates in 20mhz channel */
1797static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = {
1798	.cap = IEEE80211_HT_CAP_SGI_20 |
1799	       IEEE80211_HT_CAP_GRN_FLD,
1800	.ht_supported = true,
1801	.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
1802	.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
1803	.mcs = {
1804		.rx_mask = { 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, },
1805		.rx_highest = cpu_to_le16(144),
1806		.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
1807		},
1808};
1809
1810static const struct ieee80211_iface_limit wl18xx_iface_limits[] = {
1811	{
1812		.max = 2,
1813		.types = BIT(NL80211_IFTYPE_STATION),
1814	},
1815	{
1816		.max = 1,
1817		.types =   BIT(NL80211_IFTYPE_AP)
1818			 | BIT(NL80211_IFTYPE_P2P_GO)
1819			 | BIT(NL80211_IFTYPE_P2P_CLIENT)
1820#ifdef CONFIG_MAC80211_MESH
1821			 | BIT(NL80211_IFTYPE_MESH_POINT)
1822#endif
1823	},
1824	{
1825		.max = 1,
1826		.types = BIT(NL80211_IFTYPE_P2P_DEVICE),
1827	},
1828};
1829
1830static const struct ieee80211_iface_limit wl18xx_iface_ap_limits[] = {
1831	{
1832		.max = 2,
1833		.types = BIT(NL80211_IFTYPE_AP),
1834	},
1835#ifdef CONFIG_MAC80211_MESH
1836	{
1837		.max = 1,
1838		.types = BIT(NL80211_IFTYPE_MESH_POINT),
1839	},
1840#endif
1841	{
1842		.max = 1,
1843		.types = BIT(NL80211_IFTYPE_P2P_DEVICE),
1844	},
1845};
1846
1847static const struct ieee80211_iface_combination
1848wl18xx_iface_combinations[] = {
1849	{
1850		.max_interfaces = 3,
1851		.limits = wl18xx_iface_limits,
1852		.n_limits = ARRAY_SIZE(wl18xx_iface_limits),
1853		.num_different_channels = 2,
1854	},
1855	{
1856		.max_interfaces = 2,
1857		.limits = wl18xx_iface_ap_limits,
1858		.n_limits = ARRAY_SIZE(wl18xx_iface_ap_limits),
1859		.num_different_channels = 1,
1860		.radar_detect_widths =	BIT(NL80211_CHAN_NO_HT) |
1861					BIT(NL80211_CHAN_HT20) |
1862					BIT(NL80211_CHAN_HT40MINUS) |
1863					BIT(NL80211_CHAN_HT40PLUS),
1864	}
1865};
1866
1867static int wl18xx_setup(struct wl1271 *wl)
1868{
1869	struct wl18xx_priv *priv = wl->priv;
1870	int ret;
1871
1872	BUILD_BUG_ON(WL18XX_MAX_LINKS > WLCORE_MAX_LINKS);
1873	BUILD_BUG_ON(WL18XX_MAX_AP_STATIONS > WL18XX_MAX_LINKS);
1874	BUILD_BUG_ON(WL18XX_CONF_SG_PARAMS_MAX > WLCORE_CONF_SG_PARAMS_MAX);
1875
1876	wl->rtable = wl18xx_rtable;
1877	wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS;
1878	wl->num_rx_desc = WL18XX_NUM_RX_DESCRIPTORS;
1879	wl->num_links = WL18XX_MAX_LINKS;
1880	wl->max_ap_stations = WL18XX_MAX_AP_STATIONS;
1881	wl->iface_combinations = wl18xx_iface_combinations;
1882	wl->n_iface_combinations = ARRAY_SIZE(wl18xx_iface_combinations);
1883	wl->num_mac_addr = WL18XX_NUM_MAC_ADDRESSES;
1884	wl->band_rate_to_idx = wl18xx_band_rate_to_idx;
1885	wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX;
1886	wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0;
1887	wl->fw_status_len = sizeof(struct wl18xx_fw_status);
1888	wl->fw_status_priv_len = sizeof(struct wl18xx_fw_status_priv);
1889	wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics);
1890	wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv);
1891
1892	if (num_rx_desc_param != -1)
1893		wl->num_rx_desc = num_rx_desc_param;
1894
1895	ret = wl18xx_conf_init(wl, wl->dev);
1896	if (ret < 0)
1897		return ret;
1898
1899	/* If the module param is set, update it in conf */
1900	if (board_type_param) {
1901		if (!strcmp(board_type_param, "fpga")) {
1902			priv->conf.phy.board_type = BOARD_TYPE_FPGA_18XX;
1903		} else if (!strcmp(board_type_param, "hdk")) {
1904			priv->conf.phy.board_type = BOARD_TYPE_HDK_18XX;
1905		} else if (!strcmp(board_type_param, "dvp")) {
1906			priv->conf.phy.board_type = BOARD_TYPE_DVP_18XX;
1907		} else if (!strcmp(board_type_param, "evb")) {
1908			priv->conf.phy.board_type = BOARD_TYPE_EVB_18XX;
1909		} else if (!strcmp(board_type_param, "com8")) {
1910			priv->conf.phy.board_type = BOARD_TYPE_COM8_18XX;
1911		} else {
1912			wl1271_error("invalid board type '%s'",
1913				board_type_param);
1914			return -EINVAL;
1915		}
1916	}
1917
1918	if (priv->conf.phy.board_type >= NUM_BOARD_TYPES) {
1919		wl1271_error("invalid board type '%d'",
1920			priv->conf.phy.board_type);
1921		return -EINVAL;
1922	}
1923
1924	if (low_band_component_param != -1)
1925		priv->conf.phy.low_band_component = low_band_component_param;
1926	if (low_band_component_type_param != -1)
1927		priv->conf.phy.low_band_component_type =
1928			low_band_component_type_param;
1929	if (high_band_component_param != -1)
1930		priv->conf.phy.high_band_component = high_band_component_param;
1931	if (high_band_component_type_param != -1)
1932		priv->conf.phy.high_band_component_type =
1933			high_band_component_type_param;
1934	if (pwr_limit_reference_11_abg_param != -1)
1935		priv->conf.phy.pwr_limit_reference_11_abg =
1936			pwr_limit_reference_11_abg_param;
1937	if (n_antennas_2_param != -1)
1938		priv->conf.phy.number_of_assembled_ant2_4 = n_antennas_2_param;
1939	if (n_antennas_5_param != -1)
1940		priv->conf.phy.number_of_assembled_ant5 = n_antennas_5_param;
1941	if (dc2dc_param != -1)
1942		priv->conf.phy.external_pa_dc2dc = dc2dc_param;
1943
1944	if (ht_mode_param) {
1945		if (!strcmp(ht_mode_param, "default"))
1946			priv->conf.ht.mode = HT_MODE_DEFAULT;
1947		else if (!strcmp(ht_mode_param, "wide"))
1948			priv->conf.ht.mode = HT_MODE_WIDE;
1949		else if (!strcmp(ht_mode_param, "siso20"))
1950			priv->conf.ht.mode = HT_MODE_SISO20;
1951		else {
1952			wl1271_error("invalid ht_mode '%s'", ht_mode_param);
1953			return -EINVAL;
1954		}
1955	}
1956
1957	if (priv->conf.ht.mode == HT_MODE_DEFAULT) {
1958		/*
1959		 * Only support mimo with multiple antennas. Fall back to
1960		 * siso40.
1961		 */
1962		if (wl18xx_is_mimo_supported(wl))
1963			wlcore_set_ht_cap(wl, NL80211_BAND_2GHZ,
1964					  &wl18xx_mimo_ht_cap_2ghz);
1965		else
1966			wlcore_set_ht_cap(wl, NL80211_BAND_2GHZ,
1967					  &wl18xx_siso40_ht_cap_2ghz);
1968
1969		/* 5Ghz is always wide */
1970		wlcore_set_ht_cap(wl, NL80211_BAND_5GHZ,
1971				  &wl18xx_siso40_ht_cap_5ghz);
1972	} else if (priv->conf.ht.mode == HT_MODE_WIDE) {
1973		wlcore_set_ht_cap(wl, NL80211_BAND_2GHZ,
1974				  &wl18xx_siso40_ht_cap_2ghz);
1975		wlcore_set_ht_cap(wl, NL80211_BAND_5GHZ,
1976				  &wl18xx_siso40_ht_cap_5ghz);
1977	} else if (priv->conf.ht.mode == HT_MODE_SISO20) {
1978		wlcore_set_ht_cap(wl, NL80211_BAND_2GHZ,
1979				  &wl18xx_siso20_ht_cap);
1980		wlcore_set_ht_cap(wl, NL80211_BAND_5GHZ,
1981				  &wl18xx_siso20_ht_cap);
1982	}
1983
1984	if (!checksum_param) {
1985		wl18xx_ops.set_rx_csum = NULL;
1986		wl18xx_ops.init_vif = NULL;
1987	}
1988
1989	/* Enable 11a Band only if we have 5G antennas */
1990	wl->enable_11a = (priv->conf.phy.number_of_assembled_ant5 != 0);
1991
1992	return 0;
1993}
1994
1995static int wl18xx_probe(struct platform_device *pdev)
1996{
1997	struct wl1271 *wl;
1998	struct ieee80211_hw *hw;
1999	int ret;
2000
2001	hw = wlcore_alloc_hw(sizeof(struct wl18xx_priv),
2002			     WL18XX_AGGR_BUFFER_SIZE,
2003			     sizeof(struct wl18xx_event_mailbox));
2004	if (IS_ERR(hw)) {
2005		wl1271_error("can't allocate hw");
2006		ret = PTR_ERR(hw);
2007		goto out;
2008	}
2009
2010	wl = hw->priv;
2011	wl->ops = &wl18xx_ops;
2012	wl->ptable = wl18xx_ptable;
2013	ret = wlcore_probe(wl, pdev);
2014	if (ret)
2015		goto out_free;
2016
2017	return ret;
2018
2019out_free:
2020	wlcore_free_hw(wl);
2021out:
2022	return ret;
2023}
2024
2025static const struct platform_device_id wl18xx_id_table[] = {
2026	{ "wl18xx", 0 },
2027	{  } /* Terminating Entry */
2028};
2029MODULE_DEVICE_TABLE(platform, wl18xx_id_table);
2030
2031static struct platform_driver wl18xx_driver = {
2032	.probe		= wl18xx_probe,
2033	.remove_new	= wlcore_remove,
2034	.id_table	= wl18xx_id_table,
2035	.driver = {
2036		.name	= "wl18xx_driver",
2037	}
2038};
2039
2040module_platform_driver(wl18xx_driver);
2041module_param_named(ht_mode, ht_mode_param, charp, 0400);
2042MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or siso20");
2043
2044module_param_named(board_type, board_type_param, charp, 0400);
2045MODULE_PARM_DESC(board_type, "Board type: fpga, hdk (default), evb, com8 or "
2046		 "dvp");
2047
2048module_param_named(checksum, checksum_param, bool, 0400);
2049MODULE_PARM_DESC(checksum, "Enable TCP checksum: boolean (defaults to false)");
2050
2051module_param_named(dc2dc, dc2dc_param, int, 0400);
2052MODULE_PARM_DESC(dc2dc, "External DC2DC: u8 (defaults to 0)");
2053
2054module_param_named(n_antennas_2, n_antennas_2_param, int, 0400);
2055MODULE_PARM_DESC(n_antennas_2,
2056		 "Number of installed 2.4GHz antennas: 1 (default) or 2");
2057
2058module_param_named(n_antennas_5, n_antennas_5_param, int, 0400);
2059MODULE_PARM_DESC(n_antennas_5,
2060		 "Number of installed 5GHz antennas: 1 (default) or 2");
2061
2062module_param_named(low_band_component, low_band_component_param, int, 0400);
2063MODULE_PARM_DESC(low_band_component, "Low band component: u8 "
2064		 "(default is 0x01)");
2065
2066module_param_named(low_band_component_type, low_band_component_type_param,
2067		   int, 0400);
2068MODULE_PARM_DESC(low_band_component_type, "Low band component type: u8 "
2069		 "(default is 0x05 or 0x06 depending on the board_type)");
2070
2071module_param_named(high_band_component, high_band_component_param, int, 0400);
2072MODULE_PARM_DESC(high_band_component, "High band component: u8, "
2073		 "(default is 0x01)");
2074
2075module_param_named(high_band_component_type, high_band_component_type_param,
2076		   int, 0400);
2077MODULE_PARM_DESC(high_band_component_type, "High band component type: u8 "
2078		 "(default is 0x09)");
2079
2080module_param_named(pwr_limit_reference_11_abg,
2081		   pwr_limit_reference_11_abg_param, int, 0400);
2082MODULE_PARM_DESC(pwr_limit_reference_11_abg, "Power limit reference: u8 "
2083		 "(default is 0xc8)");
2084
2085module_param_named(num_rx_desc, num_rx_desc_param, int, 0400);
2086MODULE_PARM_DESC(num_rx_desc_param,
2087		 "Number of Rx descriptors: u8 (default is 32)");
2088
2089MODULE_DESCRIPTION("TI WiLink 8 wireless driver");
2090MODULE_LICENSE("GPL v2");
2091MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
2092MODULE_FIRMWARE(WL18XX_FW_NAME);
2093