blob: 083e1d8be173d2d5b09f62feba20228e33818dde [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
Arik Nemtsov3edab302011-12-07 23:38:47 +020042#define WL12XX_TX_HW_BLOCK_SPARE_DEFAULT 1
43#define WL12XX_TX_HW_BLOCK_GEM_SPARE 2
Arik Nemtsovb3b4b4b2011-12-12 11:41:44 +020044#define WL12XX_TX_HW_BLOCK_SIZE 252
Arik Nemtsov3edab302011-12-07 23:38:47 +020045
Arik Nemtsov43a8bc52011-12-08 00:43:48 +020046static 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};
Arik Nemtsov3edab302011-12-07 23:38:47 +0200136
Luciano Coelho25a43d72011-11-21 20:37:14 +0200137static 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
Luciano Coelho00782132011-11-29 13:38:37 +0200157 [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
Luciano Coelho25a43d72011-11-21 20:37:14 +0200177 [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
Luciano Coelho00782132011-11-29 13:38:37 +0200216static 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
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200236/* 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
Luciano Coelhob14684a2011-12-12 12:15:08 +0200245static 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
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200268static 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
Arik Nemtsovf83985bb2011-12-13 12:11:26 +0200277 /* 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;
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200281 wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
282 wl->mr_fw_name = WL127X_FW_NAME_MULTI;
Luciano Coelhob14684a2011-12-12 12:15:08 +0200283
284 /* read data preparation is only needed by wl127x */
285 wl->ops->prepare_read = wl127x_prepare_read;
286
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200287 break;
288
289 case CHIP_ID_1271_PG20:
290 wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
291 wl->chip.id);
292
Arik Nemtsovf83985bb2011-12-13 12:11:26 +0200293 /* 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;
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200297 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;
Luciano Coelhob14684a2011-12-12 12:15:08 +0200300
301 /* read data preparation is only needed by wl127x */
302 wl->ops->prepare_read = wl127x_prepare_read;
303
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200304 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
Luciano Coelhodd5512eb2012-04-11 11:03:14 +0300324static 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
Arik Nemtsov5d10b192011-12-13 12:27:22 +0200710static void wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
711 void *buf, size_t len)
Luciano Coelhof16ff752012-04-11 10:15:46 +0300712{
Arik Nemtsov5d10b192011-12-13 12:27:22 +0200713 wl1271_write(wl, cmd_box_addr, buf, len, false);
Luciano Coelhof16ff752012-04-11 10:15:46 +0300714 wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD);
715}
716
717static void wl12xx_ack_event(struct wl1271 *wl)
718{
719 wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_EVENT_ACK);
720}
721
Arik Nemtsovb3b4b4b2011-12-12 11:41:44 +0200722static u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
723{
724 u32 blk_size = WL12XX_TX_HW_BLOCK_SIZE;
725 u32 align_len = wlcore_calc_packet_alignment(wl, len);
726
727 return (align_len + blk_size - 1) / blk_size + spare_blks;
728}
729
Arik Nemtsov4a3b97ee2011-12-12 11:44:27 +0200730static void
731wl12xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
732 u32 blks, u32 spare_blks)
733{
734 if (wl->chip.id == CHIP_ID_1283_PG20) {
735 desc->wl128x_mem.total_mem_blocks = blks;
736 } else {
737 desc->wl127x_mem.extra_blocks = spare_blks;
738 desc->wl127x_mem.total_mem_blocks = blks;
739 }
740}
741
Arik Nemtsov6f266e92011-12-12 11:47:09 +0200742static void
743wl12xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
744 struct sk_buff *skb)
745{
746 u32 aligned_len = wlcore_calc_packet_alignment(wl, skb->len);
747
748 if (wl->chip.id == CHIP_ID_1283_PG20) {
749 desc->wl128x_mem.extra_bytes = aligned_len - skb->len;
750 desc->length = cpu_to_le16(aligned_len >> 2);
751
752 wl1271_debug(DEBUG_TX,
753 "tx_fill_hdr: hlid: %d len: %d life: %d mem: %d extra: %d",
754 desc->hlid,
755 le16_to_cpu(desc->length),
756 le16_to_cpu(desc->life_time),
757 desc->wl128x_mem.total_mem_blocks,
758 desc->wl128x_mem.extra_bytes);
759 } else {
760 /* calculate number of padding bytes */
761 int pad = aligned_len - skb->len;
762 desc->tx_attr |=
763 cpu_to_le16(pad << TX_HW_ATTR_OFST_LAST_WORD_PAD);
764
765 /* Store the aligned length in terms of words */
766 desc->length = cpu_to_le16(aligned_len >> 2);
767
768 wl1271_debug(DEBUG_TX,
769 "tx_fill_hdr: pad: %d hlid: %d len: %d life: %d mem: %d",
770 pad, desc->hlid,
771 le16_to_cpu(desc->length),
772 le16_to_cpu(desc->life_time),
773 desc->wl127x_mem.total_mem_blocks);
774 }
775}
776
Arik Nemtsovcd70f6a2011-12-12 12:11:43 +0200777static enum wl_rx_buf_align
778wl12xx_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
779{
780 if (rx_desc & RX_BUF_UNALIGNED_PAYLOAD)
781 return WLCORE_RX_BUF_UNALIGNED;
782
783 return WLCORE_RX_BUF_ALIGNED;
784}
785
Arik Nemtsov41581492011-12-12 12:18:17 +0200786static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
787 u32 data_len)
788{
789 struct wl1271_rx_descriptor *desc = rx_data;
790
791 /* invalid packet */
792 if (data_len < sizeof(*desc) ||
793 data_len < sizeof(*desc) + desc->pad_len)
794 return 0;
795
796 return data_len - sizeof(*desc) - desc->pad_len;
797}
798
Arik Nemtsov53d67a52011-12-12 11:32:37 +0200799static void wl12xx_tx_delayed_compl(struct wl1271 *wl)
800{
801 if (wl->fw_status->tx_results_counter == (wl->tx_results_count & 0xff))
802 return;
803
804 wl1271_tx_complete(wl);
805}
806
Luciano Coelho9d68d1e2011-12-02 00:47:45 +0200807static int wl12xx_hw_init(struct wl1271 *wl)
808{
809 int ret;
810
811 if (wl->chip.id == CHIP_ID_1283_PG20) {
812 u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE;
813
814 ret = wl128x_cmd_general_parms(wl);
815 if (ret < 0)
816 goto out;
817 ret = wl128x_cmd_radio_parms(wl);
818 if (ret < 0)
819 goto out;
820
821 if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN)
822 /* Enable SDIO padding */
823 host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK;
824
825 /* Must be before wl1271_acx_init_mem_config() */
826 ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap);
827 if (ret < 0)
828 goto out;
829 } else {
830 ret = wl1271_cmd_general_parms(wl);
831 if (ret < 0)
832 goto out;
833 ret = wl1271_cmd_radio_parms(wl);
834 if (ret < 0)
835 goto out;
836 ret = wl1271_cmd_ext_radio_parms(wl);
837 if (ret < 0)
838 goto out;
839 }
840out:
841 return ret;
842}
843
Luciano Coelho30d9b4a2012-04-11 11:07:28 +0300844static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
845{
846 bool supported = false;
847 u8 major, minor;
848
849 if (wl->chip.id == CHIP_ID_1283_PG20) {
850 major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver);
851 minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver);
852
853 /* in wl128x we have the MAC address if the PG is >= (2, 1) */
854 if (major > 2 || (major == 2 && minor >= 1))
855 supported = true;
856 } else {
857 major = WL127X_PG_GET_MAJOR(wl->hw_pg_ver);
858 minor = WL127X_PG_GET_MINOR(wl->hw_pg_ver);
859
860 /* in wl127x we have the MAC address if the PG is >= (3, 1) */
861 if (major == 3 && minor >= 1)
862 supported = true;
863 }
864
865 wl1271_debug(DEBUG_PROBE,
866 "PG Ver major = %d minor = %d, MAC %s present",
867 major, minor, supported ? "is" : "is not");
868
869 return supported;
870}
871
872static void wl12xx_get_fuse_mac(struct wl1271 *wl)
873{
874 u32 mac1, mac2;
875
876 wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
877
878 mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1);
879 mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2);
880
881 /* these are the two parts of the BD_ADDR */
882 wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
883 ((mac1 & 0xff000000) >> 24);
884 wl->fuse_nic_addr = mac1 & 0xffffff;
885
886 wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
887}
888
Luciano Coelho4ded91c2012-04-11 10:54:52 +0300889static s8 wl12xx_get_pg_ver(struct wl1271 *wl)
890{
891 u32 die_info;
892
893 if (wl->chip.id == CHIP_ID_1283_PG20)
Luciano Coelhodd5512eb2012-04-11 11:03:14 +0300894 die_info = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1);
Luciano Coelho4ded91c2012-04-11 10:54:52 +0300895 else
Luciano Coelhodd5512eb2012-04-11 11:03:14 +0300896 die_info = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1);
Luciano Coelho4ded91c2012-04-11 10:54:52 +0300897
898 return (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET;
899}
900
Luciano Coelho30d9b4a2012-04-11 11:07:28 +0300901static void wl12xx_get_mac(struct wl1271 *wl)
902{
903 if (wl12xx_mac_in_fuse(wl))
904 wl12xx_get_fuse_mac(wl);
905}
906
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200907static struct wlcore_ops wl12xx_ops = {
Arik Nemtsov4a3b97ee2011-12-12 11:44:27 +0200908 .identify_chip = wl12xx_identify_chip,
909 .boot = wl12xx_boot,
910 .trigger_cmd = wl12xx_trigger_cmd,
911 .ack_event = wl12xx_ack_event,
912 .calc_tx_blocks = wl12xx_calc_tx_blocks,
913 .set_tx_desc_blocks = wl12xx_set_tx_desc_blocks,
Arik Nemtsov6f266e92011-12-12 11:47:09 +0200914 .set_tx_desc_data_len = wl12xx_set_tx_desc_data_len,
Arik Nemtsovcd70f6a2011-12-12 12:11:43 +0200915 .get_rx_buf_align = wl12xx_get_rx_buf_align,
Arik Nemtsov41581492011-12-12 12:18:17 +0200916 .get_rx_packet_len = wl12xx_get_rx_packet_len,
Arik Nemtsov53d67a52011-12-12 11:32:37 +0200917 .tx_immediate_compl = NULL,
918 .tx_delayed_compl = wl12xx_tx_delayed_compl,
Luciano Coelho9d68d1e2011-12-02 00:47:45 +0200919 .hw_init = wl12xx_hw_init,
Arik Nemtsov8a9affc2011-12-13 12:15:09 +0200920 .init_vif = NULL,
Arik Nemtsov4a3b97ee2011-12-12 11:44:27 +0200921 .get_pg_ver = wl12xx_get_pg_ver,
922 .get_mac = wl12xx_get_mac,
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200923};
924
Arik Nemtsov96e0c682011-12-07 21:09:03 +0200925struct wl12xx_priv {
926};
927
Luciano Coelhoffeb5012011-11-21 18:55:51 +0200928static int __devinit wl12xx_probe(struct platform_device *pdev)
929{
930 struct wl1271 *wl;
931 struct ieee80211_hw *hw;
Arik Nemtsov96e0c682011-12-07 21:09:03 +0200932 struct wl12xx_priv *priv;
Luciano Coelhoffeb5012011-11-21 18:55:51 +0200933
Arik Nemtsov96e0c682011-12-07 21:09:03 +0200934 hw = wlcore_alloc_hw(sizeof(*priv));
Luciano Coelhoffeb5012011-11-21 18:55:51 +0200935 if (IS_ERR(hw)) {
936 wl1271_error("can't allocate hw");
937 return PTR_ERR(hw);
938 }
939
940 wl = hw->priv;
Luciano Coelhoc31be252011-11-21 19:25:24 +0200941 wl->ops = &wl12xx_ops;
Luciano Coelho25a43d72011-11-21 20:37:14 +0200942 wl->ptable = wl12xx_ptable;
Luciano Coelho00782132011-11-29 13:38:37 +0200943 wl->rtable = wl12xx_rtable;
Arik Nemtsov72b06242011-12-07 21:21:51 +0200944 wl->num_tx_desc = 16;
Arik Nemtsov3edab302011-12-07 23:38:47 +0200945 wl->normal_tx_spare = WL12XX_TX_HW_BLOCK_SPARE_DEFAULT;
946 wl->gem_tx_spare = WL12XX_TX_HW_BLOCK_GEM_SPARE;
Arik Nemtsov43a8bc52011-12-08 00:43:48 +0200947 wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
948 wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX;
949 wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0;
Luciano Coelhoffeb5012011-11-21 18:55:51 +0200950
951 return wlcore_probe(wl, pdev);
952}
Luciano Coelhob2ba99f2011-11-20 23:32:10 +0200953
954static const struct platform_device_id wl12xx_id_table[] __devinitconst = {
955 { "wl12xx", 0 },
956 { } /* Terminating Entry */
957};
958MODULE_DEVICE_TABLE(platform, wl12xx_id_table);
959
960static struct platform_driver wl12xx_driver = {
Luciano Coelhoffeb5012011-11-21 18:55:51 +0200961 .probe = wl12xx_probe,
Luciano Coelhob2ba99f2011-11-20 23:32:10 +0200962 .remove = __devexit_p(wlcore_remove),
963 .id_table = wl12xx_id_table,
964 .driver = {
965 .name = "wl12xx_driver",
966 .owner = THIS_MODULE,
967 }
968};
969
970static int __init wl12xx_init(void)
971{
972 return platform_driver_register(&wl12xx_driver);
973}
974module_init(wl12xx_init);
975
976static void __exit wl12xx_exit(void)
977{
978 platform_driver_unregister(&wl12xx_driver);
979}
980module_exit(wl12xx_exit);
981
982MODULE_LICENSE("GPL v2");
983MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200984MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
985MODULE_FIRMWARE(WL127X_FW_NAME_MULTI);
986MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
987MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE);
988MODULE_FIRMWARE(WL128X_FW_NAME_MULTI);
989MODULE_FIRMWARE(WL128X_PLT_FW_NAME);