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