Commit 7f066108 authored by Tomas Winkler's avatar Tomas Winkler Committed by John W. Linville

iwlwifi: implement apm reset flow

This patch implements apm reset flow for 4965 and 5000.
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 8f061891
...@@ -642,9 +642,9 @@ void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv) ...@@ -642,9 +642,9 @@ void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv)
iwl_hw_txq_ctx_free(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; unsigned long flags;
iwl4965_hw_nic_stop_master(priv); iwl4965_hw_nic_stop_master(priv);
...@@ -655,33 +655,40 @@ int iwl4965_hw_nic_reset(struct iwl_priv *priv) ...@@ -655,33 +655,40 @@ int iwl4965_hw_nic_reset(struct iwl_priv *priv)
udelay(10); udelay(10);
/* FIXME: put here L1A -L0S w/a */
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); 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,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25); CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25);
if (ret)
goto out;
udelay(10); udelay(10);
rc = iwl_grab_nic_access(priv); ret = iwl_grab_nic_access(priv);
if (!rc) { if (ret)
iwl_write_prph(priv, APMG_CLK_EN_REG, goto out;
APMG_CLK_VAL_DMA_CLK_RQT | /* Enable DMA and BSM Clock */
APMG_CLK_VAL_BSM_CLK_RQT); 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, /* disable L1A */
APMG_PCIDEV_STT_VAL_L1_ACT_DIS); 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); clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
wake_up_interruptible(&priv->wait_command_queue); wake_up_interruptible(&priv->wait_command_queue);
out:
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
return rc; return ret;
} }
...@@ -3617,6 +3624,7 @@ static struct iwl_lib_ops iwl4965_lib = { ...@@ -3617,6 +3624,7 @@ static struct iwl_lib_ops iwl4965_lib = {
.load_ucode = iwl4965_load_bsm, .load_ucode = iwl4965_load_bsm,
.apm_ops = { .apm_ops = {
.init = iwl4965_apm_init, .init = iwl4965_apm_init,
.reset = iwl4965_apm_reset,
.config = iwl4965_nic_config, .config = iwl4965_nic_config,
.set_pwr_src = iwl4965_set_pwr_src, .set_pwr_src = iwl4965_set_pwr_src,
}, },
......
...@@ -100,6 +100,59 @@ static int iwl5000_apm_init(struct iwl_priv *priv) ...@@ -100,6 +100,59 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
return ret; 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) static void iwl5000_nic_config(struct iwl_priv *priv)
{ {
unsigned long flags; unsigned long flags;
...@@ -805,6 +858,7 @@ static struct iwl_lib_ops iwl5000_lib = { ...@@ -805,6 +858,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.alive_notify = iwl5000_alive_notify, .alive_notify = iwl5000_alive_notify,
.apm_ops = { .apm_ops = {
.init = iwl5000_apm_init, .init = iwl5000_apm_init,
.reset = iwl5000_apm_reset,
.config = iwl5000_nic_config, .config = iwl5000_nic_config,
.set_pwr_src = iwl4965_set_pwr_src, .set_pwr_src = iwl4965_set_pwr_src,
}, },
......
...@@ -124,6 +124,7 @@ struct iwl_lib_ops { ...@@ -124,6 +124,7 @@ struct iwl_lib_ops {
/* power management */ /* power management */
struct { struct {
int (*init)(struct iwl_priv *priv); int (*init)(struct iwl_priv *priv);
int (*reset)(struct iwl_priv *priv);
void (*config)(struct iwl_priv *priv); void (*config)(struct iwl_priv *priv);
int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src); int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
} apm_ops; } apm_ops;
......
...@@ -688,7 +688,6 @@ extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv); ...@@ -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_set_hw_params(struct iwl_priv *priv);
extern int iwl4965_hw_nic_stop_master(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 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 int iwl4965_hw_get_temperature(struct iwl_priv *priv);
extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
struct iwl_frame *frame, u8 rate); struct iwl_frame *frame, u8 rate);
......
...@@ -3417,9 +3417,8 @@ static void __iwl4965_down(struct iwl_priv *priv) ...@@ -3417,9 +3417,8 @@ static void __iwl4965_down(struct iwl_priv *priv)
udelay(5); udelay(5);
iwl4965_hw_nic_stop_master(priv); /* FIXME: apm_ops.suspend(priv) */
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); priv->cfg->ops->lib->apm_ops.reset(priv);
iwl4965_hw_nic_reset(priv);
priv->cfg->ops->lib->free_shared_mem(priv); priv->cfg->ops->lib->free_shared_mem(priv);
exit: exit:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment