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