aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-eeprom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-eeprom.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c113
1 files changed, 68 insertions, 45 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 833194a2c639..47a56bc1cd12 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -142,6 +142,45 @@ static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */
*
******************************************************************************/
+/*
+ * The device's EEPROM semaphore prevents conflicts between driver and uCode
+ * when accessing the EEPROM; each access is a series of pulses to/from the
+ * EEPROM chip, not a single event, so even reads could conflict if they
+ * weren't arbitrated by the semaphore.
+ */
+static int iwl_eeprom_acquire_semaphore(struct iwl_priv *priv)
+{
+ u16 count;
+ int ret;
+
+ for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
+ /* Request semaphore */
+ iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+
+ /* See if we got it */
+ ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+ EEPROM_SEM_TIMEOUT);
+ if (ret >= 0) {
+ IWL_DEBUG_EEPROM(priv,
+ "Acquired semaphore after %d tries.\n",
+ count+1);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static void iwl_eeprom_release_semaphore(struct iwl_priv *priv)
+{
+ iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+
+}
+
static int iwl_eeprom_verify_signature(struct iwl_priv *priv)
{
u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
@@ -177,29 +216,26 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv)
static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
{
- u32 otpgp;
+ iwl_read32(priv, CSR_OTP_GP_REG);
- otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
if (mode == IWL_OTP_ACCESS_ABSOLUTE)
iwl_clear_bit(priv, CSR_OTP_GP_REG,
- CSR_OTP_GP_REG_OTP_ACCESS_MODE);
+ CSR_OTP_GP_REG_OTP_ACCESS_MODE);
else
iwl_set_bit(priv, CSR_OTP_GP_REG,
- CSR_OTP_GP_REG_OTP_ACCESS_MODE);
+ CSR_OTP_GP_REG_OTP_ACCESS_MODE);
}
-static int iwlcore_get_nvm_type(struct iwl_priv *priv)
+static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev)
{
u32 otpgp;
int nvm_type;
/* OTP only valid for CP/PP and after */
- switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
+ switch (hw_rev & CSR_HW_REV_TYPE_MSK) {
case CSR_HW_REV_TYPE_NONE:
IWL_ERR(priv, "Unknown hardware type\n");
return -ENOENT;
- case CSR_HW_REV_TYPE_3945:
- case CSR_HW_REV_TYPE_4965:
case CSR_HW_REV_TYPE_5300:
case CSR_HW_REV_TYPE_5350:
case CSR_HW_REV_TYPE_5100:
@@ -217,26 +253,20 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv)
return nvm_type;
}
-const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
-{
- BUG_ON(offset >= priv->cfg->base_params->eeprom_size);
- return &priv->eeprom[offset];
-}
-
static int iwl_init_otp_access(struct iwl_priv *priv)
{
int ret;
/* Enable 40MHz radio clock */
- _iwl_write32(priv, CSR_GP_CNTRL,
- _iwl_read32(priv, CSR_GP_CNTRL) |
- CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+ iwl_write32(priv, CSR_GP_CNTRL,
+ iwl_read32(priv, CSR_GP_CNTRL) |
+ CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/* wait for clock to be ready */
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);
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+ 25000);
if (ret < 0)
IWL_ERR(priv, "Time out access OTP\n");
else {
@@ -263,17 +293,17 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat
u32 r;
u32 otpgp;
- _iwl_write32(priv, CSR_EEPROM_REG,
- CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
+ iwl_write32(priv, CSR_EEPROM_REG,
+ CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
ret = iwl_poll_bit(priv, CSR_EEPROM_REG,
- CSR_EEPROM_REG_READ_VALID_MSK,
- CSR_EEPROM_REG_READ_VALID_MSK,
- IWL_EEPROM_ACCESS_TIMEOUT);
+ CSR_EEPROM_REG_READ_VALID_MSK,
+ CSR_EEPROM_REG_READ_VALID_MSK,
+ IWL_EEPROM_ACCESS_TIMEOUT);
if (ret < 0) {
IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
return ret;
}
- r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
+ r = iwl_read32(priv, CSR_EEPROM_REG);
/* check for ECC errors: */
otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
@@ -396,7 +426,7 @@ u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
*
* NOTE: This routine uses the non-debug IO access functions.
*/
-int iwl_eeprom_init(struct iwl_priv *priv)
+int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
{
__le16 *e;
u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
@@ -406,7 +436,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
u16 validblockaddr = 0;
u16 cache_addr = 0;
- priv->nvm_device_type = iwlcore_get_nvm_type(priv);
+ priv->nvm_device_type = iwlcore_get_nvm_type(priv, hw_rev);
if (priv->nvm_device_type == -ENOENT)
return -ENOENT;
/* allocate eeprom */
@@ -429,7 +459,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
}
/* Make sure driver (instead of uCode) is allowed to read EEPROM */
- ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv);
+ ret = iwl_eeprom_acquire_semaphore(priv);
if (ret < 0) {
IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n");
ret = -ENOENT;
@@ -444,9 +474,9 @@ int iwl_eeprom_init(struct iwl_priv *priv)
ret = -ENOENT;
goto done;
}
- _iwl_write32(priv, CSR_EEPROM_GP,
- iwl_read32(priv, CSR_EEPROM_GP) &
- ~CSR_EEPROM_GP_IF_OWNER_MSK);
+ iwl_write32(priv, CSR_EEPROM_GP,
+ iwl_read32(priv, CSR_EEPROM_GP) &
+ ~CSR_EEPROM_GP_IF_OWNER_MSK);
iwl_set_bit(priv, CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
@@ -473,8 +503,8 @@ int iwl_eeprom_init(struct iwl_priv *priv)
for (addr = 0; addr < sz; addr += sizeof(u16)) {
u32 r;
- _iwl_write32(priv, CSR_EEPROM_REG,
- CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
+ iwl_write32(priv, CSR_EEPROM_REG,
+ CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
ret = iwl_poll_bit(priv, CSR_EEPROM_REG,
CSR_EEPROM_REG_READ_VALID_MSK,
@@ -484,7 +514,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr);
goto done;
}
- r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
+ r = iwl_read32(priv, CSR_EEPROM_REG);
e[addr / 2] = cpu_to_le16(r >> 16);
}
}
@@ -496,7 +526,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
ret = 0;
done:
- priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv);
+ iwl_eeprom_release_semaphore(priv);
err:
if (ret)
@@ -719,13 +749,6 @@ int iwl_init_channel_map(struct iwl_priv *priv)
flags & EEPROM_CHANNEL_RADAR))
? "" : "not ");
- /* Set the tx_power_user_lmt to the highest power
- * supported by any channel */
- if (eeprom_ch_info[ch].max_power_avg >
- priv->tx_power_user_lmt)
- priv->tx_power_user_lmt =
- eeprom_ch_info[ch].max_power_avg;
-
ch_info++;
}
}