blob: 242bb5f4e0fcf89cab32b3221fe46003129cd419 [file] [log] [blame]
Luciano Coelhob2ba99f2011-11-20 23:32:10 +02001/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2008-2010 Nokia Corporation
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>
24
Luciano Coelhoffeb5012011-11-21 18:55:51 +020025#include <linux/err.h>
26
Luciano Coelhodd5512eb2012-04-11 11:03:14 +030027#include <linux/wl12xx.h>
28
Luciano Coelhob2ba99f2011-11-20 23:32:10 +020029#include "../wlcore/wlcore.h"
Luciano Coelhoffeb5012011-11-21 18:55:51 +020030#include "../wlcore/debug.h"
Luciano Coelho4ded91c2012-04-11 10:54:52 +030031#include "../wlcore/io.h"
Luciano Coelhodd5512eb2012-04-11 11:03:14 +030032#include "../wlcore/acx.h"
Arik Nemtsovb3b4b4b2011-12-12 11:41:44 +020033#include "../wlcore/tx.h"
Arik Nemtsovcd70f6a2011-12-12 12:11:43 +020034#include "../wlcore/rx.h"
Luciano Coelhob14684a2011-12-12 12:15:08 +020035#include "../wlcore/io.h"
Luciano Coelhodd5512eb2012-04-11 11:03:14 +030036#include "../wlcore/boot.h"
Luciano Coelhoffeb5012011-11-21 18:55:51 +020037
Luciano Coelho00782132011-11-29 13:38:37 +020038#include "reg.h"
Luciano Coelho9d68d1e2011-12-02 00:47:45 +020039#include "cmd.h"
40#include "acx.h"
Luciano Coelho25a43d72011-11-21 20:37:14 +020041
Luciano Coelhoe87288f2011-12-05 16:12:54 +020042static struct wlcore_conf wl12xx_conf = {
43 .sg = {
44 .params = {
45 [CONF_SG_ACL_BT_MASTER_MIN_BR] = 10,
46 [CONF_SG_ACL_BT_MASTER_MAX_BR] = 180,
47 [CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10,
48 [CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180,
49 [CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10,
50 [CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80,
51 [CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10,
52 [CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80,
53 [CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8,
54 [CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8,
55 [CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20,
56 [CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20,
57 [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20,
58 [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35,
59 [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16,
60 [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35,
61 [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32,
62 [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50,
63 [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28,
64 [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50,
65 [CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10,
66 [CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20,
67 [CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75,
68 [CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15,
69 [CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27,
70 [CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17,
71 /* active scan params */
72 [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
73 [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
74 [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
75 /* passive scan params */
76 [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800,
77 [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200,
78 [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
79 /* passive scan in dual antenna params */
80 [CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0,
81 [CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0,
82 [CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0,
83 /* general params */
84 [CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1,
85 [CONF_SG_ANTENNA_CONFIGURATION] = 0,
86 [CONF_SG_BEACON_MISS_PERCENT] = 60,
87 [CONF_SG_DHCP_TIME] = 5000,
88 [CONF_SG_RXT] = 1200,
89 [CONF_SG_TXT] = 1000,
90 [CONF_SG_ADAPTIVE_RXT_TXT] = 1,
91 [CONF_SG_GENERAL_USAGE_BIT_MAP] = 3,
92 [CONF_SG_HV3_MAX_SERVED] = 6,
93 [CONF_SG_PS_POLL_TIMEOUT] = 10,
94 [CONF_SG_UPSD_TIMEOUT] = 10,
95 [CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2,
96 [CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5,
97 [CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30,
98 /* AP params */
99 [CONF_AP_BEACON_MISS_TX] = 3,
100 [CONF_AP_RX_WINDOW_AFTER_BEACON] = 10,
101 [CONF_AP_BEACON_WINDOW_INTERVAL] = 2,
102 [CONF_AP_CONNECTION_PROTECTION_TIME] = 0,
103 [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25,
104 [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25,
105 /* CTS Diluting params */
106 [CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0,
107 [CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0,
108 },
109 .state = CONF_SG_PROTECTIVE,
110 },
111 .rx = {
112 .rx_msdu_life_time = 512000,
113 .packet_detection_threshold = 0,
114 .ps_poll_timeout = 15,
115 .upsd_timeout = 15,
116 .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD,
117 .rx_cca_threshold = 0,
118 .irq_blk_threshold = 0xFFFF,
119 .irq_pkt_threshold = 0,
120 .irq_timeout = 600,
121 .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
122 },
123 .tx = {
124 .tx_energy_detection = 0,
125 .sta_rc_conf = {
126 .enabled_rates = 0,
127 .short_retry_limit = 10,
128 .long_retry_limit = 10,
129 .aflags = 0,
130 },
131 .ac_conf_count = 4,
132 .ac_conf = {
133 [CONF_TX_AC_BE] = {
134 .ac = CONF_TX_AC_BE,
135 .cw_min = 15,
136 .cw_max = 63,
137 .aifsn = 3,
138 .tx_op_limit = 0,
139 },
140 [CONF_TX_AC_BK] = {
141 .ac = CONF_TX_AC_BK,
142 .cw_min = 15,
143 .cw_max = 63,
144 .aifsn = 7,
145 .tx_op_limit = 0,
146 },
147 [CONF_TX_AC_VI] = {
148 .ac = CONF_TX_AC_VI,
149 .cw_min = 15,
150 .cw_max = 63,
151 .aifsn = CONF_TX_AIFS_PIFS,
152 .tx_op_limit = 3008,
153 },
154 [CONF_TX_AC_VO] = {
155 .ac = CONF_TX_AC_VO,
156 .cw_min = 15,
157 .cw_max = 63,
158 .aifsn = CONF_TX_AIFS_PIFS,
159 .tx_op_limit = 1504,
160 },
161 },
162 .max_tx_retries = 100,
163 .ap_aging_period = 300,
164 .tid_conf_count = 4,
165 .tid_conf = {
166 [CONF_TX_AC_BE] = {
167 .queue_id = CONF_TX_AC_BE,
168 .channel_type = CONF_CHANNEL_TYPE_EDCF,
169 .tsid = CONF_TX_AC_BE,
170 .ps_scheme = CONF_PS_SCHEME_LEGACY,
171 .ack_policy = CONF_ACK_POLICY_LEGACY,
172 .apsd_conf = {0, 0},
173 },
174 [CONF_TX_AC_BK] = {
175 .queue_id = CONF_TX_AC_BK,
176 .channel_type = CONF_CHANNEL_TYPE_EDCF,
177 .tsid = CONF_TX_AC_BK,
178 .ps_scheme = CONF_PS_SCHEME_LEGACY,
179 .ack_policy = CONF_ACK_POLICY_LEGACY,
180 .apsd_conf = {0, 0},
181 },
182 [CONF_TX_AC_VI] = {
183 .queue_id = CONF_TX_AC_VI,
184 .channel_type = CONF_CHANNEL_TYPE_EDCF,
185 .tsid = CONF_TX_AC_VI,
186 .ps_scheme = CONF_PS_SCHEME_LEGACY,
187 .ack_policy = CONF_ACK_POLICY_LEGACY,
188 .apsd_conf = {0, 0},
189 },
190 [CONF_TX_AC_VO] = {
191 .queue_id = CONF_TX_AC_VO,
192 .channel_type = CONF_CHANNEL_TYPE_EDCF,
193 .tsid = CONF_TX_AC_VO,
194 .ps_scheme = CONF_PS_SCHEME_LEGACY,
195 .ack_policy = CONF_ACK_POLICY_LEGACY,
196 .apsd_conf = {0, 0},
197 },
198 },
199 .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
200 .tx_compl_timeout = 700,
201 .tx_compl_threshold = 4,
202 .basic_rate = CONF_HW_BIT_RATE_1MBPS,
203 .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS,
204 .tmpl_short_retry_limit = 10,
205 .tmpl_long_retry_limit = 10,
206 .tx_watchdog_timeout = 5000,
207 },
208 .conn = {
209 .wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
210 .listen_interval = 1,
211 .suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM,
212 .suspend_listen_interval = 3,
213 .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED,
214 .bcn_filt_ie_count = 2,
215 .bcn_filt_ie = {
216 [0] = {
217 .ie = WLAN_EID_CHANNEL_SWITCH,
218 .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE,
219 },
220 [1] = {
221 .ie = WLAN_EID_HT_OPERATION,
222 .rule = CONF_BCN_RULE_PASS_ON_CHANGE,
223 },
224 },
225 .synch_fail_thold = 10,
226 .bss_lose_timeout = 100,
227 .beacon_rx_timeout = 10000,
228 .broadcast_timeout = 20000,
229 .rx_broadcast_in_ps = 1,
230 .ps_poll_threshold = 10,
231 .bet_enable = CONF_BET_MODE_ENABLE,
232 .bet_max_consecutive = 50,
233 .psm_entry_retries = 8,
234 .psm_exit_retries = 16,
235 .psm_entry_nullfunc_retries = 3,
236 .dynamic_ps_timeout = 40,
237 .forced_ps = false,
238 .keep_alive_interval = 55000,
239 .max_listen_interval = 20,
240 },
241 .itrim = {
242 .enable = false,
243 .timeout = 50000,
244 },
245 .pm_config = {
246 .host_clk_settling_time = 5000,
247 .host_fast_wakeup_support = false
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_passive = 100000,
260 .max_dwell_time_passive = 100000,
261 .num_probe_reqs = 2,
262 .split_scan_timeout = 50000,
263 },
264 .sched_scan = {
265 /*
266 * Values are in TU/1000 but since sched scan FW command
267 * params are in TUs rounding up may occur.
268 */
269 .base_dwell_time = 7500,
270 .max_dwell_time_delta = 22500,
271 /* based on 250bits per probe @1Mbps */
272 .dwell_time_delta_per_probe = 2000,
273 /* based on 250bits per probe @6Mbps (plus a bit more) */
274 .dwell_time_delta_per_probe_5 = 350,
275 .dwell_time_passive = 100000,
276 .dwell_time_dfs = 150000,
277 .num_probe_reqs = 2,
278 .rssi_threshold = -90,
279 .snr_threshold = 0,
280 },
281 .rf = {
282 .tx_per_channel_power_compensation_2 = {
283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284 },
285 .tx_per_channel_power_compensation_5 = {
286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
288 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
289 },
290 },
291 .ht = {
292 .rx_ba_win_size = 8,
293 .tx_ba_win_size = 64,
294 .inactivity_timeout = 10000,
295 .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
296 },
297 .mem_wl127x = {
298 .num_stations = 1,
299 .ssid_profiles = 1,
300 .rx_block_num = 70,
301 .tx_min_block_num = 40,
302 .dynamic_memory = 1,
303 .min_req_tx_blocks = 100,
304 .min_req_rx_blocks = 22,
305 .tx_min = 27,
306 },
307 .mem_wl128x = {
308 .num_stations = 1,
309 .ssid_profiles = 1,
310 .rx_block_num = 40,
311 .tx_min_block_num = 40,
312 .dynamic_memory = 1,
313 .min_req_tx_blocks = 45,
314 .min_req_rx_blocks = 22,
315 .tx_min = 27,
316 },
317 .fm_coex = {
318 .enable = true,
319 .swallow_period = 5,
320 .n_divider_fref_set_1 = 0xff, /* default */
321 .n_divider_fref_set_2 = 12,
322 .m_divider_fref_set_1 = 148,
323 .m_divider_fref_set_2 = 0xffff, /* default */
324 .coex_pll_stabilization_time = 0xffffffff, /* default */
325 .ldo_stabilization_time = 0xffff, /* default */
326 .fm_disturbed_band_margin = 0xff, /* default */
327 .swallow_clk_diff = 0xff, /* default */
328 },
329 .rx_streaming = {
330 .duration = 150,
331 .queues = 0x1,
332 .interval = 20,
333 .always = 0,
334 },
335 .fwlog = {
336 .mode = WL12XX_FWLOG_ON_DEMAND,
337 .mem_blocks = 2,
338 .severity = 0,
339 .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED,
340 .output = WL12XX_FWLOG_OUTPUT_HOST,
341 .threshold = 0,
342 },
343 .rate = {
344 .rate_retry_score = 32000,
345 .per_add = 8192,
346 .per_th1 = 2048,
347 .per_th2 = 4096,
348 .max_per = 8100,
349 .inverse_curiosity_factor = 5,
350 .tx_fail_low_th = 4,
351 .tx_fail_high_th = 10,
352 .per_alpha_shift = 4,
353 .per_add_shift = 13,
354 .per_beta1_shift = 10,
355 .per_beta2_shift = 8,
356 .rate_check_up = 2,
357 .rate_check_down = 12,
358 .rate_retry_policy = {
359 0x00, 0x00, 0x00, 0x00, 0x00,
360 0x00, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00,
362 },
363 },
364 .hangover = {
365 .recover_time = 0,
366 .hangover_period = 20,
367 .dynamic_mode = 1,
368 .early_termination_mode = 1,
369 .max_period = 20,
370 .min_period = 1,
371 .increase_delta = 1,
372 .decrease_delta = 2,
373 .quiet_time = 4,
374 .increase_time = 1,
375 .window_size = 16,
376 },
377};
378
379
Arik Nemtsov3edab302011-12-07 23:38:47 +0200380#define WL12XX_TX_HW_BLOCK_SPARE_DEFAULT 1
381#define WL12XX_TX_HW_BLOCK_GEM_SPARE 2
Arik Nemtsovb3b4b4b2011-12-12 11:41:44 +0200382#define WL12XX_TX_HW_BLOCK_SIZE 252
Arik Nemtsov3edab302011-12-07 23:38:47 +0200383
Arik Nemtsov43a8bc52011-12-08 00:43:48 +0200384static const u8 wl12xx_rate_to_idx_2ghz[] = {
385 /* MCS rates are used only with 11n */
386 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI */
387 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7 */
388 6, /* WL12XX_CONF_HW_RXTX_RATE_MCS6 */
389 5, /* WL12XX_CONF_HW_RXTX_RATE_MCS5 */
390 4, /* WL12XX_CONF_HW_RXTX_RATE_MCS4 */
391 3, /* WL12XX_CONF_HW_RXTX_RATE_MCS3 */
392 2, /* WL12XX_CONF_HW_RXTX_RATE_MCS2 */
393 1, /* WL12XX_CONF_HW_RXTX_RATE_MCS1 */
394 0, /* WL12XX_CONF_HW_RXTX_RATE_MCS0 */
395
396 11, /* WL12XX_CONF_HW_RXTX_RATE_54 */
397 10, /* WL12XX_CONF_HW_RXTX_RATE_48 */
398 9, /* WL12XX_CONF_HW_RXTX_RATE_36 */
399 8, /* WL12XX_CONF_HW_RXTX_RATE_24 */
400
401 /* TI-specific rate */
402 CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_22 */
403
404 7, /* WL12XX_CONF_HW_RXTX_RATE_18 */
405 6, /* WL12XX_CONF_HW_RXTX_RATE_12 */
406 3, /* WL12XX_CONF_HW_RXTX_RATE_11 */
407 5, /* WL12XX_CONF_HW_RXTX_RATE_9 */
408 4, /* WL12XX_CONF_HW_RXTX_RATE_6 */
409 2, /* WL12XX_CONF_HW_RXTX_RATE_5_5 */
410 1, /* WL12XX_CONF_HW_RXTX_RATE_2 */
411 0 /* WL12XX_CONF_HW_RXTX_RATE_1 */
412};
413
414static const u8 wl12xx_rate_to_idx_5ghz[] = {
415 /* MCS rates are used only with 11n */
416 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI */
417 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7 */
418 6, /* WL12XX_CONF_HW_RXTX_RATE_MCS6 */
419 5, /* WL12XX_CONF_HW_RXTX_RATE_MCS5 */
420 4, /* WL12XX_CONF_HW_RXTX_RATE_MCS4 */
421 3, /* WL12XX_CONF_HW_RXTX_RATE_MCS3 */
422 2, /* WL12XX_CONF_HW_RXTX_RATE_MCS2 */
423 1, /* WL12XX_CONF_HW_RXTX_RATE_MCS1 */
424 0, /* WL12XX_CONF_HW_RXTX_RATE_MCS0 */
425
426 7, /* WL12XX_CONF_HW_RXTX_RATE_54 */
427 6, /* WL12XX_CONF_HW_RXTX_RATE_48 */
428 5, /* WL12XX_CONF_HW_RXTX_RATE_36 */
429 4, /* WL12XX_CONF_HW_RXTX_RATE_24 */
430
431 /* TI-specific rate */
432 CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_22 */
433
434 3, /* WL12XX_CONF_HW_RXTX_RATE_18 */
435 2, /* WL12XX_CONF_HW_RXTX_RATE_12 */
436 CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_11 */
437 1, /* WL12XX_CONF_HW_RXTX_RATE_9 */
438 0, /* WL12XX_CONF_HW_RXTX_RATE_6 */
439 CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_5_5 */
440 CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_2 */
441 CONF_HW_RXTX_RATE_UNSUPPORTED /* WL12XX_CONF_HW_RXTX_RATE_1 */
442};
443
444static const u8 *wl12xx_band_rate_to_idx[] = {
445 [IEEE80211_BAND_2GHZ] = wl12xx_rate_to_idx_2ghz,
446 [IEEE80211_BAND_5GHZ] = wl12xx_rate_to_idx_5ghz
447};
448
449enum wl12xx_hw_rates {
450 WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI = 0,
451 WL12XX_CONF_HW_RXTX_RATE_MCS7,
452 WL12XX_CONF_HW_RXTX_RATE_MCS6,
453 WL12XX_CONF_HW_RXTX_RATE_MCS5,
454 WL12XX_CONF_HW_RXTX_RATE_MCS4,
455 WL12XX_CONF_HW_RXTX_RATE_MCS3,
456 WL12XX_CONF_HW_RXTX_RATE_MCS2,
457 WL12XX_CONF_HW_RXTX_RATE_MCS1,
458 WL12XX_CONF_HW_RXTX_RATE_MCS0,
459 WL12XX_CONF_HW_RXTX_RATE_54,
460 WL12XX_CONF_HW_RXTX_RATE_48,
461 WL12XX_CONF_HW_RXTX_RATE_36,
462 WL12XX_CONF_HW_RXTX_RATE_24,
463 WL12XX_CONF_HW_RXTX_RATE_22,
464 WL12XX_CONF_HW_RXTX_RATE_18,
465 WL12XX_CONF_HW_RXTX_RATE_12,
466 WL12XX_CONF_HW_RXTX_RATE_11,
467 WL12XX_CONF_HW_RXTX_RATE_9,
468 WL12XX_CONF_HW_RXTX_RATE_6,
469 WL12XX_CONF_HW_RXTX_RATE_5_5,
470 WL12XX_CONF_HW_RXTX_RATE_2,
471 WL12XX_CONF_HW_RXTX_RATE_1,
472 WL12XX_CONF_HW_RXTX_RATE_MAX,
473};
Arik Nemtsov3edab302011-12-07 23:38:47 +0200474
Luciano Coelho25a43d72011-11-21 20:37:14 +0200475static struct wlcore_partition_set wl12xx_ptable[PART_TABLE_LEN] = {
476 [PART_DOWN] = {
477 .mem = {
478 .start = 0x00000000,
479 .size = 0x000177c0
480 },
481 .reg = {
482 .start = REGISTERS_BASE,
483 .size = 0x00008800
484 },
485 .mem2 = {
486 .start = 0x00000000,
487 .size = 0x00000000
488 },
489 .mem3 = {
490 .start = 0x00000000,
491 .size = 0x00000000
492 },
493 },
494
Luciano Coelho00782132011-11-29 13:38:37 +0200495 [PART_BOOT] = { /* in wl12xx we can use a mix of work and down
496 * partition here */
497 .mem = {
498 .start = 0x00040000,
499 .size = 0x00014fc0
500 },
501 .reg = {
502 .start = REGISTERS_BASE,
503 .size = 0x00008800
504 },
505 .mem2 = {
506 .start = 0x00000000,
507 .size = 0x00000000
508 },
509 .mem3 = {
510 .start = 0x00000000,
511 .size = 0x00000000
512 },
513 },
514
Luciano Coelho25a43d72011-11-21 20:37:14 +0200515 [PART_WORK] = {
516 .mem = {
517 .start = 0x00040000,
518 .size = 0x00014fc0
519 },
520 .reg = {
521 .start = REGISTERS_BASE,
522 .size = 0x0000a000
523 },
524 .mem2 = {
525 .start = 0x003004f8,
526 .size = 0x00000004
527 },
528 .mem3 = {
529 .start = 0x00040404,
530 .size = 0x00000000
531 },
532 },
533
534 [PART_DRPW] = {
535 .mem = {
536 .start = 0x00040000,
537 .size = 0x00014fc0
538 },
539 .reg = {
540 .start = DRPW_BASE,
541 .size = 0x00006000
542 },
543 .mem2 = {
544 .start = 0x00000000,
545 .size = 0x00000000
546 },
547 .mem3 = {
548 .start = 0x00000000,
549 .size = 0x00000000
550 }
551 }
552};
553
Luciano Coelho00782132011-11-29 13:38:37 +0200554static const int wl12xx_rtable[REG_TABLE_LEN] = {
555 [REG_ECPU_CONTROL] = WL12XX_REG_ECPU_CONTROL,
556 [REG_INTERRUPT_NO_CLEAR] = WL12XX_REG_INTERRUPT_NO_CLEAR,
557 [REG_INTERRUPT_ACK] = WL12XX_REG_INTERRUPT_ACK,
558 [REG_COMMAND_MAILBOX_PTR] = WL12XX_REG_COMMAND_MAILBOX_PTR,
559 [REG_EVENT_MAILBOX_PTR] = WL12XX_REG_EVENT_MAILBOX_PTR,
560 [REG_INTERRUPT_TRIG] = WL12XX_REG_INTERRUPT_TRIG,
561 [REG_INTERRUPT_MASK] = WL12XX_REG_INTERRUPT_MASK,
562 [REG_PC_ON_RECOVERY] = WL12XX_SCR_PAD4,
563 [REG_CHIP_ID_B] = WL12XX_CHIP_ID_B,
564 [REG_CMD_MBOX_ADDRESS] = WL12XX_CMD_MBOX_ADDRESS,
565
566 /* data access memory addresses, used with partition translation */
567 [REG_SLV_MEM_DATA] = WL1271_SLV_MEM_DATA,
568 [REG_SLV_REG_DATA] = WL1271_SLV_REG_DATA,
569
570 /* raw data access memory addresses */
571 [REG_RAW_FW_STATUS_ADDR] = FW_STATUS_ADDR,
572};
573
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200574/* TODO: maybe move to a new header file? */
575#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin"
576#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin"
577#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin"
578
579#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin"
580#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin"
581#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin"
582
Luciano Coelhob14684a2011-12-12 12:15:08 +0200583static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
584{
585 if (wl->chip.id != CHIP_ID_1283_PG20) {
586 struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
587 struct wl1271_rx_mem_pool_addr rx_mem_addr;
588
589 /*
590 * Choose the block we want to read
591 * For aggregated packets, only the first memory block
592 * should be retrieved. The FW takes care of the rest.
593 */
594 u32 mem_block = rx_desc & RX_MEM_BLOCK_MASK;
595
596 rx_mem_addr.addr = (mem_block << 8) +
597 le32_to_cpu(wl_mem_map->packet_memory_pool_start);
598
599 rx_mem_addr.addr_extra = rx_mem_addr.addr + 4;
600
601 wl1271_write(wl, WL1271_SLV_REG_DATA,
602 &rx_mem_addr, sizeof(rx_mem_addr), false);
603 }
604}
605
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200606static int wl12xx_identify_chip(struct wl1271 *wl)
607{
608 int ret = 0;
609
610 switch (wl->chip.id) {
611 case CHIP_ID_1271_PG10:
612 wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
613 wl->chip.id);
614
Arik Nemtsovf83985bb2011-12-13 12:11:26 +0200615 /* clear the alignment quirk, since we don't support it */
616 wl->quirks &= ~WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN;
617
618 wl->quirks |= WLCORE_QUIRK_LEGACY_NVS;
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200619 wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
620 wl->mr_fw_name = WL127X_FW_NAME_MULTI;
Luciano Coelhob14684a2011-12-12 12:15:08 +0200621
622 /* read data preparation is only needed by wl127x */
623 wl->ops->prepare_read = wl127x_prepare_read;
624
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200625 break;
626
627 case CHIP_ID_1271_PG20:
628 wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
629 wl->chip.id);
630
Arik Nemtsovf83985bb2011-12-13 12:11:26 +0200631 /* clear the alignment quirk, since we don't support it */
632 wl->quirks &= ~WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN;
633
634 wl->quirks |= WLCORE_QUIRK_LEGACY_NVS;
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200635 wl->plt_fw_name = WL127X_PLT_FW_NAME;
636 wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
637 wl->mr_fw_name = WL127X_FW_NAME_MULTI;
Luciano Coelhob14684a2011-12-12 12:15:08 +0200638
639 /* read data preparation is only needed by wl127x */
640 wl->ops->prepare_read = wl127x_prepare_read;
641
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200642 break;
643
644 case CHIP_ID_1283_PG20:
645 wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)",
646 wl->chip.id);
647 wl->plt_fw_name = WL128X_PLT_FW_NAME;
648 wl->sr_fw_name = WL128X_FW_NAME_SINGLE;
649 wl->mr_fw_name = WL128X_FW_NAME_MULTI;
650 break;
651 case CHIP_ID_1283_PG10:
652 default:
653 wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
654 ret = -ENODEV;
655 goto out;
656 }
657
658out:
659 return ret;
660}
661
Luciano Coelhodd5512eb2012-04-11 11:03:14 +0300662static void wl12xx_top_reg_write(struct wl1271 *wl, int addr, u16 val)
663{
664 /* write address >> 1 + 0x30000 to OCP_POR_CTR */
665 addr = (addr >> 1) + 0x30000;
666 wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr);
667
668 /* write value to OCP_POR_WDATA */
669 wl1271_write32(wl, WL12XX_OCP_DATA_WRITE, val);
670
671 /* write 1 to OCP_CMD */
672 wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE);
673}
674
675static u16 wl12xx_top_reg_read(struct wl1271 *wl, int addr)
676{
677 u32 val;
678 int timeout = OCP_CMD_LOOP;
679
680 /* write address >> 1 + 0x30000 to OCP_POR_CTR */
681 addr = (addr >> 1) + 0x30000;
682 wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr);
683
684 /* write 2 to OCP_CMD */
685 wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ);
686
687 /* poll for data ready */
688 do {
689 val = wl1271_read32(wl, WL12XX_OCP_DATA_READ);
690 } while (!(val & OCP_READY_MASK) && --timeout);
691
692 if (!timeout) {
693 wl1271_warning("Top register access timed out.");
694 return 0xffff;
695 }
696
697 /* check data status and return if OK */
698 if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
699 return val & 0xffff;
700 else {
701 wl1271_warning("Top register access returned error.");
702 return 0xffff;
703 }
704}
705
706static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
707{
708 u16 spare_reg;
709
710 /* Mask bits [2] & [8:4] in the sys_clk_cfg register */
711 spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG);
712 if (spare_reg == 0xFFFF)
713 return -EFAULT;
714 spare_reg |= (BIT(3) | BIT(5) | BIT(6));
715 wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
716
717 /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */
718 wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG,
719 WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);
720
721 /* Delay execution for 15msec, to let the HW settle */
722 mdelay(15);
723
724 return 0;
725}
726
727static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
728{
729 u16 tcxo_detection;
730
731 tcxo_detection = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG);
732 if (tcxo_detection & TCXO_DET_FAILED)
733 return false;
734
735 return true;
736}
737
738static bool wl128x_is_fref_valid(struct wl1271 *wl)
739{
740 u16 fref_detection;
741
742 fref_detection = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG);
743 if (fref_detection & FREF_CLK_DETECT_FAIL)
744 return false;
745
746 return true;
747}
748
749static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl)
750{
751 wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL);
752 wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL);
753 wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL);
754
755 return 0;
756}
757
758static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
759{
760 u16 spare_reg;
761 u16 pll_config;
762 u8 input_freq;
763
764 /* Mask bits [3:1] in the sys_clk_cfg register */
765 spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG);
766 if (spare_reg == 0xFFFF)
767 return -EFAULT;
768 spare_reg |= BIT(2);
769 wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
770
771 /* Handle special cases of the TCXO clock */
772 if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 ||
773 wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6)
774 return wl128x_manually_configure_mcs_pll(wl);
775
776 /* Set the input frequency according to the selected clock source */
777 input_freq = (clk & 1) + 1;
778
779 pll_config = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG);
780 if (pll_config == 0xFFFF)
781 return -EFAULT;
782 pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT);
783 pll_config |= MCS_PLL_ENABLE_HP;
784 wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config);
785
786 return 0;
787}
788
789/*
790 * WL128x has two clocks input - TCXO and FREF.
791 * TCXO is the main clock of the device, while FREF is used to sync
792 * between the GPS and the cellular modem.
793 * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used
794 * as the WLAN/BT main clock.
795 */
796static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
797{
798 u16 sys_clk_cfg;
799
800 /* For XTAL-only modes, FREF will be used after switching from TCXO */
801 if (wl->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
802 wl->ref_clock == WL12XX_REFCLOCK_38_XTAL) {
803 if (!wl128x_switch_tcxo_to_fref(wl))
804 return -EINVAL;
805 goto fref_clk;
806 }
807
808 /* Query the HW, to determine which clock source we should use */
809 sys_clk_cfg = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG);
810 if (sys_clk_cfg == 0xFFFF)
811 return -EINVAL;
812 if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF)
813 goto fref_clk;
814
815 /* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */
816 if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_368 ||
817 wl->tcxo_clock == WL12XX_TCXOCLOCK_32_736) {
818 if (!wl128x_switch_tcxo_to_fref(wl))
819 return -EINVAL;
820 goto fref_clk;
821 }
822
823 /* TCXO clock is selected */
824 if (!wl128x_is_tcxo_valid(wl))
825 return -EINVAL;
826 *selected_clock = wl->tcxo_clock;
827 goto config_mcs_pll;
828
829fref_clk:
830 /* FREF clock is selected */
831 if (!wl128x_is_fref_valid(wl))
832 return -EINVAL;
833 *selected_clock = wl->ref_clock;
834
835config_mcs_pll:
836 return wl128x_configure_mcs_pll(wl, *selected_clock);
837}
838
839static int wl127x_boot_clk(struct wl1271 *wl)
840{
841 u32 pause;
842 u32 clk;
843
844 if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
845 wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION;
846
847 if (wl->ref_clock == CONF_REF_CLK_19_2_E ||
848 wl->ref_clock == CONF_REF_CLK_38_4_E ||
849 wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL)
850 /* ref clk: 19.2/38.4/38.4-XTAL */
851 clk = 0x3;
852 else if (wl->ref_clock == CONF_REF_CLK_26_E ||
853 wl->ref_clock == CONF_REF_CLK_52_E)
854 /* ref clk: 26/52 */
855 clk = 0x5;
856 else
857 return -EINVAL;
858
859 if (wl->ref_clock != CONF_REF_CLK_19_2_E) {
860 u16 val;
861 /* Set clock type (open drain) */
862 val = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE);
863 val &= FREF_CLK_TYPE_BITS;
864 wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
865
866 /* Set clock pull mode (no pull) */
867 val = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL);
868 val |= NO_PULL;
869 wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val);
870 } else {
871 u16 val;
872 /* Set clock polarity */
873 val = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY);
874 val &= FREF_CLK_POLARITY_BITS;
875 val |= CLK_REQ_OUTN_SEL;
876 wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
877 }
878
879 wl1271_write32(wl, WL12XX_PLL_PARAMETERS, clk);
880
881 pause = wl1271_read32(wl, WL12XX_PLL_PARAMETERS);
882
883 wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
884
885 pause &= ~(WU_COUNTER_PAUSE_VAL);
886 pause |= WU_COUNTER_PAUSE_VAL;
887 wl1271_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause);
888
889 return 0;
890}
891
892static int wl1271_boot_soft_reset(struct wl1271 *wl)
893{
894 unsigned long timeout;
895 u32 boot_data;
896
897 /* perform soft reset */
898 wl1271_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
899
900 /* SOFT_RESET is self clearing */
901 timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
902 while (1) {
903 boot_data = wl1271_read32(wl, WL12XX_SLV_SOFT_RESET);
904 wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
905 if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
906 break;
907
908 if (time_after(jiffies, timeout)) {
909 /* 1.2 check pWhalBus->uSelfClearTime if the
910 * timeout was reached */
911 wl1271_error("soft reset timeout");
912 return -1;
913 }
914
915 udelay(SOFT_RESET_STALL_TIME);
916 }
917
918 /* disable Rx/Tx */
919 wl1271_write32(wl, WL12XX_ENABLE, 0x0);
920
921 /* disable auto calibration on start*/
922 wl1271_write32(wl, WL12XX_SPARE_A2, 0xffff);
923
924 return 0;
925}
926
927static int wl12xx_pre_boot(struct wl1271 *wl)
928{
929 int ret = 0;
930 u32 clk;
931 int selected_clock = -1;
932
933 if (wl->chip.id == CHIP_ID_1283_PG20) {
934 ret = wl128x_boot_clk(wl, &selected_clock);
935 if (ret < 0)
936 goto out;
937 } else {
938 ret = wl127x_boot_clk(wl);
939 if (ret < 0)
940 goto out;
941 }
942
943 /* Continue the ELP wake up sequence */
944 wl1271_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
945 udelay(500);
946
947 wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
948
949 /* Read-modify-write DRPW_SCRATCH_START register (see next state)
950 to be used by DRPw FW. The RTRIM value will be added by the FW
951 before taking DRPw out of reset */
952
953 clk = wl1271_read32(wl, WL12XX_DRPW_SCRATCH_START);
954
955 wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
956
957 if (wl->chip.id == CHIP_ID_1283_PG20)
958 clk |= ((selected_clock & 0x3) << 1) << 4;
959 else
960 clk |= (wl->ref_clock << 1) << 4;
961
962 wl1271_write32(wl, WL12XX_DRPW_SCRATCH_START, clk);
963
964 wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
965
966 /* Disable interrupts */
967 wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
968
969 ret = wl1271_boot_soft_reset(wl);
970 if (ret < 0)
971 goto out;
972
973out:
974 return ret;
975}
976
977static void wl12xx_pre_upload(struct wl1271 *wl)
978{
979 u32 tmp;
980
981 /* write firmware's last address (ie. it's length) to
982 * ACX_EEPROMLESS_IND_REG */
983 wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");
984
985 wl1271_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND);
986
987 tmp = wlcore_read_reg(wl, REG_CHIP_ID_B);
988
989 wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
990
991 /* 6. read the EEPROM parameters */
992 tmp = wl1271_read32(wl, WL12XX_SCR_PAD2);
993
994 /* WL1271: The reference driver skips steps 7 to 10 (jumps directly
995 * to upload_fw) */
996
997 if (wl->chip.id == CHIP_ID_1283_PG20)
998 wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
999}
1000
1001static void wl12xx_enable_interrupts(struct wl1271 *wl)
1002{
1003 u32 polarity;
1004
1005 polarity = wl12xx_top_reg_read(wl, OCP_REG_POLARITY);
1006
1007 /* We use HIGH polarity, so unset the LOW bit */
1008 polarity &= ~POLARITY_LOW;
1009 wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity);
1010
1011 wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_ALL_EVENTS_VECTOR);
1012
1013 wlcore_enable_interrupts(wl);
1014 wlcore_write_reg(wl, REG_INTERRUPT_MASK,
1015 WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
1016
1017 wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL);
1018}
1019
1020static int wl12xx_boot(struct wl1271 *wl)
1021{
1022 int ret;
1023
1024 ret = wl12xx_pre_boot(wl);
1025 if (ret < 0)
1026 goto out;
1027
1028 ret = wlcore_boot_upload_nvs(wl);
1029 if (ret < 0)
1030 goto out;
1031
1032 wl12xx_pre_upload(wl);
1033
1034 ret = wlcore_boot_upload_firmware(wl);
1035 if (ret < 0)
1036 goto out;
1037
1038 ret = wlcore_boot_run_firmware(wl);
1039 if (ret < 0)
1040 goto out;
1041
1042 wl12xx_enable_interrupts(wl);
1043
1044out:
1045 return ret;
1046}
1047
Arik Nemtsov5d10b192011-12-13 12:27:22 +02001048static void wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
1049 void *buf, size_t len)
Luciano Coelhof16ff752012-04-11 10:15:46 +03001050{
Arik Nemtsov5d10b192011-12-13 12:27:22 +02001051 wl1271_write(wl, cmd_box_addr, buf, len, false);
Luciano Coelhof16ff752012-04-11 10:15:46 +03001052 wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD);
1053}
1054
1055static void wl12xx_ack_event(struct wl1271 *wl)
1056{
1057 wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_EVENT_ACK);
1058}
1059
Arik Nemtsovb3b4b4b2011-12-12 11:41:44 +02001060static u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
1061{
1062 u32 blk_size = WL12XX_TX_HW_BLOCK_SIZE;
1063 u32 align_len = wlcore_calc_packet_alignment(wl, len);
1064
1065 return (align_len + blk_size - 1) / blk_size + spare_blks;
1066}
1067
Arik Nemtsov4a3b97ee2011-12-12 11:44:27 +02001068static void
1069wl12xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
1070 u32 blks, u32 spare_blks)
1071{
1072 if (wl->chip.id == CHIP_ID_1283_PG20) {
1073 desc->wl128x_mem.total_mem_blocks = blks;
1074 } else {
1075 desc->wl127x_mem.extra_blocks = spare_blks;
1076 desc->wl127x_mem.total_mem_blocks = blks;
1077 }
1078}
1079
Arik Nemtsov6f266e92011-12-12 11:47:09 +02001080static void
1081wl12xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
1082 struct sk_buff *skb)
1083{
1084 u32 aligned_len = wlcore_calc_packet_alignment(wl, skb->len);
1085
1086 if (wl->chip.id == CHIP_ID_1283_PG20) {
1087 desc->wl128x_mem.extra_bytes = aligned_len - skb->len;
1088 desc->length = cpu_to_le16(aligned_len >> 2);
1089
1090 wl1271_debug(DEBUG_TX,
1091 "tx_fill_hdr: hlid: %d len: %d life: %d mem: %d extra: %d",
1092 desc->hlid,
1093 le16_to_cpu(desc->length),
1094 le16_to_cpu(desc->life_time),
1095 desc->wl128x_mem.total_mem_blocks,
1096 desc->wl128x_mem.extra_bytes);
1097 } else {
1098 /* calculate number of padding bytes */
1099 int pad = aligned_len - skb->len;
1100 desc->tx_attr |=
1101 cpu_to_le16(pad << TX_HW_ATTR_OFST_LAST_WORD_PAD);
1102
1103 /* Store the aligned length in terms of words */
1104 desc->length = cpu_to_le16(aligned_len >> 2);
1105
1106 wl1271_debug(DEBUG_TX,
1107 "tx_fill_hdr: pad: %d hlid: %d len: %d life: %d mem: %d",
1108 pad, desc->hlid,
1109 le16_to_cpu(desc->length),
1110 le16_to_cpu(desc->life_time),
1111 desc->wl127x_mem.total_mem_blocks);
1112 }
1113}
1114
Arik Nemtsovcd70f6a2011-12-12 12:11:43 +02001115static enum wl_rx_buf_align
1116wl12xx_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
1117{
1118 if (rx_desc & RX_BUF_UNALIGNED_PAYLOAD)
1119 return WLCORE_RX_BUF_UNALIGNED;
1120
1121 return WLCORE_RX_BUF_ALIGNED;
1122}
1123
Arik Nemtsov41581492011-12-12 12:18:17 +02001124static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
1125 u32 data_len)
1126{
1127 struct wl1271_rx_descriptor *desc = rx_data;
1128
1129 /* invalid packet */
1130 if (data_len < sizeof(*desc) ||
1131 data_len < sizeof(*desc) + desc->pad_len)
1132 return 0;
1133
1134 return data_len - sizeof(*desc) - desc->pad_len;
1135}
1136
Arik Nemtsov53d67a52011-12-12 11:32:37 +02001137static void wl12xx_tx_delayed_compl(struct wl1271 *wl)
1138{
1139 if (wl->fw_status->tx_results_counter == (wl->tx_results_count & 0xff))
1140 return;
1141
1142 wl1271_tx_complete(wl);
1143}
1144
Luciano Coelho9d68d1e2011-12-02 00:47:45 +02001145static int wl12xx_hw_init(struct wl1271 *wl)
1146{
1147 int ret;
1148
1149 if (wl->chip.id == CHIP_ID_1283_PG20) {
1150 u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE;
1151
1152 ret = wl128x_cmd_general_parms(wl);
1153 if (ret < 0)
1154 goto out;
1155 ret = wl128x_cmd_radio_parms(wl);
1156 if (ret < 0)
1157 goto out;
1158
1159 if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN)
1160 /* Enable SDIO padding */
1161 host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK;
1162
1163 /* Must be before wl1271_acx_init_mem_config() */
1164 ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap);
1165 if (ret < 0)
1166 goto out;
1167 } else {
1168 ret = wl1271_cmd_general_parms(wl);
1169 if (ret < 0)
1170 goto out;
1171 ret = wl1271_cmd_radio_parms(wl);
1172 if (ret < 0)
1173 goto out;
1174 ret = wl1271_cmd_ext_radio_parms(wl);
1175 if (ret < 0)
1176 goto out;
1177 }
1178out:
1179 return ret;
1180}
1181
Luciano Coelhoe87288f2011-12-05 16:12:54 +02001182static void wl12xx_conf_init(struct wl1271 *wl)
1183{
1184 /* apply driver default configuration */
1185 memcpy(&wl->conf, &wl12xx_conf, sizeof(wl12xx_conf));
1186}
1187
Luciano Coelho30d9b4a2012-04-11 11:07:28 +03001188static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
1189{
1190 bool supported = false;
1191 u8 major, minor;
1192
1193 if (wl->chip.id == CHIP_ID_1283_PG20) {
1194 major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver);
1195 minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver);
1196
1197 /* in wl128x we have the MAC address if the PG is >= (2, 1) */
1198 if (major > 2 || (major == 2 && minor >= 1))
1199 supported = true;
1200 } else {
1201 major = WL127X_PG_GET_MAJOR(wl->hw_pg_ver);
1202 minor = WL127X_PG_GET_MINOR(wl->hw_pg_ver);
1203
1204 /* in wl127x we have the MAC address if the PG is >= (3, 1) */
1205 if (major == 3 && minor >= 1)
1206 supported = true;
1207 }
1208
1209 wl1271_debug(DEBUG_PROBE,
1210 "PG Ver major = %d minor = %d, MAC %s present",
1211 major, minor, supported ? "is" : "is not");
1212
1213 return supported;
1214}
1215
1216static void wl12xx_get_fuse_mac(struct wl1271 *wl)
1217{
1218 u32 mac1, mac2;
1219
1220 wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
1221
1222 mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1);
1223 mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2);
1224
1225 /* these are the two parts of the BD_ADDR */
1226 wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
1227 ((mac1 & 0xff000000) >> 24);
1228 wl->fuse_nic_addr = mac1 & 0xffffff;
1229
1230 wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
1231}
1232
Luciano Coelho4ded91c2012-04-11 10:54:52 +03001233static s8 wl12xx_get_pg_ver(struct wl1271 *wl)
1234{
1235 u32 die_info;
1236
1237 if (wl->chip.id == CHIP_ID_1283_PG20)
Luciano Coelhodd5512eb2012-04-11 11:03:14 +03001238 die_info = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1);
Luciano Coelho4ded91c2012-04-11 10:54:52 +03001239 else
Luciano Coelhodd5512eb2012-04-11 11:03:14 +03001240 die_info = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1);
Luciano Coelho4ded91c2012-04-11 10:54:52 +03001241
1242 return (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET;
1243}
1244
Luciano Coelho30d9b4a2012-04-11 11:07:28 +03001245static void wl12xx_get_mac(struct wl1271 *wl)
1246{
1247 if (wl12xx_mac_in_fuse(wl))
1248 wl12xx_get_fuse_mac(wl);
1249}
1250
Luciano Coelho6f7dd162011-11-29 16:27:31 +02001251static struct wlcore_ops wl12xx_ops = {
Arik Nemtsov4a3b97ee2011-12-12 11:44:27 +02001252 .identify_chip = wl12xx_identify_chip,
1253 .boot = wl12xx_boot,
1254 .trigger_cmd = wl12xx_trigger_cmd,
1255 .ack_event = wl12xx_ack_event,
1256 .calc_tx_blocks = wl12xx_calc_tx_blocks,
1257 .set_tx_desc_blocks = wl12xx_set_tx_desc_blocks,
Arik Nemtsov6f266e92011-12-12 11:47:09 +02001258 .set_tx_desc_data_len = wl12xx_set_tx_desc_data_len,
Arik Nemtsovcd70f6a2011-12-12 12:11:43 +02001259 .get_rx_buf_align = wl12xx_get_rx_buf_align,
Arik Nemtsov41581492011-12-12 12:18:17 +02001260 .get_rx_packet_len = wl12xx_get_rx_packet_len,
Arik Nemtsov53d67a52011-12-12 11:32:37 +02001261 .tx_immediate_compl = NULL,
1262 .tx_delayed_compl = wl12xx_tx_delayed_compl,
Luciano Coelho9d68d1e2011-12-02 00:47:45 +02001263 .hw_init = wl12xx_hw_init,
Arik Nemtsov8a9affc2011-12-13 12:15:09 +02001264 .init_vif = NULL,
Arik Nemtsov4a3b97ee2011-12-12 11:44:27 +02001265 .get_pg_ver = wl12xx_get_pg_ver,
1266 .get_mac = wl12xx_get_mac,
Luciano Coelho6f7dd162011-11-29 16:27:31 +02001267};
1268
Arik Nemtsov96e0c682011-12-07 21:09:03 +02001269struct wl12xx_priv {
1270};
1271
Luciano Coelhoffeb5012011-11-21 18:55:51 +02001272static int __devinit wl12xx_probe(struct platform_device *pdev)
1273{
1274 struct wl1271 *wl;
1275 struct ieee80211_hw *hw;
Arik Nemtsov96e0c682011-12-07 21:09:03 +02001276 struct wl12xx_priv *priv;
Luciano Coelhoffeb5012011-11-21 18:55:51 +02001277
Arik Nemtsov96e0c682011-12-07 21:09:03 +02001278 hw = wlcore_alloc_hw(sizeof(*priv));
Luciano Coelhoffeb5012011-11-21 18:55:51 +02001279 if (IS_ERR(hw)) {
1280 wl1271_error("can't allocate hw");
1281 return PTR_ERR(hw);
1282 }
1283
1284 wl = hw->priv;
Luciano Coelhoc31be252011-11-21 19:25:24 +02001285 wl->ops = &wl12xx_ops;
Luciano Coelho25a43d72011-11-21 20:37:14 +02001286 wl->ptable = wl12xx_ptable;
Luciano Coelho00782132011-11-29 13:38:37 +02001287 wl->rtable = wl12xx_rtable;
Arik Nemtsov72b06242011-12-07 21:21:51 +02001288 wl->num_tx_desc = 16;
Arik Nemtsov3edab302011-12-07 23:38:47 +02001289 wl->normal_tx_spare = WL12XX_TX_HW_BLOCK_SPARE_DEFAULT;
1290 wl->gem_tx_spare = WL12XX_TX_HW_BLOCK_GEM_SPARE;
Arik Nemtsov43a8bc52011-12-08 00:43:48 +02001291 wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
1292 wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX;
1293 wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0;
Luciano Coelhoe87288f2011-12-05 16:12:54 +02001294 wl12xx_conf_init(wl);
Luciano Coelhoffeb5012011-11-21 18:55:51 +02001295
1296 return wlcore_probe(wl, pdev);
1297}
Luciano Coelhob2ba99f2011-11-20 23:32:10 +02001298
1299static const struct platform_device_id wl12xx_id_table[] __devinitconst = {
1300 { "wl12xx", 0 },
1301 { } /* Terminating Entry */
1302};
1303MODULE_DEVICE_TABLE(platform, wl12xx_id_table);
1304
1305static struct platform_driver wl12xx_driver = {
Luciano Coelhoffeb5012011-11-21 18:55:51 +02001306 .probe = wl12xx_probe,
Luciano Coelhob2ba99f2011-11-20 23:32:10 +02001307 .remove = __devexit_p(wlcore_remove),
1308 .id_table = wl12xx_id_table,
1309 .driver = {
1310 .name = "wl12xx_driver",
1311 .owner = THIS_MODULE,
1312 }
1313};
1314
1315static int __init wl12xx_init(void)
1316{
1317 return platform_driver_register(&wl12xx_driver);
1318}
1319module_init(wl12xx_init);
1320
1321static void __exit wl12xx_exit(void)
1322{
1323 platform_driver_unregister(&wl12xx_driver);
1324}
1325module_exit(wl12xx_exit);
1326
1327MODULE_LICENSE("GPL v2");
1328MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
Luciano Coelho6f7dd162011-11-29 16:27:31 +02001329MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
1330MODULE_FIRMWARE(WL127X_FW_NAME_MULTI);
1331MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
1332MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE);
1333MODULE_FIRMWARE(WL128X_FW_NAME_MULTI);
1334MODULE_FIRMWARE(WL128X_PLT_FW_NAME);