aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/wl1271_boot.c
diff options
context:
space:
mode:
authorLuciano Coelho <luciano.coelho@nokia.com>2009-08-06 09:25:28 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:12:46 -0400
commitf5fc0f86b02afef1119b523623b4cde41475bc8c (patch)
tree793be075412781fef4fcd752032e9b3680eaf96f /drivers/net/wireless/wl12xx/wl1271_boot.c
parentb935df01ed4f0848f29b1e39c4f95d87b0206dea (diff)
wl1271: add wl1271 driver files
This driver supports the wl1271 chipset from Texas Instruments based on the WiLink(tm) 6.0 mobile platform. Support for wl1273 should be relatively easy to add. This chipset is designed for embedded devices, with good powersaving capabilities. The wl1271 chipset is the successor of wl1251 and supports the 802.11b/g/n standards, but currently this driver supports only b/g. More information about this chipset can be found here: http://focus.ti.com/general/docs/wtbu/wtbuproductcontent.tsp?templateId=6123&navigationId=12762&contentId=29993 Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_boot.c')
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_boot.c540
1 files changed, 540 insertions, 0 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
new file mode 100644
index 000000000000..4c22f25fd8f0
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -0,0 +1,540 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/gpio.h>
25
26#include "wl1271_acx.h"
27#include "wl1271_reg.h"
28#include "wl1271_boot.h"
29#include "wl1271_spi.h"
30#include "wl1271_event.h"
31
32static struct wl1271_partition_set part_table[PART_TABLE_LEN] = {
33 [PART_DOWN] = {
34 .mem = {
35 .start = 0x00000000,
36 .size = 0x000177c0
37 },
38 .reg = {
39 .start = REGISTERS_BASE,
40 .size = 0x00008800
41 },
42 },
43
44 [PART_WORK] = {
45 .mem = {
46 .start = 0x00040000,
47 .size = 0x00014fc0
48 },
49 .reg = {
50 .start = REGISTERS_BASE,
51 .size = 0x0000b000
52 },
53 },
54
55 [PART_DRPW] = {
56 .mem = {
57 .start = 0x00040000,
58 .size = 0x00014fc0
59 },
60 .reg = {
61 .start = DRPW_BASE,
62 .size = 0x00006000
63 }
64 }
65};
66
67static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
68{
69 u32 cpu_ctrl;
70
71 /* 10.5.0 run the firmware (I) */
72 cpu_ctrl = wl1271_reg_read32(wl, ACX_REG_ECPU_CONTROL);
73
74 /* 10.5.1 run the firmware (II) */
75 cpu_ctrl |= flag;
76 wl1271_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
77}
78
79static void wl1271_boot_fw_version(struct wl1271 *wl)
80{
81 struct wl1271_static_data static_data;
82
83 wl1271_spi_mem_read(wl, wl->cmd_box_addr,
84 &static_data, sizeof(static_data));
85
86 strncpy(wl->chip.fw_ver, static_data.fw_version,
87 sizeof(wl->chip.fw_ver));
88
89 /* make sure the string is NULL-terminated */
90 wl->chip.fw_ver[sizeof(wl->chip.fw_ver) - 1] = '\0';
91}
92
93static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
94 size_t fw_data_len, u32 dest)
95{
96 int addr, chunk_num, partition_limit;
97 u8 *p;
98
99 /* whal_FwCtrl_LoadFwImageSm() */
100
101 wl1271_debug(DEBUG_BOOT, "starting firmware upload");
102
103 wl1271_debug(DEBUG_BOOT, "fw_data_len %d chunk_size %d", fw_data_len,
104 CHUNK_SIZE);
105
106
107 if ((fw_data_len % 4) != 0) {
108 wl1271_error("firmware length not multiple of four");
109 return -EIO;
110 }
111
112 wl1271_set_partition(wl, dest,
113 part_table[PART_DOWN].mem.size,
114 part_table[PART_DOWN].reg.start,
115 part_table[PART_DOWN].reg.size);
116
117 /* 10.1 set partition limit and chunk num */
118 chunk_num = 0;
119 partition_limit = part_table[PART_DOWN].mem.size;
120
121 while (chunk_num < fw_data_len / CHUNK_SIZE) {
122 /* 10.2 update partition, if needed */
123 addr = dest + (chunk_num + 2) * CHUNK_SIZE;
124 if (addr > partition_limit) {
125 addr = dest + chunk_num * CHUNK_SIZE;
126 partition_limit = chunk_num * CHUNK_SIZE +
127 part_table[PART_DOWN].mem.size;
128
129 /* FIXME: Over 80 chars! */
130 wl1271_set_partition(wl,
131 addr,
132 part_table[PART_DOWN].mem.size,
133 part_table[PART_DOWN].reg.start,
134 part_table[PART_DOWN].reg.size);
135 }
136
137 /* 10.3 upload the chunk */
138 addr = dest + chunk_num * CHUNK_SIZE;
139 p = buf + chunk_num * CHUNK_SIZE;
140 wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
141 p, addr);
142 wl1271_spi_mem_write(wl, addr, p, CHUNK_SIZE);
143
144 chunk_num++;
145 }
146
147 /* 10.4 upload the last chunk */
148 addr = dest + chunk_num * CHUNK_SIZE;
149 p = buf + chunk_num * CHUNK_SIZE;
150 wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%d B) 0x%p to 0x%x",
151 fw_data_len % CHUNK_SIZE, p, addr);
152 wl1271_spi_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE);
153
154 return 0;
155}
156
157static int wl1271_boot_upload_firmware(struct wl1271 *wl)
158{
159 u32 chunks, addr, len;
160 u8 *fw;
161
162 fw = wl->fw;
163 chunks = be32_to_cpup((u32 *) fw);
164 fw += sizeof(u32);
165
166 wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks);
167
168 while (chunks--) {
169 addr = be32_to_cpup((u32 *) fw);
170 fw += sizeof(u32);
171 len = be32_to_cpup((u32 *) fw);
172 fw += sizeof(u32);
173
174 if (len > 300000) {
175 wl1271_info("firmware chunk too long: %u", len);
176 return -EINVAL;
177 }
178 wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u",
179 chunks, addr, len);
180 wl1271_boot_upload_firmware_chunk(wl, fw, len, addr);
181 fw += len;
182 }
183
184 return 0;
185}
186
187static int wl1271_boot_upload_nvs(struct wl1271 *wl)
188{
189 size_t nvs_len, burst_len;
190 int i;
191 u32 dest_addr, val;
192 u8 *nvs_ptr, *nvs, *nvs_aligned;
193
194 nvs = wl->nvs;
195 if (nvs == NULL)
196 return -ENODEV;
197
198 nvs_ptr = nvs;
199
200 nvs_len = wl->nvs_len;
201
202 /* Update the device MAC address into the nvs */
203 nvs[11] = wl->mac_addr[0];
204 nvs[10] = wl->mac_addr[1];
205 nvs[6] = wl->mac_addr[2];
206 nvs[5] = wl->mac_addr[3];
207 nvs[4] = wl->mac_addr[4];
208 nvs[3] = wl->mac_addr[5];
209
210 /*
211 * Layout before the actual NVS tables:
212 * 1 byte : burst length.
213 * 2 bytes: destination address.
214 * n bytes: data to burst copy.
215 *
216 * This is ended by a 0 length, then the NVS tables.
217 */
218
219 /* FIXME: Do we need to check here whether the LSB is 1? */
220 while (nvs_ptr[0]) {
221 burst_len = nvs_ptr[0];
222 dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
223
224 /* FIXME: Due to our new wl1271_translate_reg_addr function,
225 we need to add the REGISTER_BASE to the destination */
226 dest_addr += REGISTERS_BASE;
227
228 /* We move our pointer to the data */
229 nvs_ptr += 3;
230
231 for (i = 0; i < burst_len; i++) {
232 val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
233 | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
234
235 wl1271_debug(DEBUG_BOOT,
236 "nvs burst write 0x%x: 0x%x",
237 dest_addr, val);
238 wl1271_reg_write32(wl, dest_addr, val);
239
240 nvs_ptr += 4;
241 dest_addr += 4;
242 }
243 }
244
245 /*
246 * We've reached the first zero length, the first NVS table
247 * is 7 bytes further.
248 */
249 nvs_ptr += 7;
250 nvs_len -= nvs_ptr - nvs;
251 nvs_len = ALIGN(nvs_len, 4);
252
253 /* FIXME: The driver sets the partition here, but this is not needed,
254 since it sets to the same one as currently in use */
255 /* Now we must set the partition correctly */
256 wl1271_set_partition(wl,
257 part_table[PART_WORK].mem.start,
258 part_table[PART_WORK].mem.size,
259 part_table[PART_WORK].reg.start,
260 part_table[PART_WORK].reg.size);
261
262 /* Copy the NVS tables to a new block to ensure alignment */
263 nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
264
265 /* And finally we upload the NVS tables */
266 /* FIXME: In wl1271, we upload everything at once.
267 No endianness handling needed here?! The ref driver doesn't do
268 anything about it at this point */
269 wl1271_spi_mem_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len);
270
271 kfree(nvs_aligned);
272 return 0;
273}
274
275static void wl1271_boot_enable_interrupts(struct wl1271 *wl)
276{
277 enable_irq(wl->irq);
278 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(WL1271_INTR_MASK));
279 wl1271_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
280}
281
282static int wl1271_boot_soft_reset(struct wl1271 *wl)
283{
284 unsigned long timeout;
285 u32 boot_data;
286
287 /* perform soft reset */
288 wl1271_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
289
290 /* SOFT_RESET is self clearing */
291 timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
292 while (1) {
293 boot_data = wl1271_reg_read32(wl, ACX_REG_SLV_SOFT_RESET);
294 wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
295 if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
296 break;
297
298 if (time_after(jiffies, timeout)) {
299 /* 1.2 check pWhalBus->uSelfClearTime if the
300 * timeout was reached */
301 wl1271_error("soft reset timeout");
302 return -1;
303 }
304
305 udelay(SOFT_RESET_STALL_TIME);
306 }
307
308 /* disable Rx/Tx */
309 wl1271_reg_write32(wl, ENABLE, 0x0);
310
311 /* disable auto calibration on start*/
312 wl1271_reg_write32(wl, SPARE_A2, 0xffff);
313
314 return 0;
315}
316
317static int wl1271_boot_run_firmware(struct wl1271 *wl)
318{
319 int loop, ret;
320 u32 chip_id, interrupt;
321
322 wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
323
324 chip_id = wl1271_reg_read32(wl, CHIP_ID_B);
325
326 wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
327
328 if (chip_id != wl->chip.id) {
329 wl1271_error("chip id doesn't match after firmware boot");
330 return -EIO;
331 }
332
333 /* wait for init to complete */
334 loop = 0;
335 while (loop++ < INIT_LOOP) {
336 udelay(INIT_LOOP_DELAY);
337 interrupt = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
338
339 if (interrupt == 0xffffffff) {
340 wl1271_error("error reading hardware complete "
341 "init indication");
342 return -EIO;
343 }
344 /* check that ACX_INTR_INIT_COMPLETE is enabled */
345 else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) {
346 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
347 WL1271_ACX_INTR_INIT_COMPLETE);
348 break;
349 }
350 }
351
352 if (loop >= INIT_LOOP) {
353 wl1271_error("timeout waiting for the hardware to "
354 "complete initialization");
355 return -EIO;
356 }
357
358 /* get hardware config command mail box */
359 wl->cmd_box_addr = wl1271_reg_read32(wl, REG_COMMAND_MAILBOX_PTR);
360
361 /* get hardware config event mail box */
362 wl->event_box_addr = wl1271_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
363
364 /* set the working partition to its "running" mode offset */
365 wl1271_set_partition(wl,
366 part_table[PART_WORK].mem.start,
367 part_table[PART_WORK].mem.size,
368 part_table[PART_WORK].reg.start,
369 part_table[PART_WORK].reg.size);
370
371 wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
372 wl->cmd_box_addr, wl->event_box_addr);
373
374 wl1271_boot_fw_version(wl);
375
376 /*
377 * in case of full asynchronous mode the firmware event must be
378 * ready to receive event from the command mailbox
379 */
380
381 /* enable gpio interrupts */
382 wl1271_boot_enable_interrupts(wl);
383
384 /* unmask all mbox events */
385 wl->event_mask = 0xffffffff;
386
387 ret = wl1271_event_unmask(wl);
388 if (ret < 0) {
389 wl1271_error("EVENT mask setting failed");
390 return ret;
391 }
392
393 wl1271_event_mbox_config(wl);
394
395 /* firmware startup completed */
396 return 0;
397}
398
399static int wl1271_boot_write_irq_polarity(struct wl1271 *wl)
400{
401 u32 polarity, status, i;
402
403 wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY);
404 wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_READ);
405
406 /* Wait until the command is complete (ie. bit 18 is set) */
407 for (i = 0; i < OCP_CMD_LOOP; i++) {
408 polarity = wl1271_reg_read32(wl, OCP_DATA_READ);
409 if (polarity & OCP_READY_MASK)
410 break;
411 }
412 if (i == OCP_CMD_LOOP) {
413 wl1271_error("OCP command timeout!");
414 return -EIO;
415 }
416
417 status = polarity & OCP_STATUS_MASK;
418 if (status != OCP_STATUS_OK) {
419 wl1271_error("OCP command failed (%d)", status);
420 return -EIO;
421 }
422
423 /* We use HIGH polarity, so unset the LOW bit */
424 polarity &= ~POLARITY_LOW;
425
426 wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY);
427 wl1271_reg_write32(wl, OCP_DATA_WRITE, polarity);
428 wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_WRITE);
429
430 return 0;
431}
432
433int wl1271_boot(struct wl1271 *wl)
434{
435 int ret = 0;
436 u32 tmp, clk, pause;
437
438 if (REF_CLOCK == 0 || REF_CLOCK == 2)
439 /* ref clk: 19.2/38.4 */
440 clk = 0x3;
441 else if (REF_CLOCK == 1 || REF_CLOCK == 3)
442 /* ref clk: 26/52 */
443 clk = 0x5;
444
445 wl1271_reg_write32(wl, PLL_PARAMETERS, clk);
446
447 pause = wl1271_reg_read32(wl, PLL_PARAMETERS);
448
449 wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
450
451 pause &= ~(WU_COUNTER_PAUSE_VAL); /* FIXME: This should probably be
452 * WU_COUNTER_PAUSE_VAL instead of
453 * 0x3ff (magic number ). How does
454 * this work?! */
455 pause |= WU_COUNTER_PAUSE_VAL;
456 wl1271_reg_write32(wl, WU_COUNTER_PAUSE, pause);
457
458 /* Continue the ELP wake up sequence */
459 wl1271_reg_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
460 udelay(500);
461
462 wl1271_set_partition(wl,
463 part_table[PART_DRPW].mem.start,
464 part_table[PART_DRPW].mem.size,
465 part_table[PART_DRPW].reg.start,
466 part_table[PART_DRPW].reg.size);
467
468 /* Read-modify-write DRPW_SCRATCH_START register (see next state)
469 to be used by DRPw FW. The RTRIM value will be added by the FW
470 before taking DRPw out of reset */
471
472 wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START);
473 clk = wl1271_reg_read32(wl, DRPW_SCRATCH_START);
474
475 wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
476
477 /* 2 */
478 clk |= (REF_CLOCK << 1) << 4;
479 wl1271_reg_write32(wl, DRPW_SCRATCH_START, clk);
480
481 wl1271_set_partition(wl,
482 part_table[PART_WORK].mem.start,
483 part_table[PART_WORK].mem.size,
484 part_table[PART_WORK].reg.start,
485 part_table[PART_WORK].reg.size);
486
487 /* Disable interrupts */
488 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
489
490 ret = wl1271_boot_soft_reset(wl);
491 if (ret < 0)
492 goto out;
493
494 /* 2. start processing NVS file */
495 ret = wl1271_boot_upload_nvs(wl);
496 if (ret < 0)
497 goto out;
498
499 /* write firmware's last address (ie. it's length) to
500 * ACX_EEPROMLESS_IND_REG */
501 wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");
502
503 wl1271_reg_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG);
504
505 tmp = wl1271_reg_read32(wl, CHIP_ID_B);
506
507 wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
508
509 /* 6. read the EEPROM parameters */
510 tmp = wl1271_reg_read32(wl, SCR_PAD2);
511
512 ret = wl1271_boot_write_irq_polarity(wl);
513 if (ret < 0)
514 goto out;
515
516 /* FIXME: Need to check whether this is really what we want */
517 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
518 WL1271_ACX_ALL_EVENTS_VECTOR);
519
520 /* WL1271: The reference driver skips steps 7 to 10 (jumps directly
521 * to upload_fw) */
522
523 ret = wl1271_boot_upload_firmware(wl);
524 if (ret < 0)
525 goto out;
526
527 /* 10.5 start firmware */
528 ret = wl1271_boot_run_firmware(wl);
529 if (ret < 0)
530 goto out;
531
532 /* set the wl1271 default filters */
533 wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
534 wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
535
536 wl1271_event_mbox_config(wl);
537
538out:
539 return ret;
540}