/* * iwl_find_otp_image: find EEPROM image in OTP * finding the OTP block that contains the EEPROM image. * the last valid block on the link list (the block _before_ the last block) * is the block we should read and used to configure the device. * If all the available OTP blocks are full, the last block will be the block * we should read and used to configure the device. * only perform this operation if shadow RAM is disabled */ static int iwl_find_otp_image(struct iwl_priv *priv, u16 *validblockaddr) { u16 next_link_addr = 0, link_value = 0, valid_addr; int ret = 0; int usedblocks = 0; /* set addressing mode to absolute to traverse the link list */ iwl_set_otp_access(priv, IWL_OTP_ACCESS_ABSOLUTE); /* checking for empty OTP or error */ if (iwl_is_otp_empty(priv)) return -EINVAL; /* * start traverse link list * until reach the max number of OTP blocks * different devices have different number of OTP blocks */ do { /* save current valid block address * check for more block on the link list */ valid_addr = next_link_addr; next_link_addr = link_value; IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n", usedblocks, next_link_addr); if (iwl_read_otp_word(priv, next_link_addr, &link_value)) return -EINVAL; if (!link_value) { /* * reach the end of link list, * set address point to the starting address * of the image */ goto done; } /* more in the link list, continue */ usedblocks++; } while (usedblocks < priv->cfg->max_ll_items); /* OTP full, use last block */ IWL_DEBUG_INFO(priv, "OTP is full, use last block\n"); done: *validblockaddr = valid_addr; /* skip first 2 bytes (link list pointer) */ *validblockaddr += 2; return ret; }
/* * iwl_find_otp_image: find EEPROM image in OTP * finding the OTP block that contains the EEPROM image. * the last valid block on the link list (the block _before_ the last block) * is the block we should read and used to configure the device. * If all the available OTP blocks are full, the last block will be the block * we should read and used to configure the device. * only perform this operation if shadow RAM is disabled */ static int iwl_find_otp_image(struct iwl_trans *trans, u16 *validblockaddr) { u16 next_link_addr = 0, valid_addr; __le16 link_value = 0; int usedblocks = 0; /* set addressing mode to absolute to traverse the link list */ iwl_set_otp_access_absolute(trans); /* checking for empty OTP or error */ if (iwl_is_otp_empty(trans)) return -EINVAL; /* * start traverse link list * until reach the max number of OTP blocks * different devices have different number of OTP blocks */ do { /* save current valid block address * check for more block on the link list */ valid_addr = next_link_addr; next_link_addr = le16_to_cpu(link_value) * sizeof(u16); IWL_DEBUG_EEPROM(trans->dev, "OTP blocks %d addr 0x%x\n", usedblocks, next_link_addr); if (iwl_read_otp_word(trans, next_link_addr, &link_value)) return -EINVAL; if (!link_value) { /* * reach the end of link list, return success and * set address point to the starting address * of the image */ *validblockaddr = valid_addr; /* skip first 2 bytes (link list pointer) */ *validblockaddr += 2; return 0; } /* more in the link list, continue */ usedblocks++; } while (usedblocks <= trans->cfg->base_params->max_ll_items); /* OTP has no valid blocks */ IWL_DEBUG_EEPROM(trans->dev, "OTP has no valid blocks\n"); return -EINVAL; }