iwlwifi: implement apm reset flow
authorTomas Winkler <tomas.winkler@intel.com>
Thu, 29 May 2008 08:34:57 +0000 (16:34 +0800)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 3 Jun 2008 19:00:20 +0000 (15:00 -0400)
This patch implements apm reset flow for 4965 and 5000.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl4965-base.c

index bf0bd4a..646c589 100644 (file)
@@ -642,9 +642,9 @@ void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv)
        iwl_hw_txq_ctx_free(priv);
 }
 
-int iwl4965_hw_nic_reset(struct iwl_priv *priv)
+static int iwl4965_apm_reset(struct iwl_priv *priv)
 {
-       int rc = 0;
+       int ret = 0;
        unsigned long flags;
 
        iwl4965_hw_nic_stop_master(priv);
@@ -655,33 +655,40 @@ int iwl4965_hw_nic_reset(struct iwl_priv *priv)
 
        udelay(10);
 
+       /* FIXME: put here L1A -L0S w/a */
+
        iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-       rc = iwl_poll_bit(priv, CSR_RESET,
+       ret = iwl_poll_bit(priv, CSR_RESET,
                          CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
                          CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25);
 
+       if (ret)
+               goto out;
+
        udelay(10);
 
-       rc = iwl_grab_nic_access(priv);
-       if (!rc) {
-               iwl_write_prph(priv, APMG_CLK_EN_REG,
-                               APMG_CLK_VAL_DMA_CLK_RQT |
-                               APMG_CLK_VAL_BSM_CLK_RQT);
+       ret = iwl_grab_nic_access(priv);
+       if (ret)
+               goto out;
+       /* Enable DMA and BSM Clock */
+       iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT |
+                                             APMG_CLK_VAL_BSM_CLK_RQT);
 
-               udelay(10);
+       udelay(10);
 
-               iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
-                                       APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+       /* disable L1A */
+       iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
+                         APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
 
-               iwl_release_nic_access(priv);
-       }
+       iwl_release_nic_access(priv);
 
        clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
        wake_up_interruptible(&priv->wait_command_queue);
 
+out:
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       return rc;
+       return ret;
 
 }
 
@@ -3617,6 +3624,7 @@ static struct iwl_lib_ops iwl4965_lib = {
        .load_ucode = iwl4965_load_bsm,
        .apm_ops = {
                .init = iwl4965_apm_init,
+               .reset = iwl4965_apm_reset,
                .config = iwl4965_nic_config,
                .set_pwr_src = iwl4965_set_pwr_src,
        },
index b1c5045..10054bd 100644 (file)
@@ -100,6 +100,59 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
        return ret;
 }
 
+static int iwl5000_apm_reset(struct iwl_priv *priv)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       iwl4965_hw_nic_stop_master(priv);
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+
+       udelay(10);
+
+
+       /* FIXME: put here L1A -L0S w/a */
+
+       iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL);
+
+       /* set "initialization complete" bit to move adapter
+        * D0U* --> D0A* state */
+       iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
+       /* wait for clock stabilization */
+       ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
+                         CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+                         CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+       if (ret < 0) {
+               IWL_DEBUG_INFO("Failed to init the card\n");
+               goto out;
+       }
+
+       ret = iwl_grab_nic_access(priv);
+       if (ret)
+               goto out;
+
+       /* enable DMA */
+       iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT);
+
+       udelay(20);
+
+       /* disable L1-Active */
+       iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
+                         APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+
+       iwl_release_nic_access(priv);
+
+out:
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return ret;
+}
+
+
 static void iwl5000_nic_config(struct iwl_priv *priv)
 {
        unsigned long flags;
@@ -805,6 +858,7 @@ static struct iwl_lib_ops iwl5000_lib = {
        .alive_notify = iwl5000_alive_notify,
        .apm_ops = {
                .init = iwl5000_apm_init,
+               .reset = iwl5000_apm_reset,
                .config = iwl5000_nic_config,
                .set_pwr_src = iwl4965_set_pwr_src,
        },
index 9392fcf..d82660c 100644 (file)
@@ -124,6 +124,7 @@ struct iwl_lib_ops {
         /* power management */
        struct {
                int (*init)(struct iwl_priv *priv);
+               int (*reset)(struct iwl_priv *priv);
                void (*config)(struct iwl_priv *priv);
                int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
        } apm_ops;
index da4d606..d193da3 100644 (file)
@@ -688,7 +688,6 @@ extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv);
 extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv);
 extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv);
 extern void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv);
-extern int iwl4965_hw_nic_reset(struct iwl_priv *priv);
 extern int iwl4965_hw_get_temperature(struct iwl_priv *priv);
 extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
                                 struct iwl_frame *frame, u8 rate);
index ee9fe56..af0ffd3 100644 (file)
@@ -3417,9 +3417,8 @@ static void __iwl4965_down(struct iwl_priv *priv)
 
        udelay(5);
 
-       iwl4965_hw_nic_stop_master(priv);
-       iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
-       iwl4965_hw_nic_reset(priv);
+       /* FIXME: apm_ops.suspend(priv) */
+       priv->cfg->ops->lib->apm_ops.reset(priv);
        priv->cfg->ops->lib->free_shared_mem(priv);
 
  exit: