aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorShahar Levi <shahar_levi@ti.com>2011-03-06 09:32:11 -0500
committerLuciano Coelho <coelho@ti.com>2011-04-19 09:48:58 -0400
commit5ea417ae7749076ddaacb5b36487cae6ac920413 (patch)
tree3969114b764d6101adda23e626bb80940115abe4 /drivers/net
parentbc765bf3b9a095b3e41c8cda80643901884c3dd4 (diff)
wl12xx: 1281/1283 support - New boot sequence
Boot sequence support FREF clock and TCXO clock. WL128x has two clocks input - TCXO and FREF. TCXO is the main clock of the device, while FREF is used to sync between the GPS and the cellular modem. Auto-detection checks where TCXO is 32.736MHz or 16.368MHz, in that case the FREF will be used as the WLAN/BT main clock. [Use clock enumeration as defined in linux/wl12xx.h; remove unnecessary else block in wl128x_switch_fref; remove unnecessary change in main.c; remove some unnecessary debug prints and comments; fix potential use of uninitialized value (pll_config) -- Luca] Signed-off-by: Shahar Levi <shahar_levi@ti.com> Reviewed-by: Luciano Coelho <coelho@ti.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/wl12xx/boot.c183
-rw-r--r--drivers/net/wireless/wl12xx/sdio.c1
-rw-r--r--drivers/net/wireless/wl12xx/sdio_test.c1
-rw-r--r--drivers/net/wireless/wl12xx/spi.c1
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h1
5 files changed, 179 insertions, 8 deletions
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 38f3e8ba2628..9d742c1e75a9 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"
@@ -520,24 +521,159 @@ static void wl1271_boot_hw_version(struct wl1271 *wl)
520 wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; 521 wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
521} 522}
522 523
523/* uploads NVS and firmware */ 524/*
524int wl1271_load_firmware(struct wl1271 *wl) 525 * WL128x has two clocks input - TCXO and FREF.
526 * TCXO is the main clock of the device, while FREF is used to sync
527 * between the GPS and the cellular modem.
528 * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used
529 * as the WLAN/BT main clock.
530 */
531static int wl128x_switch_fref(struct wl1271 *wl, bool *is_ref_clk)
525{ 532{
526 int ret = 0; 533 u16 sys_clk_cfg_val;
527 u32 tmp, clk, pause; 534
535 /* if working on XTAL-only mode go directly to TCXO TO FREF SWITCH */
536 if ((wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) ||
537 (wl->ref_clock == CONF_REF_CLK_26_M_XTAL))
538 return true;
539
540 /* Read clock source FREF or TCXO */
541 sys_clk_cfg_val = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG);
542
543 if (sys_clk_cfg_val & PRCM_CM_EN_MUX_WLAN_FREF) {
544 /* if bit 3 is set - working with FREF clock */
545 wl1271_debug(DEBUG_BOOT, "working with FREF clock, skip"
546 " to FREF");
547
548 *is_ref_clk = true;
549 } else {
550 /* if bit 3 is clear - working with TCXO clock */
551 wl1271_debug(DEBUG_BOOT, "working with TCXO clock");
552
553 /* TCXO to FREF switch, check TXCO clock config */
554 if ((wl->tcxo_clock != WL12XX_TCXOCLOCK_16_368) &&
555 (wl->tcxo_clock != WL12XX_TCXOCLOCK_32_736)) {
556 /*
557 * not 16.368Mhz and not 32.736Mhz - skip to
558 * configure ELP stage
559 */
560 wl1271_debug(DEBUG_BOOT, "NEW PLL ALGO:"
561 " TcxoRefClk=%d - not 16.368Mhz and not"
562 " 32.736Mhz - skip to configure ELP"
563 " stage", wl->tcxo_clock);
564
565 *is_ref_clk = false;
566 } else {
567 wl1271_debug(DEBUG_BOOT, "NEW PLL ALGO:"
568 "TcxoRefClk=%d - 16.368Mhz or 32.736Mhz"
569 " - TCXO to FREF switch",
570 wl->tcxo_clock);
571
572 return true;
573 }
574 }
575
576 return false;
577}
578
579static int wl128x_boot_clk(struct wl1271 *wl, bool *is_ref_clk)
580{
581 if (wl128x_switch_fref(wl, is_ref_clk)) {
582 wl1271_debug(DEBUG_BOOT, "XTAL-only mode go directly to"
583 " TCXO TO FREF SWITCH");
584 /* TCXO to FREF switch - for PG2.0 */
585 wl1271_top_reg_write(wl, WL_SPARE_REG,
586 WL_SPARE_MASK_8526);
587
588 wl1271_top_reg_write(wl, SYS_CLK_CFG_REG,
589 WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);
590
591 *is_ref_clk = true;
592 mdelay(15);
593 }
594
595 /* Set bit 2 in spare register to avoid illegal access */
596 wl1271_top_reg_write(wl, WL_SPARE_REG, WL_SPARE_VAL);
597
598 /* working with TCXO clock */
599 if ((*is_ref_clk == false) &&
600 ((wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8) ||
601 (wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6))) {
602 wl1271_debug(DEBUG_BOOT, "16_8_M or 33_6_M TCXO detected");
603
604 /* Manually Configure MCS PLL settings PG2.0 Only */
605 wl1271_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL);
606 wl1271_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL);
607 wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG,
608 MCS_PLL_CONFIG_REG_VAL);
609 } else {
610 int pll_config;
611 u16 mcs_pll_config_val;
612
613 /*
614 * Configure MCS PLL settings to FREF Freq
615 * Set the values that determine the time elapse since the PLL's
616 * get their enable signal until the lock indication is set
617 */
618 wl1271_top_reg_write(wl, PLL_LOCK_COUNTERS_REG,
619 PLL_LOCK_COUNTERS_COEX | PLL_LOCK_COUNTERS_MCS);
620
621 mcs_pll_config_val = wl1271_top_reg_read(wl,
622 MCS_PLL_CONFIG_REG);
623 /*
624 * Set the MCS PLL input frequency value according to the
625 * reference clock value detected/read
626 */
627 if (*is_ref_clk == false) {
628 if ((wl->tcxo_clock == WL12XX_TCXOCLOCK_19_2) ||
629 (wl->tcxo_clock == WL12XX_TCXOCLOCK_38_4))
630 pll_config = 1;
631 else if ((wl->tcxo_clock == WL12XX_TCXOCLOCK_26)
632 ||
633 (wl->tcxo_clock == WL12XX_TCXOCLOCK_52))
634 pll_config = 2;
635 else
636 return -EINVAL;
637 } else {
638 if ((wl->ref_clock == CONF_REF_CLK_19_2_E) ||
639 (wl->ref_clock == CONF_REF_CLK_38_4_E))
640 pll_config = 1;
641 else if ((wl->ref_clock == CONF_REF_CLK_26_E) ||
642 (wl->ref_clock == CONF_REF_CLK_52_E))
643 pll_config = 2;
644 else
645 return -EINVAL;
646 }
647
648 mcs_pll_config_val |= (pll_config << (MCS_SEL_IN_FREQ_SHIFT)) &
649 (MCS_SEL_IN_FREQ_MASK);
650 wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG,
651 mcs_pll_config_val);
652 }
653
654 return 0;
655}
656
657static int wl127x_boot_clk(struct wl1271 *wl)
658{
659 u32 pause;
660 u32 clk;
528 661
529 wl1271_boot_hw_version(wl); 662 wl1271_boot_hw_version(wl);
530 663
531 if (wl->ref_clock == 0 || wl->ref_clock == 2 || wl->ref_clock == 4) 664 if (wl->ref_clock == CONF_REF_CLK_19_2_E ||
665 wl->ref_clock == CONF_REF_CLK_38_4_E ||
666 wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL)
532 /* ref clk: 19.2/38.4/38.4-XTAL */ 667 /* ref clk: 19.2/38.4/38.4-XTAL */
533 clk = 0x3; 668 clk = 0x3;
534 else if (wl->ref_clock == 1 || wl->ref_clock == 3) 669 else if (wl->ref_clock == CONF_REF_CLK_26_E ||
670 wl->ref_clock == CONF_REF_CLK_52_E)
535 /* ref clk: 26/52 */ 671 /* ref clk: 26/52 */
536 clk = 0x5; 672 clk = 0x5;
537 else 673 else
538 return -EINVAL; 674 return -EINVAL;
539 675
540 if (wl->ref_clock != 0) { 676 if (wl->ref_clock != CONF_REF_CLK_19_2_E) {
541 u16 val; 677 u16 val;
542 /* Set clock type (open drain) */ 678 /* Set clock type (open drain) */
543 val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); 679 val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE);
@@ -567,6 +703,26 @@ int wl1271_load_firmware(struct wl1271 *wl)
567 pause |= WU_COUNTER_PAUSE_VAL; 703 pause |= WU_COUNTER_PAUSE_VAL;
568 wl1271_write32(wl, WU_COUNTER_PAUSE, pause); 704 wl1271_write32(wl, WU_COUNTER_PAUSE, pause);
569 705
706 return 0;
707}
708
709/* uploads NVS and firmware */
710int wl1271_load_firmware(struct wl1271 *wl)
711{
712 int ret = 0;
713 u32 tmp, clk;
714 bool is_ref_clk = false;
715
716 if (wl->chip.id == CHIP_ID_1283_PG20) {
717 ret = wl128x_boot_clk(wl, &is_ref_clk);
718 if (ret < 0)
719 goto out;
720 } else {
721 ret = wl127x_boot_clk(wl);
722 if (ret < 0)
723 goto out;
724 }
725
570 /* Continue the ELP wake up sequence */ 726 /* Continue the ELP wake up sequence */
571 wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); 727 wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
572 udelay(500); 728 udelay(500);
@@ -582,7 +738,15 @@ int wl1271_load_firmware(struct wl1271 *wl)
582 738
583 wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); 739 wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
584 740
585 clk |= (wl->ref_clock << 1) << 4; 741 if (wl->chip.id == CHIP_ID_1283_PG20) {
742 if (is_ref_clk == false)
743 clk |= ((wl->tcxo_clock & 0x3) << 1) << 4;
744 else
745 clk |= ((wl->ref_clock & 0x3) << 1) << 4;
746 } else {
747 clk |= (wl->ref_clock << 1) << 4;
748 }
749
586 wl1271_write32(wl, DRPW_SCRATCH_START, clk); 750 wl1271_write32(wl, DRPW_SCRATCH_START, clk);
587 751
588 wl1271_set_partition(wl, &part_table[PART_WORK]); 752 wl1271_set_partition(wl, &part_table[PART_WORK]);
@@ -615,6 +779,9 @@ int wl1271_load_firmware(struct wl1271 *wl)
615 /* WL1271: The reference driver skips steps 7 to 10 (jumps directly 779 /* WL1271: The reference driver skips steps 7 to 10 (jumps directly
616 * to upload_fw) */ 780 * to upload_fw) */
617 781
782 if (wl->chip.id == CHIP_ID_1283_PG20)
783 wl1271_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
784
618 ret = wl1271_boot_upload_firmware(wl); 785 ret = wl1271_boot_upload_firmware(wl);
619 if (ret < 0) 786 if (ret < 0)
620 goto out; 787 goto out;
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index 7491b3d8487a..f6dd3dea4f30 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -255,6 +255,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
255 255
256 wl->irq = wlan_data->irq; 256 wl->irq = wlan_data->irq;
257 wl->ref_clock = wlan_data->board_ref_clock; 257 wl->ref_clock = wlan_data->board_ref_clock;
258 wl->tcxo_clock = wlan_data->board_tcxo_clock;
258 259
259 ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, 260 ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
260 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 261 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c
index e6e2ad63a1c1..c02c87046615 100644
--- a/drivers/net/wireless/wl12xx/sdio_test.c
+++ b/drivers/net/wireless/wl12xx/sdio_test.c
@@ -421,6 +421,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
421 421
422 wl->irq = wlan_data->irq; 422 wl->irq = wlan_data->irq;
423 wl->ref_clock = wlan_data->board_ref_clock; 423 wl->ref_clock = wlan_data->board_ref_clock;
424 wl->tcxo_clock = wlan_data->board_tcxo_clock;
424 425
425 sdio_set_drvdata(func, wl_test); 426 sdio_set_drvdata(func, wl_test);
426 427
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index bfb1171176ca..f5525361f2f5 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -401,6 +401,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
401 } 401 }
402 402
403 wl->ref_clock = pdata->board_ref_clock; 403 wl->ref_clock = pdata->board_ref_clock;
404 wl->tcxo_clock = pdata->board_tcxo_clock;
404 405
405 wl->irq = spi->irq; 406 wl->irq = spi->irq;
406 if (wl->irq < 0) { 407 if (wl->irq < 0) {
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index e59f5392e909..4b556776fd57 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -535,6 +535,7 @@ struct wl1271 {
535 u8 ba_rx_bitmap; 535 u8 ba_rx_bitmap;
536 536
537 u32 block_size; 537 u32 block_size;
538 int tcxo_clock;
538 539
539 /* 540 /*
540 * AP-mode - links indexed by HLID. The global and broadcast links 541 * AP-mode - links indexed by HLID. The global and broadcast links