carl9170 firmware: investigate 80/88MHz clock freezes
[carl9170fw.git] / carlfw / src / rf.c
index be705a7934b49c75f345e8bb41762ac4ba67982a..5448abfe32bc5842aa6c30b84b2bd68c768962b0 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (c) 2000-2005 ZyDAS Technology Corporation
  * Copyright (c) 2007-2009 Atheros Communications, Inc.
  * Copyright   2009    Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2009, 2010 Christian Lamparter <chunkeey@googlemail.com>
+ * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include "shared/phy.h"
 
 #ifdef CONFIG_CARL9170FW_RADIO_FUNCTIONS
-static void set_channel_start(void)
-{
-       /* Manipulate CCA threshold to stop transmission */
-       set(AR9170_PHY_REG_CCA_THRESHOLD, 0x300);
-       /* Enable Virtual CCA */
-       orl(AR9170_MAC_REG_QOS_PRIORITY_VIRTUAL_CCA,
-           AR9170_MAC_VIRTUAL_CCA_ALL);
-}
-
 static void set_channel_end(void)
 {
        /* Manipulate CCA threshold to resume transmission */
@@ -46,11 +37,23 @@ static void set_channel_end(void)
        /* Disable Virtual CCA */
        andl(AR9170_MAC_REG_QOS_PRIORITY_VIRTUAL_CCA,
             ~AR9170_MAC_VIRTUAL_CCA_ALL);
+
+       fw.phy.state = CARL9170_PHY_ON;
 }
 
 void rf_notify_set_channel(void)
 {
-       set_channel_start();
+       /* Manipulate CCA threshold to stop transmission */
+       set(AR9170_PHY_REG_CCA_THRESHOLD, 0x300);
+       /* Enable Virtual CCA */
+       orl(AR9170_MAC_REG_QOS_PRIORITY_VIRTUAL_CCA,
+           AR9170_MAC_VIRTUAL_CCA_ALL);
+
+       /* reset CCA stats */
+       fw.tally.active = 0;
+       fw.tally.cca = 0;
+       fw.tally.tx_time = 0;
+       fw.phy.state = CARL9170_PHY_OFF;
 }
 
 /*
@@ -136,7 +139,7 @@ static uint32_t AGC_calibration(uint32_t loop)
        uint32_t wrdata;
        uint32_t ret;
 
-#define AGC_CAL_NF     (AR9170_PHY_AGC_CONTROL_CAL | AR9170_PHY_AGC_CONTROL_NF);
+#define AGC_CAL_NF     (AR9170_PHY_AGC_CONTROL_CAL | AR9170_PHY_AGC_CONTROL_NF)
 
        wrdata = get_async(AR9170_PHY_REG_AGC_CONTROL) | AGC_CAL_NF;
        set(AR9170_PHY_REG_AGC_CONTROL, wrdata);
@@ -144,14 +147,10 @@ static uint32_t AGC_calibration(uint32_t loop)
        ret = get_async(AR9170_PHY_REG_AGC_CONTROL) & AGC_CAL_NF;
 
        /* sitesurvey : 100 ms / current connected 200 ms */
