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