/** * iwl_eeprom_init - read EEPROM contents * * Load the EEPROM contents from adapter into priv->eeprom * * NOTE: This routine uses the non-debug IO access functions. */ int iwl_eeprom_init(struct iwl_priv *priv) { u16 *e; u32 gp = iwl_read32(priv, CSR_EEPROM_GP); int sz; int ret; u16 addr; u16 validblockaddr = 0; u16 cache_addr = 0; priv->nvm_device_type = iwlcore_get_nvm_type(priv); /* allocate eeprom */ IWL_DEBUG_INFO(priv, "NVM size = %d\n", priv->cfg->eeprom_size); sz = priv->cfg->eeprom_size; priv->eeprom = kzalloc(sz, GFP_KERNEL); if (!priv->eeprom) { ret = -ENOMEM; goto alloc_err; } e = (u16 *)priv->eeprom; ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); if (ret < 0) { IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); ret = -ENOENT; goto err; } /* Make sure driver (instead of uCode) is allowed to read EEPROM */ ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv); if (ret < 0) { IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n"); ret = -ENOENT; goto err; } if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { ret = iwl_init_otp_access(priv); if (ret) { IWL_ERR(priv, "Failed to initialize OTP access.\n"); ret = -ENOENT; goto done; } _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 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); /* traversing the linked list if no shadow ram supported */ if (!priv->cfg->shadow_ram_support) { if (iwl_find_otp_image(priv, &validblockaddr)) { ret = -ENOENT; goto done; } } for (addr = validblockaddr; addr < validblockaddr + sz; addr += sizeof(u16)) { u16 eeprom_data; ret = iwl_read_otp_word(priv, addr, &eeprom_data); if (ret) goto done; e[cache_addr / 2] = eeprom_data; cache_addr += sizeof(u16); } } else { /* eeprom is an array of 16bit values */ for (addr = 0; addr < sz; addr += sizeof(u16)) { u32 r; _iwl_write32(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); if (ret < 0) { IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); goto done; } r = _iwl_read_direct32(priv, CSR_EEPROM_REG); e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); } } ret = 0; done: priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); err: if (ret) iwl_eeprom_free(priv); alloc_err: return ret; }
/** * iwl_read_eeprom - read EEPROM contents * * Load the EEPROM contents from adapter and return it * and its size. * * NOTE: This routine uses the non-debug IO access functions. */ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) { __le16 *e; u32 gp = iwl_read32(trans, CSR_EEPROM_GP); int sz; int ret; u16 addr; u16 validblockaddr = 0; u16 cache_addr = 0; int nvm_is_otp; if (!eeprom || !eeprom_size) return -EINVAL; nvm_is_otp = iwl_nvm_is_otp(trans); if (nvm_is_otp < 0) return nvm_is_otp; sz = trans->cfg->base_params->eeprom_size; IWL_DEBUG_EEPROM(trans->dev, "NVM size = %d\n", sz); e = kmalloc(sz, GFP_KERNEL); if (!e) return -ENOMEM; ret = iwl_eeprom_verify_signature(trans, nvm_is_otp); if (ret < 0) { IWL_ERR(trans, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); goto err_free; } /* Make sure driver (instead of uCode) is allowed to read EEPROM */ ret = iwl_eeprom_acquire_semaphore(trans); if (ret < 0) { IWL_ERR(trans, "Failed to acquire EEPROM semaphore.\n"); goto err_free; } if (nvm_is_otp) { ret = iwl_init_otp_access(trans); if (ret) { IWL_ERR(trans, "Failed to initialize OTP access.\n"); goto err_unlock; } iwl_write32(trans, CSR_EEPROM_GP, iwl_read32(trans, CSR_EEPROM_GP) & ~CSR_EEPROM_GP_IF_OWNER_MSK); iwl_set_bit(trans, CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); /* traversing the linked list if no shadow ram supported */ if (!trans->cfg->base_params->shadow_ram_support) { ret = iwl_find_otp_image(trans, &validblockaddr); if (ret) goto err_unlock; } for (addr = validblockaddr; addr < validblockaddr + sz; addr += sizeof(u16)) { __le16 eeprom_data; ret = iwl_read_otp_word(trans, addr, &eeprom_data); if (ret) goto err_unlock; e[cache_addr / 2] = eeprom_data; cache_addr += sizeof(u16); } } else { /* eeprom is an array of 16bit values */ for (addr = 0; addr < sz; addr += sizeof(u16)) { u32 r; iwl_write32(trans, CSR_EEPROM_REG, CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); ret = iwl_poll_bit(trans, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); if (ret < 0) { IWL_ERR(trans, "Time out reading EEPROM[%d]\n", addr); goto err_unlock; } r = iwl_read32(trans, CSR_EEPROM_REG); e[addr / 2] = cpu_to_le16(r >> 16); } } IWL_DEBUG_EEPROM(trans->dev, "NVM Type: %s\n", nvm_is_otp ? "OTP" : "EEPROM"); iwl_eeprom_release_semaphore(trans); *eeprom_size = sz; *eeprom = (u8 *)e; return 0; err_unlock: iwl_eeprom_release_semaphore(trans); err_free: kfree(e); return ret; }