1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * This file is part of wl1271 |
4 | * |
5 | * Copyright (C) 2008-2010 Nokia Corporation |
6 | */ |
7 | |
8 | #include <linux/module.h> |
9 | #include <linux/mod_devicetable.h> |
10 | #include <linux/platform_device.h> |
11 | |
12 | #include <linux/err.h> |
13 | |
14 | #include "../wlcore/wlcore.h" |
15 | #include "../wlcore/debug.h" |
16 | #include "../wlcore/io.h" |
17 | #include "../wlcore/acx.h" |
18 | #include "../wlcore/tx.h" |
19 | #include "../wlcore/rx.h" |
20 | #include "../wlcore/boot.h" |
21 | |
22 | #include "wl12xx.h" |
23 | #include "reg.h" |
24 | #include "cmd.h" |
25 | #include "acx.h" |
26 | #include "scan.h" |
27 | #include "event.h" |
28 | #include "debugfs.h" |
29 | #include "conf.h" |
30 | |
31 | static char *fref_param; |
32 | static char *tcxo_param; |
33 | |
34 | static struct wlcore_conf wl12xx_conf = { |
35 | .sg = { |
36 | .params = { |
37 | [WL12XX_CONF_SG_ACL_BT_MASTER_MIN_BR] = 10, |
38 | [WL12XX_CONF_SG_ACL_BT_MASTER_MAX_BR] = 180, |
39 | [WL12XX_CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10, |
40 | [WL12XX_CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180, |
41 | [WL12XX_CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10, |
42 | [WL12XX_CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80, |
43 | [WL12XX_CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10, |
44 | [WL12XX_CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80, |
45 | [WL12XX_CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8, |
46 | [WL12XX_CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8, |
47 | [WL12XX_CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20, |
48 | [WL12XX_CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20, |
49 | [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20, |
50 | [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35, |
51 | [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16, |
52 | [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35, |
53 | [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32, |
54 | [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50, |
55 | [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28, |
56 | [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50, |
57 | [WL12XX_CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10, |
58 | [WL12XX_CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20, |
59 | [WL12XX_CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75, |
60 | [WL12XX_CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15, |
61 | [WL12XX_CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27, |
62 | [WL12XX_CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17, |
63 | /* active scan params */ |
64 | [WL12XX_CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, |
65 | [WL12XX_CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, |
66 | [WL12XX_CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, |
67 | /* passive scan params */ |
68 | [WL12XX_CONF_SG_PASSIVE_SCAN_DUR_FACTOR_A2DP_BR] = 800, |
69 | [WL12XX_CONF_SG_PASSIVE_SCAN_DUR_FACTOR_A2DP_EDR] = 200, |
70 | [WL12XX_CONF_SG_PASSIVE_SCAN_DUR_FACTOR_HV3] = 200, |
71 | /* passive scan in dual antenna params */ |
72 | [WL12XX_CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0, |
73 | [WL12XX_CONF_SG_BCN_HV3_COLL_THR_IN_PASSIVE_SCAN] = 0, |
74 | [WL12XX_CONF_SG_TX_RX_PROTECT_BW_IN_PASSIVE_SCAN] = 0, |
75 | /* general params */ |
76 | [WL12XX_CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1, |
77 | [WL12XX_CONF_SG_ANTENNA_CONFIGURATION] = 0, |
78 | [WL12XX_CONF_SG_BEACON_MISS_PERCENT] = 60, |
79 | [WL12XX_CONF_SG_DHCP_TIME] = 5000, |
80 | [WL12XX_CONF_SG_RXT] = 1200, |
81 | [WL12XX_CONF_SG_TXT] = 1000, |
82 | [WL12XX_CONF_SG_ADAPTIVE_RXT_TXT] = 1, |
83 | [WL12XX_CONF_SG_GENERAL_USAGE_BIT_MAP] = 3, |
84 | [WL12XX_CONF_SG_HV3_MAX_SERVED] = 6, |
85 | [WL12XX_CONF_SG_PS_POLL_TIMEOUT] = 10, |
86 | [WL12XX_CONF_SG_UPSD_TIMEOUT] = 10, |
87 | [WL12XX_CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2, |
88 | [WL12XX_CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5, |
89 | [WL12XX_CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30, |
90 | /* AP params */ |
91 | [WL12XX_CONF_AP_BEACON_MISS_TX] = 3, |
92 | [WL12XX_CONF_AP_RX_WINDOW_AFTER_BEACON] = 10, |
93 | [WL12XX_CONF_AP_BEACON_WINDOW_INTERVAL] = 2, |
94 | [WL12XX_CONF_AP_CONNECTION_PROTECTION_TIME] = 0, |
95 | [WL12XX_CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25, |
96 | [WL12XX_CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25, |
97 | /* CTS Diluting params */ |
98 | [WL12XX_CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0, |
99 | [WL12XX_CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0, |
100 | }, |
101 | .state = CONF_SG_PROTECTIVE, |
102 | }, |
103 | .rx = { |
104 | .rx_msdu_life_time = 512000, |
105 | .packet_detection_threshold = 0, |
106 | .ps_poll_timeout = 15, |
107 | .upsd_timeout = 15, |
108 | .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD, |
109 | .rx_cca_threshold = 0, |
110 | .irq_blk_threshold = 0xFFFF, |
111 | .irq_pkt_threshold = 0, |
112 | .irq_timeout = 600, |
113 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, |
114 | }, |
115 | .tx = { |
116 | .tx_energy_detection = 0, |
117 | .sta_rc_conf = { |
118 | .enabled_rates = 0, |
119 | .short_retry_limit = 10, |
120 | .long_retry_limit = 10, |
121 | .aflags = 0, |
122 | }, |
123 | .ac_conf_count = 4, |
124 | .ac_conf = { |
125 | [CONF_TX_AC_BE] = { |
126 | .ac = CONF_TX_AC_BE, |
127 | .cw_min = 15, |
128 | .cw_max = 63, |
129 | .aifsn = 3, |
130 | .tx_op_limit = 0, |
131 | }, |
132 | [CONF_TX_AC_BK] = { |
133 | .ac = CONF_TX_AC_BK, |
134 | .cw_min = 15, |
135 | .cw_max = 63, |
136 | .aifsn = 7, |
137 | .tx_op_limit = 0, |
138 | }, |
139 | [CONF_TX_AC_VI] = { |
140 | .ac = CONF_TX_AC_VI, |
141 | .cw_min = 15, |
142 | .cw_max = 63, |
143 | .aifsn = CONF_TX_AIFS_PIFS, |
144 | .tx_op_limit = 3008, |
145 | }, |
146 | [CONF_TX_AC_VO] = { |
147 | .ac = CONF_TX_AC_VO, |
148 | .cw_min = 15, |
149 | .cw_max = 63, |
150 | .aifsn = CONF_TX_AIFS_PIFS, |
151 | .tx_op_limit = 1504, |
152 | }, |
153 | }, |
154 | .max_tx_retries = 100, |
155 | .ap_aging_period = 300, |
156 | .tid_conf_count = 4, |
157 | .tid_conf = { |
158 | [CONF_TX_AC_BE] = { |
159 | .queue_id = CONF_TX_AC_BE, |
160 | .channel_type = CONF_CHANNEL_TYPE_EDCF, |
161 | .tsid = CONF_TX_AC_BE, |
162 | .ps_scheme = CONF_PS_SCHEME_LEGACY, |
163 | .ack_policy = CONF_ACK_POLICY_LEGACY, |
164 | .apsd_conf = {0, 0}, |
165 | }, |
166 | [CONF_TX_AC_BK] = { |
167 | .queue_id = CONF_TX_AC_BK, |
168 | .channel_type = CONF_CHANNEL_TYPE_EDCF, |
169 | .tsid = CONF_TX_AC_BK, |
170 | .ps_scheme = CONF_PS_SCHEME_LEGACY, |
171 | .ack_policy = CONF_ACK_POLICY_LEGACY, |
172 | .apsd_conf = {0, 0}, |
173 | }, |
174 | [CONF_TX_AC_VI] = { |
175 | .queue_id = CONF_TX_AC_VI, |
176 | .channel_type = CONF_CHANNEL_TYPE_EDCF, |
177 | .tsid = CONF_TX_AC_VI, |
178 | .ps_scheme = CONF_PS_SCHEME_LEGACY, |
179 | .ack_policy = CONF_ACK_POLICY_LEGACY, |
180 | .apsd_conf = {0, 0}, |
181 | }, |
182 | [CONF_TX_AC_VO] = { |
183 | .queue_id = CONF_TX_AC_VO, |
184 | .channel_type = CONF_CHANNEL_TYPE_EDCF, |
185 | .tsid = CONF_TX_AC_VO, |
186 | .ps_scheme = CONF_PS_SCHEME_LEGACY, |
187 | .ack_policy = CONF_ACK_POLICY_LEGACY, |
188 | .apsd_conf = {0, 0}, |
189 | }, |
190 | }, |
191 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, |
192 | .tx_compl_timeout = 700, |
193 | .tx_compl_threshold = 4, |
194 | .basic_rate = CONF_HW_BIT_RATE_1MBPS, |
195 | .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, |
196 | .tmpl_short_retry_limit = 10, |
197 | .tmpl_long_retry_limit = 10, |
198 | .tx_watchdog_timeout = 5000, |
199 | .slow_link_thold = 3, |
200 | .fast_link_thold = 10, |
201 | }, |
202 | .conn = { |
203 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
204 | .listen_interval = 1, |
205 | .suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM, |
206 | .suspend_listen_interval = 3, |
207 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, |
208 | .bcn_filt_ie_count = 3, |
209 | .bcn_filt_ie = { |
210 | [0] = { |
211 | .ie = WLAN_EID_CHANNEL_SWITCH, |
212 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, |
213 | }, |
214 | [1] = { |
215 | .ie = WLAN_EID_HT_OPERATION, |
216 | .rule = CONF_BCN_RULE_PASS_ON_CHANGE, |
217 | }, |
218 | [2] = { |
219 | .ie = WLAN_EID_ERP_INFO, |
220 | .rule = CONF_BCN_RULE_PASS_ON_CHANGE, |
221 | }, |
222 | }, |
223 | .synch_fail_thold = 12, |
224 | .bss_lose_timeout = 400, |
225 | .beacon_rx_timeout = 10000, |
226 | .broadcast_timeout = 20000, |
227 | .rx_broadcast_in_ps = 1, |
228 | .ps_poll_threshold = 10, |
229 | .bet_enable = CONF_BET_MODE_ENABLE, |
230 | .bet_max_consecutive = 50, |
231 | .psm_entry_retries = 8, |
232 | .psm_exit_retries = 16, |
233 | .psm_entry_nullfunc_retries = 3, |
234 | .dynamic_ps_timeout = 1500, |
235 | .forced_ps = false, |
236 | .keep_alive_interval = 55000, |
237 | .max_listen_interval = 20, |
238 | .sta_sleep_auth = WL1271_PSM_ILLEGAL, |
239 | .suspend_rx_ba_activity = 0, |
240 | }, |
241 | .itrim = { |
242 | .enable = false, |
243 | .timeout = 50000, |
244 | }, |
245 | .pm_config = { |
246 | .host_clk_settling_time = 5000, |
247 | .host_fast_wakeup_support = CONF_FAST_WAKEUP_DISABLE, |
248 | }, |
249 | .roam_trigger = { |
250 | .trigger_pacing = 1, |
251 | .avg_weight_rssi_beacon = 20, |
252 | .avg_weight_rssi_data = 10, |
253 | .avg_weight_snr_beacon = 20, |
254 | .avg_weight_snr_data = 10, |
255 | }, |
256 | .scan = { |
257 | .min_dwell_time_active = 7500, |
258 | .max_dwell_time_active = 30000, |
259 | .min_dwell_time_active_long = 25000, |
260 | .max_dwell_time_active_long = 50000, |
261 | .dwell_time_passive = 100000, |
262 | .dwell_time_dfs = 150000, |
263 | .num_probe_reqs = 2, |
264 | .split_scan_timeout = 50000, |
265 | }, |
266 | .sched_scan = { |
267 | /* |
268 | * Values are in TU/1000 but since sched scan FW command |
269 | * params are in TUs rounding up may occur. |
270 | */ |
271 | .base_dwell_time = 7500, |
272 | .max_dwell_time_delta = 22500, |
273 | /* based on 250bits per probe @1Mbps */ |
274 | .dwell_time_delta_per_probe = 2000, |
275 | /* based on 250bits per probe @6Mbps (plus a bit more) */ |
276 | .dwell_time_delta_per_probe_5 = 350, |
277 | .dwell_time_passive = 100000, |
278 | .dwell_time_dfs = 150000, |
279 | .num_probe_reqs = 2, |
280 | .rssi_threshold = -90, |
281 | .snr_threshold = 0, |
282 | }, |
283 | .ht = { |
284 | .rx_ba_win_size = 8, |
285 | .tx_ba_win_size = 64, |
286 | .inactivity_timeout = 10000, |
287 | .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP, |
288 | }, |
289 | /* |
290 | * Memory config for wl127x chips is given in the |
291 | * wl12xx_default_priv_conf struct. The below configuration is |
292 | * for wl128x chips. |
293 | */ |
294 | .mem = { |
295 | .num_stations = 1, |
296 | .ssid_profiles = 1, |
297 | .rx_block_num = 40, |
298 | .tx_min_block_num = 40, |
299 | .dynamic_memory = 1, |
300 | .min_req_tx_blocks = 45, |
301 | .min_req_rx_blocks = 22, |
302 | .tx_min = 27, |
303 | }, |
304 | .fm_coex = { |
305 | .enable = true, |
306 | .swallow_period = 5, |
307 | .n_divider_fref_set_1 = 0xff, /* default */ |
308 | .n_divider_fref_set_2 = 12, |
309 | .m_divider_fref_set_1 = 0xffff, |
310 | .m_divider_fref_set_2 = 148, /* default */ |
311 | .coex_pll_stabilization_time = 0xffffffff, /* default */ |
312 | .ldo_stabilization_time = 0xffff, /* default */ |
313 | .fm_disturbed_band_margin = 0xff, /* default */ |
314 | .swallow_clk_diff = 0xff, /* default */ |
315 | }, |
316 | .rx_streaming = { |
317 | .duration = 150, |
318 | .queues = 0x1, |
319 | .interval = 20, |
320 | .always = 0, |
321 | }, |
322 | .fwlog = { |
323 | .mode = WL12XX_FWLOG_CONTINUOUS, |
324 | .mem_blocks = 2, |
325 | .severity = 0, |
326 | .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, |
327 | .output = WL12XX_FWLOG_OUTPUT_DBG_PINS, |
328 | .threshold = 0, |
329 | }, |
330 | .rate = { |
331 | .rate_retry_score = 32000, |
332 | .per_add = 8192, |
333 | .per_th1 = 2048, |
334 | .per_th2 = 4096, |
335 | .max_per = 8100, |
336 | .inverse_curiosity_factor = 5, |
337 | .tx_fail_low_th = 4, |
338 | .tx_fail_high_th = 10, |
339 | .per_alpha_shift = 4, |
340 | .per_add_shift = 13, |
341 | .per_beta1_shift = 10, |
342 | .per_beta2_shift = 8, |
343 | .rate_check_up = 2, |
344 | .rate_check_down = 12, |
345 | .rate_retry_policy = { |
346 | 0x00, 0x00, 0x00, 0x00, 0x00, |
347 | 0x00, 0x00, 0x00, 0x00, 0x00, |
348 | 0x00, 0x00, 0x00, |
349 | }, |
350 | }, |
351 | .hangover = { |
352 | .recover_time = 0, |
353 | .hangover_period = 20, |
354 | .dynamic_mode = 1, |
355 | .early_termination_mode = 1, |
356 | .max_period = 20, |
357 | .min_period = 1, |
358 | .increase_delta = 1, |
359 | .decrease_delta = 2, |
360 | .quiet_time = 4, |
361 | .increase_time = 1, |
362 | .window_size = 16, |
363 | }, |
364 | .recovery = { |
365 | .bug_on_recovery = 0, |
366 | .no_recovery = 0, |
367 | }, |
368 | }; |
369 | |
370 | static struct wl12xx_priv_conf wl12xx_default_priv_conf = { |
371 | .rf = { |
372 | .tx_per_channel_power_compensation_2 = { |
373 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
374 | }, |
375 | .tx_per_channel_power_compensation_5 = { |
376 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
377 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
378 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
379 | }, |
380 | }, |
381 | .mem_wl127x = { |
382 | .num_stations = 1, |
383 | .ssid_profiles = 1, |
384 | .rx_block_num = 70, |
385 | .tx_min_block_num = 40, |
386 | .dynamic_memory = 1, |
387 | .min_req_tx_blocks = 100, |
388 | .min_req_rx_blocks = 22, |
389 | .tx_min = 27, |
390 | }, |
391 | |
392 | }; |
393 | |
394 | #define WL12XX_TX_HW_BLOCK_SPARE_DEFAULT 1 |
395 | #define WL12XX_TX_HW_BLOCK_GEM_SPARE 2 |
396 | #define WL12XX_TX_HW_BLOCK_SIZE 252 |
397 | |
398 | static const u8 wl12xx_rate_to_idx_2ghz[] = { |
399 | /* MCS rates are used only with 11n */ |
400 | 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI */ |
401 | 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7 */ |
402 | 6, /* WL12XX_CONF_HW_RXTX_RATE_MCS6 */ |
403 | 5, /* WL12XX_CONF_HW_RXTX_RATE_MCS5 */ |
404 | 4, /* WL12XX_CONF_HW_RXTX_RATE_MCS4 */ |
405 | 3, /* WL12XX_CONF_HW_RXTX_RATE_MCS3 */ |
406 | 2, /* WL12XX_CONF_HW_RXTX_RATE_MCS2 */ |
407 | 1, /* WL12XX_CONF_HW_RXTX_RATE_MCS1 */ |
408 | 0, /* WL12XX_CONF_HW_RXTX_RATE_MCS0 */ |
409 | |
410 | 11, /* WL12XX_CONF_HW_RXTX_RATE_54 */ |
411 | 10, /* WL12XX_CONF_HW_RXTX_RATE_48 */ |
412 | 9, /* WL12XX_CONF_HW_RXTX_RATE_36 */ |
413 | 8, /* WL12XX_CONF_HW_RXTX_RATE_24 */ |
414 | |
415 | /* TI-specific rate */ |
416 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_22 */ |
417 | |
418 | 7, /* WL12XX_CONF_HW_RXTX_RATE_18 */ |
419 | 6, /* WL12XX_CONF_HW_RXTX_RATE_12 */ |
420 | 3, /* WL12XX_CONF_HW_RXTX_RATE_11 */ |
421 | 5, /* WL12XX_CONF_HW_RXTX_RATE_9 */ |
422 | 4, /* WL12XX_CONF_HW_RXTX_RATE_6 */ |
423 | 2, /* WL12XX_CONF_HW_RXTX_RATE_5_5 */ |
424 | 1, /* WL12XX_CONF_HW_RXTX_RATE_2 */ |
425 | 0 /* WL12XX_CONF_HW_RXTX_RATE_1 */ |
426 | }; |
427 | |
428 | static const u8 wl12xx_rate_to_idx_5ghz[] = { |
429 | /* MCS rates are used only with 11n */ |
430 | 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI */ |
431 | 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7 */ |
432 | 6, /* WL12XX_CONF_HW_RXTX_RATE_MCS6 */ |
433 | 5, /* WL12XX_CONF_HW_RXTX_RATE_MCS5 */ |
434 | 4, /* WL12XX_CONF_HW_RXTX_RATE_MCS4 */ |
435 | 3, /* WL12XX_CONF_HW_RXTX_RATE_MCS3 */ |
436 | 2, /* WL12XX_CONF_HW_RXTX_RATE_MCS2 */ |
437 | 1, /* WL12XX_CONF_HW_RXTX_RATE_MCS1 */ |
438 | 0, /* WL12XX_CONF_HW_RXTX_RATE_MCS0 */ |
439 | |
440 | 7, /* WL12XX_CONF_HW_RXTX_RATE_54 */ |
441 | 6, /* WL12XX_CONF_HW_RXTX_RATE_48 */ |
442 | 5, /* WL12XX_CONF_HW_RXTX_RATE_36 */ |
443 | 4, /* WL12XX_CONF_HW_RXTX_RATE_24 */ |
444 | |
445 | /* TI-specific rate */ |
446 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_22 */ |
447 | |
448 | 3, /* WL12XX_CONF_HW_RXTX_RATE_18 */ |
449 | 2, /* WL12XX_CONF_HW_RXTX_RATE_12 */ |
450 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_11 */ |
451 | 1, /* WL12XX_CONF_HW_RXTX_RATE_9 */ |
452 | 0, /* WL12XX_CONF_HW_RXTX_RATE_6 */ |
453 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_5_5 */ |
454 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_2 */ |
455 | CONF_HW_RXTX_RATE_UNSUPPORTED /* WL12XX_CONF_HW_RXTX_RATE_1 */ |
456 | }; |
457 | |
458 | static const u8 *wl12xx_band_rate_to_idx[] = { |
459 | [NL80211_BAND_2GHZ] = wl12xx_rate_to_idx_2ghz, |
460 | [NL80211_BAND_5GHZ] = wl12xx_rate_to_idx_5ghz |
461 | }; |
462 | |
463 | enum wl12xx_hw_rates { |
464 | WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI = 0, |
465 | WL12XX_CONF_HW_RXTX_RATE_MCS7, |
466 | WL12XX_CONF_HW_RXTX_RATE_MCS6, |
467 | WL12XX_CONF_HW_RXTX_RATE_MCS5, |
468 | WL12XX_CONF_HW_RXTX_RATE_MCS4, |
469 | WL12XX_CONF_HW_RXTX_RATE_MCS3, |
470 | WL12XX_CONF_HW_RXTX_RATE_MCS2, |
471 | WL12XX_CONF_HW_RXTX_RATE_MCS1, |
472 | WL12XX_CONF_HW_RXTX_RATE_MCS0, |
473 | WL12XX_CONF_HW_RXTX_RATE_54, |
474 | WL12XX_CONF_HW_RXTX_RATE_48, |
475 | WL12XX_CONF_HW_RXTX_RATE_36, |
476 | WL12XX_CONF_HW_RXTX_RATE_24, |
477 | WL12XX_CONF_HW_RXTX_RATE_22, |
478 | WL12XX_CONF_HW_RXTX_RATE_18, |
479 | WL12XX_CONF_HW_RXTX_RATE_12, |
480 | WL12XX_CONF_HW_RXTX_RATE_11, |
481 | WL12XX_CONF_HW_RXTX_RATE_9, |
482 | WL12XX_CONF_HW_RXTX_RATE_6, |
483 | WL12XX_CONF_HW_RXTX_RATE_5_5, |
484 | WL12XX_CONF_HW_RXTX_RATE_2, |
485 | WL12XX_CONF_HW_RXTX_RATE_1, |
486 | WL12XX_CONF_HW_RXTX_RATE_MAX, |
487 | }; |
488 | |
489 | static struct wlcore_partition_set wl12xx_ptable[PART_TABLE_LEN] = { |
490 | [PART_DOWN] = { |
491 | .mem = { |
492 | .start = 0x00000000, |
493 | .size = 0x000177c0 |
494 | }, |
495 | .reg = { |
496 | .start = REGISTERS_BASE, |
497 | .size = 0x00008800 |
498 | }, |
499 | .mem2 = { |
500 | .start = 0x00000000, |
501 | .size = 0x00000000 |
502 | }, |
503 | .mem3 = { |
504 | .start = 0x00000000, |
505 | .size = 0x00000000 |
506 | }, |
507 | }, |
508 | |
509 | [PART_BOOT] = { /* in wl12xx we can use a mix of work and down |
510 | * partition here */ |
511 | .mem = { |
512 | .start = 0x00040000, |
513 | .size = 0x00014fc0 |
514 | }, |
515 | .reg = { |
516 | .start = REGISTERS_BASE, |
517 | .size = 0x00008800 |
518 | }, |
519 | .mem2 = { |
520 | .start = 0x00000000, |
521 | .size = 0x00000000 |
522 | }, |
523 | .mem3 = { |
524 | .start = 0x00000000, |
525 | .size = 0x00000000 |
526 | }, |
527 | }, |
528 | |
529 | [PART_WORK] = { |
530 | .mem = { |
531 | .start = 0x00040000, |
532 | .size = 0x00014fc0 |
533 | }, |
534 | .reg = { |
535 | .start = REGISTERS_BASE, |
536 | .size = 0x0000a000 |
537 | }, |
538 | .mem2 = { |
539 | .start = 0x003004f8, |
540 | .size = 0x00000004 |
541 | }, |
542 | .mem3 = { |
543 | .start = 0x00000000, |
544 | .size = 0x00040404 |
545 | }, |
546 | }, |
547 | |
548 | [PART_DRPW] = { |
549 | .mem = { |
550 | .start = 0x00040000, |
551 | .size = 0x00014fc0 |
552 | }, |
553 | .reg = { |
554 | .start = DRPW_BASE, |
555 | .size = 0x00006000 |
556 | }, |
557 | .mem2 = { |
558 | .start = 0x00000000, |
559 | .size = 0x00000000 |
560 | }, |
561 | .mem3 = { |
562 | .start = 0x00000000, |
563 | .size = 0x00000000 |
564 | } |
565 | } |
566 | }; |
567 | |
568 | static const int wl12xx_rtable[REG_TABLE_LEN] = { |
569 | [REG_ECPU_CONTROL] = WL12XX_REG_ECPU_CONTROL, |
570 | [REG_INTERRUPT_NO_CLEAR] = WL12XX_REG_INTERRUPT_NO_CLEAR, |
571 | [REG_INTERRUPT_ACK] = WL12XX_REG_INTERRUPT_ACK, |
572 | [REG_COMMAND_MAILBOX_PTR] = WL12XX_REG_COMMAND_MAILBOX_PTR, |
573 | [REG_EVENT_MAILBOX_PTR] = WL12XX_REG_EVENT_MAILBOX_PTR, |
574 | [REG_INTERRUPT_TRIG] = WL12XX_REG_INTERRUPT_TRIG, |
575 | [REG_INTERRUPT_MASK] = WL12XX_REG_INTERRUPT_MASK, |
576 | [REG_PC_ON_RECOVERY] = WL12XX_SCR_PAD4, |
577 | [REG_CHIP_ID_B] = WL12XX_CHIP_ID_B, |
578 | [REG_CMD_MBOX_ADDRESS] = WL12XX_CMD_MBOX_ADDRESS, |
579 | |
580 | /* data access memory addresses, used with partition translation */ |
581 | [REG_SLV_MEM_DATA] = WL1271_SLV_MEM_DATA, |
582 | [REG_SLV_REG_DATA] = WL1271_SLV_REG_DATA, |
583 | |
584 | /* raw data access memory addresses */ |
585 | [REG_RAW_FW_STATUS_ADDR] = FW_STATUS_ADDR, |
586 | }; |
587 | |
588 | /* TODO: maybe move to a new header file? */ |
589 | #define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-5-mr.bin" |
590 | #define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-5-sr.bin" |
591 | #define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-5-plt.bin" |
592 | |
593 | #define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-5-mr.bin" |
594 | #define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-5-sr.bin" |
595 | #define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-5-plt.bin" |
596 | |
597 | static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) |
598 | { |
599 | int ret; |
600 | |
601 | if (wl->chip.id != CHIP_ID_128X_PG20) { |
602 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; |
603 | struct wl12xx_priv *priv = wl->priv; |
604 | |
605 | /* |
606 | * Choose the block we want to read |
607 | * For aggregated packets, only the first memory block |
608 | * should be retrieved. The FW takes care of the rest. |
609 | */ |
610 | u32 mem_block = rx_desc & RX_MEM_BLOCK_MASK; |
611 | |
612 | priv->rx_mem_addr->addr = (mem_block << 8) + |
613 | le32_to_cpu(wl_mem_map->packet_memory_pool_start); |
614 | |
615 | priv->rx_mem_addr->addr_extra = priv->rx_mem_addr->addr + 4; |
616 | |
617 | ret = wlcore_write(wl, WL1271_SLV_REG_DATA, buf: priv->rx_mem_addr, |
618 | len: sizeof(*priv->rx_mem_addr), fixed: false); |
619 | if (ret < 0) |
620 | return ret; |
621 | } |
622 | |
623 | return 0; |
624 | } |
625 | |
626 | static int wl12xx_identify_chip(struct wl1271 *wl) |
627 | { |
628 | int ret = 0; |
629 | |
630 | switch (wl->chip.id) { |
631 | case CHIP_ID_127X_PG10: |
632 | wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete" , |
633 | wl->chip.id); |
634 | |
635 | wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | |
636 | WLCORE_QUIRK_DUAL_PROBE_TMPL | |
637 | WLCORE_QUIRK_TKIP_HEADER_SPACE | |
638 | WLCORE_QUIRK_AP_ZERO_SESSION_ID; |
639 | wl->sr_fw_name = WL127X_FW_NAME_SINGLE; |
640 | wl->mr_fw_name = WL127X_FW_NAME_MULTI; |
641 | memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x, |
642 | sizeof(wl->conf.mem)); |
643 | |
644 | /* read data preparation is only needed by wl127x */ |
645 | wl->ops->prepare_read = wl127x_prepare_read; |
646 | |
647 | wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, |
648 | WL127X_IFTYPE_SR_VER, WL127X_MAJOR_SR_VER, |
649 | WL127X_SUBTYPE_SR_VER, WL127X_MINOR_SR_VER, |
650 | WL127X_IFTYPE_MR_VER, WL127X_MAJOR_MR_VER, |
651 | WL127X_SUBTYPE_MR_VER, WL127X_MINOR_MR_VER); |
652 | break; |
653 | |
654 | case CHIP_ID_127X_PG20: |
655 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)" , |
656 | wl->chip.id); |
657 | |
658 | wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | |
659 | WLCORE_QUIRK_DUAL_PROBE_TMPL | |
660 | WLCORE_QUIRK_TKIP_HEADER_SPACE | |
661 | WLCORE_QUIRK_AP_ZERO_SESSION_ID; |
662 | wl->plt_fw_name = WL127X_PLT_FW_NAME; |
663 | wl->sr_fw_name = WL127X_FW_NAME_SINGLE; |
664 | wl->mr_fw_name = WL127X_FW_NAME_MULTI; |
665 | memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x, |
666 | sizeof(wl->conf.mem)); |
667 | |
668 | /* read data preparation is only needed by wl127x */ |
669 | wl->ops->prepare_read = wl127x_prepare_read; |
670 | |
671 | wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, |
672 | WL127X_IFTYPE_SR_VER, WL127X_MAJOR_SR_VER, |
673 | WL127X_SUBTYPE_SR_VER, WL127X_MINOR_SR_VER, |
674 | WL127X_IFTYPE_MR_VER, WL127X_MAJOR_MR_VER, |
675 | WL127X_SUBTYPE_MR_VER, WL127X_MINOR_MR_VER); |
676 | break; |
677 | |
678 | case CHIP_ID_128X_PG20: |
679 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)" , |
680 | wl->chip.id); |
681 | wl->plt_fw_name = WL128X_PLT_FW_NAME; |
682 | wl->sr_fw_name = WL128X_FW_NAME_SINGLE; |
683 | wl->mr_fw_name = WL128X_FW_NAME_MULTI; |
684 | |
685 | /* wl128x requires TX blocksize alignment */ |
686 | wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | |
687 | WLCORE_QUIRK_DUAL_PROBE_TMPL | |
688 | WLCORE_QUIRK_TKIP_HEADER_SPACE | |
689 | WLCORE_QUIRK_AP_ZERO_SESSION_ID; |
690 | |
691 | wlcore_set_min_fw_ver(wl, WL128X_CHIP_VER, |
692 | WL128X_IFTYPE_SR_VER, WL128X_MAJOR_SR_VER, |
693 | WL128X_SUBTYPE_SR_VER, WL128X_MINOR_SR_VER, |
694 | WL128X_IFTYPE_MR_VER, WL128X_MAJOR_MR_VER, |
695 | WL128X_SUBTYPE_MR_VER, WL128X_MINOR_MR_VER); |
696 | break; |
697 | case CHIP_ID_128X_PG10: |
698 | default: |
699 | wl1271_warning("unsupported chip id: 0x%x" , wl->chip.id); |
700 | ret = -ENODEV; |
701 | goto out; |
702 | } |
703 | |
704 | wl->fw_mem_block_size = 256; |
705 | wl->fwlog_end = 0x2000000; |
706 | |
707 | /* common settings */ |
708 | wl->scan_templ_id_2_4 = CMD_TEMPL_APP_PROBE_REQ_2_4_LEGACY; |
709 | wl->scan_templ_id_5 = CMD_TEMPL_APP_PROBE_REQ_5_LEGACY; |
710 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; |
711 | wl->sched_scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; |
712 | wl->max_channels_5 = WL12XX_MAX_CHANNELS_5GHZ; |
713 | wl->ba_rx_session_count_max = WL12XX_RX_BA_MAX_SESSIONS; |
714 | out: |
715 | return ret; |
716 | } |
717 | |
718 | static int __must_check wl12xx_top_reg_write(struct wl1271 *wl, int addr, |
719 | u16 val) |
720 | { |
721 | int ret; |
722 | |
723 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ |
724 | addr = (addr >> 1) + 0x30000; |
725 | ret = wlcore_write32(wl, WL12XX_OCP_POR_CTR, val: addr); |
726 | if (ret < 0) |
727 | goto out; |
728 | |
729 | /* write value to OCP_POR_WDATA */ |
730 | ret = wlcore_write32(wl, WL12XX_OCP_DATA_WRITE, val); |
731 | if (ret < 0) |
732 | goto out; |
733 | |
734 | /* write 1 to OCP_CMD */ |
735 | ret = wlcore_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE); |
736 | if (ret < 0) |
737 | goto out; |
738 | |
739 | out: |
740 | return ret; |
741 | } |
742 | |
743 | static int __must_check wl12xx_top_reg_read(struct wl1271 *wl, int addr, |
744 | u16 *out) |
745 | { |
746 | u32 val; |
747 | int timeout = OCP_CMD_LOOP; |
748 | int ret; |
749 | |
750 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ |
751 | addr = (addr >> 1) + 0x30000; |
752 | ret = wlcore_write32(wl, WL12XX_OCP_POR_CTR, val: addr); |
753 | if (ret < 0) |
754 | return ret; |
755 | |
756 | /* write 2 to OCP_CMD */ |
757 | ret = wlcore_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ); |
758 | if (ret < 0) |
759 | return ret; |
760 | |
761 | /* poll for data ready */ |
762 | do { |
763 | ret = wlcore_read32(wl, WL12XX_OCP_DATA_READ, val: &val); |
764 | if (ret < 0) |
765 | return ret; |
766 | } while (!(val & OCP_READY_MASK) && --timeout); |
767 | |
768 | if (!timeout) { |
769 | wl1271_warning("Top register access timed out." ); |
770 | return -ETIMEDOUT; |
771 | } |
772 | |
773 | /* check data status and return if OK */ |
774 | if ((val & OCP_STATUS_MASK) != OCP_STATUS_OK) { |
775 | wl1271_warning("Top register access returned error." ); |
776 | return -EIO; |
777 | } |
778 | |
779 | if (out) |
780 | *out = val & 0xffff; |
781 | |
782 | return 0; |
783 | } |
784 | |
785 | static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) |
786 | { |
787 | u16 spare_reg; |
788 | int ret; |
789 | |
790 | /* Mask bits [2] & [8:4] in the sys_clk_cfg register */ |
791 | ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, out: &spare_reg); |
792 | if (ret < 0) |
793 | return ret; |
794 | |
795 | if (spare_reg == 0xFFFF) |
796 | return -EFAULT; |
797 | spare_reg |= (BIT(3) | BIT(5) | BIT(6)); |
798 | ret = wl12xx_top_reg_write(wl, WL_SPARE_REG, val: spare_reg); |
799 | if (ret < 0) |
800 | return ret; |
801 | |
802 | /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */ |
803 | ret = wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG, |
804 | WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); |
805 | if (ret < 0) |
806 | return ret; |
807 | |
808 | /* Delay execution for 15msec, to let the HW settle */ |
809 | mdelay(15); |
810 | |
811 | return 0; |
812 | } |
813 | |
814 | static bool wl128x_is_tcxo_valid(struct wl1271 *wl) |
815 | { |
816 | u16 tcxo_detection; |
817 | int ret; |
818 | |
819 | ret = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG, out: &tcxo_detection); |
820 | if (ret < 0) |
821 | return false; |
822 | |
823 | if (tcxo_detection & TCXO_DET_FAILED) |
824 | return false; |
825 | |
826 | return true; |
827 | } |
828 | |
829 | static bool wl128x_is_fref_valid(struct wl1271 *wl) |
830 | { |
831 | u16 fref_detection; |
832 | int ret; |
833 | |
834 | ret = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG, out: &fref_detection); |
835 | if (ret < 0) |
836 | return false; |
837 | |
838 | if (fref_detection & FREF_CLK_DETECT_FAIL) |
839 | return false; |
840 | |
841 | return true; |
842 | } |
843 | |
844 | static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl) |
845 | { |
846 | int ret; |
847 | |
848 | ret = wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); |
849 | if (ret < 0) |
850 | goto out; |
851 | |
852 | ret = wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); |
853 | if (ret < 0) |
854 | goto out; |
855 | |
856 | ret = wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, |
857 | MCS_PLL_CONFIG_REG_VAL); |
858 | |
859 | out: |
860 | return ret; |
861 | } |
862 | |
863 | static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) |
864 | { |
865 | u16 spare_reg; |
866 | u16 pll_config; |
867 | u8 input_freq; |
868 | struct wl12xx_priv *priv = wl->priv; |
869 | int ret; |
870 | |
871 | /* Mask bits [3:1] in the sys_clk_cfg register */ |
872 | ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, out: &spare_reg); |
873 | if (ret < 0) |
874 | return ret; |
875 | |
876 | if (spare_reg == 0xFFFF) |
877 | return -EFAULT; |
878 | spare_reg |= BIT(2); |
879 | ret = wl12xx_top_reg_write(wl, WL_SPARE_REG, val: spare_reg); |
880 | if (ret < 0) |
881 | return ret; |
882 | |
883 | /* Handle special cases of the TCXO clock */ |
884 | if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || |
885 | priv->tcxo_clock == WL12XX_TCXOCLOCK_33_6) |
886 | return wl128x_manually_configure_mcs_pll(wl); |
887 | |
888 | /* Set the input frequency according to the selected clock source */ |
889 | input_freq = (clk & 1) + 1; |
890 | |
891 | ret = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG, out: &pll_config); |
892 | if (ret < 0) |
893 | return ret; |
894 | |
895 | if (pll_config == 0xFFFF) |
896 | return -EFAULT; |
897 | pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT); |
898 | pll_config |= MCS_PLL_ENABLE_HP; |
899 | ret = wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, val: pll_config); |
900 | |
901 | return ret; |
902 | } |
903 | |
904 | /* |
905 | * WL128x has two clocks input - TCXO and FREF. |
906 | * TCXO is the main clock of the device, while FREF is used to sync |
907 | * between the GPS and the cellular modem. |
908 | * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used |
909 | * as the WLAN/BT main clock. |
910 | */ |
911 | static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) |
912 | { |
913 | struct wl12xx_priv *priv = wl->priv; |
914 | u16 sys_clk_cfg; |
915 | int ret; |
916 | |
917 | /* For XTAL-only modes, FREF will be used after switching from TCXO */ |
918 | if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL || |
919 | priv->ref_clock == WL12XX_REFCLOCK_38_XTAL) { |
920 | if (!wl128x_switch_tcxo_to_fref(wl)) |
921 | return -EINVAL; |
922 | goto fref_clk; |
923 | } |
924 | |
925 | /* Query the HW, to determine which clock source we should use */ |
926 | ret = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG, out: &sys_clk_cfg); |
927 | if (ret < 0) |
928 | return ret; |
929 | |
930 | if (sys_clk_cfg == 0xFFFF) |
931 | return -EINVAL; |
932 | if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF) |
933 | goto fref_clk; |
934 | |
935 | /* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */ |
936 | if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_368 || |
937 | priv->tcxo_clock == WL12XX_TCXOCLOCK_32_736) { |
938 | if (!wl128x_switch_tcxo_to_fref(wl)) |
939 | return -EINVAL; |
940 | goto fref_clk; |
941 | } |
942 | |
943 | /* TCXO clock is selected */ |
944 | if (!wl128x_is_tcxo_valid(wl)) |
945 | return -EINVAL; |
946 | *selected_clock = priv->tcxo_clock; |
947 | goto config_mcs_pll; |
948 | |
949 | fref_clk: |
950 | /* FREF clock is selected */ |
951 | if (!wl128x_is_fref_valid(wl)) |
952 | return -EINVAL; |
953 | *selected_clock = priv->ref_clock; |
954 | |
955 | config_mcs_pll: |
956 | return wl128x_configure_mcs_pll(wl, clk: *selected_clock); |
957 | } |
958 | |
959 | static int wl127x_boot_clk(struct wl1271 *wl) |
960 | { |
961 | struct wl12xx_priv *priv = wl->priv; |
962 | u32 pause; |
963 | u32 clk; |
964 | int ret; |
965 | |
966 | if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) |
967 | wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION; |
968 | |
969 | if (priv->ref_clock == CONF_REF_CLK_19_2_E || |
970 | priv->ref_clock == CONF_REF_CLK_38_4_E || |
971 | priv->ref_clock == CONF_REF_CLK_38_4_M_XTAL) |
972 | /* ref clk: 19.2/38.4/38.4-XTAL */ |
973 | clk = 0x3; |
974 | else if (priv->ref_clock == CONF_REF_CLK_26_E || |
975 | priv->ref_clock == CONF_REF_CLK_26_M_XTAL || |
976 | priv->ref_clock == CONF_REF_CLK_52_E) |
977 | /* ref clk: 26/52 */ |
978 | clk = 0x5; |
979 | else |
980 | return -EINVAL; |
981 | |
982 | if (priv->ref_clock != CONF_REF_CLK_19_2_E) { |
983 | u16 val; |
984 | /* Set clock type (open drain) */ |
985 | ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE, out: &val); |
986 | if (ret < 0) |
987 | goto out; |
988 | |
989 | val &= FREF_CLK_TYPE_BITS; |
990 | ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val); |
991 | if (ret < 0) |
992 | goto out; |
993 | |
994 | /* Set clock pull mode (no pull) */ |
995 | ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL, out: &val); |
996 | if (ret < 0) |
997 | goto out; |
998 | |
999 | val |= NO_PULL; |
1000 | ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val); |
1001 | if (ret < 0) |
1002 | goto out; |
1003 | } else { |
1004 | u16 val; |
1005 | /* Set clock polarity */ |
1006 | ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY, out: &val); |
1007 | if (ret < 0) |
1008 | goto out; |
1009 | |
1010 | val &= FREF_CLK_POLARITY_BITS; |
1011 | val |= CLK_REQ_OUTN_SEL; |
1012 | ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); |
1013 | if (ret < 0) |
1014 | goto out; |
1015 | } |
1016 | |
1017 | ret = wlcore_write32(wl, WL12XX_PLL_PARAMETERS, val: clk); |
1018 | if (ret < 0) |
1019 | goto out; |
1020 | |
1021 | ret = wlcore_read32(wl, WL12XX_PLL_PARAMETERS, val: &pause); |
1022 | if (ret < 0) |
1023 | goto out; |
1024 | |
1025 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x" , pause); |
1026 | |
1027 | pause &= ~(WU_COUNTER_PAUSE_VAL); |
1028 | pause |= WU_COUNTER_PAUSE_VAL; |
1029 | ret = wlcore_write32(wl, WL12XX_WU_COUNTER_PAUSE, val: pause); |
1030 | |
1031 | out: |
1032 | return ret; |
1033 | } |
1034 | |
1035 | static int wl1271_boot_soft_reset(struct wl1271 *wl) |
1036 | { |
1037 | unsigned long timeout; |
1038 | u32 boot_data; |
1039 | int ret = 0; |
1040 | |
1041 | /* perform soft reset */ |
1042 | ret = wlcore_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); |
1043 | if (ret < 0) |
1044 | goto out; |
1045 | |
1046 | /* SOFT_RESET is self clearing */ |
1047 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); |
1048 | while (1) { |
1049 | ret = wlcore_read32(wl, WL12XX_SLV_SOFT_RESET, val: &boot_data); |
1050 | if (ret < 0) |
1051 | goto out; |
1052 | |
1053 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x" , boot_data); |
1054 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) |
1055 | break; |
1056 | |
1057 | if (time_after(jiffies, timeout)) { |
1058 | /* 1.2 check pWhalBus->uSelfClearTime if the |
1059 | * timeout was reached */ |
1060 | wl1271_error("soft reset timeout" ); |
1061 | return -1; |
1062 | } |
1063 | |
1064 | udelay(SOFT_RESET_STALL_TIME); |
1065 | } |
1066 | |
1067 | /* disable Rx/Tx */ |
1068 | ret = wlcore_write32(wl, WL12XX_ENABLE, val: 0x0); |
1069 | if (ret < 0) |
1070 | goto out; |
1071 | |
1072 | /* disable auto calibration on start*/ |
1073 | ret = wlcore_write32(wl, WL12XX_SPARE_A2, val: 0xffff); |
1074 | |
1075 | out: |
1076 | return ret; |
1077 | } |
1078 | |
1079 | static int wl12xx_pre_boot(struct wl1271 *wl) |
1080 | { |
1081 | struct wl12xx_priv *priv = wl->priv; |
1082 | int ret = 0; |
1083 | u32 clk; |
1084 | int selected_clock = -1; |
1085 | |
1086 | if (wl->chip.id == CHIP_ID_128X_PG20) { |
1087 | ret = wl128x_boot_clk(wl, selected_clock: &selected_clock); |
1088 | if (ret < 0) |
1089 | goto out; |
1090 | } else { |
1091 | ret = wl127x_boot_clk(wl); |
1092 | if (ret < 0) |
1093 | goto out; |
1094 | } |
1095 | |
1096 | /* Continue the ELP wake up sequence */ |
1097 | ret = wlcore_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); |
1098 | if (ret < 0) |
1099 | goto out; |
1100 | |
1101 | udelay(500); |
1102 | |
1103 | ret = wlcore_set_partition(wl, p: &wl->ptable[PART_DRPW]); |
1104 | if (ret < 0) |
1105 | goto out; |
1106 | |
1107 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) |
1108 | to be used by DRPw FW. The RTRIM value will be added by the FW |
1109 | before taking DRPw out of reset */ |
1110 | |
1111 | ret = wlcore_read32(wl, WL12XX_DRPW_SCRATCH_START, val: &clk); |
1112 | if (ret < 0) |
1113 | goto out; |
1114 | |
1115 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x" , clk); |
1116 | |
1117 | if (wl->chip.id == CHIP_ID_128X_PG20) |
1118 | clk |= ((selected_clock & 0x3) << 1) << 4; |
1119 | else |
1120 | clk |= (priv->ref_clock << 1) << 4; |
1121 | |
1122 | ret = wlcore_write32(wl, WL12XX_DRPW_SCRATCH_START, val: clk); |
1123 | if (ret < 0) |
1124 | goto out; |
1125 | |
1126 | ret = wlcore_set_partition(wl, p: &wl->ptable[PART_WORK]); |
1127 | if (ret < 0) |
1128 | goto out; |
1129 | |
1130 | /* Disable interrupts */ |
1131 | ret = wlcore_write_reg(wl, reg: REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
1132 | if (ret < 0) |
1133 | goto out; |
1134 | |
1135 | ret = wl1271_boot_soft_reset(wl); |
1136 | if (ret < 0) |
1137 | goto out; |
1138 | |
1139 | out: |
1140 | return ret; |
1141 | } |
1142 | |
1143 | static int wl12xx_pre_upload(struct wl1271 *wl) |
1144 | { |
1145 | u32 tmp; |
1146 | u16 polarity; |
1147 | int ret; |
1148 | |
1149 | /* write firmware's last address (ie. it's length) to |
1150 | * ACX_EEPROMLESS_IND_REG */ |
1151 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG" ); |
1152 | |
1153 | ret = wlcore_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND); |
1154 | if (ret < 0) |
1155 | goto out; |
1156 | |
1157 | ret = wlcore_read_reg(wl, reg: REG_CHIP_ID_B, val: &tmp); |
1158 | if (ret < 0) |
1159 | goto out; |
1160 | |
1161 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x" , tmp); |
1162 | |
1163 | /* 6. read the EEPROM parameters */ |
1164 | ret = wlcore_read32(wl, WL12XX_SCR_PAD2, val: &tmp); |
1165 | if (ret < 0) |
1166 | goto out; |
1167 | |
1168 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly |
1169 | * to upload_fw) */ |
1170 | |
1171 | if (wl->chip.id == CHIP_ID_128X_PG20) { |
1172 | ret = wl12xx_top_reg_write(wl, SDIO_IO_DS, val: HCI_IO_DS_6MA); |
1173 | if (ret < 0) |
1174 | goto out; |
1175 | } |
1176 | |
1177 | /* polarity must be set before the firmware is loaded */ |
1178 | ret = wl12xx_top_reg_read(wl, OCP_REG_POLARITY, out: &polarity); |
1179 | if (ret < 0) |
1180 | goto out; |
1181 | |
1182 | /* We use HIGH polarity, so unset the LOW bit */ |
1183 | polarity &= ~POLARITY_LOW; |
1184 | ret = wl12xx_top_reg_write(wl, OCP_REG_POLARITY, val: polarity); |
1185 | |
1186 | out: |
1187 | return ret; |
1188 | } |
1189 | |
1190 | static int wl12xx_enable_interrupts(struct wl1271 *wl) |
1191 | { |
1192 | int ret; |
1193 | |
1194 | ret = wlcore_write_reg(wl, reg: REG_INTERRUPT_MASK, |
1195 | WL12XX_ACX_ALL_EVENTS_VECTOR); |
1196 | if (ret < 0) |
1197 | goto out; |
1198 | |
1199 | wlcore_enable_interrupts(wl); |
1200 | ret = wlcore_write_reg(wl, reg: REG_INTERRUPT_MASK, |
1201 | WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK)); |
1202 | if (ret < 0) |
1203 | goto disable_interrupts; |
1204 | |
1205 | ret = wlcore_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); |
1206 | if (ret < 0) |
1207 | goto disable_interrupts; |
1208 | |
1209 | return ret; |
1210 | |
1211 | disable_interrupts: |
1212 | wlcore_disable_interrupts(wl); |
1213 | |
1214 | out: |
1215 | return ret; |
1216 | } |
1217 | |
1218 | static int wl12xx_boot(struct wl1271 *wl) |
1219 | { |
1220 | int ret; |
1221 | |
1222 | ret = wl12xx_pre_boot(wl); |
1223 | if (ret < 0) |
1224 | goto out; |
1225 | |
1226 | ret = wlcore_boot_upload_nvs(wl); |
1227 | if (ret < 0) |
1228 | goto out; |
1229 | |
1230 | ret = wl12xx_pre_upload(wl); |
1231 | if (ret < 0) |
1232 | goto out; |
1233 | |
1234 | ret = wlcore_boot_upload_firmware(wl); |
1235 | if (ret < 0) |
1236 | goto out; |
1237 | |
1238 | wl->event_mask = BSS_LOSE_EVENT_ID | |
1239 | REGAINED_BSS_EVENT_ID | |
1240 | SCAN_COMPLETE_EVENT_ID | |
1241 | ROLE_STOP_COMPLETE_EVENT_ID | |
1242 | RSSI_SNR_TRIGGER_0_EVENT_ID | |
1243 | PSPOLL_DELIVERY_FAILURE_EVENT_ID | |
1244 | SOFT_GEMINI_SENSE_EVENT_ID | |
1245 | PERIODIC_SCAN_REPORT_EVENT_ID | |
1246 | PERIODIC_SCAN_COMPLETE_EVENT_ID | |
1247 | DUMMY_PACKET_EVENT_ID | |
1248 | PEER_REMOVE_COMPLETE_EVENT_ID | |
1249 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | |
1250 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | |
1251 | INACTIVE_STA_EVENT_ID | |
1252 | CHANNEL_SWITCH_COMPLETE_EVENT_ID; |
1253 | |
1254 | wl->ap_event_mask = MAX_TX_RETRY_EVENT_ID; |
1255 | |
1256 | ret = wlcore_boot_run_firmware(wl); |
1257 | if (ret < 0) |
1258 | goto out; |
1259 | |
1260 | ret = wl12xx_enable_interrupts(wl); |
1261 | |
1262 | out: |
1263 | return ret; |
1264 | } |
1265 | |
1266 | static int wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, |
1267 | void *buf, size_t len) |
1268 | { |
1269 | int ret; |
1270 | |
1271 | ret = wlcore_write(wl, addr: cmd_box_addr, buf, len, fixed: false); |
1272 | if (ret < 0) |
1273 | return ret; |
1274 | |
1275 | ret = wlcore_write_reg(wl, reg: REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD); |
1276 | |
1277 | return ret; |
1278 | } |
1279 | |
1280 | static int wl12xx_ack_event(struct wl1271 *wl) |
1281 | { |
1282 | return wlcore_write_reg(wl, reg: REG_INTERRUPT_TRIG, |
1283 | WL12XX_INTR_TRIG_EVENT_ACK); |
1284 | } |
1285 | |
1286 | static u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) |
1287 | { |
1288 | u32 blk_size = WL12XX_TX_HW_BLOCK_SIZE; |
1289 | u32 align_len = wlcore_calc_packet_alignment(wl, packet_length: len); |
1290 | |
1291 | return (align_len + blk_size - 1) / blk_size + spare_blks; |
1292 | } |
1293 | |
1294 | static void |
1295 | wl12xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, |
1296 | u32 blks, u32 spare_blks) |
1297 | { |
1298 | if (wl->chip.id == CHIP_ID_128X_PG20) { |
1299 | desc->wl128x_mem.total_mem_blocks = blks; |
1300 | } else { |
1301 | desc->wl127x_mem.extra_blocks = spare_blks; |
1302 | desc->wl127x_mem.total_mem_blocks = blks; |
1303 | } |
1304 | } |
1305 | |
1306 | static void |
1307 | wl12xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, |
1308 | struct sk_buff *skb) |
1309 | { |
1310 | u32 aligned_len = wlcore_calc_packet_alignment(wl, packet_length: skb->len); |
1311 | |
1312 | if (wl->chip.id == CHIP_ID_128X_PG20) { |
1313 | desc->wl128x_mem.extra_bytes = aligned_len - skb->len; |
1314 | desc->length = cpu_to_le16(aligned_len >> 2); |
1315 | |
1316 | wl1271_debug(DEBUG_TX, |
1317 | "tx_fill_hdr: hlid: %d len: %d life: %d mem: %d extra: %d" , |
1318 | desc->hlid, |
1319 | le16_to_cpu(desc->length), |
1320 | le16_to_cpu(desc->life_time), |
1321 | desc->wl128x_mem.total_mem_blocks, |
1322 | desc->wl128x_mem.extra_bytes); |
1323 | } else { |
1324 | /* calculate number of padding bytes */ |
1325 | int pad = aligned_len - skb->len; |
1326 | desc->tx_attr |= |
1327 | cpu_to_le16(pad << TX_HW_ATTR_OFST_LAST_WORD_PAD); |
1328 | |
1329 | /* Store the aligned length in terms of words */ |
1330 | desc->length = cpu_to_le16(aligned_len >> 2); |
1331 | |
1332 | wl1271_debug(DEBUG_TX, |
1333 | "tx_fill_hdr: pad: %d hlid: %d len: %d life: %d mem: %d" , |
1334 | pad, desc->hlid, |
1335 | le16_to_cpu(desc->length), |
1336 | le16_to_cpu(desc->life_time), |
1337 | desc->wl127x_mem.total_mem_blocks); |
1338 | } |
1339 | } |
1340 | |
1341 | static enum wl_rx_buf_align |
1342 | wl12xx_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc) |
1343 | { |
1344 | if (rx_desc & RX_BUF_UNALIGNED_PAYLOAD) |
1345 | return WLCORE_RX_BUF_UNALIGNED; |
1346 | |
1347 | return WLCORE_RX_BUF_ALIGNED; |
1348 | } |
1349 | |
1350 | static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data, |
1351 | u32 data_len) |
1352 | { |
1353 | struct wl1271_rx_descriptor *desc = rx_data; |
1354 | |
1355 | /* invalid packet */ |
1356 | if (data_len < sizeof(*desc) || |
1357 | data_len < sizeof(*desc) + desc->pad_len) |
1358 | return 0; |
1359 | |
1360 | return data_len - sizeof(*desc) - desc->pad_len; |
1361 | } |
1362 | |
1363 | static int wl12xx_tx_delayed_compl(struct wl1271 *wl) |
1364 | { |
1365 | if (wl->fw_status->tx_results_counter == |
1366 | (wl->tx_results_count & 0xff)) |
1367 | return 0; |
1368 | |
1369 | return wlcore_tx_complete(wl); |
1370 | } |
1371 | |
1372 | static int wl12xx_hw_init(struct wl1271 *wl) |
1373 | { |
1374 | int ret; |
1375 | |
1376 | if (wl->chip.id == CHIP_ID_128X_PG20) { |
1377 | u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE; |
1378 | |
1379 | ret = wl128x_cmd_general_parms(wl); |
1380 | if (ret < 0) |
1381 | goto out; |
1382 | |
1383 | /* |
1384 | * If we are in calibrator based auto detect then we got the FEM nr |
1385 | * in wl->fem_manuf. No need to continue further |
1386 | */ |
1387 | if (wl->plt_mode == PLT_FEM_DETECT) |
1388 | goto out; |
1389 | |
1390 | ret = wl128x_cmd_radio_parms(wl); |
1391 | if (ret < 0) |
1392 | goto out; |
1393 | |
1394 | if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN) |
1395 | /* Enable SDIO padding */ |
1396 | host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK; |
1397 | |
1398 | /* Must be before wl1271_acx_init_mem_config() */ |
1399 | ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap); |
1400 | if (ret < 0) |
1401 | goto out; |
1402 | } else { |
1403 | ret = wl1271_cmd_general_parms(wl); |
1404 | if (ret < 0) |
1405 | goto out; |
1406 | |
1407 | /* |
1408 | * If we are in calibrator based auto detect then we got the FEM nr |
1409 | * in wl->fem_manuf. No need to continue further |
1410 | */ |
1411 | if (wl->plt_mode == PLT_FEM_DETECT) |
1412 | goto out; |
1413 | |
1414 | ret = wl1271_cmd_radio_parms(wl); |
1415 | if (ret < 0) |
1416 | goto out; |
1417 | ret = wl1271_cmd_ext_radio_parms(wl); |
1418 | if (ret < 0) |
1419 | goto out; |
1420 | } |
1421 | out: |
1422 | return ret; |
1423 | } |
1424 | |
1425 | static void wl12xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status, |
1426 | struct wl_fw_status *fw_status) |
1427 | { |
1428 | struct wl12xx_fw_status *int_fw_status = raw_fw_status; |
1429 | |
1430 | fw_status->intr = le32_to_cpu(int_fw_status->intr); |
1431 | fw_status->fw_rx_counter = int_fw_status->fw_rx_counter; |
1432 | fw_status->drv_rx_counter = int_fw_status->drv_rx_counter; |
1433 | fw_status->tx_results_counter = int_fw_status->tx_results_counter; |
1434 | fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs; |
1435 | |
1436 | fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime); |
1437 | fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap); |
1438 | fw_status->link_fast_bitmap = |
1439 | le32_to_cpu(int_fw_status->link_fast_bitmap); |
1440 | fw_status->total_released_blks = |
1441 | le32_to_cpu(int_fw_status->total_released_blks); |
1442 | fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total); |
1443 | |
1444 | fw_status->counters.tx_released_pkts = |
1445 | int_fw_status->counters.tx_released_pkts; |
1446 | fw_status->counters.tx_lnk_free_pkts = |
1447 | int_fw_status->counters.tx_lnk_free_pkts; |
1448 | fw_status->counters.tx_voice_released_blks = |
1449 | int_fw_status->counters.tx_voice_released_blks; |
1450 | fw_status->counters.tx_last_rate = |
1451 | int_fw_status->counters.tx_last_rate; |
1452 | |
1453 | fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr); |
1454 | } |
1455 | |
1456 | static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl, |
1457 | struct wl12xx_vif *wlvif) |
1458 | { |
1459 | return wlvif->rate_set; |
1460 | } |
1461 | |
1462 | static void wl12xx_conf_init(struct wl1271 *wl) |
1463 | { |
1464 | struct wl12xx_priv *priv = wl->priv; |
1465 | |
1466 | /* apply driver default configuration */ |
1467 | memcpy(&wl->conf, &wl12xx_conf, sizeof(wl12xx_conf)); |
1468 | |
1469 | /* apply default private configuration */ |
1470 | memcpy(&priv->conf, &wl12xx_default_priv_conf, sizeof(priv->conf)); |
1471 | } |
1472 | |
1473 | static bool wl12xx_mac_in_fuse(struct wl1271 *wl) |
1474 | { |
1475 | bool supported = false; |
1476 | u8 major, minor; |
1477 | |
1478 | if (wl->chip.id == CHIP_ID_128X_PG20) { |
1479 | major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver); |
1480 | minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver); |
1481 | |
1482 | /* in wl128x we have the MAC address if the PG is >= (2, 1) */ |
1483 | if (major > 2 || (major == 2 && minor >= 1)) |
1484 | supported = true; |
1485 | } else { |
1486 | major = WL127X_PG_GET_MAJOR(wl->hw_pg_ver); |
1487 | minor = WL127X_PG_GET_MINOR(wl->hw_pg_ver); |
1488 | |
1489 | /* in wl127x we have the MAC address if the PG is >= (3, 1) */ |
1490 | if (major == 3 && minor >= 1) |
1491 | supported = true; |
1492 | } |
1493 | |
1494 | wl1271_debug(DEBUG_PROBE, |
1495 | "PG Ver major = %d minor = %d, MAC %s present" , |
1496 | major, minor, supported ? "is" : "is not" ); |
1497 | |
1498 | return supported; |
1499 | } |
1500 | |
1501 | static int wl12xx_get_fuse_mac(struct wl1271 *wl) |
1502 | { |
1503 | u32 mac1, mac2; |
1504 | int ret; |
1505 | |
1506 | /* Device may be in ELP from the bootloader or kexec */ |
1507 | ret = wlcore_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); |
1508 | if (ret < 0) |
1509 | goto out; |
1510 | |
1511 | usleep_range(min: 500000, max: 700000); |
1512 | |
1513 | ret = wlcore_set_partition(wl, p: &wl->ptable[PART_DRPW]); |
1514 | if (ret < 0) |
1515 | goto out; |
1516 | |
1517 | ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1, val: &mac1); |
1518 | if (ret < 0) |
1519 | goto out; |
1520 | |
1521 | ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2, val: &mac2); |
1522 | if (ret < 0) |
1523 | goto out; |
1524 | |
1525 | /* these are the two parts of the BD_ADDR */ |
1526 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + |
1527 | ((mac1 & 0xff000000) >> 24); |
1528 | wl->fuse_nic_addr = mac1 & 0xffffff; |
1529 | |
1530 | ret = wlcore_set_partition(wl, p: &wl->ptable[PART_DOWN]); |
1531 | |
1532 | out: |
1533 | return ret; |
1534 | } |
1535 | |
1536 | static int wl12xx_get_pg_ver(struct wl1271 *wl, s8 *ver) |
1537 | { |
1538 | u16 die_info; |
1539 | int ret; |
1540 | |
1541 | if (wl->chip.id == CHIP_ID_128X_PG20) |
1542 | ret = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1, |
1543 | out: &die_info); |
1544 | else |
1545 | ret = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1, |
1546 | out: &die_info); |
1547 | |
1548 | if (ret >= 0 && ver) |
1549 | *ver = (s8)((die_info & PG_VER_MASK) >> PG_VER_OFFSET); |
1550 | |
1551 | return ret; |
1552 | } |
1553 | |
1554 | static int wl12xx_get_mac(struct wl1271 *wl) |
1555 | { |
1556 | if (wl12xx_mac_in_fuse(wl)) |
1557 | return wl12xx_get_fuse_mac(wl); |
1558 | |
1559 | return 0; |
1560 | } |
1561 | |
1562 | static void wl12xx_set_tx_desc_csum(struct wl1271 *wl, |
1563 | struct wl1271_tx_hw_descr *desc, |
1564 | struct sk_buff *skb) |
1565 | { |
1566 | desc->wl12xx_reserved = 0; |
1567 | } |
1568 | |
1569 | static int wl12xx_plt_init(struct wl1271 *wl) |
1570 | { |
1571 | int ret; |
1572 | |
1573 | ret = wl->ops->boot(wl); |
1574 | if (ret < 0) |
1575 | goto out; |
1576 | |
1577 | ret = wl->ops->hw_init(wl); |
1578 | if (ret < 0) |
1579 | goto out_irq_disable; |
1580 | |
1581 | /* |
1582 | * If we are in calibrator based auto detect then we got the FEM nr |
1583 | * in wl->fem_manuf. No need to continue further |
1584 | */ |
1585 | if (wl->plt_mode == PLT_FEM_DETECT) |
1586 | goto out; |
1587 | |
1588 | ret = wl1271_acx_init_mem_config(wl); |
1589 | if (ret < 0) |
1590 | goto out_irq_disable; |
1591 | |
1592 | ret = wl12xx_acx_mem_cfg(wl); |
1593 | if (ret < 0) |
1594 | goto out_free_memmap; |
1595 | |
1596 | /* Enable data path */ |
1597 | ret = wl1271_cmd_data_path(wl, enable: 1); |
1598 | if (ret < 0) |
1599 | goto out_free_memmap; |
1600 | |
1601 | /* Configure for CAM power saving (ie. always active) */ |
1602 | ret = wl1271_acx_sleep_auth(wl, sleep_auth: WL1271_PSM_CAM); |
1603 | if (ret < 0) |
1604 | goto out_free_memmap; |
1605 | |
1606 | /* configure PM */ |
1607 | ret = wl1271_acx_pm_config(wl); |
1608 | if (ret < 0) |
1609 | goto out_free_memmap; |
1610 | |
1611 | goto out; |
1612 | |
1613 | out_free_memmap: |
1614 | kfree(objp: wl->target_mem_map); |
1615 | wl->target_mem_map = NULL; |
1616 | |
1617 | out_irq_disable: |
1618 | mutex_unlock(lock: &wl->mutex); |
1619 | /* Unlocking the mutex in the middle of handling is |
1620 | inherently unsafe. In this case we deem it safe to do, |
1621 | because we need to let any possibly pending IRQ out of |
1622 | the system (and while we are WL1271_STATE_OFF the IRQ |
1623 | work function will not do anything.) Also, any other |
1624 | possible concurrent operations will fail due to the |
1625 | current state, hence the wl1271 struct should be safe. */ |
1626 | wlcore_disable_interrupts(wl); |
1627 | mutex_lock(&wl->mutex); |
1628 | out: |
1629 | return ret; |
1630 | } |
1631 | |
1632 | static int wl12xx_get_spare_blocks(struct wl1271 *wl, bool is_gem) |
1633 | { |
1634 | if (is_gem) |
1635 | return WL12XX_TX_HW_BLOCK_GEM_SPARE; |
1636 | |
1637 | return WL12XX_TX_HW_BLOCK_SPARE_DEFAULT; |
1638 | } |
1639 | |
1640 | static int wl12xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, |
1641 | struct ieee80211_vif *vif, |
1642 | struct ieee80211_sta *sta, |
1643 | struct ieee80211_key_conf *key_conf) |
1644 | { |
1645 | return wlcore_set_key(wl, cmd, vif, sta, key_conf); |
1646 | } |
1647 | |
1648 | static int wl12xx_set_peer_cap(struct wl1271 *wl, |
1649 | struct ieee80211_sta_ht_cap *ht_cap, |
1650 | bool allow_ht_operation, |
1651 | u32 rate_set, u8 hlid) |
1652 | { |
1653 | return wl1271_acx_set_ht_capabilities(wl, ht_cap, allow_ht_operation, |
1654 | hlid); |
1655 | } |
1656 | |
1657 | static bool wl12xx_lnk_high_prio(struct wl1271 *wl, u8 hlid, |
1658 | struct wl1271_link *lnk) |
1659 | { |
1660 | u8 thold; |
1661 | |
1662 | if (test_bit(hlid, &wl->fw_fast_lnk_map)) |
1663 | thold = wl->conf.tx.fast_link_thold; |
1664 | else |
1665 | thold = wl->conf.tx.slow_link_thold; |
1666 | |
1667 | return lnk->allocated_pkts < thold; |
1668 | } |
1669 | |
1670 | static bool wl12xx_lnk_low_prio(struct wl1271 *wl, u8 hlid, |
1671 | struct wl1271_link *lnk) |
1672 | { |
1673 | /* any link is good for low priority */ |
1674 | return true; |
1675 | } |
1676 | |
1677 | static u32 wl12xx_convert_hwaddr(struct wl1271 *wl, u32 hwaddr) |
1678 | { |
1679 | return hwaddr << 5; |
1680 | } |
1681 | |
1682 | static int wl12xx_setup(struct wl1271 *wl); |
1683 | |
1684 | static struct wlcore_ops wl12xx_ops = { |
1685 | .setup = wl12xx_setup, |
1686 | .identify_chip = wl12xx_identify_chip, |
1687 | .boot = wl12xx_boot, |
1688 | .plt_init = wl12xx_plt_init, |
1689 | .trigger_cmd = wl12xx_trigger_cmd, |
1690 | .ack_event = wl12xx_ack_event, |
1691 | .wait_for_event = wl12xx_wait_for_event, |
1692 | .process_mailbox_events = wl12xx_process_mailbox_events, |
1693 | .calc_tx_blocks = wl12xx_calc_tx_blocks, |
1694 | .set_tx_desc_blocks = wl12xx_set_tx_desc_blocks, |
1695 | .set_tx_desc_data_len = wl12xx_set_tx_desc_data_len, |
1696 | .get_rx_buf_align = wl12xx_get_rx_buf_align, |
1697 | .get_rx_packet_len = wl12xx_get_rx_packet_len, |
1698 | .tx_immediate_compl = NULL, |
1699 | .tx_delayed_compl = wl12xx_tx_delayed_compl, |
1700 | .hw_init = wl12xx_hw_init, |
1701 | .init_vif = NULL, |
1702 | .convert_fw_status = wl12xx_convert_fw_status, |
1703 | .sta_get_ap_rate_mask = wl12xx_sta_get_ap_rate_mask, |
1704 | .get_pg_ver = wl12xx_get_pg_ver, |
1705 | .get_mac = wl12xx_get_mac, |
1706 | .set_tx_desc_csum = wl12xx_set_tx_desc_csum, |
1707 | .set_rx_csum = NULL, |
1708 | .ap_get_mimo_wide_rate_mask = NULL, |
1709 | .debugfs_init = wl12xx_debugfs_add_files, |
1710 | .scan_start = wl12xx_scan_start, |
1711 | .scan_stop = wl12xx_scan_stop, |
1712 | .sched_scan_start = wl12xx_sched_scan_start, |
1713 | .sched_scan_stop = wl12xx_scan_sched_scan_stop, |
1714 | .get_spare_blocks = wl12xx_get_spare_blocks, |
1715 | .set_key = wl12xx_set_key, |
1716 | .channel_switch = wl12xx_cmd_channel_switch, |
1717 | .pre_pkt_send = NULL, |
1718 | .set_peer_cap = wl12xx_set_peer_cap, |
1719 | .convert_hwaddr = wl12xx_convert_hwaddr, |
1720 | .lnk_high_prio = wl12xx_lnk_high_prio, |
1721 | .lnk_low_prio = wl12xx_lnk_low_prio, |
1722 | .interrupt_notify = NULL, |
1723 | .rx_ba_filter = NULL, |
1724 | .ap_sleep = NULL, |
1725 | }; |
1726 | |
1727 | static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { |
1728 | .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | |
1729 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), |
1730 | .ht_supported = true, |
1731 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, |
1732 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, |
1733 | .mcs = { |
1734 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, |
1735 | .rx_highest = cpu_to_le16(72), |
1736 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, |
1737 | }, |
1738 | }; |
1739 | |
1740 | static const struct ieee80211_iface_limit wl12xx_iface_limits[] = { |
1741 | { |
1742 | .max = 3, |
1743 | .types = BIT(NL80211_IFTYPE_STATION), |
1744 | }, |
1745 | { |
1746 | .max = 1, |
1747 | .types = BIT(NL80211_IFTYPE_AP) | |
1748 | BIT(NL80211_IFTYPE_P2P_GO) | |
1749 | BIT(NL80211_IFTYPE_P2P_CLIENT), |
1750 | }, |
1751 | }; |
1752 | |
1753 | static const struct ieee80211_iface_combination |
1754 | wl12xx_iface_combinations[] = { |
1755 | { |
1756 | .max_interfaces = 3, |
1757 | .limits = wl12xx_iface_limits, |
1758 | .n_limits = ARRAY_SIZE(wl12xx_iface_limits), |
1759 | .num_different_channels = 1, |
1760 | }, |
1761 | }; |
1762 | |
1763 | static const struct wl12xx_clock wl12xx_refclock_table[] = { |
1764 | { 19200000, false, WL12XX_REFCLOCK_19 }, |
1765 | { 26000000, false, WL12XX_REFCLOCK_26 }, |
1766 | { 26000000, true, WL12XX_REFCLOCK_26_XTAL }, |
1767 | { 38400000, false, WL12XX_REFCLOCK_38 }, |
1768 | { 38400000, true, WL12XX_REFCLOCK_38_XTAL }, |
1769 | { 52000000, false, WL12XX_REFCLOCK_52 }, |
1770 | { 0, false, 0 } |
1771 | }; |
1772 | |
1773 | static const struct wl12xx_clock wl12xx_tcxoclock_table[] = { |
1774 | { 16368000, true, WL12XX_TCXOCLOCK_16_368 }, |
1775 | { 16800000, true, WL12XX_TCXOCLOCK_16_8 }, |
1776 | { 19200000, true, WL12XX_TCXOCLOCK_19_2 }, |
1777 | { 26000000, true, WL12XX_TCXOCLOCK_26 }, |
1778 | { 32736000, true, WL12XX_TCXOCLOCK_32_736 }, |
1779 | { 33600000, true, WL12XX_TCXOCLOCK_33_6 }, |
1780 | { 38400000, true, WL12XX_TCXOCLOCK_38_4 }, |
1781 | { 52000000, true, WL12XX_TCXOCLOCK_52 }, |
1782 | { 0, false, 0 } |
1783 | }; |
1784 | |
1785 | static int wl12xx_get_clock_idx(const struct wl12xx_clock *table, |
1786 | u32 freq, bool xtal) |
1787 | { |
1788 | int i; |
1789 | |
1790 | for (i = 0; table[i].freq != 0; i++) |
1791 | if ((table[i].freq == freq) && (table[i].xtal == xtal)) |
1792 | return table[i].hw_idx; |
1793 | |
1794 | return -EINVAL; |
1795 | } |
1796 | |
1797 | static int wl12xx_setup(struct wl1271 *wl) |
1798 | { |
1799 | struct wl12xx_priv *priv = wl->priv; |
1800 | struct wlcore_platdev_data *pdev_data = dev_get_platdata(dev: &wl->pdev->dev); |
1801 | |
1802 | BUILD_BUG_ON(WL12XX_MAX_LINKS > WLCORE_MAX_LINKS); |
1803 | BUILD_BUG_ON(WL12XX_MAX_AP_STATIONS > WL12XX_MAX_LINKS); |
1804 | BUILD_BUG_ON(WL12XX_CONF_SG_PARAMS_MAX > WLCORE_CONF_SG_PARAMS_MAX); |
1805 | |
1806 | wl->rtable = wl12xx_rtable; |
1807 | wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS; |
1808 | wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS; |
1809 | wl->num_links = WL12XX_MAX_LINKS; |
1810 | wl->max_ap_stations = WL12XX_MAX_AP_STATIONS; |
1811 | wl->iface_combinations = wl12xx_iface_combinations; |
1812 | wl->n_iface_combinations = ARRAY_SIZE(wl12xx_iface_combinations); |
1813 | wl->num_mac_addr = WL12XX_NUM_MAC_ADDRESSES; |
1814 | wl->band_rate_to_idx = wl12xx_band_rate_to_idx; |
1815 | wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; |
1816 | wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; |
1817 | wl->fw_status_len = sizeof(struct wl12xx_fw_status); |
1818 | wl->fw_status_priv_len = 0; |
1819 | wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics); |
1820 | wl->ofdm_only_ap = true; |
1821 | wlcore_set_ht_cap(wl, band: NL80211_BAND_2GHZ, ht_cap: &wl12xx_ht_cap); |
1822 | wlcore_set_ht_cap(wl, band: NL80211_BAND_5GHZ, ht_cap: &wl12xx_ht_cap); |
1823 | wl12xx_conf_init(wl); |
1824 | |
1825 | if (!fref_param) { |
1826 | priv->ref_clock = wl12xx_get_clock_idx(table: wl12xx_refclock_table, |
1827 | freq: pdev_data->ref_clock_freq, |
1828 | xtal: pdev_data->ref_clock_xtal); |
1829 | if (priv->ref_clock < 0) { |
1830 | wl1271_error("Invalid ref_clock frequency (%d Hz, %s)" , |
1831 | pdev_data->ref_clock_freq, |
1832 | pdev_data->ref_clock_xtal ? |
1833 | "XTAL" : "not XTAL" ); |
1834 | |
1835 | return priv->ref_clock; |
1836 | } |
1837 | } else { |
1838 | if (!strcmp(fref_param, "19.2" )) |
1839 | priv->ref_clock = WL12XX_REFCLOCK_19; |
1840 | else if (!strcmp(fref_param, "26" )) |
1841 | priv->ref_clock = WL12XX_REFCLOCK_26; |
1842 | else if (!strcmp(fref_param, "26x" )) |
1843 | priv->ref_clock = WL12XX_REFCLOCK_26_XTAL; |
1844 | else if (!strcmp(fref_param, "38.4" )) |
1845 | priv->ref_clock = WL12XX_REFCLOCK_38; |
1846 | else if (!strcmp(fref_param, "38.4x" )) |
1847 | priv->ref_clock = WL12XX_REFCLOCK_38_XTAL; |
1848 | else if (!strcmp(fref_param, "52" )) |
1849 | priv->ref_clock = WL12XX_REFCLOCK_52; |
1850 | else |
1851 | wl1271_error("Invalid fref parameter %s" , fref_param); |
1852 | } |
1853 | |
1854 | if (!tcxo_param && pdev_data->tcxo_clock_freq) { |
1855 | priv->tcxo_clock = wl12xx_get_clock_idx(table: wl12xx_tcxoclock_table, |
1856 | freq: pdev_data->tcxo_clock_freq, |
1857 | xtal: true); |
1858 | if (priv->tcxo_clock < 0) { |
1859 | wl1271_error("Invalid tcxo_clock frequency (%d Hz)" , |
1860 | pdev_data->tcxo_clock_freq); |
1861 | |
1862 | return priv->tcxo_clock; |
1863 | } |
1864 | } else if (tcxo_param) { |
1865 | if (!strcmp(tcxo_param, "19.2" )) |
1866 | priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2; |
1867 | else if (!strcmp(tcxo_param, "26" )) |
1868 | priv->tcxo_clock = WL12XX_TCXOCLOCK_26; |
1869 | else if (!strcmp(tcxo_param, "38.4" )) |
1870 | priv->tcxo_clock = WL12XX_TCXOCLOCK_38_4; |
1871 | else if (!strcmp(tcxo_param, "52" )) |
1872 | priv->tcxo_clock = WL12XX_TCXOCLOCK_52; |
1873 | else if (!strcmp(tcxo_param, "16.368" )) |
1874 | priv->tcxo_clock = WL12XX_TCXOCLOCK_16_368; |
1875 | else if (!strcmp(tcxo_param, "32.736" )) |
1876 | priv->tcxo_clock = WL12XX_TCXOCLOCK_32_736; |
1877 | else if (!strcmp(tcxo_param, "16.8" )) |
1878 | priv->tcxo_clock = WL12XX_TCXOCLOCK_16_8; |
1879 | else if (!strcmp(tcxo_param, "33.6" )) |
1880 | priv->tcxo_clock = WL12XX_TCXOCLOCK_33_6; |
1881 | else |
1882 | wl1271_error("Invalid tcxo parameter %s" , tcxo_param); |
1883 | } |
1884 | |
1885 | priv->rx_mem_addr = kmalloc(size: sizeof(*priv->rx_mem_addr), GFP_KERNEL); |
1886 | if (!priv->rx_mem_addr) |
1887 | return -ENOMEM; |
1888 | |
1889 | return 0; |
1890 | } |
1891 | |
1892 | static int wl12xx_probe(struct platform_device *pdev) |
1893 | { |
1894 | struct wl1271 *wl; |
1895 | struct ieee80211_hw *hw; |
1896 | int ret; |
1897 | |
1898 | hw = wlcore_alloc_hw(priv_size: sizeof(struct wl12xx_priv), |
1899 | WL12XX_AGGR_BUFFER_SIZE, |
1900 | mbox_size: sizeof(struct wl12xx_event_mailbox)); |
1901 | if (IS_ERR(ptr: hw)) { |
1902 | wl1271_error("can't allocate hw" ); |
1903 | ret = PTR_ERR(ptr: hw); |
1904 | goto out; |
1905 | } |
1906 | |
1907 | wl = hw->priv; |
1908 | wl->ops = &wl12xx_ops; |
1909 | wl->ptable = wl12xx_ptable; |
1910 | ret = wlcore_probe(wl, pdev); |
1911 | if (ret) |
1912 | goto out_free; |
1913 | |
1914 | return ret; |
1915 | |
1916 | out_free: |
1917 | wlcore_free_hw(wl); |
1918 | out: |
1919 | return ret; |
1920 | } |
1921 | |
1922 | static void wl12xx_remove(struct platform_device *pdev) |
1923 | { |
1924 | struct wl1271 *wl = platform_get_drvdata(pdev); |
1925 | struct wl12xx_priv *priv; |
1926 | |
1927 | priv = wl->priv; |
1928 | |
1929 | kfree(objp: priv->rx_mem_addr); |
1930 | |
1931 | wlcore_remove(pdev); |
1932 | } |
1933 | |
1934 | static const struct platform_device_id wl12xx_id_table[] = { |
1935 | { "wl12xx" , 0 }, |
1936 | { } /* Terminating Entry */ |
1937 | }; |
1938 | MODULE_DEVICE_TABLE(platform, wl12xx_id_table); |
1939 | |
1940 | static struct platform_driver wl12xx_driver = { |
1941 | .probe = wl12xx_probe, |
1942 | .remove_new = wl12xx_remove, |
1943 | .id_table = wl12xx_id_table, |
1944 | .driver = { |
1945 | .name = "wl12xx_driver" , |
1946 | } |
1947 | }; |
1948 | |
1949 | module_platform_driver(wl12xx_driver); |
1950 | |
1951 | module_param_named(fref, fref_param, charp, 0); |
1952 | MODULE_PARM_DESC(fref, "FREF clock: 19.2, 26, 26x, 38.4, 38.4x, 52" ); |
1953 | |
1954 | module_param_named(tcxo, tcxo_param, charp, 0); |
1955 | MODULE_PARM_DESC(tcxo, |
1956 | "TCXO clock: 19.2, 26, 38.4, 52, 16.368, 32.736, 16.8, 33.6" ); |
1957 | |
1958 | MODULE_DESCRIPTION("TI WL12xx wireless driver" ); |
1959 | MODULE_LICENSE("GPL v2" ); |
1960 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>" ); |
1961 | MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE); |
1962 | MODULE_FIRMWARE(WL127X_FW_NAME_MULTI); |
1963 | MODULE_FIRMWARE(WL127X_PLT_FW_NAME); |
1964 | MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE); |
1965 | MODULE_FIRMWARE(WL128X_FW_NAME_MULTI); |
1966 | MODULE_FIRMWARE(WL128X_PLT_FW_NAME); |
1967 | |