aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl1251/boot.c
diff options
context:
space:
mode:
authorKalle Valo <kvalo@adurom.com>2010-10-10 04:28:32 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-10-11 15:04:23 -0400
commit9bc6772e15d25f58c1be638031280e04514287d4 (patch)
tree4cff1bcbeb40698df1bbdff7c06cd3a089bcc205 /drivers/net/wireless/wl1251/boot.c
parentf03ee1ec73d8cad07b0ef5ba6106a9fc4d179ecb (diff)
wl1251: move to it's own directory
wl1271 driver is under heavy development but on the other hand the older wl1251 driver is currently considered more as a legacy driver. To make it easier to develop wl1271 features move wl1251 to it's own directory, drivers/net/wireless/wl1251. There are no functional changes, only moving of files. One regression is that Kconfig won't be updated automatically and user needs to enable wl1251 manually with an older config file. Signed-off-by: Kalle Valo <kvalo@adurom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/wl1251/boot.c')
-rw-r--r--drivers/net/wireless/wl1251/boot.c557
1 files changed, 557 insertions, 0 deletions
diff --git a/drivers/net/wireless/wl1251/boot.c b/drivers/net/wireless/wl1251/boot.c
new file mode 100644
index 000000000000..61572dfa1f60
--- /dev/null
+++ b/drivers/net/wireless/wl1251/boot.c
@@ -0,0 +1,557 @@
1/*
2 * This file is part of wl1251
3 *
4 * Copyright (C) 2008 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/gpio.h>
23#include <linux/slab.h>
24
25#include "reg.h"
26#include "boot.h"
27#include "io.h"
28#include "spi.h"
29#include "event.h"
30#include "acx.h"
31
32void wl1251_boot_target_enable_interrupts(struct wl1251 *wl)
33{
34 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
35 wl1251_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
36}
37
38int wl1251_boot_soft_reset(struct wl1251 *wl)
39{
40 unsigned long timeout;
41 u32 boot_data;
42
43 /* perform soft reset */
44 wl1251_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
45
46 /* SOFT_RESET is self clearing */
47 timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
48 while (1) {
49 boot_data = wl1251_reg_read32(wl, ACX_REG_SLV_SOFT_RESET);
50 wl1251_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
51 if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
52 break;
53
54 if (time_after(jiffies, timeout)) {
55 /* 1.2 check pWhalBus->uSelfClearTime if the
56 * timeout was reached */
57 wl1251_error("soft reset timeout");
58 return -1;
59 }
60
61 udelay(SOFT_RESET_STALL_TIME);
62 }
63
64 /* disable Rx/Tx */
65 wl1251_reg_write32(wl, ENABLE, 0x0);
66
67 /* disable auto calibration on start*/
68 wl1251_reg_write32(wl, SPARE_A2, 0xffff);
69
70 return 0;
71}
72
73int wl1251_boot_init_seq(struct wl1251 *wl)
74{
75 u32 scr_pad6, init_data, tmp, elp_cmd, ref_freq;
76
77 /*
78 * col #1: INTEGER_DIVIDER
79 * col #2: FRACTIONAL_DIVIDER
80 * col #3: ATTN_BB
81 * col #4: ALPHA_BB
82 * col #5: STOP_TIME_BB
83 * col #6: BB_PLL_LOOP_FILTER
84 */
85 static const u32 LUT[REF_FREQ_NUM][LUT_PARAM_NUM] = {
86
87 { 83, 87381, 0xB, 5, 0xF00, 3}, /* REF_FREQ_19_2*/
88 { 61, 141154, 0xB, 5, 0x1450, 2}, /* REF_FREQ_26_0*/
89 { 41, 174763, 0xC, 6, 0x2D00, 1}, /* REF_FREQ_38_4*/
90 { 40, 0, 0xC, 6, 0x2EE0, 1}, /* REF_FREQ_40_0*/
91 { 47, 162280, 0xC, 6, 0x2760, 1} /* REF_FREQ_33_6 */
92 };
93
94 /* read NVS params */
95 scr_pad6 = wl1251_reg_read32(wl, SCR_PAD6);
96 wl1251_debug(DEBUG_BOOT, "scr_pad6 0x%x", scr_pad6);
97
98 /* read ELP_CMD */
99 elp_cmd = wl1251_reg_read32(wl, ELP_CMD);
100 wl1251_debug(DEBUG_BOOT, "elp_cmd 0x%x", elp_cmd);
101
102 /* set the BB calibration time to be 300 usec (PLL_CAL_TIME) */
103 ref_freq = scr_pad6 & 0x000000FF;
104 wl1251_debug(DEBUG_BOOT, "ref_freq 0x%x", ref_freq);
105
106 wl1251_reg_write32(wl, PLL_CAL_TIME, 0x9);
107
108 /*
109 * PG 1.2: set the clock buffer time to be 210 usec (CLK_BUF_TIME)
110 */
111 wl1251_reg_write32(wl, CLK_BUF_TIME, 0x6);
112
113 /*
114 * set the clock detect feature to work in the restart wu procedure
115 * (ELP_CFG_MODE[14]) and Select the clock source type
116 * (ELP_CFG_MODE[13:12])
117 */
118 tmp = ((scr_pad6 & 0x0000FF00) << 4) | 0x00004000;
119 wl1251_reg_write32(wl, ELP_CFG_MODE, tmp);
120
121 /* PG 1.2: enable the BB PLL fix. Enable the PLL_LIMP_CLK_EN_CMD */
122 elp_cmd |= 0x00000040;
123 wl1251_reg_write32(wl, ELP_CMD, elp_cmd);
124
125 /* PG 1.2: Set the BB PLL stable time to be 1000usec
126 * (PLL_STABLE_TIME) */
127 wl1251_reg_write32(wl, CFG_PLL_SYNC_CNT, 0x20);
128
129 /* PG 1.2: read clock request time */
130 init_data = wl1251_reg_read32(wl, CLK_REQ_TIME);
131
132 /*
133 * PG 1.2: set the clock request time to be ref_clk_settling_time -
134 * 1ms = 4ms
135 */
136 if (init_data > 0x21)
137 tmp = init_data - 0x21;
138 else
139 tmp = 0;
140 wl1251_reg_write32(wl, CLK_REQ_TIME, tmp);
141
142 /* set BB PLL configurations in RF AFE */
143 wl1251_reg_write32(wl, 0x003058cc, 0x4B5);
144
145 /* set RF_AFE_REG_5 */
146 wl1251_reg_write32(wl, 0x003058d4, 0x50);
147
148 /* set RF_AFE_CTRL_REG_2 */
149 wl1251_reg_write32(wl, 0x00305948, 0x11c001);
150
151 /*
152 * change RF PLL and BB PLL divider for VCO clock and adjust VCO
153 * bais current(RF_AFE_REG_13)
154 */
155 wl1251_reg_write32(wl, 0x003058f4, 0x1e);
156
157 /* set BB PLL configurations */
158 tmp = LUT[ref_freq][LUT_PARAM_INTEGER_DIVIDER] | 0x00017000;
159 wl1251_reg_write32(wl, 0x00305840, tmp);
160
161 /* set fractional divider according to Appendix C-BB PLL
162 * Calculations
163 */
164 tmp = LUT[ref_freq][LUT_PARAM_FRACTIONAL_DIVIDER];
165 wl1251_reg_write32(wl, 0x00305844, tmp);
166
167 /* set the initial data for the sigma delta */
168 wl1251_reg_write32(wl, 0x00305848, 0x3039);
169
170 /*
171 * set the accumulator attenuation value, calibration loop1
172 * (alpha), calibration loop2 (beta), calibration loop3 (gamma) and
173 * the VCO gain
174 */
175 tmp = (LUT[ref_freq][LUT_PARAM_ATTN_BB] << 16) |
176 (LUT[ref_freq][LUT_PARAM_ALPHA_BB] << 12) | 0x1;
177 wl1251_reg_write32(wl, 0x00305854, tmp);
178
179 /*
180 * set the calibration stop time after holdoff time expires and set
181 * settling time HOLD_OFF_TIME_BB
182 */
183 tmp = LUT[ref_freq][LUT_PARAM_STOP_TIME_BB] | 0x000A0000;
184 wl1251_reg_write32(wl, 0x00305858, tmp);
185
186 /*
187 * set BB PLL Loop filter capacitor3- BB_C3[2:0] and set BB PLL
188 * constant leakage current to linearize PFD to 0uA -
189 * BB_ILOOPF[7:3]
190 */
191 tmp = LUT[ref_freq][LUT_PARAM_BB_PLL_LOOP_FILTER] | 0x00000030;
192 wl1251_reg_write32(wl, 0x003058f8, tmp);
193
194 /*
195 * set regulator output voltage for n divider to
196 * 1.35-BB_REFDIV[1:0], set charge pump current- BB_CPGAIN[4:2],
197 * set BB PLL Loop filter capacitor2- BB_C2[7:5], set gain of BB
198 * PLL auto-call to normal mode- BB_CALGAIN_3DB[8]
199 */
200 wl1251_reg_write32(wl, 0x003058f0, 0x29);
201
202 /* enable restart wakeup sequence (ELP_CMD[0]) */
203 wl1251_reg_write32(wl, ELP_CMD, elp_cmd | 0x1);
204
205 /* restart sequence completed */
206 udelay(2000);
207
208 return 0;
209}
210
211static void wl1251_boot_set_ecpu_ctrl(struct wl1251 *wl, u32 flag)
212{
213 u32 cpu_ctrl;
214
215 /* 10.5.0 run the firmware (I) */
216 cpu_ctrl = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
217
218 /* 10.5.1 run the firmware (II) */
219 cpu_ctrl &= ~flag;
220 wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
221}
222
223int wl1251_boot_run_firmware(struct wl1251 *wl)
224{
225 int loop, ret;
226 u32 chip_id, acx_intr;
227
228 wl1251_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
229
230 chip_id = wl1251_reg_read32(wl, CHIP_ID_B);
231
232 wl1251_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
233
234 if (chip_id != wl->chip_id) {
235 wl1251_error("chip id doesn't match after firmware boot");
236 return -EIO;
237 }
238
239 /* wait for init to complete */
240 loop = 0;
241 while (loop++ < INIT_LOOP) {
242 udelay(INIT_LOOP_DELAY);
243 acx_intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
244
245 if (acx_intr == 0xffffffff) {
246 wl1251_error("error reading hardware complete "
247 "init indication");
248 return -EIO;
249 }
250 /* check that ACX_INTR_INIT_COMPLETE is enabled */
251 else if (acx_intr & WL1251_ACX_INTR_INIT_COMPLETE) {
252 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
253 WL1251_ACX_INTR_INIT_COMPLETE);
254 break;
255 }
256 }
257
258 if (loop > INIT_LOOP) {
259 wl1251_error("timeout waiting for the hardware to "
260 "complete initialization");
261 return -EIO;
262 }
263
264 /* get hardware config command mail box */
265 wl->cmd_box_addr = wl1251_reg_read32(wl, REG_COMMAND_MAILBOX_PTR);
266
267 /* get hardware config event mail box */
268 wl->event_box_addr = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
269
270 /* set the working partition to its "running" mode offset */
271 wl1251_set_partition(wl, WL1251_PART_WORK_MEM_START,
272 WL1251_PART_WORK_MEM_SIZE,
273 WL1251_PART_WORK_REG_START,
274 WL1251_PART_WORK_REG_SIZE);
275
276 wl1251_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
277 wl->cmd_box_addr, wl->event_box_addr);
278
279 wl1251_acx_fw_version(wl, wl->fw_ver, sizeof(wl->fw_ver));
280
281 /*
282 * in case of full asynchronous mode the firmware event must be
283 * ready to receive event from the command mailbox
284 */
285
286 /* enable gpio interrupts */
287 wl1251_enable_interrupts(wl);
288
289 /* Enable target's interrupts */
290 wl->intr_mask = WL1251_ACX_INTR_RX0_DATA |
291 WL1251_ACX_INTR_RX1_DATA |
292 WL1251_ACX_INTR_TX_RESULT |
293 WL1251_ACX_INTR_EVENT_A |
294 WL1251_ACX_INTR_EVENT_B |
295 WL1251_ACX_INTR_INIT_COMPLETE;
296 wl1251_boot_target_enable_interrupts(wl);
297
298 wl->event_mask = SCAN_COMPLETE_EVENT_ID | BSS_LOSE_EVENT_ID |
299 SYNCHRONIZATION_TIMEOUT_EVENT_ID |
300 ROAMING_TRIGGER_LOW_RSSI_EVENT_ID |
301 ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID |
302 REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID |
303 BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID;
304
305 ret = wl1251_event_unmask(wl);
306 if (ret < 0) {
307 wl1251_error("EVENT mask setting failed");
308 return ret;
309 }
310
311 wl1251_event_mbox_config(wl);
312
313 /* firmware startup completed */
314 return 0;
315}
316
317static int wl1251_boot_upload_firmware(struct wl1251 *wl)
318{
319 int addr, chunk_num, partition_limit;
320 size_t fw_data_len, len;
321 u8 *p, *buf;
322
323 /* whal_FwCtrl_LoadFwImageSm() */
324
325 wl1251_debug(DEBUG_BOOT, "chip id before fw upload: 0x%x",
326 wl1251_reg_read32(wl, CHIP_ID_B));
327
328 /* 10.0 check firmware length and set partition */
329 fw_data_len = (wl->fw[4] << 24) | (wl->fw[5] << 16) |
330 (wl->fw[6] << 8) | (wl->fw[7]);
331
332 wl1251_debug(DEBUG_BOOT, "fw_data_len %zu chunk_size %d", fw_data_len,
333 CHUNK_SIZE);
334
335 if ((fw_data_len % 4) != 0) {
336 wl1251_error("firmware length not multiple of four");
337 return -EIO;
338 }
339
340 buf = kmalloc(CHUNK_SIZE, GFP_KERNEL);
341 if (!buf) {
342 wl1251_error("allocation for firmware upload chunk failed");
343 return -ENOMEM;
344 }
345
346 wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START,
347 WL1251_PART_DOWN_MEM_SIZE,
348 WL1251_PART_DOWN_REG_START,
349 WL1251_PART_DOWN_REG_SIZE);
350
351 /* 10.1 set partition limit and chunk num */
352 chunk_num = 0;
353 partition_limit = WL1251_PART_DOWN_MEM_SIZE;
354
355 while (chunk_num < fw_data_len / CHUNK_SIZE) {
356 /* 10.2 update partition, if needed */
357 addr = WL1251_PART_DOWN_MEM_START +
358 (chunk_num + 2) * CHUNK_SIZE;
359 if (addr > partition_limit) {
360 addr = WL1251_PART_DOWN_MEM_START +
361 chunk_num * CHUNK_SIZE;
362 partition_limit = chunk_num * CHUNK_SIZE +
363 WL1251_PART_DOWN_MEM_SIZE;
364 wl1251_set_partition(wl,
365 addr,
366 WL1251_PART_DOWN_MEM_SIZE,
367 WL1251_PART_DOWN_REG_START,
368 WL1251_PART_DOWN_REG_SIZE);
369 }
370
371 /* 10.3 upload the chunk */
372 addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
373 p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
374 wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
375 p, addr);
376
377 /* need to copy the chunk for dma */
378 len = CHUNK_SIZE;
379 memcpy(buf, p, len);
380 wl1251_mem_write(wl, addr, buf, len);
381
382 chunk_num++;
383 }
384
385 /* 10.4 upload the last chunk */
386 addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
387 p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
388
389 /* need to copy the chunk for dma */
390 len = fw_data_len % CHUNK_SIZE;
391 memcpy(buf, p, len);
392
393 wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x",
394 len, p, addr);
395 wl1251_mem_write(wl, addr, buf, len);
396
397 kfree(buf);
398
399 return 0;
400}
401
402static int wl1251_boot_upload_nvs(struct wl1251 *wl)
403{
404 size_t nvs_len, nvs_bytes_written, burst_len;
405 int nvs_start, i;
406 u32 dest_addr, val;
407 u8 *nvs_ptr, *nvs;
408
409 nvs = wl->nvs;
410 if (nvs == NULL)
411 return -ENODEV;
412
413 nvs_ptr = nvs;
414
415 nvs_len = wl->nvs_len;
416 nvs_start = wl->fw_len;
417
418 /*
419 * Layout before the actual NVS tables:
420 * 1 byte : burst length.
421 * 2 bytes: destination address.
422 * n bytes: data to burst copy.
423 *
424 * This is ended by a 0 length, then the NVS tables.
425 */
426
427 while (nvs_ptr[0]) {
428 burst_len = nvs_ptr[0];
429 dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
430
431 /* We move our pointer to the data */
432 nvs_ptr += 3;
433
434 for (i = 0; i < burst_len; i++) {
435 val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
436 | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
437
438 wl1251_debug(DEBUG_BOOT,
439 "nvs burst write 0x%x: 0x%x",
440 dest_addr, val);
441 wl1251_mem_write32(wl, dest_addr, val);
442
443 nvs_ptr += 4;
444 dest_addr += 4;
445 }
446 }
447
448 /*
449 * We've reached the first zero length, the first NVS table
450 * is 7 bytes further.
451 */
452 nvs_ptr += 7;
453 nvs_len -= nvs_ptr - nvs;
454 nvs_len = ALIGN(nvs_len, 4);
455
456 /* Now we must set the partition correctly */
457 wl1251_set_partition(wl, nvs_start,
458 WL1251_PART_DOWN_MEM_SIZE,
459 WL1251_PART_DOWN_REG_START,
460 WL1251_PART_DOWN_REG_SIZE);
461
462 /* And finally we upload the NVS tables */
463 nvs_bytes_written = 0;
464 while (nvs_bytes_written < nvs_len) {
465 val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
466 | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
467
468 val = cpu_to_le32(val);
469
470 wl1251_debug(DEBUG_BOOT,
471 "nvs write table 0x%x: 0x%x",
472 nvs_start, val);
473 wl1251_mem_write32(wl, nvs_start, val);
474
475 nvs_ptr += 4;
476 nvs_bytes_written += 4;
477 nvs_start += 4;
478 }
479
480 return 0;
481}
482
483int wl1251_boot(struct wl1251 *wl)
484{
485 int ret = 0, minor_minor_e2_ver;
486 u32 tmp, boot_data;
487
488 /* halt embedded ARM CPU while loading firmware */
489 wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, ECPU_CONTROL_HALT);
490
491 ret = wl1251_boot_soft_reset(wl);
492 if (ret < 0)
493 goto out;
494
495 /* 2. start processing NVS file */
496 if (wl->use_eeprom) {
497 wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR);
498 /* Wait for EEPROM NVS burst read to complete */
499 msleep(40);
500 wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM);
501 } else {
502 ret = wl1251_boot_upload_nvs(wl);
503 if (ret < 0)
504 goto out;
505
506 /* write firmware's last address (ie. it's length) to
507 * ACX_EEPROMLESS_IND_REG */
508 wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len);
509 }
510
511 /* 6. read the EEPROM parameters */
512 tmp = wl1251_reg_read32(wl, SCR_PAD2);
513
514 /* 7. read bootdata */
515 wl->boot_attr.radio_type = (tmp & 0x0000FF00) >> 8;
516 wl->boot_attr.major = (tmp & 0x00FF0000) >> 16;
517 tmp = wl1251_reg_read32(wl, SCR_PAD3);
518
519 /* 8. check bootdata and call restart sequence */
520 wl->boot_attr.minor = (tmp & 0x00FF0000) >> 16;
521 minor_minor_e2_ver = (tmp & 0xFF000000) >> 24;
522
523 wl1251_debug(DEBUG_BOOT, "radioType 0x%x majorE2Ver 0x%x "
524 "minorE2Ver 0x%x minor_minor_e2_ver 0x%x",
525 wl->boot_attr.radio_type, wl->boot_attr.major,
526 wl->boot_attr.minor, minor_minor_e2_ver);
527
528 ret = wl1251_boot_init_seq(wl);
529 if (ret < 0)
530 goto out;
531
532 /* 9. NVS processing done */
533 boot_data = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
534
535 wl1251_debug(DEBUG_BOOT, "halt boot_data 0x%x", boot_data);
536
537 /* 10. check that ECPU_CONTROL_HALT bits are set in
538 * pWhalBus->uBootData and start uploading firmware
539 */
540 if ((boot_data & ECPU_CONTROL_HALT) == 0) {
541 wl1251_error("boot failed, ECPU_CONTROL_HALT not set");
542 ret = -EIO;
543 goto out;
544 }
545
546 ret = wl1251_boot_upload_firmware(wl);
547 if (ret < 0)
548 goto out;
549
550 /* 10.5 start firmware */
551 ret = wl1251_boot_run_firmware(wl);
552 if (ret < 0)
553 goto out;
554
555out:
556 return ret;
557}