-       while (loop && ret != 0x0) {
-               ret = get_async(AR9170_PHY_REG_AGC_CONTROL) & AGC_CAL_NF;
-
-               if (ret == 0)
-                       break;
-
+       while ((ret != 0) && loop--) {
                udelay(100);
-               loop--;
+
+               ret = get_async(AR9170_PHY_REG_AGC_CONTROL) & AGC_CAL_NF;
        }
 
        /* return the AGC/Noise calibration state to the driver */
@@ -185,10 +184,6 @@ static uint32_t rf_init(const uint32_t delta_slope_coeff_exp,
                set(AR9170_PHY_REG_ANALOG_SWAP, AR9170_PHY_ANALOG_SWAP_AB |
                                                AR9170_PHY_ANALOG_SWAP_ALT_CHAIN);
 
-               /* configure mask */
-               set(AR9170_PHY_REG_RX_CHAINMASK, 0x5);  /* chain 0 + chain 2 */
-               set(AR9170_PHY_REG_CAL_CHAINMASK, 0x5); /* chain 0 + chain 2 */
-
                /* Activate BB */
                set(AR9170_PHY_REG_ACTIVE, AR9170_PHY_ACTIVE_EN);
                delay(10);
@@ -207,10 +202,17 @@ void rf_cmd(const struct carl9170_cmd *cmd, struct carl9170_rsp *resp)
        fw.phy.ht_settings = cmd->rf_init.ht_settings;
        fw.phy.frequency = cmd->rf_init.freq;
 
+       /*
+        * Is the clock controlled by the PHY?
+        */
+#ifdef CONFIG_CARL9170FW_80MHZ_CLOCK
        if ((fw.phy.ht_settings & EIGHTY_FLAG) == EIGHTY_FLAG)
-               clock_set(true, AHB_80_88MHZ);
+               clock_set(AHB_80_88MHZ, true);
        else
-               clock_set(true, AHB_40_44MHZ);
+               clock_set(AHB_40_44MHZ, true);
+#else
+       clock_set(AHB_40_44MHZ, true);
+#endif
 
        ret = rf_init(le32_to_cpu(cmd->rf_init.delta_slope_coeff_exp),
                      le32_to_cpu(cmd->rf_init.delta_slope_coeff_man),
@@ -221,26 +223,12 @@ void rf_cmd(const struct carl9170_cmd *cmd, struct carl9170_rsp *resp)
 
        resp->hdr.len = sizeof(struct carl9170_rf_init_result);
        resp->rf_init_res.ret = cpu_to_le32(ret);
-
-       resp->rf_init_res.regs[0] = get(AR9170_PHY_REG_CCA);
-       resp->rf_init_res.regs[3] = get(AR9170_PHY_REG_EXT_CCA);
-
-       resp->rf_init_res.regs[1] = get(AR9170_PHY_REG_CH1_CCA);
-       resp->rf_init_res.regs[4] = get(AR9170_PHY_REG_CH1_EXT_CCA);
-
-       resp->rf_init_res.regs[2] = get(AR9170_PHY_REG_CH2_CCA);
-       resp->rf_init_res.regs[5] = get(AR9170_PHY_REG_CH2_EXT_CCA);
 }
 
-#ifdef CONFIG_CARL9170FW_PSM
 void rf_psm(void)
 {
        u32 bank3;
 
-       /*
-        * FIXME: Does not work on 5GHz band!
-        */
-
        if (fw.phy.psm.state == CARL9170_PSM_SOFTWARE) {
                /* not enabled by the driver */
                return;
@@ -261,7 +249,7 @@ void rf_psm(void)
                /* Synthesizer off + RX off */
                bank3 = 0x00400018;
 
-               clock_set(true, AHB_20_22MHZ);
+               fw.phy.state = CARL9170_PHY_OFF;
        } else {
                /* advance to the next PSM step */
                fw.phy.psm.state--;
@@ -278,20 +266,16 @@ void rf_psm(void)
                        /* Synthesizer on + RX on */
                        bank3 = 0x01420098;
 
-                       if ((fw.phy.ht_settings & EIGHTY_FLAG) == EIGHTY_FLAG)
-                               clock_set(true, AHB_80_88MHZ);
-                       else
-                               clock_set(true, AHB_40_44MHZ);
+                       fw.phy.state = CARL9170_PHY_ON;
                } else {
                        return ;
                }
        }
 
-       if (fw.phy.frequency < 30000000)
+       if (fw.phy.frequency < 3000000)
                bank3 |= 0x00800000;
 
        set(0x1c58f0, bank3);
 }
-#endif /* CONFIG_CARL9170FW_PSM */
 
 #endif /* CONFIG_CARL9170FW_RADIO_FUNCTIONS */