aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/boot.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-05-05 13:32:35 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-05-05 13:32:35 -0400
commita70171dce9cd44cb06c7d299eba9fa87a8933045 (patch)
tree5425df5f33fadc617c7dec99578d06f0d933578e /drivers/net/wireless/wl12xx/boot.c
parent5a412ad7f4c95bb5b756aa12b52646e857e7c75d (diff)
parenteaef6a93bd52a2cc47b9fce201310010707afdb4 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts: drivers/net/wireless/libertas/if_cs.c drivers/net/wireless/rtlwifi/pci.c net/bluetooth/l2cap_sock.c
Diffstat (limited to 'drivers/net/wireless/wl12xx/boot.c')
-rw-r--r--drivers/net/wireless/wl12xx/boot.c285
1 files changed, 240 insertions, 45 deletions
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 6934dffd5174..d263ebb6f974 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -22,6 +22,7 @@
22 */ 22 */
23 23
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/wl12xx.h>
25 26
26#include "acx.h" 27#include "acx.h"
27#include "reg.h" 28#include "reg.h"
@@ -243,33 +244,57 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
243 if (wl->nvs == NULL) 244 if (wl->nvs == NULL)
244 return -ENODEV; 245 return -ENODEV;
245 246
246 /* 247 if (wl->chip.id == CHIP_ID_1283_PG20) {
247 * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band 248 struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs;
248 * configurations) can be removed when those NVS files stop floating 249
249 * around. 250 if (wl->nvs_len == sizeof(struct wl128x_nvs_file)) {
250 */ 251 if (nvs->general_params.dual_mode_select)
251 if (wl->nvs_len == sizeof(struct wl1271_nvs_file) || 252 wl->enable_11a = true;
252 wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) { 253 } else {
253 /* for now 11a is unsupported in AP mode */ 254 wl1271_error("nvs size is not as expected: %zu != %zu",
254 if (wl->bss_type != BSS_TYPE_AP_BSS && 255 wl->nvs_len,
255 wl->nvs->general_params.dual_mode_select) 256 sizeof(struct wl128x_nvs_file));
256 wl->enable_11a = true; 257 kfree(wl->nvs);
257 } 258 wl->nvs = NULL;
259 wl->nvs_len = 0;
260 return -EILSEQ;
261 }
258 262
259 if (wl->nvs_len != sizeof(struct wl1271_nvs_file) && 263 /* only the first part of the NVS needs to be uploaded */
260 (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE || 264 nvs_len = sizeof(nvs->nvs);
261 wl->enable_11a)) { 265 nvs_ptr = (u8 *)nvs->nvs;
262 wl1271_error("nvs size is not as expected: %zu != %zu", 266
263 wl->nvs_len, sizeof(struct wl1271_nvs_file)); 267 } else {
264 kfree(wl->nvs); 268 struct wl1271_nvs_file *nvs =
265 wl->nvs = NULL; 269 (struct wl1271_nvs_file *)wl->nvs;
266 wl->nvs_len = 0; 270 /*
267 return -EILSEQ; 271 * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz
268 } 272 * band configurations) can be removed when those NVS files stop
273 * floating around.
274 */
275 if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
276 wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
277 /* for now 11a is unsupported in AP mode */
278 if (wl->bss_type != BSS_TYPE_AP_BSS &&
279 nvs->general_params.dual_mode_select)
280 wl->enable_11a = true;
281 }
269 282
270 /* only the first part of the NVS needs to be uploaded */ 283 if (wl->nvs_len != sizeof(struct wl1271_nvs_file) &&
271 nvs_len = sizeof(wl->nvs->nvs); 284 (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
272 nvs_ptr = (u8 *)wl->nvs->nvs; 285 wl->enable_11a)) {
286 wl1271_error("nvs size is not as expected: %zu != %zu",
287 wl->nvs_len, sizeof(struct wl1271_nvs_file));
288 kfree(wl->nvs);
289 wl->nvs = NULL;
290 wl->nvs_len = 0;
291 return -EILSEQ;
292 }
293
294 /* only the first part of the NVS needs to be uploaded */
295 nvs_len = sizeof(nvs->nvs);
296 nvs_ptr = (u8 *) nvs->nvs;
297 }
273 298
274 /* update current MAC address to NVS */ 299 /* update current MAC address to NVS */
275 nvs_ptr[11] = wl->mac_addr[0]; 300 nvs_ptr[11] = wl->mac_addr[0];
@@ -319,10 +344,13 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
319 /* 344 /*
320 * We've reached the first zero length, the first NVS table 345 * We've reached the first zero length, the first NVS table
321 * is located at an aligned offset which is at least 7 bytes further. 346 * is located at an aligned offset which is at least 7 bytes further.
347 * NOTE: The wl->nvs->nvs element must be first, in order to
348 * simplify the casting, we assume it is at the beginning of
349 * the wl->nvs structure.
322 */ 350 */
323 nvs_ptr = (u8 *)wl->nvs->nvs + 351 nvs_ptr = (u8 *)wl->nvs +
324 ALIGN(nvs_ptr - (u8 *)wl->nvs->nvs + 7, 4); 352 ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4);
325 nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs; 353 nvs_len -= nvs_ptr - (u8 *)wl->nvs;
326 354
327 /* Now we must set the partition correctly */ 355 /* Now we must set the partition correctly */
328 wl1271_set_partition(wl, &part_table[PART_WORK]); 356 wl1271_set_partition(wl, &part_table[PART_WORK]);
@@ -450,10 +478,14 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
450 DISCONNECT_EVENT_COMPLETE_ID | 478 DISCONNECT_EVENT_COMPLETE_ID |
451 RSSI_SNR_TRIGGER_0_EVENT_ID | 479 RSSI_SNR_TRIGGER_0_EVENT_ID |
452 PSPOLL_DELIVERY_FAILURE_EVENT_ID | 480 PSPOLL_DELIVERY_FAILURE_EVENT_ID |
453 SOFT_GEMINI_SENSE_EVENT_ID; 481 SOFT_GEMINI_SENSE_EVENT_ID |
482 MAX_TX_RETRY_EVENT_ID;
454 483
455 if (wl->bss_type == BSS_TYPE_AP_BSS) 484 if (wl->bss_type == BSS_TYPE_AP_BSS)
456 wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; 485 wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID |
486 INACTIVE_STA_EVENT_ID;
487 else
488 wl->event_mask |= DUMMY_PACKET_EVENT_ID;
457 489
458 ret = wl1271_event_unmask(wl); 490 ret = wl1271_event_unmask(wl);
459 if (ret < 0) { 491 if (ret < 0) {
@@ -493,24 +525,159 @@ static void wl1271_boot_hw_version(struct wl1271 *wl)
493 wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; 525 wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
494} 526}
495 527
496/* uploads NVS and firmware */ 528static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
497int wl1271_load_firmware(struct wl1271 *wl)
498{ 529{
499 int ret = 0; 530 u16 spare_reg;
500 u32 tmp, clk, pause; 531
532 /* Mask bits [2] & [8:4] in the sys_clk_cfg register */
533 spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG);
534 if (spare_reg == 0xFFFF)
535 return -EFAULT;
536 spare_reg |= (BIT(3) | BIT(5) | BIT(6));
537 wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg);
538
539 /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */
540 wl1271_top_reg_write(wl, SYS_CLK_CFG_REG,
541 WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);
542
543 /* Delay execution for 15msec, to let the HW settle */
544 mdelay(15);
545
546 return 0;
547}
548
549static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
550{
551 u16 tcxo_detection;
552
553 tcxo_detection = wl1271_top_reg_read(wl, TCXO_CLK_DETECT_REG);
554 if (tcxo_detection & TCXO_DET_FAILED)
555 return false;
556
557 return true;
558}
559
560static bool wl128x_is_fref_valid(struct wl1271 *wl)
561{
562 u16 fref_detection;
563
564 fref_detection = wl1271_top_reg_read(wl, FREF_CLK_DETECT_REG);
565 if (fref_detection & FREF_CLK_DETECT_FAIL)
566 return false;
567
568 return true;
569}
570
571static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl)
572{
573 wl1271_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL);
574 wl1271_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL);
575 wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL);
576
577 return 0;
578}
579
580static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
581{
582 u16 spare_reg;
583 u16 pll_config;
584 u8 input_freq;
585
586 /* Mask bits [3:1] in the sys_clk_cfg register */
587 spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG);
588 if (spare_reg == 0xFFFF)
589 return -EFAULT;
590 spare_reg |= BIT(2);
591 wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg);
592
593 /* Handle special cases of the TCXO clock */
594 if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 ||
595 wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6)
596 return wl128x_manually_configure_mcs_pll(wl);
597
598 /* Set the input frequency according to the selected clock source */
599 input_freq = (clk & 1) + 1;
600
601 pll_config = wl1271_top_reg_read(wl, MCS_PLL_CONFIG_REG);
602 if (pll_config == 0xFFFF)
603 return -EFAULT;
604 pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT);
605 pll_config |= MCS_PLL_ENABLE_HP;
606 wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config);
607
608 return 0;
609}
610
611/*
612 * WL128x has two clocks input - TCXO and FREF.
613 * TCXO is the main clock of the device, while FREF is used to sync
614 * between the GPS and the cellular modem.
615 * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used
616 * as the WLAN/BT main clock.
617 */
618static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
619{
620 u16 sys_clk_cfg;
621
622 /* For XTAL-only modes, FREF will be used after switching from TCXO */
623 if (wl->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
624 wl->ref_clock == WL12XX_REFCLOCK_38_XTAL) {
625 if (!wl128x_switch_tcxo_to_fref(wl))
626 return -EINVAL;
627 goto fref_clk;
628 }
629
630 /* Query the HW, to determine which clock source we should use */
631 sys_clk_cfg = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG);
632 if (sys_clk_cfg == 0xFFFF)
633 return -EINVAL;
634 if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF)
635 goto fref_clk;
636
637 /* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */
638 if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_368 ||
639 wl->tcxo_clock == WL12XX_TCXOCLOCK_32_736) {
640 if (!wl128x_switch_tcxo_to_fref(wl))
641 return -EINVAL;
642 goto fref_clk;
643 }
644
645 /* TCXO clock is selected */
646 if (!wl128x_is_tcxo_valid(wl))
647 return -EINVAL;
648 *selected_clock = wl->tcxo_clock;
649 goto config_mcs_pll;
650
651fref_clk:
652 /* FREF clock is selected */
653 if (!wl128x_is_fref_valid(wl))
654 return -EINVAL;
655 *selected_clock = wl->ref_clock;
656
657config_mcs_pll:
658 return wl128x_configure_mcs_pll(wl, *selected_clock);
659}
660
661static int wl127x_boot_clk(struct wl1271 *wl)
662{
663 u32 pause;
664 u32 clk;
501 665
502 wl1271_boot_hw_version(wl); 666 wl1271_boot_hw_version(wl);
503 667
504 if (wl->ref_clock == 0 || wl->ref_clock == 2 || wl->ref_clock == 4) 668 if (wl->ref_clock == CONF_REF_CLK_19_2_E ||
669 wl->ref_clock == CONF_REF_CLK_38_4_E ||
670 wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL)
505 /* ref clk: 19.2/38.4/38.4-XTAL */ 671 /* ref clk: 19.2/38.4/38.4-XTAL */
506 clk = 0x3; 672 clk = 0x3;
507 else if (wl->ref_clock == 1 || wl->ref_clock == 3) 673 else if (wl->ref_clock == CONF_REF_CLK_26_E ||
674 wl->ref_clock == CONF_REF_CLK_52_E)
508 /* ref clk: 26/52 */ 675 /* ref clk: 26/52 */
509 clk = 0x5; 676 clk = 0x5;
510 else 677 else
511 return -EINVAL; 678 return -EINVAL;
512 679
513 if (wl->ref_clock != 0) { 680 if (wl->ref_clock != CONF_REF_CLK_19_2_E) {
514 u16 val; 681 u16 val;
515 /* Set clock type (open drain) */ 682 /* Set clock type (open drain) */
516 val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); 683 val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE);
@@ -540,6 +707,26 @@ int wl1271_load_firmware(struct wl1271 *wl)
540 pause |= WU_COUNTER_PAUSE_VAL; 707 pause |= WU_COUNTER_PAUSE_VAL;
541 wl1271_write32(wl, WU_COUNTER_PAUSE, pause); 708 wl1271_write32(wl, WU_COUNTER_PAUSE, pause);
542 709
710 return 0;
711}
712
713/* uploads NVS and firmware */
714int wl1271_load_firmware(struct wl1271 *wl)
715{
716 int ret = 0;
717 u32 tmp, clk;
718 int selected_clock = -1;
719
720 if (wl->chip.id == CHIP_ID_1283_PG20) {
721 ret = wl128x_boot_clk(wl, &selected_clock);
722 if (ret < 0)
723 goto out;
724 } else {
725 ret = wl127x_boot_clk(wl);
726 if (ret < 0)
727 goto out;
728 }
729
543 /* Continue the ELP wake up sequence */ 730 /* Continue the ELP wake up sequence */
544 wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); 731 wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
545 udelay(500); 732 udelay(500);
@@ -555,7 +742,12 @@ int wl1271_load_firmware(struct wl1271 *wl)
555 742
556 wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); 743 wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
557 744
558 clk |= (wl->ref_clock << 1) << 4; 745 if (wl->chip.id == CHIP_ID_1283_PG20) {
746 clk |= ((selected_clock & 0x3) << 1) << 4;
747 } else {
748 clk |= (wl->ref_clock << 1) << 4;
749 }
750
559 wl1271_write32(wl, DRPW_SCRATCH_START, clk); 751 wl1271_write32(wl, DRPW_SCRATCH_START, clk);
560 752
561 wl1271_set_partition(wl, &part_table[PART_WORK]); 753 wl1271_set_partition(wl, &part_table[PART_WORK]);
@@ -585,16 +777,12 @@ int wl1271_load_firmware(struct wl1271 *wl)
585 /* 6. read the EEPROM parameters */ 777 /* 6. read the EEPROM parameters */
586 tmp = wl1271_read32(wl, SCR_PAD2); 778 tmp = wl1271_read32(wl, SCR_PAD2);
587 779
588 ret = wl1271_boot_write_irq_polarity(wl);
589 if (ret < 0)
590 goto out;
591
592 wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
593 WL1271_ACX_ALL_EVENTS_VECTOR);
594
595 /* WL1271: The reference driver skips steps 7 to 10 (jumps directly 780 /* WL1271: The reference driver skips steps 7 to 10 (jumps directly
596 * to upload_fw) */ 781 * to upload_fw) */
597 782
783 if (wl->chip.id == CHIP_ID_1283_PG20)
784 wl1271_top_reg_write(wl, SDIO_IO_DS, wl->conf.hci_io_ds);
785
598 ret = wl1271_boot_upload_firmware(wl); 786 ret = wl1271_boot_upload_firmware(wl);
599 if (ret < 0) 787 if (ret < 0)
600 goto out; 788 goto out;
@@ -618,6 +806,13 @@ int wl1271_boot(struct wl1271 *wl)
618 if (ret < 0) 806 if (ret < 0)
619 goto out; 807 goto out;
620 808
809 ret = wl1271_boot_write_irq_polarity(wl);
810 if (ret < 0)
811 goto out;
812
813 wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
814 WL1271_ACX_ALL_EVENTS_VECTOR);
815
621 /* Enable firmware interrupts now */ 816 /* Enable firmware interrupts now */
622 wl1271_boot_enable_interrupts(wl); 817 wl1271_boot_enable_interrupts(wl);
623 818