blob: 43c2c7fcd4bd143853d7da2ceb8e0e9dbb5decc7 [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 Coelhodd5512eb2012-04-11 11:03:14 +030035#include "../wlcore/boot.h"
Luciano Coelhoffeb5012011-11-21 18:55:51 +020036
Luciano Coelho00782132011-11-29 13:38:37 +020037#include "reg.h"
Luciano Coelho25a43d72011-11-21 20:37:14 +020038
Arik Nemtsov3edab302011-12-07 23:38:47 +020039#define WL12XX_TX_HW_BLOCK_SPARE_DEFAULT 1
40#define WL12XX_TX_HW_BLOCK_GEM_SPARE 2
Arik Nemtsovb3b4b4b2011-12-12 11:41:44 +020041#define WL12XX_TX_HW_BLOCK_SIZE 252
Arik Nemtsov3edab302011-12-07 23:38:47 +020042
Arik Nemtsov43a8bc52011-12-08 00:43:48 +020043static const u8 wl12xx_rate_to_idx_2ghz[] = {
44 /* MCS rates are used only with 11n */
45 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI */
46 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7 */
47 6, /* WL12XX_CONF_HW_RXTX_RATE_MCS6 */
48 5, /* WL12XX_CONF_HW_RXTX_RATE_MCS5 */
49 4, /* WL12XX_CONF_HW_RXTX_RATE_MCS4 */
50 3, /* WL12XX_CONF_HW_RXTX_RATE_MCS3 */
51 2, /* WL12XX_CONF_HW_RXTX_RATE_MCS2 */
52 1, /* WL12XX_CONF_HW_RXTX_RATE_MCS1 */
53 0, /* WL12XX_CONF_HW_RXTX_RATE_MCS0 */
54
55 11, /* WL12XX_CONF_HW_RXTX_RATE_54 */
56 10, /* WL12XX_CONF_HW_RXTX_RATE_48 */
57 9, /* WL12XX_CONF_HW_RXTX_RATE_36 */
58 8, /* WL12XX_CONF_HW_RXTX_RATE_24 */
59
60 /* TI-specific rate */
61 CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_22 */
62
63 7, /* WL12XX_CONF_HW_RXTX_RATE_18 */
64 6, /* WL12XX_CONF_HW_RXTX_RATE_12 */
65 3, /* WL12XX_CONF_HW_RXTX_RATE_11 */
66 5, /* WL12XX_CONF_HW_RXTX_RATE_9 */
67 4, /* WL12XX_CONF_HW_RXTX_RATE_6 */
68 2, /* WL12XX_CONF_HW_RXTX_RATE_5_5 */
69 1, /* WL12XX_CONF_HW_RXTX_RATE_2 */
70 0 /* WL12XX_CONF_HW_RXTX_RATE_1 */
71};
72
73static const u8 wl12xx_rate_to_idx_5ghz[] = {
74 /* MCS rates are used only with 11n */
75 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI */
76 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7 */
77 6, /* WL12XX_CONF_HW_RXTX_RATE_MCS6 */
78 5, /* WL12XX_CONF_HW_RXTX_RATE_MCS5 */
79 4, /* WL12XX_CONF_HW_RXTX_RATE_MCS4 */
80 3, /* WL12XX_CONF_HW_RXTX_RATE_MCS3 */
81 2, /* WL12XX_CONF_HW_RXTX_RATE_MCS2 */
82 1, /* WL12XX_CONF_HW_RXTX_RATE_MCS1 */
83 0, /* WL12XX_CONF_HW_RXTX_RATE_MCS0 */
84
85 7, /* WL12XX_CONF_HW_RXTX_RATE_54 */
86 6, /* WL12XX_CONF_HW_RXTX_RATE_48 */
87 5, /* WL12XX_CONF_HW_RXTX_RATE_36 */
88 4, /* WL12XX_CONF_HW_RXTX_RATE_24 */
89
90 /* TI-specific rate */
91 CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_22 */
92
93 3, /* WL12XX_CONF_HW_RXTX_RATE_18 */
94 2, /* WL12XX_CONF_HW_RXTX_RATE_12 */
95 CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_11 */
96 1, /* WL12XX_CONF_HW_RXTX_RATE_9 */
97 0, /* WL12XX_CONF_HW_RXTX_RATE_6 */
98 CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_5_5 */
99 CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_2 */
100 CONF_HW_RXTX_RATE_UNSUPPORTED /* WL12XX_CONF_HW_RXTX_RATE_1 */
101};
102
103static const u8 *wl12xx_band_rate_to_idx[] = {
104 [IEEE80211_BAND_2GHZ] = wl12xx_rate_to_idx_2ghz,
105 [IEEE80211_BAND_5GHZ] = wl12xx_rate_to_idx_5ghz
106};
107
108enum wl12xx_hw_rates {
109 WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI = 0,
110 WL12XX_CONF_HW_RXTX_RATE_MCS7,
111 WL12XX_CONF_HW_RXTX_RATE_MCS6,
112 WL12XX_CONF_HW_RXTX_RATE_MCS5,
113 WL12XX_CONF_HW_RXTX_RATE_MCS4,
114 WL12XX_CONF_HW_RXTX_RATE_MCS3,
115 WL12XX_CONF_HW_RXTX_RATE_MCS2,
116 WL12XX_CONF_HW_RXTX_RATE_MCS1,
117 WL12XX_CONF_HW_RXTX_RATE_MCS0,
118 WL12XX_CONF_HW_RXTX_RATE_54,
119 WL12XX_CONF_HW_RXTX_RATE_48,
120 WL12XX_CONF_HW_RXTX_RATE_36,
121 WL12XX_CONF_HW_RXTX_RATE_24,
122 WL12XX_CONF_HW_RXTX_RATE_22,
123 WL12XX_CONF_HW_RXTX_RATE_18,
124 WL12XX_CONF_HW_RXTX_RATE_12,
125 WL12XX_CONF_HW_RXTX_RATE_11,
126 WL12XX_CONF_HW_RXTX_RATE_9,
127 WL12XX_CONF_HW_RXTX_RATE_6,
128 WL12XX_CONF_HW_RXTX_RATE_5_5,
129 WL12XX_CONF_HW_RXTX_RATE_2,
130 WL12XX_CONF_HW_RXTX_RATE_1,
131 WL12XX_CONF_HW_RXTX_RATE_MAX,
132};
Arik Nemtsov3edab302011-12-07 23:38:47 +0200133
Luciano Coelho25a43d72011-11-21 20:37:14 +0200134static struct wlcore_partition_set wl12xx_ptable[PART_TABLE_LEN] = {
135 [PART_DOWN] = {
136 .mem = {
137 .start = 0x00000000,
138 .size = 0x000177c0
139 },
140 .reg = {
141 .start = REGISTERS_BASE,
142 .size = 0x00008800
143 },
144 .mem2 = {
145 .start = 0x00000000,
146 .size = 0x00000000
147 },
148 .mem3 = {
149 .start = 0x00000000,
150 .size = 0x00000000
151 },
152 },
153
Luciano Coelho00782132011-11-29 13:38:37 +0200154 [PART_BOOT] = { /* in wl12xx we can use a mix of work and down
155 * partition here */
156 .mem = {
157 .start = 0x00040000,
158 .size = 0x00014fc0
159 },
160 .reg = {
161 .start = REGISTERS_BASE,
162 .size = 0x00008800
163 },
164 .mem2 = {
165 .start = 0x00000000,
166 .size = 0x00000000
167 },
168 .mem3 = {
169 .start = 0x00000000,
170 .size = 0x00000000
171 },
172 },
173
Luciano Coelho25a43d72011-11-21 20:37:14 +0200174 [PART_WORK] = {
175 .mem = {
176 .start = 0x00040000,
177 .size = 0x00014fc0
178 },
179 .reg = {
180 .start = REGISTERS_BASE,
181 .size = 0x0000a000
182 },
183 .mem2 = {
184 .start = 0x003004f8,
185 .size = 0x00000004
186 },
187 .mem3 = {
188 .start = 0x00040404,
189 .size = 0x00000000
190 },
191 },
192
193 [PART_DRPW] = {
194 .mem = {
195 .start = 0x00040000,
196 .size = 0x00014fc0
197 },
198 .reg = {
199 .start = DRPW_BASE,
200 .size = 0x00006000
201 },
202 .mem2 = {
203 .start = 0x00000000,
204 .size = 0x00000000
205 },
206 .mem3 = {
207 .start = 0x00000000,
208 .size = 0x00000000
209 }
210 }
211};
212
Luciano Coelho00782132011-11-29 13:38:37 +0200213static const int wl12xx_rtable[REG_TABLE_LEN] = {
214 [REG_ECPU_CONTROL] = WL12XX_REG_ECPU_CONTROL,
215 [REG_INTERRUPT_NO_CLEAR] = WL12XX_REG_INTERRUPT_NO_CLEAR,
216 [REG_INTERRUPT_ACK] = WL12XX_REG_INTERRUPT_ACK,
217 [REG_COMMAND_MAILBOX_PTR] = WL12XX_REG_COMMAND_MAILBOX_PTR,
218 [REG_EVENT_MAILBOX_PTR] = WL12XX_REG_EVENT_MAILBOX_PTR,
219 [REG_INTERRUPT_TRIG] = WL12XX_REG_INTERRUPT_TRIG,
220 [REG_INTERRUPT_MASK] = WL12XX_REG_INTERRUPT_MASK,
221 [REG_PC_ON_RECOVERY] = WL12XX_SCR_PAD4,
222 [REG_CHIP_ID_B] = WL12XX_CHIP_ID_B,
223 [REG_CMD_MBOX_ADDRESS] = WL12XX_CMD_MBOX_ADDRESS,
224
225 /* data access memory addresses, used with partition translation */
226 [REG_SLV_MEM_DATA] = WL1271_SLV_MEM_DATA,
227 [REG_SLV_REG_DATA] = WL1271_SLV_REG_DATA,
228
229 /* raw data access memory addresses */
230 [REG_RAW_FW_STATUS_ADDR] = FW_STATUS_ADDR,
231};
232
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200233/* TODO: maybe move to a new header file? */
234#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin"
235#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin"
236#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin"
237
238#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin"
239#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin"
240#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin"
241
242static int wl12xx_identify_chip(struct wl1271 *wl)
243{
244 int ret = 0;
245
246 switch (wl->chip.id) {
247 case CHIP_ID_1271_PG10:
248 wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
249 wl->chip.id);
250
Luciano Coelhod203e592011-11-30 12:30:01 +0200251 wl->quirks |= WLCORE_QUIRK_NO_BLOCKSIZE_ALIGNMENT |
252 WLCORE_QUIRK_LEGACY_NVS;
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200253 wl->plt_fw_name = WL127X_PLT_FW_NAME;
254 wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
255 wl->mr_fw_name = WL127X_FW_NAME_MULTI;
256 break;
257
258 case CHIP_ID_1271_PG20:
259 wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
260 wl->chip.id);
261
Luciano Coelhod203e592011-11-30 12:30:01 +0200262 wl->quirks |= WLCORE_QUIRK_NO_BLOCKSIZE_ALIGNMENT |
263 WLCORE_QUIRK_LEGACY_NVS;
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200264 wl->plt_fw_name = WL127X_PLT_FW_NAME;
265 wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
266 wl->mr_fw_name = WL127X_FW_NAME_MULTI;
267 break;
268
269 case CHIP_ID_1283_PG20:
270 wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)",
271 wl->chip.id);
272 wl->plt_fw_name = WL128X_PLT_FW_NAME;
273 wl->sr_fw_name = WL128X_FW_NAME_SINGLE;
274 wl->mr_fw_name = WL128X_FW_NAME_MULTI;
275 break;
276 case CHIP_ID_1283_PG10:
277 default:
278 wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
279 ret = -ENODEV;
280 goto out;
281 }
282
283out:
284 return ret;
285}
286
Luciano Coelhodd5512eb2012-04-11 11:03:14 +0300287static void wl12xx_top_reg_write(struct wl1271 *wl, int addr, u16 val)
288{
289 /* write address >> 1 + 0x30000 to OCP_POR_CTR */
290 addr = (addr >> 1) + 0x30000;
291 wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr);
292
293 /* write value to OCP_POR_WDATA */
294 wl1271_write32(wl, WL12XX_OCP_DATA_WRITE, val);
295
296 /* write 1 to OCP_CMD */
297 wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE);
298}
299
300static u16 wl12xx_top_reg_read(struct wl1271 *wl, int addr)
301{
302 u32 val;
303 int timeout = OCP_CMD_LOOP;
304
305 /* write address >> 1 + 0x30000 to OCP_POR_CTR */
306 addr = (addr >> 1) + 0x30000;
307 wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr);
308
309 /* write 2 to OCP_CMD */
310 wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ);
311
312 /* poll for data ready */
313 do {
314 val = wl1271_read32(wl, WL12XX_OCP_DATA_READ);
315 } while (!(val & OCP_READY_MASK) && --timeout);
316
317 if (!timeout) {
318 wl1271_warning("Top register access timed out.");
319 return 0xffff;
320 }
321
322 /* check data status and return if OK */
323 if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
324 return val & 0xffff;
325 else {
326 wl1271_warning("Top register access returned error.");
327 return 0xffff;
328 }
329}
330
331static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
332{
333 u16 spare_reg;
334
335 /* Mask bits [2] & [8:4] in the sys_clk_cfg register */
336 spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG);
337 if (spare_reg == 0xFFFF)
338 return -EFAULT;
339 spare_reg |= (BIT(3) | BIT(5) | BIT(6));
340 wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
341
342 /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */
343 wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG,
344 WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);
345
346 /* Delay execution for 15msec, to let the HW settle */
347 mdelay(15);
348
349 return 0;
350}
351
352static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
353{
354 u16 tcxo_detection;
355
356 tcxo_detection = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG);
357 if (tcxo_detection & TCXO_DET_FAILED)
358 return false;
359
360 return true;
361}
362
363static bool wl128x_is_fref_valid(struct wl1271 *wl)
364{
365 u16 fref_detection;
366
367 fref_detection = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG);
368 if (fref_detection & FREF_CLK_DETECT_FAIL)
369 return false;
370
371 return true;
372}
373
374static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl)
375{
376 wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL);
377 wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL);
378 wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL);
379
380 return 0;
381}
382
383static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
384{
385 u16 spare_reg;
386 u16 pll_config;
387 u8 input_freq;
388
389 /* Mask bits [3:1] in the sys_clk_cfg register */
390 spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG);
391 if (spare_reg == 0xFFFF)
392 return -EFAULT;
393 spare_reg |= BIT(2);
394 wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
395
396 /* Handle special cases of the TCXO clock */
397 if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 ||
398 wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6)
399 return wl128x_manually_configure_mcs_pll(wl);
400
401 /* Set the input frequency according to the selected clock source */
402 input_freq = (clk & 1) + 1;
403
404 pll_config = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG);
405 if (pll_config == 0xFFFF)
406 return -EFAULT;
407 pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT);
408 pll_config |= MCS_PLL_ENABLE_HP;
409 wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config);
410
411 return 0;
412}
413
414/*
415 * WL128x has two clocks input - TCXO and FREF.
416 * TCXO is the main clock of the device, while FREF is used to sync
417 * between the GPS and the cellular modem.
418 * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used
419 * as the WLAN/BT main clock.
420 */
421static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
422{
423 u16 sys_clk_cfg;
424
425 /* For XTAL-only modes, FREF will be used after switching from TCXO */
426 if (wl->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
427 wl->ref_clock == WL12XX_REFCLOCK_38_XTAL) {
428 if (!wl128x_switch_tcxo_to_fref(wl))
429 return -EINVAL;
430 goto fref_clk;
431 }
432
433 /* Query the HW, to determine which clock source we should use */
434 sys_clk_cfg = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG);
435 if (sys_clk_cfg == 0xFFFF)
436 return -EINVAL;
437 if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF)
438 goto fref_clk;
439
440 /* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */
441 if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_368 ||
442 wl->tcxo_clock == WL12XX_TCXOCLOCK_32_736) {
443 if (!wl128x_switch_tcxo_to_fref(wl))
444 return -EINVAL;
445 goto fref_clk;
446 }
447
448 /* TCXO clock is selected */
449 if (!wl128x_is_tcxo_valid(wl))
450 return -EINVAL;
451 *selected_clock = wl->tcxo_clock;
452 goto config_mcs_pll;
453
454fref_clk:
455 /* FREF clock is selected */
456 if (!wl128x_is_fref_valid(wl))
457 return -EINVAL;
458 *selected_clock = wl->ref_clock;
459
460config_mcs_pll:
461 return wl128x_configure_mcs_pll(wl, *selected_clock);
462}
463
464static int wl127x_boot_clk(struct wl1271 *wl)
465{
466 u32 pause;
467 u32 clk;
468
469 if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
470 wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION;
471
472 if (wl->ref_clock == CONF_REF_CLK_19_2_E ||
473 wl->ref_clock == CONF_REF_CLK_38_4_E ||
474 wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL)
475 /* ref clk: 19.2/38.4/38.4-XTAL */
476 clk = 0x3;
477 else if (wl->ref_clock == CONF_REF_CLK_26_E ||
478 wl->ref_clock == CONF_REF_CLK_52_E)
479 /* ref clk: 26/52 */
480 clk = 0x5;
481 else
482 return -EINVAL;
483
484 if (wl->ref_clock != CONF_REF_CLK_19_2_E) {
485 u16 val;
486 /* Set clock type (open drain) */
487 val = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE);
488 val &= FREF_CLK_TYPE_BITS;
489 wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
490
491 /* Set clock pull mode (no pull) */
492 val = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL);
493 val |= NO_PULL;
494 wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val);
495 } else {
496 u16 val;
497 /* Set clock polarity */
498 val = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY);
499 val &= FREF_CLK_POLARITY_BITS;
500 val |= CLK_REQ_OUTN_SEL;
501 wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
502 }
503
504 wl1271_write32(wl, WL12XX_PLL_PARAMETERS, clk);
505
506 pause = wl1271_read32(wl, WL12XX_PLL_PARAMETERS);
507
508 wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
509
510 pause &= ~(WU_COUNTER_PAUSE_VAL);
511 pause |= WU_COUNTER_PAUSE_VAL;
512 wl1271_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause);
513
514 return 0;
515}
516
517static int wl1271_boot_soft_reset(struct wl1271 *wl)
518{
519 unsigned long timeout;
520 u32 boot_data;
521
522 /* perform soft reset */
523 wl1271_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
524
525 /* SOFT_RESET is self clearing */
526 timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
527 while (1) {
528 boot_data = wl1271_read32(wl, WL12XX_SLV_SOFT_RESET);
529 wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
530 if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
531 break;
532
533 if (time_after(jiffies, timeout)) {
534 /* 1.2 check pWhalBus->uSelfClearTime if the
535 * timeout was reached */
536 wl1271_error("soft reset timeout");
537 return -1;
538 }
539
540 udelay(SOFT_RESET_STALL_TIME);
541 }
542
543 /* disable Rx/Tx */
544 wl1271_write32(wl, WL12XX_ENABLE, 0x0);
545
546 /* disable auto calibration on start*/
547 wl1271_write32(wl, WL12XX_SPARE_A2, 0xffff);
548
549 return 0;
550}
551
552static int wl12xx_pre_boot(struct wl1271 *wl)
553{
554 int ret = 0;
555 u32 clk;
556 int selected_clock = -1;
557
558 if (wl->chip.id == CHIP_ID_1283_PG20) {
559 ret = wl128x_boot_clk(wl, &selected_clock);
560 if (ret < 0)
561 goto out;
562 } else {
563 ret = wl127x_boot_clk(wl);
564 if (ret < 0)
565 goto out;
566 }
567
568 /* Continue the ELP wake up sequence */
569 wl1271_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
570 udelay(500);
571
572 wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
573
574 /* Read-modify-write DRPW_SCRATCH_START register (see next state)
575 to be used by DRPw FW. The RTRIM value will be added by the FW
576 before taking DRPw out of reset */
577
578 clk = wl1271_read32(wl, WL12XX_DRPW_SCRATCH_START);
579
580 wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
581
582 if (wl->chip.id == CHIP_ID_1283_PG20)
583 clk |= ((selected_clock & 0x3) << 1) << 4;
584 else
585 clk |= (wl->ref_clock << 1) << 4;
586
587 wl1271_write32(wl, WL12XX_DRPW_SCRATCH_START, clk);
588
589 wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
590
591 /* Disable interrupts */
592 wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
593
594 ret = wl1271_boot_soft_reset(wl);
595 if (ret < 0)
596 goto out;
597
598out:
599 return ret;
600}
601
602static void wl12xx_pre_upload(struct wl1271 *wl)
603{
604 u32 tmp;
605
606 /* write firmware's last address (ie. it's length) to
607 * ACX_EEPROMLESS_IND_REG */
608 wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");
609
610 wl1271_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND);
611
612 tmp = wlcore_read_reg(wl, REG_CHIP_ID_B);
613
614 wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
615
616 /* 6. read the EEPROM parameters */
617 tmp = wl1271_read32(wl, WL12XX_SCR_PAD2);
618
619 /* WL1271: The reference driver skips steps 7 to 10 (jumps directly
620 * to upload_fw) */
621
622 if (wl->chip.id == CHIP_ID_1283_PG20)
623 wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
624}
625
626static void wl12xx_enable_interrupts(struct wl1271 *wl)
627{
628 u32 polarity;
629
630 polarity = wl12xx_top_reg_read(wl, OCP_REG_POLARITY);
631
632 /* We use HIGH polarity, so unset the LOW bit */
633 polarity &= ~POLARITY_LOW;
634 wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity);
635
636 wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_ALL_EVENTS_VECTOR);
637
638 wlcore_enable_interrupts(wl);
639 wlcore_write_reg(wl, REG_INTERRUPT_MASK,
640 WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
641
642 wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL);
643}
644
645static int wl12xx_boot(struct wl1271 *wl)
646{
647 int ret;
648
649 ret = wl12xx_pre_boot(wl);
650 if (ret < 0)
651 goto out;
652
653 ret = wlcore_boot_upload_nvs(wl);
654 if (ret < 0)
655 goto out;
656
657 wl12xx_pre_upload(wl);
658
659 ret = wlcore_boot_upload_firmware(wl);
660 if (ret < 0)
661 goto out;
662
663 ret = wlcore_boot_run_firmware(wl);
664 if (ret < 0)
665 goto out;
666
667 wl12xx_enable_interrupts(wl);
668
669out:
670 return ret;
671}
672
Luciano Coelhof16ff752012-04-11 10:15:46 +0300673static void wl12xx_trigger_cmd(struct wl1271 *wl)
674{
675 wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD);
676}
677
678static void wl12xx_ack_event(struct wl1271 *wl)
679{
680 wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_EVENT_ACK);
681}
682
Arik Nemtsovb3b4b4b2011-12-12 11:41:44 +0200683static u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
684{
685 u32 blk_size = WL12XX_TX_HW_BLOCK_SIZE;
686 u32 align_len = wlcore_calc_packet_alignment(wl, len);
687
688 return (align_len + blk_size - 1) / blk_size + spare_blks;
689}
690
Arik Nemtsov4a3b97ee2011-12-12 11:44:27 +0200691static void
692wl12xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
693 u32 blks, u32 spare_blks)
694{
695 if (wl->chip.id == CHIP_ID_1283_PG20) {
696 desc->wl128x_mem.total_mem_blocks = blks;
697 } else {
698 desc->wl127x_mem.extra_blocks = spare_blks;
699 desc->wl127x_mem.total_mem_blocks = blks;
700 }
701}
702
Arik Nemtsov6f266e92011-12-12 11:47:09 +0200703static void
704wl12xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
705 struct sk_buff *skb)
706{
707 u32 aligned_len = wlcore_calc_packet_alignment(wl, skb->len);
708
709 if (wl->chip.id == CHIP_ID_1283_PG20) {
710 desc->wl128x_mem.extra_bytes = aligned_len - skb->len;
711 desc->length = cpu_to_le16(aligned_len >> 2);
712
713 wl1271_debug(DEBUG_TX,
714 "tx_fill_hdr: hlid: %d len: %d life: %d mem: %d extra: %d",
715 desc->hlid,
716 le16_to_cpu(desc->length),
717 le16_to_cpu(desc->life_time),
718 desc->wl128x_mem.total_mem_blocks,
719 desc->wl128x_mem.extra_bytes);
720 } else {
721 /* calculate number of padding bytes */
722 int pad = aligned_len - skb->len;
723 desc->tx_attr |=
724 cpu_to_le16(pad << TX_HW_ATTR_OFST_LAST_WORD_PAD);
725
726 /* Store the aligned length in terms of words */
727 desc->length = cpu_to_le16(aligned_len >> 2);
728
729 wl1271_debug(DEBUG_TX,
730 "tx_fill_hdr: pad: %d hlid: %d len: %d life: %d mem: %d",
731 pad, desc->hlid,
732 le16_to_cpu(desc->length),
733 le16_to_cpu(desc->life_time),
734 desc->wl127x_mem.total_mem_blocks);
735 }
736}
737
Arik Nemtsovcd70f6a2011-12-12 12:11:43 +0200738static enum wl_rx_buf_align
739wl12xx_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
740{
741 if (rx_desc & RX_BUF_UNALIGNED_PAYLOAD)
742 return WLCORE_RX_BUF_UNALIGNED;
743
744 return WLCORE_RX_BUF_ALIGNED;
745}
746
Luciano Coelho30d9b4a2012-04-11 11:07:28 +0300747static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
748{
749 bool supported = false;
750 u8 major, minor;
751
752 if (wl->chip.id == CHIP_ID_1283_PG20) {
753 major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver);
754 minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver);
755
756 /* in wl128x we have the MAC address if the PG is >= (2, 1) */
757 if (major > 2 || (major == 2 && minor >= 1))
758 supported = true;
759 } else {
760 major = WL127X_PG_GET_MAJOR(wl->hw_pg_ver);
761 minor = WL127X_PG_GET_MINOR(wl->hw_pg_ver);
762
763 /* in wl127x we have the MAC address if the PG is >= (3, 1) */
764 if (major == 3 && minor >= 1)
765 supported = true;
766 }
767
768 wl1271_debug(DEBUG_PROBE,
769 "PG Ver major = %d minor = %d, MAC %s present",
770 major, minor, supported ? "is" : "is not");
771
772 return supported;
773}
774
775static void wl12xx_get_fuse_mac(struct wl1271 *wl)
776{
777 u32 mac1, mac2;
778
779 wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
780
781 mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1);
782 mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2);
783
784 /* these are the two parts of the BD_ADDR */
785 wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
786 ((mac1 & 0xff000000) >> 24);
787 wl->fuse_nic_addr = mac1 & 0xffffff;
788
789 wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
790}
791
Luciano Coelho4ded91c2012-04-11 10:54:52 +0300792static s8 wl12xx_get_pg_ver(struct wl1271 *wl)
793{
794 u32 die_info;
795
796 if (wl->chip.id == CHIP_ID_1283_PG20)
Luciano Coelhodd5512eb2012-04-11 11:03:14 +0300797 die_info = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1);
Luciano Coelho4ded91c2012-04-11 10:54:52 +0300798 else
Luciano Coelhodd5512eb2012-04-11 11:03:14 +0300799 die_info = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1);
Luciano Coelho4ded91c2012-04-11 10:54:52 +0300800
801 return (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET;
802}
803
Luciano Coelho30d9b4a2012-04-11 11:07:28 +0300804static void wl12xx_get_mac(struct wl1271 *wl)
805{
806 if (wl12xx_mac_in_fuse(wl))
807 wl12xx_get_fuse_mac(wl);
808}
809
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200810static struct wlcore_ops wl12xx_ops = {
Arik Nemtsov4a3b97ee2011-12-12 11:44:27 +0200811 .identify_chip = wl12xx_identify_chip,
812 .boot = wl12xx_boot,
813 .trigger_cmd = wl12xx_trigger_cmd,
814 .ack_event = wl12xx_ack_event,
815 .calc_tx_blocks = wl12xx_calc_tx_blocks,
816 .set_tx_desc_blocks = wl12xx_set_tx_desc_blocks,
Arik Nemtsov6f266e92011-12-12 11:47:09 +0200817 .set_tx_desc_data_len = wl12xx_set_tx_desc_data_len,
Arik Nemtsovcd70f6a2011-12-12 12:11:43 +0200818 .get_rx_buf_align = wl12xx_get_rx_buf_align,
Arik Nemtsov4a3b97ee2011-12-12 11:44:27 +0200819 .get_pg_ver = wl12xx_get_pg_ver,
820 .get_mac = wl12xx_get_mac,
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200821};
822
Arik Nemtsov96e0c682011-12-07 21:09:03 +0200823struct wl12xx_priv {
824};
825
Luciano Coelhoffeb5012011-11-21 18:55:51 +0200826static int __devinit wl12xx_probe(struct platform_device *pdev)
827{
828 struct wl1271 *wl;
829 struct ieee80211_hw *hw;
Arik Nemtsov96e0c682011-12-07 21:09:03 +0200830 struct wl12xx_priv *priv;
Luciano Coelhoffeb5012011-11-21 18:55:51 +0200831
Arik Nemtsov96e0c682011-12-07 21:09:03 +0200832 hw = wlcore_alloc_hw(sizeof(*priv));
Luciano Coelhoffeb5012011-11-21 18:55:51 +0200833 if (IS_ERR(hw)) {
834 wl1271_error("can't allocate hw");
835 return PTR_ERR(hw);
836 }
837
838 wl = hw->priv;
Luciano Coelhoc31be252011-11-21 19:25:24 +0200839 wl->ops = &wl12xx_ops;
Luciano Coelho25a43d72011-11-21 20:37:14 +0200840 wl->ptable = wl12xx_ptable;
Luciano Coelho00782132011-11-29 13:38:37 +0200841 wl->rtable = wl12xx_rtable;
Arik Nemtsov72b06242011-12-07 21:21:51 +0200842 wl->num_tx_desc = 16;
Arik Nemtsov3edab302011-12-07 23:38:47 +0200843 wl->normal_tx_spare = WL12XX_TX_HW_BLOCK_SPARE_DEFAULT;
844 wl->gem_tx_spare = WL12XX_TX_HW_BLOCK_GEM_SPARE;
Arik Nemtsov43a8bc52011-12-08 00:43:48 +0200845 wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
846 wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX;
847 wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0;
Luciano Coelhoffeb5012011-11-21 18:55:51 +0200848
849 return wlcore_probe(wl, pdev);
850}
Luciano Coelhob2ba99f2011-11-20 23:32:10 +0200851
852static const struct platform_device_id wl12xx_id_table[] __devinitconst = {
853 { "wl12xx", 0 },
854 { } /* Terminating Entry */
855};
856MODULE_DEVICE_TABLE(platform, wl12xx_id_table);
857
858static struct platform_driver wl12xx_driver = {
Luciano Coelhoffeb5012011-11-21 18:55:51 +0200859 .probe = wl12xx_probe,
Luciano Coelhob2ba99f2011-11-20 23:32:10 +0200860 .remove = __devexit_p(wlcore_remove),
861 .id_table = wl12xx_id_table,
862 .driver = {
863 .name = "wl12xx_driver",
864 .owner = THIS_MODULE,
865 }
866};
867
868static int __init wl12xx_init(void)
869{
870 return platform_driver_register(&wl12xx_driver);
871}
872module_init(wl12xx_init);
873
874static void __exit wl12xx_exit(void)
875{
876 platform_driver_unregister(&wl12xx_driver);
877}
878module_exit(wl12xx_exit);
879
880MODULE_LICENSE("GPL v2");
881MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200882MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
883MODULE_FIRMWARE(WL127X_FW_NAME_MULTI);
884MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
885MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE);
886MODULE_FIRMWARE(WL128X_FW_NAME_MULTI);
887MODULE_FIRMWARE(WL128X_PLT_FW_NAME);