aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2010-11-10 12:56:50 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-15 13:26:59 -0500
commitf81c1f48384d398dbe8f6c5b10377c7158086791 (patch)
treef5a813c7e3b66a024adb7db8359c920fb878a4db /drivers
parent6fe8efb2211fe61caa7b0e1c36c521670b8a10a9 (diff)
iwlagn: enable shadow register
For 6000 series devices and up, enable automatic update MAC's register for better power usage in PSP mode Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-csr.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c45
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c51
6 files changed, 70 insertions, 39 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 21ac2817722e..c7ff1bdf42cd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -487,6 +487,7 @@ static struct iwl_base_params iwl6000_base_params = {
487 .ucode_tracing = true, 487 .ucode_tracing = true,
488 .sensitivity_calib_by_driver = true, 488 .sensitivity_calib_by_driver = true,
489 .chain_noise_calib_by_driver = true, 489 .chain_noise_calib_by_driver = true,
490 .shadow_reg_enable = true,
490}; 491};
491 492
492static struct iwl_base_params iwl6050_base_params = { 493static struct iwl_base_params iwl6050_base_params = {
@@ -510,6 +511,7 @@ static struct iwl_base_params iwl6050_base_params = {
510 .ucode_tracing = true, 511 .ucode_tracing = true,
511 .sensitivity_calib_by_driver = true, 512 .sensitivity_calib_by_driver = true,
512 .chain_noise_calib_by_driver = true, 513 .chain_noise_calib_by_driver = true,
514 .shadow_reg_enable = true,
513}; 515};
514static struct iwl_base_params iwl6000_coex_base_params = { 516static struct iwl_base_params iwl6000_coex_base_params = {
515 .eeprom_size = OTP_LOW_IMAGE_SIZE, 517 .eeprom_size = OTP_LOW_IMAGE_SIZE,
@@ -532,6 +534,7 @@ static struct iwl_base_params iwl6000_coex_base_params = {
532 .ucode_tracing = true, 534 .ucode_tracing = true,
533 .sensitivity_calib_by_driver = true, 535 .sensitivity_calib_by_driver = true,
534 .chain_noise_calib_by_driver = true, 536 .chain_noise_calib_by_driver = true,
537 .shadow_reg_enable = true,
535}; 538};
536 539
537static struct iwl_ht_params iwl6000_ht_params = { 540static struct iwl_ht_params iwl6000_ht_params = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 019d4e7d7348..ca3530c4295a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -753,6 +753,12 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv)
753 } else 753 } else
754 iwlagn_txq_ctx_reset(priv); 754 iwlagn_txq_ctx_reset(priv);
755 755
756 if (priv->cfg->base_params->shadow_reg_enable) {
757 /* enable shadow regs in HW */
758 iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL,
759 0x800FFFFF);
760 }
761
756 set_bit(STATUS_INIT, &priv->status); 762 set_bit(STATUS_INIT, &priv->status);
757 763
758 return 0; 764 return 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 6064bc412e07..ee8cf240d65d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -290,6 +290,7 @@ struct iwl_mod_params {
290 * sensitivity calibration operation 290 * sensitivity calibration operation
291 * @chain_noise_calib_by_driver: driver has the capability to perform 291 * @chain_noise_calib_by_driver: driver has the capability to perform
292 * chain noise calibration operation 292 * chain noise calibration operation
293 * @shadow_reg_enable: HW shadhow register bit
293*/ 294*/
294struct iwl_base_params { 295struct iwl_base_params {
295 int eeprom_size; 296 int eeprom_size;
@@ -320,6 +321,7 @@ struct iwl_base_params {
320 const bool ucode_tracing; 321 const bool ucode_tracing;
321 const bool sensitivity_calib_by_driver; 322 const bool sensitivity_calib_by_driver;
322 const bool chain_noise_calib_by_driver; 323 const bool chain_noise_calib_by_driver;
324 const bool shadow_reg_enable;
323}; 325};
324/* 326/*
325 * @advanced_bt_coexist: support advanced bt coexist 327 * @advanced_bt_coexist: support advanced bt coexist
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index 2aa15ab13892..b80bf7dff55b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -132,6 +132,8 @@
132 132
133#define CSR_LED_REG (CSR_BASE+0x094) 133#define CSR_LED_REG (CSR_BASE+0x094)
134#define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0) 134#define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0)
135#define CSR_MAC_SHADOW_REG_CTRL (CSR_BASE+0x0A8) /* 6000 and up */
136
135 137
136/* GIO Chicken Bits (PCI Express bus link power management) */ 138/* GIO Chicken Bits (PCI Express bus link power management) */
137#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) 139#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index baca4cc0073b..87a6fd84d4d2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -134,28 +134,37 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q
134 if (q->need_update == 0) 134 if (q->need_update == 0)
135 goto exit_unlock; 135 goto exit_unlock;
136 136
137 /* If power-saving is in use, make sure device is awake */ 137 if (priv->cfg->base_params->shadow_reg_enable) {
138 if (test_bit(STATUS_POWER_PMI, &priv->status)) { 138 /* shadow register enabled */
139 reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
140
141 if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
142 IWL_DEBUG_INFO(priv, "Rx queue requesting wakeup, GP1 = 0x%x\n",
143 reg);
144 iwl_set_bit(priv, CSR_GP_CNTRL,
145 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
146 goto exit_unlock;
147 }
148
149 q->write_actual = (q->write & ~0x7);
150 iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual);
151
152 /* Else device is assumed to be awake */
153 } else {
154 /* Device expects a multiple of 8 */ 139 /* Device expects a multiple of 8 */
155 q->write_actual = (q->write & ~0x7); 140 q->write_actual = (q->write & ~0x7);
156 iwl_write32(priv, rx_wrt_ptr_reg, q->write_actual); 141 iwl_write32(priv, rx_wrt_ptr_reg, q->write_actual);
157 } 142 } else {
143 /* If power-saving is in use, make sure device is awake */
144 if (test_bit(STATUS_POWER_PMI, &priv->status)) {
145 reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
146
147 if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
148 IWL_DEBUG_INFO(priv,
149 "Rx queue requesting wakeup,"
150 " GP1 = 0x%x\n", reg);
151 iwl_set_bit(priv, CSR_GP_CNTRL,
152 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
153 goto exit_unlock;
154 }
158 155
156 q->write_actual = (q->write & ~0x7);
157 iwl_write_direct32(priv, rx_wrt_ptr_reg,
158 q->write_actual);
159
160 /* Else device is assumed to be awake */
161 } else {
162 /* Device expects a multiple of 8 */
163 q->write_actual = (q->write & ~0x7);
164 iwl_write_direct32(priv, rx_wrt_ptr_reg,
165 q->write_actual);
166 }
167 }
159 q->need_update = 0; 168 q->need_update = 0;
160 169
161 exit_unlock: 170 exit_unlock:
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 7261ee49f282..feaa3670c6bb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -49,30 +49,39 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
49 if (txq->need_update == 0) 49 if (txq->need_update == 0)
50 return; 50 return;
51 51
52 /* if we're trying to save power */ 52 if (priv->cfg->base_params->shadow_reg_enable) {
53 if (test_bit(STATUS_POWER_PMI, &priv->status)) { 53 /* shadow register enabled */
54 /* wake up nic if it's powered down ...
55 * uCode will wake up, and interrupt us again, so next
56 * time we'll skip this part. */
57 reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
58
59 if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
60 IWL_DEBUG_INFO(priv, "Tx queue %d requesting wakeup, GP1 = 0x%x\n",
61 txq_id, reg);
62 iwl_set_bit(priv, CSR_GP_CNTRL,
63 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
64 return;
65 }
66
67 iwl_write_direct32(priv, HBUS_TARG_WRPTR,
68 txq->q.write_ptr | (txq_id << 8));
69
70 /* else not in power-save mode, uCode will never sleep when we're
71 * trying to tx (during RFKILL, we're not trying to tx). */
72 } else
73 iwl_write32(priv, HBUS_TARG_WRPTR, 54 iwl_write32(priv, HBUS_TARG_WRPTR,
74 txq->q.write_ptr | (txq_id << 8)); 55 txq->q.write_ptr | (txq_id << 8));
56 } else {
57 /* if we're trying to save power */
58 if (test_bit(STATUS_POWER_PMI, &priv->status)) {
59 /* wake up nic if it's powered down ...
60 * uCode will wake up, and interrupt us again, so next
61 * time we'll skip this part. */
62 reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
63
64 if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
65 IWL_DEBUG_INFO(priv,
66 "Tx queue %d requesting wakeup,"
67 " GP1 = 0x%x\n", txq_id, reg);
68 iwl_set_bit(priv, CSR_GP_CNTRL,
69 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
70 return;
71 }
72
73 iwl_write_direct32(priv, HBUS_TARG_WRPTR,
74 txq->q.write_ptr | (txq_id << 8));
75 75
76 /*
77 * else not in power-save mode,
78 * uCode will never sleep when we're
79 * trying to tx (during RFKILL, we're not trying to tx).
80 */
81 } else
82 iwl_write32(priv, HBUS_TARG_WRPTR,
83 txq->q.write_ptr | (txq_id << 8));
84 }
76 txq->need_update = 0; 85 txq->need_update = 0;
77} 86}
78EXPORT_SYMBOL(iwl_txq_update_write_ptr); 87EXPORT_SYMBOL(iwl_txq_update_write_ptr);