171d10453SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */ 2015f8cc5SEric Joyner /* Copyright (c) 2024, Intel Corporation 371d10453SEric Joyner * All rights reserved. 471d10453SEric Joyner * 571d10453SEric Joyner * Redistribution and use in source and binary forms, with or without 671d10453SEric Joyner * modification, are permitted provided that the following conditions are met: 771d10453SEric Joyner * 871d10453SEric Joyner * 1. Redistributions of source code must retain the above copyright notice, 971d10453SEric Joyner * this list of conditions and the following disclaimer. 1071d10453SEric Joyner * 1171d10453SEric Joyner * 2. Redistributions in binary form must reproduce the above copyright 1271d10453SEric Joyner * notice, this list of conditions and the following disclaimer in the 1371d10453SEric Joyner * documentation and/or other materials provided with the distribution. 1471d10453SEric Joyner * 1571d10453SEric Joyner * 3. Neither the name of the Intel Corporation nor the names of its 1671d10453SEric Joyner * contributors may be used to endorse or promote products derived from 1771d10453SEric Joyner * this software without specific prior written permission. 1871d10453SEric Joyner * 1971d10453SEric Joyner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2071d10453SEric Joyner * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2171d10453SEric Joyner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2271d10453SEric Joyner * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2371d10453SEric Joyner * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2471d10453SEric Joyner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2571d10453SEric Joyner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2671d10453SEric Joyner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2771d10453SEric Joyner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2871d10453SEric Joyner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2971d10453SEric Joyner * POSSIBILITY OF SUCH DAMAGE. 3071d10453SEric Joyner */ 3171d10453SEric Joyner 3271d10453SEric Joyner #include "ice_common.h" 3371d10453SEric Joyner 3456429daeSEric Joyner #define GL_MNG_DEF_DEVID 0x000B611C 3556429daeSEric Joyner 3671d10453SEric Joyner /** 3771d10453SEric Joyner * ice_aq_read_nvm 3871d10453SEric Joyner * @hw: pointer to the HW struct 3971d10453SEric Joyner * @module_typeid: module pointer location in words from the NVM beginning 4071d10453SEric Joyner * @offset: byte offset from the module beginning 4171d10453SEric Joyner * @length: length of the section to be read (in bytes from the offset) 4271d10453SEric Joyner * @data: command buffer (size [bytes] = length) 4371d10453SEric Joyner * @last_command: tells if this is the last command in a series 4471d10453SEric Joyner * @read_shadow_ram: tell if this is a shadow RAM read 4571d10453SEric Joyner * @cd: pointer to command details structure or NULL 4671d10453SEric Joyner * 4771d10453SEric Joyner * Read the NVM using the admin queue commands (0x0701) 4871d10453SEric Joyner */ 49f2635e84SEric Joyner int 5071d10453SEric Joyner ice_aq_read_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset, u16 length, 5171d10453SEric Joyner void *data, bool last_command, bool read_shadow_ram, 5271d10453SEric Joyner struct ice_sq_cd *cd) 5371d10453SEric Joyner { 5471d10453SEric Joyner struct ice_aq_desc desc; 5571d10453SEric Joyner struct ice_aqc_nvm *cmd; 5671d10453SEric Joyner 5771d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 5871d10453SEric Joyner 5971d10453SEric Joyner cmd = &desc.params.nvm; 6071d10453SEric Joyner 6171d10453SEric Joyner if (offset > ICE_AQC_NVM_MAX_OFFSET) 6271d10453SEric Joyner return ICE_ERR_PARAM; 6371d10453SEric Joyner 6471d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_read); 6571d10453SEric Joyner 6671d10453SEric Joyner if (!read_shadow_ram && module_typeid == ICE_AQC_NVM_START_POINT) 6771d10453SEric Joyner cmd->cmd_flags |= ICE_AQC_NVM_FLASH_ONLY; 6871d10453SEric Joyner 6971d10453SEric Joyner /* If this is the last command in a series, set the proper flag. */ 7071d10453SEric Joyner if (last_command) 7171d10453SEric Joyner cmd->cmd_flags |= ICE_AQC_NVM_LAST_CMD; 7271d10453SEric Joyner cmd->module_typeid = CPU_TO_LE16(module_typeid); 7371d10453SEric Joyner cmd->offset_low = CPU_TO_LE16(offset & 0xFFFF); 7471d10453SEric Joyner cmd->offset_high = (offset >> 16) & 0xFF; 7571d10453SEric Joyner cmd->length = CPU_TO_LE16(length); 7671d10453SEric Joyner 7771d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, data, length, cd); 7871d10453SEric Joyner } 7971d10453SEric Joyner 8071d10453SEric Joyner /** 8171d10453SEric Joyner * ice_read_flat_nvm - Read portion of NVM by flat offset 8271d10453SEric Joyner * @hw: pointer to the HW struct 8371d10453SEric Joyner * @offset: offset from beginning of NVM 8471d10453SEric Joyner * @length: (in) number of bytes to read; (out) number of bytes actually read 8571d10453SEric Joyner * @data: buffer to return data in (sized to fit the specified length) 8671d10453SEric Joyner * @read_shadow_ram: if true, read from shadow RAM instead of NVM 8771d10453SEric Joyner * 8871d10453SEric Joyner * Reads a portion of the NVM, as a flat memory space. This function correctly 8971d10453SEric Joyner * breaks read requests across Shadow RAM sectors and ensures that no single 907d7af7f8SEric Joyner * read request exceeds the maximum 4KB read for a single AdminQ command. 9171d10453SEric Joyner * 9271d10453SEric Joyner * Returns a status code on failure. Note that the data pointer may be 9371d10453SEric Joyner * partially updated if some reads succeed before a failure. 9471d10453SEric Joyner */ 95f2635e84SEric Joyner int 9671d10453SEric Joyner ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data, 9771d10453SEric Joyner bool read_shadow_ram) 9871d10453SEric Joyner { 9971d10453SEric Joyner u32 inlen = *length; 10071d10453SEric Joyner u32 bytes_read = 0; 10171d10453SEric Joyner bool last_cmd; 102f2635e84SEric Joyner int status; 10371d10453SEric Joyner 10471d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 10571d10453SEric Joyner 10671d10453SEric Joyner *length = 0; 10771d10453SEric Joyner 10871d10453SEric Joyner /* Verify the length of the read if this is for the Shadow RAM */ 109d08b8680SEric Joyner if (read_shadow_ram && ((offset + inlen) > (hw->flash.sr_words * 2u))) { 1107d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_NVM, "NVM error: requested data is beyond Shadow RAM limit\n"); 11171d10453SEric Joyner return ICE_ERR_PARAM; 11271d10453SEric Joyner } 11371d10453SEric Joyner 11471d10453SEric Joyner do { 11571d10453SEric Joyner u32 read_size, sector_offset; 11671d10453SEric Joyner 1177d7af7f8SEric Joyner /* ice_aq_read_nvm cannot read more than 4KB at a time. 11871d10453SEric Joyner * Additionally, a read from the Shadow RAM may not cross over 11971d10453SEric Joyner * a sector boundary. Conveniently, the sector size is also 1207d7af7f8SEric Joyner * 4KB. 12171d10453SEric Joyner */ 12271d10453SEric Joyner sector_offset = offset % ICE_AQ_MAX_BUF_LEN; 12371d10453SEric Joyner read_size = MIN_T(u32, ICE_AQ_MAX_BUF_LEN - sector_offset, 12471d10453SEric Joyner inlen - bytes_read); 12571d10453SEric Joyner 12671d10453SEric Joyner last_cmd = !(bytes_read + read_size < inlen); 12771d10453SEric Joyner 12871d10453SEric Joyner /* ice_aq_read_nvm takes the length as a u16. Our read_size is 12971d10453SEric Joyner * calculated using a u32, but the ICE_AQ_MAX_BUF_LEN maximum 13071d10453SEric Joyner * size guarantees that it will fit within the 2 bytes. 13171d10453SEric Joyner */ 13271d10453SEric Joyner status = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, 13371d10453SEric Joyner offset, (u16)read_size, 13471d10453SEric Joyner data + bytes_read, last_cmd, 13571d10453SEric Joyner read_shadow_ram, NULL); 13671d10453SEric Joyner if (status) 13771d10453SEric Joyner break; 13871d10453SEric Joyner 13971d10453SEric Joyner bytes_read += read_size; 14071d10453SEric Joyner offset += read_size; 14171d10453SEric Joyner } while (!last_cmd); 14271d10453SEric Joyner 14371d10453SEric Joyner *length = bytes_read; 14471d10453SEric Joyner return status; 14571d10453SEric Joyner } 14671d10453SEric Joyner 14771d10453SEric Joyner /** 14871d10453SEric Joyner * ice_aq_update_nvm 14971d10453SEric Joyner * @hw: pointer to the HW struct 15071d10453SEric Joyner * @module_typeid: module pointer location in words from the NVM beginning 15171d10453SEric Joyner * @offset: byte offset from the module beginning 15271d10453SEric Joyner * @length: length of the section to be written (in bytes from the offset) 15371d10453SEric Joyner * @data: command buffer (size [bytes] = length) 15471d10453SEric Joyner * @last_command: tells if this is the last command in a series 15571d10453SEric Joyner * @command_flags: command parameters 15671d10453SEric Joyner * @cd: pointer to command details structure or NULL 15771d10453SEric Joyner * 15871d10453SEric Joyner * Update the NVM using the admin queue commands (0x0703) 15971d10453SEric Joyner */ 160f2635e84SEric Joyner int 16171d10453SEric Joyner ice_aq_update_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset, 16271d10453SEric Joyner u16 length, void *data, bool last_command, u8 command_flags, 16371d10453SEric Joyner struct ice_sq_cd *cd) 16471d10453SEric Joyner { 16571d10453SEric Joyner struct ice_aq_desc desc; 16671d10453SEric Joyner struct ice_aqc_nvm *cmd; 16771d10453SEric Joyner 16871d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 16971d10453SEric Joyner 17071d10453SEric Joyner cmd = &desc.params.nvm; 17171d10453SEric Joyner 17271d10453SEric Joyner /* In offset the highest byte must be zeroed. */ 17371d10453SEric Joyner if (offset & 0xFF000000) 17471d10453SEric Joyner return ICE_ERR_PARAM; 17571d10453SEric Joyner 17671d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_write); 17771d10453SEric Joyner 17871d10453SEric Joyner cmd->cmd_flags |= command_flags; 17971d10453SEric Joyner 18071d10453SEric Joyner /* If this is the last command in a series, set the proper flag. */ 18171d10453SEric Joyner if (last_command) 18271d10453SEric Joyner cmd->cmd_flags |= ICE_AQC_NVM_LAST_CMD; 18371d10453SEric Joyner cmd->module_typeid = CPU_TO_LE16(module_typeid); 18471d10453SEric Joyner cmd->offset_low = CPU_TO_LE16(offset & 0xFFFF); 18571d10453SEric Joyner cmd->offset_high = (offset >> 16) & 0xFF; 18671d10453SEric Joyner cmd->length = CPU_TO_LE16(length); 18771d10453SEric Joyner 18871d10453SEric Joyner desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 18971d10453SEric Joyner 19071d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, data, length, cd); 19171d10453SEric Joyner } 19271d10453SEric Joyner 19371d10453SEric Joyner /** 19471d10453SEric Joyner * ice_aq_erase_nvm 19571d10453SEric Joyner * @hw: pointer to the HW struct 19671d10453SEric Joyner * @module_typeid: module pointer location in words from the NVM beginning 19771d10453SEric Joyner * @cd: pointer to command details structure or NULL 19871d10453SEric Joyner * 19971d10453SEric Joyner * Erase the NVM sector using the admin queue commands (0x0702) 20071d10453SEric Joyner */ 201f2635e84SEric Joyner int ice_aq_erase_nvm(struct ice_hw *hw, u16 module_typeid, struct ice_sq_cd *cd) 20271d10453SEric Joyner { 20371d10453SEric Joyner struct ice_aq_desc desc; 20471d10453SEric Joyner struct ice_aqc_nvm *cmd; 205f2635e84SEric Joyner int status; 206d08b8680SEric Joyner __le16 len; 20771d10453SEric Joyner 20871d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 20971d10453SEric Joyner 210d08b8680SEric Joyner /* read a length value from SR, so module_typeid is equal to 0 */ 211d08b8680SEric Joyner /* calculate offset where module size is placed from bytes to words */ 212d08b8680SEric Joyner /* set last command and read from SR values to true */ 213d08b8680SEric Joyner status = ice_aq_read_nvm(hw, 0, 2 * module_typeid + 2, 2, &len, true, 214d08b8680SEric Joyner true, NULL); 215d08b8680SEric Joyner if (status) 216d08b8680SEric Joyner return status; 217d08b8680SEric Joyner 21871d10453SEric Joyner cmd = &desc.params.nvm; 21971d10453SEric Joyner 22071d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_erase); 22171d10453SEric Joyner 22271d10453SEric Joyner cmd->module_typeid = CPU_TO_LE16(module_typeid); 223d08b8680SEric Joyner cmd->length = len; 22471d10453SEric Joyner cmd->offset_low = 0; 22571d10453SEric Joyner cmd->offset_high = 0; 22671d10453SEric Joyner 22771d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 22871d10453SEric Joyner } 22971d10453SEric Joyner 23071d10453SEric Joyner /** 23171d10453SEric Joyner * ice_aq_read_nvm_cfg - read an NVM config block 23271d10453SEric Joyner * @hw: pointer to the HW struct 23371d10453SEric Joyner * @cmd_flags: NVM access admin command bits 23471d10453SEric Joyner * @field_id: field or feature ID 23571d10453SEric Joyner * @data: buffer for result 23671d10453SEric Joyner * @buf_size: buffer size 23771d10453SEric Joyner * @elem_count: pointer to count of elements read by FW 23871d10453SEric Joyner * @cd: pointer to command details structure or NULL 23971d10453SEric Joyner * 24071d10453SEric Joyner * Reads single or multiple feature/field ID and data (0x0704) 24171d10453SEric Joyner */ 242f2635e84SEric Joyner int 24371d10453SEric Joyner ice_aq_read_nvm_cfg(struct ice_hw *hw, u8 cmd_flags, u16 field_id, void *data, 24471d10453SEric Joyner u16 buf_size, u16 *elem_count, struct ice_sq_cd *cd) 24571d10453SEric Joyner { 24671d10453SEric Joyner struct ice_aqc_nvm_cfg *cmd; 24771d10453SEric Joyner struct ice_aq_desc desc; 248f2635e84SEric Joyner int status; 24971d10453SEric Joyner 25071d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 25171d10453SEric Joyner 25271d10453SEric Joyner cmd = &desc.params.nvm_cfg; 25371d10453SEric Joyner 25471d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_cfg_read); 25571d10453SEric Joyner 25671d10453SEric Joyner cmd->cmd_flags = cmd_flags; 25771d10453SEric Joyner cmd->id = CPU_TO_LE16(field_id); 25871d10453SEric Joyner 25971d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, data, buf_size, cd); 26071d10453SEric Joyner if (!status && elem_count) 26171d10453SEric Joyner *elem_count = LE16_TO_CPU(cmd->count); 26271d10453SEric Joyner 26371d10453SEric Joyner return status; 26471d10453SEric Joyner } 26571d10453SEric Joyner 26671d10453SEric Joyner /** 26771d10453SEric Joyner * ice_aq_write_nvm_cfg - write an NVM config block 26871d10453SEric Joyner * @hw: pointer to the HW struct 26971d10453SEric Joyner * @cmd_flags: NVM access admin command bits 27071d10453SEric Joyner * @data: buffer for result 27171d10453SEric Joyner * @buf_size: buffer size 27271d10453SEric Joyner * @elem_count: count of elements to be written 27371d10453SEric Joyner * @cd: pointer to command details structure or NULL 27471d10453SEric Joyner * 27571d10453SEric Joyner * Writes single or multiple feature/field ID and data (0x0705) 27671d10453SEric Joyner */ 277f2635e84SEric Joyner int 27871d10453SEric Joyner ice_aq_write_nvm_cfg(struct ice_hw *hw, u8 cmd_flags, void *data, u16 buf_size, 27971d10453SEric Joyner u16 elem_count, struct ice_sq_cd *cd) 28071d10453SEric Joyner { 28171d10453SEric Joyner struct ice_aqc_nvm_cfg *cmd; 28271d10453SEric Joyner struct ice_aq_desc desc; 28371d10453SEric Joyner 28471d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 28571d10453SEric Joyner 28671d10453SEric Joyner cmd = &desc.params.nvm_cfg; 28771d10453SEric Joyner 28871d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_cfg_write); 28971d10453SEric Joyner desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 29071d10453SEric Joyner 29171d10453SEric Joyner cmd->count = CPU_TO_LE16(elem_count); 29271d10453SEric Joyner cmd->cmd_flags = cmd_flags; 29371d10453SEric Joyner 29471d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, data, buf_size, cd); 29571d10453SEric Joyner } 29671d10453SEric Joyner 29771d10453SEric Joyner /** 2989e54973fSEric Joyner * ice_check_sr_access_params - verify params for Shadow RAM R/W operations 29971d10453SEric Joyner * @hw: pointer to the HW structure 30071d10453SEric Joyner * @offset: offset in words from module start 30171d10453SEric Joyner * @words: number of words to access 30271d10453SEric Joyner */ 303f2635e84SEric Joyner static int 30471d10453SEric Joyner ice_check_sr_access_params(struct ice_hw *hw, u32 offset, u16 words) 30571d10453SEric Joyner { 306d08b8680SEric Joyner if ((offset + words) > hw->flash.sr_words) { 3077d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_NVM, "NVM error: offset beyond SR lmt.\n"); 30871d10453SEric Joyner return ICE_ERR_PARAM; 30971d10453SEric Joyner } 31071d10453SEric Joyner 31171d10453SEric Joyner if (words > ICE_SR_SECTOR_SIZE_IN_WORDS) { 31271d10453SEric Joyner /* We can access only up to 4KB (one sector), in one AQ write */ 3137d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_NVM, "NVM error: tried to access %d words, limit is %d.\n", 31471d10453SEric Joyner words, ICE_SR_SECTOR_SIZE_IN_WORDS); 31571d10453SEric Joyner return ICE_ERR_PARAM; 31671d10453SEric Joyner } 31771d10453SEric Joyner 31871d10453SEric Joyner if (((offset + (words - 1)) / ICE_SR_SECTOR_SIZE_IN_WORDS) != 31971d10453SEric Joyner (offset / ICE_SR_SECTOR_SIZE_IN_WORDS)) { 32071d10453SEric Joyner /* A single access cannot spread over two sectors */ 3217d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_NVM, "NVM error: cannot spread over two sectors.\n"); 32271d10453SEric Joyner return ICE_ERR_PARAM; 32371d10453SEric Joyner } 32471d10453SEric Joyner 325f2635e84SEric Joyner return 0; 32671d10453SEric Joyner } 32771d10453SEric Joyner 32871d10453SEric Joyner /** 32971d10453SEric Joyner * ice_read_sr_word_aq - Reads Shadow RAM via AQ 33071d10453SEric Joyner * @hw: pointer to the HW structure 33171d10453SEric Joyner * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) 33271d10453SEric Joyner * @data: word read from the Shadow RAM 33371d10453SEric Joyner * 33471d10453SEric Joyner * Reads one 16 bit word from the Shadow RAM using ice_read_flat_nvm. 33571d10453SEric Joyner */ 336f2635e84SEric Joyner int ice_read_sr_word_aq(struct ice_hw *hw, u16 offset, u16 *data) 33771d10453SEric Joyner { 33871d10453SEric Joyner u32 bytes = sizeof(u16); 33971d10453SEric Joyner __le16 data_local; 340f2635e84SEric Joyner int status; 34171d10453SEric Joyner 34271d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 34371d10453SEric Joyner 34471d10453SEric Joyner /* Note that ice_read_flat_nvm checks if the read is past the Shadow 34571d10453SEric Joyner * RAM size, and ensures we don't read across a Shadow RAM sector 34671d10453SEric Joyner * boundary 34771d10453SEric Joyner */ 34871d10453SEric Joyner status = ice_read_flat_nvm(hw, offset * sizeof(u16), &bytes, 3497d7af7f8SEric Joyner (_FORCE_ u8 *)&data_local, true); 35071d10453SEric Joyner if (status) 35171d10453SEric Joyner return status; 35271d10453SEric Joyner 35371d10453SEric Joyner *data = LE16_TO_CPU(data_local); 354f2635e84SEric Joyner return 0; 35571d10453SEric Joyner } 35671d10453SEric Joyner 35771d10453SEric Joyner /** 3589e54973fSEric Joyner * ice_write_sr_aq - Writes Shadow RAM 35971d10453SEric Joyner * @hw: pointer to the HW structure 36071d10453SEric Joyner * @offset: offset in words from module start 36171d10453SEric Joyner * @words: number of words to write 36271d10453SEric Joyner * @data: buffer with words to write to the Shadow RAM 36371d10453SEric Joyner * @last_command: tells the AdminQ that this is the last command 36471d10453SEric Joyner * 36571d10453SEric Joyner * Writes a 16 bit words buffer to the Shadow RAM using the admin command. 36671d10453SEric Joyner */ 367f2635e84SEric Joyner static int 36871d10453SEric Joyner ice_write_sr_aq(struct ice_hw *hw, u32 offset, u16 words, __le16 *data, 36971d10453SEric Joyner bool last_command) 37071d10453SEric Joyner { 371f2635e84SEric Joyner int status; 37271d10453SEric Joyner 37371d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 37471d10453SEric Joyner 37571d10453SEric Joyner status = ice_check_sr_access_params(hw, offset, words); 37671d10453SEric Joyner if (!status) 37771d10453SEric Joyner status = ice_aq_update_nvm(hw, 0, 2 * offset, 2 * words, data, 37871d10453SEric Joyner last_command, 0, NULL); 37971d10453SEric Joyner 38071d10453SEric Joyner return status; 38171d10453SEric Joyner } 38271d10453SEric Joyner 38371d10453SEric Joyner /** 38471d10453SEric Joyner * ice_read_sr_buf_aq - Reads Shadow RAM buf via AQ 38571d10453SEric Joyner * @hw: pointer to the HW structure 38671d10453SEric Joyner * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) 38771d10453SEric Joyner * @words: (in) number of words to read; (out) number of words actually read 38871d10453SEric Joyner * @data: words read from the Shadow RAM 38971d10453SEric Joyner * 39071d10453SEric Joyner * Reads 16 bit words (data buf) from the Shadow RAM. Ownership of the NVM is 39171d10453SEric Joyner * taken before reading the buffer and later released. 39271d10453SEric Joyner */ 393f2635e84SEric Joyner static int 39471d10453SEric Joyner ice_read_sr_buf_aq(struct ice_hw *hw, u16 offset, u16 *words, u16 *data) 39571d10453SEric Joyner { 39671d10453SEric Joyner u32 bytes = *words * 2, i; 397f2635e84SEric Joyner int status; 39871d10453SEric Joyner 39971d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 40071d10453SEric Joyner 4017d7af7f8SEric Joyner /* ice_read_flat_nvm takes into account the 4KB AdminQ and Shadow RAM 40271d10453SEric Joyner * sector restrictions necessary when reading from the NVM. 40371d10453SEric Joyner */ 40471d10453SEric Joyner status = ice_read_flat_nvm(hw, offset * 2, &bytes, (u8 *)data, true); 40571d10453SEric Joyner 40671d10453SEric Joyner /* Report the number of words successfully read */ 4078923de59SPiotr Kubaj *words = (u16)(bytes / 2); 40871d10453SEric Joyner 40971d10453SEric Joyner /* Byte swap the words up to the amount we actually read */ 41071d10453SEric Joyner for (i = 0; i < *words; i++) 41171d10453SEric Joyner data[i] = LE16_TO_CPU(((_FORCE_ __le16 *)data)[i]); 41271d10453SEric Joyner 41371d10453SEric Joyner return status; 41471d10453SEric Joyner } 41571d10453SEric Joyner 41671d10453SEric Joyner /** 41771d10453SEric Joyner * ice_acquire_nvm - Generic request for acquiring the NVM ownership 41871d10453SEric Joyner * @hw: pointer to the HW structure 41971d10453SEric Joyner * @access: NVM access type (read or write) 42071d10453SEric Joyner * 42171d10453SEric Joyner * This function will request NVM ownership. 42271d10453SEric Joyner */ 423f2635e84SEric Joyner int ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access) 42471d10453SEric Joyner { 42571d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 426d08b8680SEric Joyner if (hw->flash.blank_nvm_mode) 427f2635e84SEric Joyner return 0; 42871d10453SEric Joyner 42971d10453SEric Joyner return ice_acquire_res(hw, ICE_NVM_RES_ID, access, ICE_NVM_TIMEOUT); 43071d10453SEric Joyner } 43171d10453SEric Joyner 43271d10453SEric Joyner /** 43371d10453SEric Joyner * ice_release_nvm - Generic request for releasing the NVM ownership 43471d10453SEric Joyner * @hw: pointer to the HW structure 43571d10453SEric Joyner * 43671d10453SEric Joyner * This function will release NVM ownership. 43771d10453SEric Joyner */ 43871d10453SEric Joyner void ice_release_nvm(struct ice_hw *hw) 43971d10453SEric Joyner { 44071d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 44171d10453SEric Joyner 442d08b8680SEric Joyner if (hw->flash.blank_nvm_mode) 44371d10453SEric Joyner return; 44471d10453SEric Joyner 44571d10453SEric Joyner ice_release_res(hw, ICE_NVM_RES_ID); 44671d10453SEric Joyner } 44771d10453SEric Joyner 44871d10453SEric Joyner /** 449d08b8680SEric Joyner * ice_get_flash_bank_offset - Get offset into requested flash bank 450d08b8680SEric Joyner * @hw: pointer to the HW structure 451d08b8680SEric Joyner * @bank: whether to read from the active or inactive flash bank 452d08b8680SEric Joyner * @module: the module to read from 453d08b8680SEric Joyner * 454d08b8680SEric Joyner * Based on the module, lookup the module offset from the beginning of the 455d08b8680SEric Joyner * flash. 456d08b8680SEric Joyner * 457d08b8680SEric Joyner * Returns the flash offset. Note that a value of zero is invalid and must be 458d08b8680SEric Joyner * treated as an error. 459d08b8680SEric Joyner */ 460d08b8680SEric Joyner static u32 ice_get_flash_bank_offset(struct ice_hw *hw, enum ice_bank_select bank, u16 module) 461d08b8680SEric Joyner { 462d08b8680SEric Joyner struct ice_bank_info *banks = &hw->flash.banks; 463d08b8680SEric Joyner enum ice_flash_bank active_bank; 464d08b8680SEric Joyner bool second_bank_active; 465d08b8680SEric Joyner u32 offset, size; 466d08b8680SEric Joyner 467d08b8680SEric Joyner switch (module) { 468d08b8680SEric Joyner case ICE_SR_1ST_NVM_BANK_PTR: 469d08b8680SEric Joyner offset = banks->nvm_ptr; 470d08b8680SEric Joyner size = banks->nvm_size; 471d08b8680SEric Joyner active_bank = banks->nvm_bank; 472d08b8680SEric Joyner break; 473d08b8680SEric Joyner case ICE_SR_1ST_OROM_BANK_PTR: 474d08b8680SEric Joyner offset = banks->orom_ptr; 475d08b8680SEric Joyner size = banks->orom_size; 476d08b8680SEric Joyner active_bank = banks->orom_bank; 477d08b8680SEric Joyner break; 478d08b8680SEric Joyner case ICE_SR_NETLIST_BANK_PTR: 479d08b8680SEric Joyner offset = banks->netlist_ptr; 480d08b8680SEric Joyner size = banks->netlist_size; 481d08b8680SEric Joyner active_bank = banks->netlist_bank; 482d08b8680SEric Joyner break; 483d08b8680SEric Joyner default: 484d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Unexpected value for flash module: 0x%04x\n", module); 485d08b8680SEric Joyner return 0; 486d08b8680SEric Joyner } 487d08b8680SEric Joyner 488d08b8680SEric Joyner switch (active_bank) { 489d08b8680SEric Joyner case ICE_1ST_FLASH_BANK: 490d08b8680SEric Joyner second_bank_active = false; 491d08b8680SEric Joyner break; 492d08b8680SEric Joyner case ICE_2ND_FLASH_BANK: 493d08b8680SEric Joyner second_bank_active = true; 494d08b8680SEric Joyner break; 495d08b8680SEric Joyner default: 496d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Unexpected value for active flash bank: %u\n", 497d08b8680SEric Joyner active_bank); 498d08b8680SEric Joyner return 0; 499d08b8680SEric Joyner } 500d08b8680SEric Joyner 501d08b8680SEric Joyner /* The second flash bank is stored immediately following the first 502d08b8680SEric Joyner * bank. Based on whether the 1st or 2nd bank is active, and whether 503d08b8680SEric Joyner * we want the active or inactive bank, calculate the desired offset. 504d08b8680SEric Joyner */ 505d08b8680SEric Joyner switch (bank) { 506d08b8680SEric Joyner case ICE_ACTIVE_FLASH_BANK: 507d08b8680SEric Joyner return offset + (second_bank_active ? size : 0); 508d08b8680SEric Joyner case ICE_INACTIVE_FLASH_BANK: 509d08b8680SEric Joyner return offset + (second_bank_active ? 0 : size); 510d08b8680SEric Joyner } 511d08b8680SEric Joyner 512d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Unexpected value for flash bank selection: %u\n", bank); 513d08b8680SEric Joyner return 0; 514d08b8680SEric Joyner } 515d08b8680SEric Joyner 516d08b8680SEric Joyner /** 517d08b8680SEric Joyner * ice_read_flash_module - Read a word from one of the main NVM modules 518d08b8680SEric Joyner * @hw: pointer to the HW structure 519d08b8680SEric Joyner * @bank: which bank of the module to read 520d08b8680SEric Joyner * @module: the module to read 521d08b8680SEric Joyner * @offset: the offset into the module in bytes 522d08b8680SEric Joyner * @data: storage for the word read from the flash 523d08b8680SEric Joyner * @length: bytes of data to read 524d08b8680SEric Joyner * 525d08b8680SEric Joyner * Read data from the specified flash module. The bank parameter indicates 526d08b8680SEric Joyner * whether or not to read from the active bank or the inactive bank of that 527d08b8680SEric Joyner * module. 528d08b8680SEric Joyner * 529d08b8680SEric Joyner * The word will be read using flat NVM access, and relies on the 530d08b8680SEric Joyner * hw->flash.banks data being setup by ice_determine_active_flash_banks() 531d08b8680SEric Joyner * during initialization. 532d08b8680SEric Joyner */ 533f2635e84SEric Joyner static int 534d08b8680SEric Joyner ice_read_flash_module(struct ice_hw *hw, enum ice_bank_select bank, u16 module, 535d08b8680SEric Joyner u32 offset, u8 *data, u32 length) 536d08b8680SEric Joyner { 537f2635e84SEric Joyner int status; 538d08b8680SEric Joyner u32 start; 539d08b8680SEric Joyner 540d08b8680SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 541d08b8680SEric Joyner 542d08b8680SEric Joyner start = ice_get_flash_bank_offset(hw, bank, module); 543d08b8680SEric Joyner if (!start) { 544d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Unable to calculate flash bank offset for module 0x%04x\n", 545d08b8680SEric Joyner module); 546d08b8680SEric Joyner return ICE_ERR_PARAM; 547d08b8680SEric Joyner } 548d08b8680SEric Joyner 549d08b8680SEric Joyner status = ice_acquire_nvm(hw, ICE_RES_READ); 550d08b8680SEric Joyner if (status) 551d08b8680SEric Joyner return status; 552d08b8680SEric Joyner 553d08b8680SEric Joyner status = ice_read_flat_nvm(hw, start + offset, &length, data, false); 554d08b8680SEric Joyner 555d08b8680SEric Joyner ice_release_nvm(hw); 556d08b8680SEric Joyner 557d08b8680SEric Joyner return status; 558d08b8680SEric Joyner } 559d08b8680SEric Joyner 560d08b8680SEric Joyner /** 561d08b8680SEric Joyner * ice_read_nvm_module - Read from the active main NVM module 562d08b8680SEric Joyner * @hw: pointer to the HW structure 563d08b8680SEric Joyner * @bank: whether to read from active or inactive NVM module 564d08b8680SEric Joyner * @offset: offset into the NVM module to read, in words 565d08b8680SEric Joyner * @data: storage for returned word value 566d08b8680SEric Joyner * 567d08b8680SEric Joyner * Read the specified word from the active NVM module. This includes the CSS 568d08b8680SEric Joyner * header at the start of the NVM module. 569d08b8680SEric Joyner */ 570f2635e84SEric Joyner static int 571d08b8680SEric Joyner ice_read_nvm_module(struct ice_hw *hw, enum ice_bank_select bank, u32 offset, u16 *data) 572d08b8680SEric Joyner { 573d08b8680SEric Joyner __le16 data_local; 574f2635e84SEric Joyner int status; 575d08b8680SEric Joyner 576d08b8680SEric Joyner status = ice_read_flash_module(hw, bank, ICE_SR_1ST_NVM_BANK_PTR, offset * sizeof(u16), 577d08b8680SEric Joyner (_FORCE_ u8 *)&data_local, sizeof(u16)); 578d08b8680SEric Joyner if (!status) 579d08b8680SEric Joyner *data = LE16_TO_CPU(data_local); 580d08b8680SEric Joyner 581d08b8680SEric Joyner return status; 582d08b8680SEric Joyner } 583d08b8680SEric Joyner 584d08b8680SEric Joyner /** 58556429daeSEric Joyner * ice_get_nvm_css_hdr_len - Read the CSS header length from the NVM CSS header 58656429daeSEric Joyner * @hw: pointer to the HW struct 58756429daeSEric Joyner * @bank: whether to read from the active or inactive flash bank 58856429daeSEric Joyner * @hdr_len: storage for header length in words 58956429daeSEric Joyner * 59056429daeSEric Joyner * Read the CSS header length from the NVM CSS header and add the Authentication 59156429daeSEric Joyner * header size, and then convert to words. 59256429daeSEric Joyner */ 593f2635e84SEric Joyner static int 59456429daeSEric Joyner ice_get_nvm_css_hdr_len(struct ice_hw *hw, enum ice_bank_select bank, 59556429daeSEric Joyner u32 *hdr_len) 59656429daeSEric Joyner { 59756429daeSEric Joyner u16 hdr_len_l, hdr_len_h; 59856429daeSEric Joyner u32 hdr_len_dword; 599f2635e84SEric Joyner int status; 60056429daeSEric Joyner 60156429daeSEric Joyner status = ice_read_nvm_module(hw, bank, ICE_NVM_CSS_HDR_LEN_L, 60256429daeSEric Joyner &hdr_len_l); 60356429daeSEric Joyner if (status) 60456429daeSEric Joyner return status; 60556429daeSEric Joyner 60656429daeSEric Joyner status = ice_read_nvm_module(hw, bank, ICE_NVM_CSS_HDR_LEN_H, 60756429daeSEric Joyner &hdr_len_h); 60856429daeSEric Joyner if (status) 60956429daeSEric Joyner return status; 61056429daeSEric Joyner 61156429daeSEric Joyner /* CSS header length is in DWORD, so convert to words and add 61256429daeSEric Joyner * authentication header size 61356429daeSEric Joyner */ 61456429daeSEric Joyner hdr_len_dword = hdr_len_h << 16 | hdr_len_l; 61556429daeSEric Joyner *hdr_len = (hdr_len_dword * 2) + ICE_NVM_AUTH_HEADER_LEN; 61656429daeSEric Joyner 617f2635e84SEric Joyner return 0; 61856429daeSEric Joyner } 61956429daeSEric Joyner 62056429daeSEric Joyner /** 621d08b8680SEric Joyner * ice_read_nvm_sr_copy - Read a word from the Shadow RAM copy in the NVM bank 622d08b8680SEric Joyner * @hw: pointer to the HW structure 623d08b8680SEric Joyner * @bank: whether to read from the active or inactive NVM module 624d08b8680SEric Joyner * @offset: offset into the Shadow RAM copy to read, in words 625d08b8680SEric Joyner * @data: storage for returned word value 626d08b8680SEric Joyner * 627d08b8680SEric Joyner * Read the specified word from the copy of the Shadow RAM found in the 628d08b8680SEric Joyner * specified NVM module. 629d08b8680SEric Joyner */ 630f2635e84SEric Joyner static int 631d08b8680SEric Joyner ice_read_nvm_sr_copy(struct ice_hw *hw, enum ice_bank_select bank, u32 offset, u16 *data) 632d08b8680SEric Joyner { 63356429daeSEric Joyner u32 hdr_len; 634f2635e84SEric Joyner int status; 63556429daeSEric Joyner 63656429daeSEric Joyner status = ice_get_nvm_css_hdr_len(hw, bank, &hdr_len); 63756429daeSEric Joyner if (status) 63856429daeSEric Joyner return status; 63956429daeSEric Joyner 64056429daeSEric Joyner hdr_len = ROUND_UP(hdr_len, 32); 64156429daeSEric Joyner 64256429daeSEric Joyner return ice_read_nvm_module(hw, bank, hdr_len + offset, data); 643d08b8680SEric Joyner } 644d08b8680SEric Joyner 645d08b8680SEric Joyner /** 646d08b8680SEric Joyner * ice_read_orom_module - Read from the active Option ROM module 647d08b8680SEric Joyner * @hw: pointer to the HW structure 648d08b8680SEric Joyner * @bank: whether to read from active or inactive OROM module 649d08b8680SEric Joyner * @offset: offset into the OROM module to read, in words 650d08b8680SEric Joyner * @data: storage for returned word value 651d08b8680SEric Joyner * 652d08b8680SEric Joyner * Read the specified word from the active Option ROM module of the flash. 653d08b8680SEric Joyner * Note that unlike the NVM module, the CSS data is stored at the end of the 654d08b8680SEric Joyner * module instead of at the beginning. 655d08b8680SEric Joyner */ 656f2635e84SEric Joyner static int 657d08b8680SEric Joyner ice_read_orom_module(struct ice_hw *hw, enum ice_bank_select bank, u32 offset, u16 *data) 658d08b8680SEric Joyner { 659d08b8680SEric Joyner __le16 data_local; 660f2635e84SEric Joyner int status; 661d08b8680SEric Joyner 662d08b8680SEric Joyner status = ice_read_flash_module(hw, bank, ICE_SR_1ST_OROM_BANK_PTR, offset * sizeof(u16), 663d08b8680SEric Joyner (_FORCE_ u8 *)&data_local, sizeof(u16)); 664d08b8680SEric Joyner if (!status) 665d08b8680SEric Joyner *data = LE16_TO_CPU(data_local); 666d08b8680SEric Joyner 667d08b8680SEric Joyner return status; 668d08b8680SEric Joyner } 669d08b8680SEric Joyner 670d08b8680SEric Joyner /** 671d08b8680SEric Joyner * ice_read_netlist_module - Read data from the netlist module area 672d08b8680SEric Joyner * @hw: pointer to the HW structure 673d08b8680SEric Joyner * @bank: whether to read from the active or inactive module 674d08b8680SEric Joyner * @offset: offset into the netlist to read from 675d08b8680SEric Joyner * @data: storage for returned word value 676d08b8680SEric Joyner * 677d08b8680SEric Joyner * Read a word from the specified netlist bank. 678d08b8680SEric Joyner */ 679f2635e84SEric Joyner static int 680d08b8680SEric Joyner ice_read_netlist_module(struct ice_hw *hw, enum ice_bank_select bank, u32 offset, u16 *data) 681d08b8680SEric Joyner { 682d08b8680SEric Joyner __le16 data_local; 683f2635e84SEric Joyner int status; 684d08b8680SEric Joyner 685d08b8680SEric Joyner status = ice_read_flash_module(hw, bank, ICE_SR_NETLIST_BANK_PTR, offset * sizeof(u16), 686d08b8680SEric Joyner (_FORCE_ u8 *)&data_local, sizeof(u16)); 687d08b8680SEric Joyner if (!status) 688d08b8680SEric Joyner *data = LE16_TO_CPU(data_local); 689d08b8680SEric Joyner 690d08b8680SEric Joyner return status; 691d08b8680SEric Joyner } 692d08b8680SEric Joyner 693d08b8680SEric Joyner /** 69471d10453SEric Joyner * ice_read_sr_word - Reads Shadow RAM word and acquire NVM if necessary 69571d10453SEric Joyner * @hw: pointer to the HW structure 69671d10453SEric Joyner * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) 69771d10453SEric Joyner * @data: word read from the Shadow RAM 69871d10453SEric Joyner * 69971d10453SEric Joyner * Reads one 16 bit word from the Shadow RAM using the ice_read_sr_word_aq. 70071d10453SEric Joyner */ 701f2635e84SEric Joyner int ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data) 70271d10453SEric Joyner { 703f2635e84SEric Joyner int status; 70471d10453SEric Joyner 70571d10453SEric Joyner status = ice_acquire_nvm(hw, ICE_RES_READ); 70671d10453SEric Joyner if (!status) { 70771d10453SEric Joyner status = ice_read_sr_word_aq(hw, offset, data); 70871d10453SEric Joyner ice_release_nvm(hw); 70971d10453SEric Joyner } 71071d10453SEric Joyner 71171d10453SEric Joyner return status; 71271d10453SEric Joyner } 71371d10453SEric Joyner 714*440addc6SEric Joyner #define check_add_overflow __builtin_add_overflow 715*440addc6SEric Joyner 71671d10453SEric Joyner /** 71771d10453SEric Joyner * ice_get_pfa_module_tlv - Reads sub module TLV from NVM PFA 71871d10453SEric Joyner * @hw: pointer to hardware structure 71971d10453SEric Joyner * @module_tlv: pointer to module TLV to return 72071d10453SEric Joyner * @module_tlv_len: pointer to module TLV length to return 72171d10453SEric Joyner * @module_type: module type requested 72271d10453SEric Joyner * 72371d10453SEric Joyner * Finds the requested sub module TLV type from the Preserved Field 72471d10453SEric Joyner * Area (PFA) and returns the TLV pointer and length. The caller can 72571d10453SEric Joyner * use these to read the variable length TLV value. 72671d10453SEric Joyner */ 727f2635e84SEric Joyner int 72871d10453SEric Joyner ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len, 72971d10453SEric Joyner u16 module_type) 73071d10453SEric Joyner { 731*440addc6SEric Joyner u16 pfa_len, pfa_ptr, next_tlv, max_tlv; 732f2635e84SEric Joyner int status; 73371d10453SEric Joyner 73471d10453SEric Joyner status = ice_read_sr_word(hw, ICE_SR_PFA_PTR, &pfa_ptr); 735f2635e84SEric Joyner if (status) { 73671d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "Preserved Field Array pointer.\n"); 73771d10453SEric Joyner return status; 73871d10453SEric Joyner } 73971d10453SEric Joyner status = ice_read_sr_word(hw, pfa_ptr, &pfa_len); 740f2635e84SEric Joyner if (status) { 74171d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "Failed to read PFA length.\n"); 74271d10453SEric Joyner return status; 74371d10453SEric Joyner } 744*440addc6SEric Joyner 745*440addc6SEric Joyner if (check_add_overflow(pfa_ptr, (u16)(pfa_len - 1), &max_tlv)) { 746*440addc6SEric Joyner ice_debug(hw, ICE_DBG_INIT, "PFA starts at offset %u. PFA length of %u caused 16-bit arithmetic overflow.\n", 747*440addc6SEric Joyner pfa_ptr, pfa_len); 748*440addc6SEric Joyner return ICE_ERR_INVAL_SIZE; 749*440addc6SEric Joyner } 750*440addc6SEric Joyner 751*440addc6SEric Joyner /* The Preserved Fields Area contains a sequence of TLVs which define 752*440addc6SEric Joyner * its contents. The PFA length includes all of the TLVs, plus its 753*440addc6SEric Joyner * initial length word itself, *and* one final word at the end of all 754*440addc6SEric Joyner * of the TLVs. 755*440addc6SEric Joyner * 756*440addc6SEric Joyner * Starting with first TLV after PFA length, iterate through the list 75771d10453SEric Joyner * of TLVs to find the requested one. 75871d10453SEric Joyner */ 75971d10453SEric Joyner next_tlv = pfa_ptr + 1; 760*440addc6SEric Joyner while (next_tlv < max_tlv) { 76171d10453SEric Joyner u16 tlv_sub_module_type; 76271d10453SEric Joyner u16 tlv_len; 76371d10453SEric Joyner 76471d10453SEric Joyner /* Read TLV type */ 765f2635e84SEric Joyner status = ice_read_sr_word(hw, (u16)next_tlv, 766f2635e84SEric Joyner &tlv_sub_module_type); 767f2635e84SEric Joyner if (status) { 76871d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV type.\n"); 76971d10453SEric Joyner break; 77071d10453SEric Joyner } 77171d10453SEric Joyner /* Read TLV length */ 772f2635e84SEric Joyner status = ice_read_sr_word(hw, (u16)(next_tlv + 1), &tlv_len); 773f2635e84SEric Joyner if (status) { 77471d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV length.\n"); 77571d10453SEric Joyner break; 77671d10453SEric Joyner } 77771d10453SEric Joyner if (tlv_sub_module_type == module_type) { 77871d10453SEric Joyner if (tlv_len) { 779f2635e84SEric Joyner *module_tlv = (u16)next_tlv; 78071d10453SEric Joyner *module_tlv_len = tlv_len; 781f2635e84SEric Joyner return 0; 78271d10453SEric Joyner } 78371d10453SEric Joyner return ICE_ERR_INVAL_SIZE; 78471d10453SEric Joyner } 785*440addc6SEric Joyner 786*440addc6SEric Joyner if (check_add_overflow(next_tlv, (u16)2, &next_tlv) || 787*440addc6SEric Joyner check_add_overflow(next_tlv, tlv_len, &next_tlv)) { 788*440addc6SEric Joyner ice_debug(hw, ICE_DBG_INIT, "TLV of type %u and length 0x%04x caused 16-bit arithmetic overflow. The PFA starts at 0x%04x and has length of 0x%04x\n", 789*440addc6SEric Joyner tlv_sub_module_type, tlv_len, pfa_ptr, pfa_len); 790*440addc6SEric Joyner return ICE_ERR_INVAL_SIZE; 791*440addc6SEric Joyner } 79271d10453SEric Joyner } 79371d10453SEric Joyner /* Module does not exist */ 79471d10453SEric Joyner return ICE_ERR_DOES_NOT_EXIST; 79571d10453SEric Joyner } 79671d10453SEric Joyner 79771d10453SEric Joyner /** 79871d10453SEric Joyner * ice_read_pba_string - Reads part number string from NVM 79971d10453SEric Joyner * @hw: pointer to hardware structure 80071d10453SEric Joyner * @pba_num: stores the part number string from the NVM 80171d10453SEric Joyner * @pba_num_size: part number string buffer length 80271d10453SEric Joyner * 80371d10453SEric Joyner * Reads the part number string from the NVM. 80471d10453SEric Joyner */ 805f2635e84SEric Joyner int ice_read_pba_string(struct ice_hw *hw, u8 *pba_num, u32 pba_num_size) 80671d10453SEric Joyner { 80771d10453SEric Joyner u16 pba_tlv, pba_tlv_len; 80871d10453SEric Joyner u16 pba_word, pba_size; 809f2635e84SEric Joyner int status; 81071d10453SEric Joyner u16 i; 81171d10453SEric Joyner 81271d10453SEric Joyner status = ice_get_pfa_module_tlv(hw, &pba_tlv, &pba_tlv_len, 81371d10453SEric Joyner ICE_SR_PBA_BLOCK_PTR); 814f2635e84SEric Joyner if (status) { 81571d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "Failed to read PBA Block TLV.\n"); 81671d10453SEric Joyner return status; 81771d10453SEric Joyner } 81871d10453SEric Joyner 81971d10453SEric Joyner /* pba_size is the next word */ 82071d10453SEric Joyner status = ice_read_sr_word(hw, (pba_tlv + 2), &pba_size); 821f2635e84SEric Joyner if (status) { 82271d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "Failed to read PBA Section size.\n"); 82371d10453SEric Joyner return status; 82471d10453SEric Joyner } 82571d10453SEric Joyner 82671d10453SEric Joyner if (pba_tlv_len < pba_size) { 82771d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "Invalid PBA Block TLV size.\n"); 82871d10453SEric Joyner return ICE_ERR_INVAL_SIZE; 82971d10453SEric Joyner } 83071d10453SEric Joyner 83171d10453SEric Joyner /* Subtract one to get PBA word count (PBA Size word is included in 83271d10453SEric Joyner * total size) 83371d10453SEric Joyner */ 83471d10453SEric Joyner pba_size--; 83571d10453SEric Joyner if (pba_num_size < (((u32)pba_size * 2) + 1)) { 8367d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_INIT, "Buffer too small for PBA data.\n"); 83771d10453SEric Joyner return ICE_ERR_PARAM; 83871d10453SEric Joyner } 83971d10453SEric Joyner 84071d10453SEric Joyner for (i = 0; i < pba_size; i++) { 84171d10453SEric Joyner status = ice_read_sr_word(hw, (pba_tlv + 2 + 1) + i, &pba_word); 842f2635e84SEric Joyner if (status) { 8437d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_INIT, "Failed to read PBA Block word %d.\n", i); 84471d10453SEric Joyner return status; 84571d10453SEric Joyner } 84671d10453SEric Joyner 84771d10453SEric Joyner pba_num[(i * 2)] = (pba_word >> 8) & 0xFF; 84871d10453SEric Joyner pba_num[(i * 2) + 1] = pba_word & 0xFF; 84971d10453SEric Joyner } 85071d10453SEric Joyner pba_num[(pba_size * 2)] = '\0'; 85171d10453SEric Joyner 85271d10453SEric Joyner return status; 85371d10453SEric Joyner } 85471d10453SEric Joyner 85571d10453SEric Joyner /** 856d08b8680SEric Joyner * ice_get_nvm_srev - Read the security revision from the NVM CSS header 85771d10453SEric Joyner * @hw: pointer to the HW struct 858d08b8680SEric Joyner * @bank: whether to read from the active or inactive flash bank 859d08b8680SEric Joyner * @srev: storage for security revision 86071d10453SEric Joyner * 861d08b8680SEric Joyner * Read the security revision out of the CSS header of the active NVM module 862d08b8680SEric Joyner * bank. 86371d10453SEric Joyner */ 864f2635e84SEric Joyner static int ice_get_nvm_srev(struct ice_hw *hw, enum ice_bank_select bank, u32 *srev) 86571d10453SEric Joyner { 866d08b8680SEric Joyner u16 srev_l, srev_h; 867f2635e84SEric Joyner int status; 86871d10453SEric Joyner 869d08b8680SEric Joyner status = ice_read_nvm_module(hw, bank, ICE_NVM_CSS_SREV_L, &srev_l); 870d08b8680SEric Joyner if (status) 87171d10453SEric Joyner return status; 87271d10453SEric Joyner 873d08b8680SEric Joyner status = ice_read_nvm_module(hw, bank, ICE_NVM_CSS_SREV_H, &srev_h); 874d08b8680SEric Joyner if (status) 87571d10453SEric Joyner return status; 87671d10453SEric Joyner 877d08b8680SEric Joyner *srev = srev_h << 16 | srev_l; 87871d10453SEric Joyner 879f2635e84SEric Joyner return 0; 88071d10453SEric Joyner } 88171d10453SEric Joyner 88271d10453SEric Joyner /** 883d08b8680SEric Joyner * ice_get_nvm_ver_info - Read NVM version information 884d08b8680SEric Joyner * @hw: pointer to the HW struct 885d08b8680SEric Joyner * @bank: whether to read from the active or inactive flash bank 886d08b8680SEric Joyner * @nvm: pointer to NVM info structure 887d08b8680SEric Joyner * 888d08b8680SEric Joyner * Read the NVM EETRACK ID and map version of the main NVM image bank, filling 8899e54973fSEric Joyner * in the NVM info structure. 890d08b8680SEric Joyner */ 891f2635e84SEric Joyner static int 892d08b8680SEric Joyner ice_get_nvm_ver_info(struct ice_hw *hw, enum ice_bank_select bank, struct ice_nvm_info *nvm) 893d08b8680SEric Joyner { 894d08b8680SEric Joyner u16 eetrack_lo, eetrack_hi, ver; 895f2635e84SEric Joyner int status; 896d08b8680SEric Joyner 897d08b8680SEric Joyner status = ice_read_nvm_sr_copy(hw, bank, ICE_SR_NVM_DEV_STARTER_VER, &ver); 898d08b8680SEric Joyner if (status) { 899d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to read DEV starter version.\n"); 900d08b8680SEric Joyner return status; 901d08b8680SEric Joyner } 902d08b8680SEric Joyner 903d08b8680SEric Joyner nvm->major = (ver & ICE_NVM_VER_HI_MASK) >> ICE_NVM_VER_HI_SHIFT; 904d08b8680SEric Joyner nvm->minor = (ver & ICE_NVM_VER_LO_MASK) >> ICE_NVM_VER_LO_SHIFT; 905d08b8680SEric Joyner 906d08b8680SEric Joyner status = ice_read_nvm_sr_copy(hw, bank, ICE_SR_NVM_EETRACK_LO, &eetrack_lo); 907d08b8680SEric Joyner if (status) { 908d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to read EETRACK lo.\n"); 909d08b8680SEric Joyner return status; 910d08b8680SEric Joyner } 911d08b8680SEric Joyner status = ice_read_nvm_sr_copy(hw, bank, ICE_SR_NVM_EETRACK_HI, &eetrack_hi); 912d08b8680SEric Joyner if (status) { 913d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to read EETRACK hi.\n"); 914d08b8680SEric Joyner return status; 915d08b8680SEric Joyner } 916d08b8680SEric Joyner 917d08b8680SEric Joyner nvm->eetrack = (eetrack_hi << 16) | eetrack_lo; 918d08b8680SEric Joyner 919d08b8680SEric Joyner status = ice_get_nvm_srev(hw, bank, &nvm->srev); 920d08b8680SEric Joyner if (status) 921d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to read NVM security revision.\n"); 922d08b8680SEric Joyner 923f2635e84SEric Joyner return 0; 924d08b8680SEric Joyner } 925d08b8680SEric Joyner 926d08b8680SEric Joyner /** 927d08b8680SEric Joyner * ice_get_inactive_nvm_ver - Read Option ROM version from the inactive bank 928d08b8680SEric Joyner * @hw: pointer to the HW structure 929d08b8680SEric Joyner * @nvm: storage for Option ROM version information 930d08b8680SEric Joyner * 931d08b8680SEric Joyner * Reads the NVM EETRACK ID, Map version, and security revision of the 932d08b8680SEric Joyner * inactive NVM bank. Used to access version data for a pending update that 933d08b8680SEric Joyner * has not yet been activated. 934d08b8680SEric Joyner */ 935f2635e84SEric Joyner int ice_get_inactive_nvm_ver(struct ice_hw *hw, struct ice_nvm_info *nvm) 936d08b8680SEric Joyner { 937d08b8680SEric Joyner return ice_get_nvm_ver_info(hw, ICE_INACTIVE_FLASH_BANK, nvm); 938d08b8680SEric Joyner } 939d08b8680SEric Joyner 940d08b8680SEric Joyner /** 941d08b8680SEric Joyner * ice_get_orom_srev - Read the security revision from the OROM CSS header 942d08b8680SEric Joyner * @hw: pointer to the HW struct 943d08b8680SEric Joyner * @bank: whether to read from active or inactive flash module 944d08b8680SEric Joyner * @srev: storage for security revision 945d08b8680SEric Joyner * 946d08b8680SEric Joyner * Read the security revision out of the CSS header of the active OROM module 947d08b8680SEric Joyner * bank. 948d08b8680SEric Joyner */ 949f2635e84SEric Joyner static int ice_get_orom_srev(struct ice_hw *hw, enum ice_bank_select bank, u32 *srev) 950d08b8680SEric Joyner { 95156429daeSEric Joyner u32 orom_size_word = hw->flash.banks.orom_size / 2; 952d08b8680SEric Joyner u16 srev_l, srev_h; 953d08b8680SEric Joyner u32 css_start; 95456429daeSEric Joyner u32 hdr_len; 955f2635e84SEric Joyner int status; 956d08b8680SEric Joyner 95756429daeSEric Joyner status = ice_get_nvm_css_hdr_len(hw, bank, &hdr_len); 95856429daeSEric Joyner if (status) 95956429daeSEric Joyner return status; 96056429daeSEric Joyner 96156429daeSEric Joyner if (orom_size_word < hdr_len) { 962d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Unexpected Option ROM Size of %u\n", 963d08b8680SEric Joyner hw->flash.banks.orom_size); 964d08b8680SEric Joyner return ICE_ERR_CFG; 965d08b8680SEric Joyner } 966d08b8680SEric Joyner 967d08b8680SEric Joyner /* calculate how far into the Option ROM the CSS header starts. Note 96856429daeSEric Joyner * that ice_read_orom_module takes a word offset 969d08b8680SEric Joyner */ 97056429daeSEric Joyner css_start = orom_size_word - hdr_len; 971d08b8680SEric Joyner status = ice_read_orom_module(hw, bank, css_start + ICE_NVM_CSS_SREV_L, &srev_l); 972d08b8680SEric Joyner if (status) 973d08b8680SEric Joyner return status; 974d08b8680SEric Joyner 975d08b8680SEric Joyner status = ice_read_orom_module(hw, bank, css_start + ICE_NVM_CSS_SREV_H, &srev_h); 976d08b8680SEric Joyner if (status) 977d08b8680SEric Joyner return status; 978d08b8680SEric Joyner 979d08b8680SEric Joyner *srev = srev_h << 16 | srev_l; 980d08b8680SEric Joyner 981f2635e84SEric Joyner return 0; 982d08b8680SEric Joyner } 983d08b8680SEric Joyner 984d08b8680SEric Joyner /** 985d08b8680SEric Joyner * ice_get_orom_civd_data - Get the combo version information from Option ROM 986d08b8680SEric Joyner * @hw: pointer to the HW struct 987d08b8680SEric Joyner * @bank: whether to read from the active or inactive flash module 988d08b8680SEric Joyner * @civd: storage for the Option ROM CIVD data. 989d08b8680SEric Joyner * 990d08b8680SEric Joyner * Searches through the Option ROM flash contents to locate the CIVD data for 991d08b8680SEric Joyner * the image. 992d08b8680SEric Joyner */ 993f2635e84SEric Joyner static int 994d08b8680SEric Joyner ice_get_orom_civd_data(struct ice_hw *hw, enum ice_bank_select bank, 995d08b8680SEric Joyner struct ice_orom_civd_info *civd) 996d08b8680SEric Joyner { 997f2635e84SEric Joyner struct ice_orom_civd_info civd_data_section; 998f2635e84SEric Joyner int status; 999d08b8680SEric Joyner u32 offset; 1000f2635e84SEric Joyner u32 tmp; 1001d08b8680SEric Joyner 1002d08b8680SEric Joyner /* The CIVD section is located in the Option ROM aligned to 512 bytes. 1003d08b8680SEric Joyner * The first 4 bytes must contain the ASCII characters "$CIV". 1004d08b8680SEric Joyner * A simple modulo 256 sum of all of the bytes of the structure must 1005d08b8680SEric Joyner * equal 0. 10069dc2f6e2SEric Joyner * 10079dc2f6e2SEric Joyner * The exact location is unknown and varies between images but is 10089dc2f6e2SEric Joyner * usually somewhere in the middle of the bank. We need to scan the 10099dc2f6e2SEric Joyner * Option ROM bank to locate it. 10109dc2f6e2SEric Joyner * 1011d08b8680SEric Joyner */ 1012d08b8680SEric Joyner 10139dc2f6e2SEric Joyner /* Scan the memory buffer to locate the CIVD data section */ 10149dc2f6e2SEric Joyner for (offset = 0; (offset + 512) <= hw->flash.banks.orom_size; offset += 512) { 10159dc2f6e2SEric Joyner u8 sum = 0, i; 10169dc2f6e2SEric Joyner 1017f2635e84SEric Joyner status = ice_read_flash_module(hw, bank, ICE_SR_1ST_OROM_BANK_PTR, 1018f2635e84SEric Joyner offset, (u8 *)&tmp, sizeof(tmp)); 1019f2635e84SEric Joyner if (status) { 1020f2635e84SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Unable to read Option ROM data\n"); 1021f2635e84SEric Joyner return status; 1022f2635e84SEric Joyner } 10239dc2f6e2SEric Joyner 1024d08b8680SEric Joyner /* Skip forward until we find a matching signature */ 1025f2635e84SEric Joyner if (memcmp("$CIV", &tmp, sizeof(tmp)) != 0) 1026d08b8680SEric Joyner continue; 1027d08b8680SEric Joyner 10289dc2f6e2SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Found CIVD section at offset %u\n", 10299dc2f6e2SEric Joyner offset); 10309dc2f6e2SEric Joyner 1031f2635e84SEric Joyner status = ice_read_flash_module(hw, bank, ICE_SR_1ST_OROM_BANK_PTR, 1032f2635e84SEric Joyner offset, (u8 *)&civd_data_section, 1033f2635e84SEric Joyner sizeof(civd_data_section)); 1034f2635e84SEric Joyner if (status) { 1035f2635e84SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Unable to read CIVD data\n"); 1036f2635e84SEric Joyner goto exit_error; 1037f2635e84SEric Joyner } 1038f2635e84SEric Joyner 1039d08b8680SEric Joyner /* Verify that the simple checksum is zero */ 1040f2635e84SEric Joyner for (i = 0; i < sizeof(civd_data_section); i++) 1041f2635e84SEric Joyner sum += ((u8 *)&civd_data_section)[i]; 1042d08b8680SEric Joyner 1043d08b8680SEric Joyner if (sum) { 1044d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Found CIVD data with invalid checksum of %u\n", 1045d08b8680SEric Joyner sum); 10469e54973fSEric Joyner status = ICE_ERR_NVM; 10479e54973fSEric Joyner goto exit_error; 1048d08b8680SEric Joyner } 1049d08b8680SEric Joyner 1050f2635e84SEric Joyner *civd = civd_data_section; 1051f2635e84SEric Joyner 1052f2635e84SEric Joyner return 0; 1053d08b8680SEric Joyner } 1054d08b8680SEric Joyner 10559e54973fSEric Joyner status = ICE_ERR_NVM; 10569dc2f6e2SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Unable to locate CIVD data within the Option ROM\n"); 10579dc2f6e2SEric Joyner 10589e54973fSEric Joyner exit_error: 10599e54973fSEric Joyner return status; 1060d08b8680SEric Joyner } 1061d08b8680SEric Joyner 1062d08b8680SEric Joyner /** 1063d08b8680SEric Joyner * ice_get_orom_ver_info - Read Option ROM version information 1064d08b8680SEric Joyner * @hw: pointer to the HW struct 1065d08b8680SEric Joyner * @bank: whether to read from the active or inactive flash module 1066d08b8680SEric Joyner * @orom: pointer to Option ROM info structure 1067d08b8680SEric Joyner * 1068d08b8680SEric Joyner * Read Option ROM version and security revision from the Option ROM flash 1069d08b8680SEric Joyner * section. 1070d08b8680SEric Joyner */ 1071f2635e84SEric Joyner static int 1072d08b8680SEric Joyner ice_get_orom_ver_info(struct ice_hw *hw, enum ice_bank_select bank, struct ice_orom_info *orom) 1073d08b8680SEric Joyner { 1074d08b8680SEric Joyner struct ice_orom_civd_info civd; 1075d08b8680SEric Joyner u32 combo_ver; 1076f2635e84SEric Joyner int status; 1077d08b8680SEric Joyner 1078d08b8680SEric Joyner status = ice_get_orom_civd_data(hw, bank, &civd); 1079d08b8680SEric Joyner if (status) { 1080d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to locate valid Option ROM CIVD data\n"); 1081d08b8680SEric Joyner return status; 1082d08b8680SEric Joyner } 1083d08b8680SEric Joyner 1084d08b8680SEric Joyner combo_ver = LE32_TO_CPU(civd.combo_ver); 1085d08b8680SEric Joyner 1086d08b8680SEric Joyner orom->major = (u8)((combo_ver & ICE_OROM_VER_MASK) >> ICE_OROM_VER_SHIFT); 1087d08b8680SEric Joyner orom->patch = (u8)(combo_ver & ICE_OROM_VER_PATCH_MASK); 1088d08b8680SEric Joyner orom->build = (u16)((combo_ver & ICE_OROM_VER_BUILD_MASK) >> ICE_OROM_VER_BUILD_SHIFT); 1089d08b8680SEric Joyner 1090d08b8680SEric Joyner status = ice_get_orom_srev(hw, bank, &orom->srev); 1091d08b8680SEric Joyner if (status) { 1092d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to read Option ROM security revision.\n"); 1093d08b8680SEric Joyner return status; 1094d08b8680SEric Joyner } 1095d08b8680SEric Joyner 1096f2635e84SEric Joyner return 0; 1097d08b8680SEric Joyner } 1098d08b8680SEric Joyner 1099d08b8680SEric Joyner /** 1100d08b8680SEric Joyner * ice_get_inactive_orom_ver - Read Option ROM version from the inactive bank 1101d08b8680SEric Joyner * @hw: pointer to the HW structure 1102d08b8680SEric Joyner * @orom: storage for Option ROM version information 1103d08b8680SEric Joyner * 1104d08b8680SEric Joyner * Reads the Option ROM version and security revision data for the inactive 1105d08b8680SEric Joyner * section of flash. Used to access version data for a pending update that has 1106d08b8680SEric Joyner * not yet been activated. 1107d08b8680SEric Joyner */ 1108f2635e84SEric Joyner int ice_get_inactive_orom_ver(struct ice_hw *hw, struct ice_orom_info *orom) 1109d08b8680SEric Joyner { 1110d08b8680SEric Joyner return ice_get_orom_ver_info(hw, ICE_INACTIVE_FLASH_BANK, orom); 1111d08b8680SEric Joyner } 1112d08b8680SEric Joyner 1113d08b8680SEric Joyner /** 1114d08b8680SEric Joyner * ice_get_netlist_info 1115d08b8680SEric Joyner * @hw: pointer to the HW struct 1116d08b8680SEric Joyner * @bank: whether to read from the active or inactive flash bank 1117d08b8680SEric Joyner * @netlist: pointer to netlist version info structure 1118d08b8680SEric Joyner * 1119d08b8680SEric Joyner * Get the netlist version information from the requested bank. Reads the Link 1120d08b8680SEric Joyner * Topology section to find the Netlist ID block and extract the relevant 1121d08b8680SEric Joyner * information into the netlist version structure. 1122d08b8680SEric Joyner */ 1123f2635e84SEric Joyner static int 1124d08b8680SEric Joyner ice_get_netlist_info(struct ice_hw *hw, enum ice_bank_select bank, 1125d08b8680SEric Joyner struct ice_netlist_info *netlist) 1126d08b8680SEric Joyner { 1127d08b8680SEric Joyner u16 module_id, length, node_count, i; 1128d08b8680SEric Joyner u16 *id_blk; 1129f2635e84SEric Joyner int status; 1130d08b8680SEric Joyner 1131d08b8680SEric Joyner status = ice_read_netlist_module(hw, bank, ICE_NETLIST_TYPE_OFFSET, &module_id); 1132d08b8680SEric Joyner if (status) 1133d08b8680SEric Joyner return status; 1134d08b8680SEric Joyner 1135d08b8680SEric Joyner if (module_id != ICE_NETLIST_LINK_TOPO_MOD_ID) { 1136d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Expected netlist module_id ID of 0x%04x, but got 0x%04x\n", 1137d08b8680SEric Joyner ICE_NETLIST_LINK_TOPO_MOD_ID, module_id); 1138d08b8680SEric Joyner return ICE_ERR_NVM; 1139d08b8680SEric Joyner } 1140d08b8680SEric Joyner 1141d08b8680SEric Joyner status = ice_read_netlist_module(hw, bank, ICE_LINK_TOPO_MODULE_LEN, &length); 1142d08b8680SEric Joyner if (status) 1143d08b8680SEric Joyner return status; 1144d08b8680SEric Joyner 1145d08b8680SEric Joyner /* sanity check that we have at least enough words to store the netlist ID block */ 1146d08b8680SEric Joyner if (length < ICE_NETLIST_ID_BLK_SIZE) { 1147d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Netlist Link Topology module too small. Expected at least %u words, but got %u words.\n", 1148d08b8680SEric Joyner ICE_NETLIST_ID_BLK_SIZE, length); 1149d08b8680SEric Joyner return ICE_ERR_NVM; 1150d08b8680SEric Joyner } 1151d08b8680SEric Joyner 1152d08b8680SEric Joyner status = ice_read_netlist_module(hw, bank, ICE_LINK_TOPO_NODE_COUNT, &node_count); 1153d08b8680SEric Joyner if (status) 1154d08b8680SEric Joyner return status; 1155d08b8680SEric Joyner node_count &= ICE_LINK_TOPO_NODE_COUNT_M; 1156d08b8680SEric Joyner 1157d08b8680SEric Joyner id_blk = (u16 *)ice_calloc(hw, ICE_NETLIST_ID_BLK_SIZE, sizeof(*id_blk)); 1158d08b8680SEric Joyner if (!id_blk) 1159d08b8680SEric Joyner return ICE_ERR_NO_MEMORY; 1160d08b8680SEric Joyner 1161d08b8680SEric Joyner /* Read out the entire Netlist ID Block at once. */ 1162d08b8680SEric Joyner status = ice_read_flash_module(hw, bank, ICE_SR_NETLIST_BANK_PTR, 1163d08b8680SEric Joyner ICE_NETLIST_ID_BLK_OFFSET(node_count) * sizeof(u16), 1164d08b8680SEric Joyner (u8 *)id_blk, ICE_NETLIST_ID_BLK_SIZE * sizeof(u16)); 1165d08b8680SEric Joyner if (status) 1166d08b8680SEric Joyner goto exit_error; 1167d08b8680SEric Joyner 1168d08b8680SEric Joyner for (i = 0; i < ICE_NETLIST_ID_BLK_SIZE; i++) 1169d08b8680SEric Joyner id_blk[i] = LE16_TO_CPU(((_FORCE_ __le16 *)id_blk)[i]); 1170d08b8680SEric Joyner 1171d08b8680SEric Joyner netlist->major = id_blk[ICE_NETLIST_ID_BLK_MAJOR_VER_HIGH] << 16 | 1172d08b8680SEric Joyner id_blk[ICE_NETLIST_ID_BLK_MAJOR_VER_LOW]; 1173d08b8680SEric Joyner netlist->minor = id_blk[ICE_NETLIST_ID_BLK_MINOR_VER_HIGH] << 16 | 1174d08b8680SEric Joyner id_blk[ICE_NETLIST_ID_BLK_MINOR_VER_LOW]; 1175d08b8680SEric Joyner netlist->type = id_blk[ICE_NETLIST_ID_BLK_TYPE_HIGH] << 16 | 1176d08b8680SEric Joyner id_blk[ICE_NETLIST_ID_BLK_TYPE_LOW]; 1177d08b8680SEric Joyner netlist->rev = id_blk[ICE_NETLIST_ID_BLK_REV_HIGH] << 16 | 1178d08b8680SEric Joyner id_blk[ICE_NETLIST_ID_BLK_REV_LOW]; 1179d08b8680SEric Joyner netlist->cust_ver = id_blk[ICE_NETLIST_ID_BLK_CUST_VER]; 1180d08b8680SEric Joyner /* Read the left most 4 bytes of SHA */ 1181d08b8680SEric Joyner netlist->hash = id_blk[ICE_NETLIST_ID_BLK_SHA_HASH_WORD(15)] << 16 | 1182d08b8680SEric Joyner id_blk[ICE_NETLIST_ID_BLK_SHA_HASH_WORD(14)]; 1183d08b8680SEric Joyner 1184d08b8680SEric Joyner exit_error: 1185d08b8680SEric Joyner ice_free(hw, id_blk); 1186d08b8680SEric Joyner 1187d08b8680SEric Joyner return status; 1188d08b8680SEric Joyner } 1189d08b8680SEric Joyner 1190d08b8680SEric Joyner /** 11917d7af7f8SEric Joyner * ice_get_netlist_ver_info 11927d7af7f8SEric Joyner * @hw: pointer to the HW struct 1193d08b8680SEric Joyner * @netlist: pointer to netlist version info structure 11947d7af7f8SEric Joyner * 11957d7af7f8SEric Joyner * Get the netlist version information 11967d7af7f8SEric Joyner */ 1197f2635e84SEric Joyner int ice_get_netlist_ver_info(struct ice_hw *hw, struct ice_netlist_info *netlist) 11987d7af7f8SEric Joyner { 1199d08b8680SEric Joyner return ice_get_netlist_info(hw, ICE_ACTIVE_FLASH_BANK, netlist); 12007d7af7f8SEric Joyner } 12017d7af7f8SEric Joyner 1202d08b8680SEric Joyner /** 1203d08b8680SEric Joyner * ice_get_inactive_netlist_ver 1204d08b8680SEric Joyner * @hw: pointer to the HW struct 1205d08b8680SEric Joyner * @netlist: pointer to netlist version info structure 1206d08b8680SEric Joyner * 1207d08b8680SEric Joyner * Read the netlist version data from the inactive netlist bank. Used to 1208d08b8680SEric Joyner * extract version data of a pending flash update in order to display the 1209d08b8680SEric Joyner * version data. 1210d08b8680SEric Joyner */ 1211f2635e84SEric Joyner int ice_get_inactive_netlist_ver(struct ice_hw *hw, struct ice_netlist_info *netlist) 1212d08b8680SEric Joyner { 1213d08b8680SEric Joyner return ice_get_netlist_info(hw, ICE_INACTIVE_FLASH_BANK, netlist); 12147d7af7f8SEric Joyner } 12157d7af7f8SEric Joyner 12167d7af7f8SEric Joyner /** 12179e54973fSEric Joyner * ice_discover_flash_size - Discover the available flash size 121871d10453SEric Joyner * @hw: pointer to the HW struct 121971d10453SEric Joyner * 122071d10453SEric Joyner * The device flash could be up to 16MB in size. However, it is possible that 122171d10453SEric Joyner * the actual size is smaller. Use bisection to determine the accessible size 122271d10453SEric Joyner * of flash memory. 122371d10453SEric Joyner */ 1224f2635e84SEric Joyner static int ice_discover_flash_size(struct ice_hw *hw) 122571d10453SEric Joyner { 122671d10453SEric Joyner u32 min_size = 0, max_size = ICE_AQC_NVM_MAX_OFFSET + 1; 1227f2635e84SEric Joyner int status; 122871d10453SEric Joyner 122971d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 123071d10453SEric Joyner 123171d10453SEric Joyner status = ice_acquire_nvm(hw, ICE_RES_READ); 123271d10453SEric Joyner if (status) 123371d10453SEric Joyner return status; 123471d10453SEric Joyner 123571d10453SEric Joyner while ((max_size - min_size) > 1) { 123671d10453SEric Joyner u32 offset = (max_size + min_size) / 2; 123771d10453SEric Joyner u32 len = 1; 123871d10453SEric Joyner u8 data; 123971d10453SEric Joyner 124071d10453SEric Joyner status = ice_read_flat_nvm(hw, offset, &len, &data, false); 124171d10453SEric Joyner if (status == ICE_ERR_AQ_ERROR && 124271d10453SEric Joyner hw->adminq.sq_last_status == ICE_AQ_RC_EINVAL) { 12437d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_NVM, "%s: New upper bound of %u bytes\n", 124471d10453SEric Joyner __func__, offset); 1245f2635e84SEric Joyner status = 0; 124671d10453SEric Joyner max_size = offset; 124771d10453SEric Joyner } else if (!status) { 12487d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_NVM, "%s: New lower bound of %u bytes\n", 124971d10453SEric Joyner __func__, offset); 125071d10453SEric Joyner min_size = offset; 125171d10453SEric Joyner } else { 125271d10453SEric Joyner /* an unexpected error occurred */ 125371d10453SEric Joyner goto err_read_flat_nvm; 125471d10453SEric Joyner } 125571d10453SEric Joyner } 125671d10453SEric Joyner 12577d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Predicted flash size is %u bytes\n", max_size); 125871d10453SEric Joyner 1259d08b8680SEric Joyner hw->flash.flash_size = max_size; 126071d10453SEric Joyner 126171d10453SEric Joyner err_read_flat_nvm: 126271d10453SEric Joyner ice_release_nvm(hw); 126371d10453SEric Joyner 126471d10453SEric Joyner return status; 126571d10453SEric Joyner } 126671d10453SEric Joyner 126771d10453SEric Joyner /** 1268d08b8680SEric Joyner * ice_read_sr_pointer - Read the value of a Shadow RAM pointer word 1269d08b8680SEric Joyner * @hw: pointer to the HW structure 1270d08b8680SEric Joyner * @offset: the word offset of the Shadow RAM word to read 1271d08b8680SEric Joyner * @pointer: pointer value read from Shadow RAM 1272d08b8680SEric Joyner * 1273d08b8680SEric Joyner * Read the given Shadow RAM word, and convert it to a pointer value specified 1274d08b8680SEric Joyner * in bytes. This function assumes the specified offset is a valid pointer 1275d08b8680SEric Joyner * word. 1276d08b8680SEric Joyner * 1277d08b8680SEric Joyner * Each pointer word specifies whether it is stored in word size or 4KB 1278d08b8680SEric Joyner * sector size by using the highest bit. The reported pointer value will be in 1279d08b8680SEric Joyner * bytes, intended for flat NVM reads. 1280d08b8680SEric Joyner */ 1281f2635e84SEric Joyner static int ice_read_sr_pointer(struct ice_hw *hw, u16 offset, u32 *pointer) 1282d08b8680SEric Joyner { 1283f2635e84SEric Joyner int status; 1284d08b8680SEric Joyner u16 value; 1285d08b8680SEric Joyner 1286d08b8680SEric Joyner status = ice_read_sr_word(hw, offset, &value); 1287d08b8680SEric Joyner if (status) 1288d08b8680SEric Joyner return status; 1289d08b8680SEric Joyner 1290d08b8680SEric Joyner /* Determine if the pointer is in 4KB or word units */ 1291d08b8680SEric Joyner if (value & ICE_SR_NVM_PTR_4KB_UNITS) 1292d08b8680SEric Joyner *pointer = (value & ~ICE_SR_NVM_PTR_4KB_UNITS) * 4 * 1024; 1293d08b8680SEric Joyner else 1294d08b8680SEric Joyner *pointer = value * 2; 1295d08b8680SEric Joyner 1296f2635e84SEric Joyner return 0; 1297d08b8680SEric Joyner } 1298d08b8680SEric Joyner 1299d08b8680SEric Joyner /** 1300d08b8680SEric Joyner * ice_read_sr_area_size - Read an area size from a Shadow RAM word 1301d08b8680SEric Joyner * @hw: pointer to the HW structure 1302d08b8680SEric Joyner * @offset: the word offset of the Shadow RAM to read 1303d08b8680SEric Joyner * @size: size value read from the Shadow RAM 1304d08b8680SEric Joyner * 1305d08b8680SEric Joyner * Read the given Shadow RAM word, and convert it to an area size value 1306d08b8680SEric Joyner * specified in bytes. This function assumes the specified offset is a valid 1307d08b8680SEric Joyner * area size word. 1308d08b8680SEric Joyner * 1309d08b8680SEric Joyner * Each area size word is specified in 4KB sector units. This function reports 1310d08b8680SEric Joyner * the size in bytes, intended for flat NVM reads. 1311d08b8680SEric Joyner */ 1312f2635e84SEric Joyner static int ice_read_sr_area_size(struct ice_hw *hw, u16 offset, u32 *size) 1313d08b8680SEric Joyner { 1314f2635e84SEric Joyner int status; 1315d08b8680SEric Joyner u16 value; 1316d08b8680SEric Joyner 1317d08b8680SEric Joyner status = ice_read_sr_word(hw, offset, &value); 1318d08b8680SEric Joyner if (status) 1319d08b8680SEric Joyner return status; 1320d08b8680SEric Joyner 1321d08b8680SEric Joyner /* Area sizes are always specified in 4KB units */ 1322d08b8680SEric Joyner *size = value * 4 * 1024; 1323d08b8680SEric Joyner 1324f2635e84SEric Joyner return 0; 1325d08b8680SEric Joyner } 1326d08b8680SEric Joyner 1327d08b8680SEric Joyner /** 1328d08b8680SEric Joyner * ice_determine_active_flash_banks - Discover active bank for each module 1329d08b8680SEric Joyner * @hw: pointer to the HW struct 1330d08b8680SEric Joyner * 1331d08b8680SEric Joyner * Read the Shadow RAM control word and determine which banks are active for 1332d08b8680SEric Joyner * the NVM, OROM, and Netlist modules. Also read and calculate the associated 1333d08b8680SEric Joyner * pointer and size. These values are then cached into the ice_flash_info 1334d08b8680SEric Joyner * structure for later use in order to calculate the correct offset to read 1335d08b8680SEric Joyner * from the active module. 1336d08b8680SEric Joyner */ 1337f2635e84SEric Joyner static int ice_determine_active_flash_banks(struct ice_hw *hw) 1338d08b8680SEric Joyner { 1339d08b8680SEric Joyner struct ice_bank_info *banks = &hw->flash.banks; 1340d08b8680SEric Joyner u16 ctrl_word; 1341f2635e84SEric Joyner int status; 1342d08b8680SEric Joyner 1343d08b8680SEric Joyner status = ice_read_sr_word(hw, ICE_SR_NVM_CTRL_WORD, &ctrl_word); 1344d08b8680SEric Joyner if (status) { 1345d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to read the Shadow RAM control word\n"); 1346d08b8680SEric Joyner return status; 1347d08b8680SEric Joyner } 1348d08b8680SEric Joyner 1349d08b8680SEric Joyner /* Check that the control word indicates validity */ 1350d08b8680SEric Joyner if ((ctrl_word & ICE_SR_CTRL_WORD_1_M) >> ICE_SR_CTRL_WORD_1_S != ICE_SR_CTRL_WORD_VALID) { 1351d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Shadow RAM control word is invalid\n"); 1352d08b8680SEric Joyner return ICE_ERR_CFG; 1353d08b8680SEric Joyner } 1354d08b8680SEric Joyner 1355d08b8680SEric Joyner if (!(ctrl_word & ICE_SR_CTRL_WORD_NVM_BANK)) 1356d08b8680SEric Joyner banks->nvm_bank = ICE_1ST_FLASH_BANK; 1357d08b8680SEric Joyner else 1358d08b8680SEric Joyner banks->nvm_bank = ICE_2ND_FLASH_BANK; 1359d08b8680SEric Joyner 1360d08b8680SEric Joyner if (!(ctrl_word & ICE_SR_CTRL_WORD_OROM_BANK)) 1361d08b8680SEric Joyner banks->orom_bank = ICE_1ST_FLASH_BANK; 1362d08b8680SEric Joyner else 1363d08b8680SEric Joyner banks->orom_bank = ICE_2ND_FLASH_BANK; 1364d08b8680SEric Joyner 1365d08b8680SEric Joyner if (!(ctrl_word & ICE_SR_CTRL_WORD_NETLIST_BANK)) 1366d08b8680SEric Joyner banks->netlist_bank = ICE_1ST_FLASH_BANK; 1367d08b8680SEric Joyner else 1368d08b8680SEric Joyner banks->netlist_bank = ICE_2ND_FLASH_BANK; 1369d08b8680SEric Joyner 1370d08b8680SEric Joyner status = ice_read_sr_pointer(hw, ICE_SR_1ST_NVM_BANK_PTR, &banks->nvm_ptr); 1371d08b8680SEric Joyner if (status) { 1372d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to read NVM bank pointer\n"); 1373d08b8680SEric Joyner return status; 1374d08b8680SEric Joyner } 1375d08b8680SEric Joyner 1376d08b8680SEric Joyner status = ice_read_sr_area_size(hw, ICE_SR_NVM_BANK_SIZE, &banks->nvm_size); 1377d08b8680SEric Joyner if (status) { 1378d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to read NVM bank area size\n"); 1379d08b8680SEric Joyner return status; 1380d08b8680SEric Joyner } 1381d08b8680SEric Joyner 1382d08b8680SEric Joyner status = ice_read_sr_pointer(hw, ICE_SR_1ST_OROM_BANK_PTR, &banks->orom_ptr); 1383d08b8680SEric Joyner if (status) { 1384d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to read OROM bank pointer\n"); 1385d08b8680SEric Joyner return status; 1386d08b8680SEric Joyner } 1387d08b8680SEric Joyner 1388d08b8680SEric Joyner status = ice_read_sr_area_size(hw, ICE_SR_OROM_BANK_SIZE, &banks->orom_size); 1389d08b8680SEric Joyner if (status) { 1390d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to read OROM bank area size\n"); 1391d08b8680SEric Joyner return status; 1392d08b8680SEric Joyner } 1393d08b8680SEric Joyner 1394d08b8680SEric Joyner status = ice_read_sr_pointer(hw, ICE_SR_NETLIST_BANK_PTR, &banks->netlist_ptr); 1395d08b8680SEric Joyner if (status) { 1396d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to read Netlist bank pointer\n"); 1397d08b8680SEric Joyner return status; 1398d08b8680SEric Joyner } 1399d08b8680SEric Joyner 1400d08b8680SEric Joyner status = ice_read_sr_area_size(hw, ICE_SR_NETLIST_BANK_SIZE, &banks->netlist_size); 1401d08b8680SEric Joyner if (status) { 1402d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to read Netlist bank area size\n"); 1403d08b8680SEric Joyner return status; 1404d08b8680SEric Joyner } 1405d08b8680SEric Joyner 1406f2635e84SEric Joyner return 0; 1407d08b8680SEric Joyner } 1408d08b8680SEric Joyner 1409d08b8680SEric Joyner /** 141071d10453SEric Joyner * ice_init_nvm - initializes NVM setting 141171d10453SEric Joyner * @hw: pointer to the HW struct 141271d10453SEric Joyner * 141371d10453SEric Joyner * This function reads and populates NVM settings such as Shadow RAM size, 141471d10453SEric Joyner * max_timeout, and blank_nvm_mode 141571d10453SEric Joyner */ 1416f2635e84SEric Joyner int ice_init_nvm(struct ice_hw *hw) 141771d10453SEric Joyner { 1418d08b8680SEric Joyner struct ice_flash_info *flash = &hw->flash; 141971d10453SEric Joyner u32 fla, gens_stat; 142071d10453SEric Joyner u8 sr_size; 1421f2635e84SEric Joyner int status; 142271d10453SEric Joyner 142371d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 142471d10453SEric Joyner 142571d10453SEric Joyner /* The SR size is stored regardless of the NVM programming mode 142671d10453SEric Joyner * as the blank mode may be used in the factory line. 142771d10453SEric Joyner */ 142871d10453SEric Joyner gens_stat = rd32(hw, GLNVM_GENS); 142971d10453SEric Joyner sr_size = (gens_stat & GLNVM_GENS_SR_SIZE_M) >> GLNVM_GENS_SR_SIZE_S; 143071d10453SEric Joyner 143171d10453SEric Joyner /* Switching to words (sr_size contains power of 2) */ 1432d08b8680SEric Joyner flash->sr_words = BIT(sr_size) * ICE_SR_WORDS_IN_1KB; 143371d10453SEric Joyner 143471d10453SEric Joyner /* Check if we are in the normal or blank NVM programming mode */ 143571d10453SEric Joyner fla = rd32(hw, GLNVM_FLA); 143671d10453SEric Joyner if (fla & GLNVM_FLA_LOCKED_M) { /* Normal programming mode */ 1437d08b8680SEric Joyner flash->blank_nvm_mode = false; 143871d10453SEric Joyner } else { 143971d10453SEric Joyner /* Blank programming mode */ 1440d08b8680SEric Joyner flash->blank_nvm_mode = true; 14417d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_NVM, "NVM init error: unsupported blank mode.\n"); 144271d10453SEric Joyner return ICE_ERR_NVM_BLANK_MODE; 144371d10453SEric Joyner } 144471d10453SEric Joyner 144571d10453SEric Joyner status = ice_discover_flash_size(hw); 144671d10453SEric Joyner if (status) { 14477d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_NVM, "NVM init error: failed to discover flash size.\n"); 144871d10453SEric Joyner return status; 144971d10453SEric Joyner } 145071d10453SEric Joyner 1451d08b8680SEric Joyner status = ice_determine_active_flash_banks(hw); 145271d10453SEric Joyner if (status) { 1453d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to determine active flash banks.\n"); 145471d10453SEric Joyner return status; 145571d10453SEric Joyner } 145671d10453SEric Joyner 1457d08b8680SEric Joyner status = ice_get_nvm_ver_info(hw, ICE_ACTIVE_FLASH_BANK, &flash->nvm); 1458d08b8680SEric Joyner if (status) { 1459d08b8680SEric Joyner ice_debug(hw, ICE_DBG_INIT, "Failed to read NVM info.\n"); 1460d08b8680SEric Joyner return status; 1461d08b8680SEric Joyner } 1462d08b8680SEric Joyner 1463d08b8680SEric Joyner status = ice_get_orom_ver_info(hw, ICE_ACTIVE_FLASH_BANK, &flash->orom); 1464d08b8680SEric Joyner if (status) 1465d08b8680SEric Joyner ice_debug(hw, ICE_DBG_INIT, "Failed to read Option ROM info.\n"); 1466d08b8680SEric Joyner 146771d10453SEric Joyner /* read the netlist version information */ 1468d08b8680SEric Joyner status = ice_get_netlist_info(hw, ICE_ACTIVE_FLASH_BANK, &flash->netlist); 146971d10453SEric Joyner if (status) 147071d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "Failed to read netlist info.\n"); 14719e54973fSEric Joyner 1472f2635e84SEric Joyner return 0; 147371d10453SEric Joyner } 147471d10453SEric Joyner 147571d10453SEric Joyner /** 147671d10453SEric Joyner * ice_read_sr_buf - Reads Shadow RAM buf and acquire lock if necessary 147771d10453SEric Joyner * @hw: pointer to the HW structure 147871d10453SEric Joyner * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) 147971d10453SEric Joyner * @words: (in) number of words to read; (out) number of words actually read 148071d10453SEric Joyner * @data: words read from the Shadow RAM 148171d10453SEric Joyner * 148271d10453SEric Joyner * Reads 16 bit words (data buf) from the SR using the ice_read_nvm_buf_aq 148371d10453SEric Joyner * method. The buf read is preceded by the NVM ownership take 148471d10453SEric Joyner * and followed by the release. 148571d10453SEric Joyner */ 1486f2635e84SEric Joyner int 148771d10453SEric Joyner ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, u16 *data) 148871d10453SEric Joyner { 1489f2635e84SEric Joyner int status; 149071d10453SEric Joyner 149171d10453SEric Joyner status = ice_acquire_nvm(hw, ICE_RES_READ); 149271d10453SEric Joyner if (!status) { 149371d10453SEric Joyner status = ice_read_sr_buf_aq(hw, offset, words, data); 149471d10453SEric Joyner ice_release_nvm(hw); 149571d10453SEric Joyner } 149671d10453SEric Joyner 149771d10453SEric Joyner return status; 149871d10453SEric Joyner } 149971d10453SEric Joyner 150071d10453SEric Joyner /** 150171d10453SEric Joyner * __ice_write_sr_word - Writes Shadow RAM word 150271d10453SEric Joyner * @hw: pointer to the HW structure 150371d10453SEric Joyner * @offset: offset of the Shadow RAM word to write 150471d10453SEric Joyner * @data: word to write to the Shadow RAM 150571d10453SEric Joyner * 150671d10453SEric Joyner * Writes a 16 bit word to the SR using the ice_write_sr_aq method. 150771d10453SEric Joyner * NVM ownership have to be acquired and released (on ARQ completion event 150871d10453SEric Joyner * reception) by caller. To commit SR to NVM update checksum function 150971d10453SEric Joyner * should be called. 151071d10453SEric Joyner */ 1511f2635e84SEric Joyner int 151271d10453SEric Joyner __ice_write_sr_word(struct ice_hw *hw, u32 offset, const u16 *data) 151371d10453SEric Joyner { 151471d10453SEric Joyner __le16 data_local = CPU_TO_LE16(*data); 151571d10453SEric Joyner 151671d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 151771d10453SEric Joyner 151871d10453SEric Joyner /* Value 0x00 below means that we treat SR as a flat mem */ 151971d10453SEric Joyner return ice_write_sr_aq(hw, offset, 1, &data_local, false); 152071d10453SEric Joyner } 152171d10453SEric Joyner 152271d10453SEric Joyner /** 152371d10453SEric Joyner * __ice_write_sr_buf - Writes Shadow RAM buf 152471d10453SEric Joyner * @hw: pointer to the HW structure 152571d10453SEric Joyner * @offset: offset of the Shadow RAM buffer to write 152671d10453SEric Joyner * @words: number of words to write 152771d10453SEric Joyner * @data: words to write to the Shadow RAM 152871d10453SEric Joyner * 152971d10453SEric Joyner * Writes a 16 bit words buffer to the Shadow RAM using the admin command. 153071d10453SEric Joyner * NVM ownership must be acquired before calling this function and released 153171d10453SEric Joyner * on ARQ completion event reception by caller. To commit SR to NVM update 153271d10453SEric Joyner * checksum function should be called. 153371d10453SEric Joyner */ 1534f2635e84SEric Joyner int 153571d10453SEric Joyner __ice_write_sr_buf(struct ice_hw *hw, u32 offset, u16 words, const u16 *data) 153671d10453SEric Joyner { 153771d10453SEric Joyner __le16 *data_local; 1538f2635e84SEric Joyner int status; 153971d10453SEric Joyner void *vmem; 154071d10453SEric Joyner u32 i; 154171d10453SEric Joyner 154271d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 154371d10453SEric Joyner 154471d10453SEric Joyner vmem = ice_calloc(hw, words, sizeof(u16)); 154571d10453SEric Joyner if (!vmem) 154671d10453SEric Joyner return ICE_ERR_NO_MEMORY; 154771d10453SEric Joyner data_local = (_FORCE_ __le16 *)vmem; 154871d10453SEric Joyner 154971d10453SEric Joyner for (i = 0; i < words; i++) 155071d10453SEric Joyner data_local[i] = CPU_TO_LE16(data[i]); 155171d10453SEric Joyner 155271d10453SEric Joyner /* Here we will only write one buffer as the size of the modules 155371d10453SEric Joyner * mirrored in the Shadow RAM is always less than 4K. 155471d10453SEric Joyner */ 155571d10453SEric Joyner status = ice_write_sr_aq(hw, offset, words, data_local, false); 155671d10453SEric Joyner 155771d10453SEric Joyner ice_free(hw, vmem); 155871d10453SEric Joyner 155971d10453SEric Joyner return status; 156071d10453SEric Joyner } 156171d10453SEric Joyner 156271d10453SEric Joyner /** 156371d10453SEric Joyner * ice_calc_sr_checksum - Calculates and returns Shadow RAM SW checksum 156471d10453SEric Joyner * @hw: pointer to hardware structure 156571d10453SEric Joyner * @checksum: pointer to the checksum 156671d10453SEric Joyner * 156771d10453SEric Joyner * This function calculates SW Checksum that covers the whole 64kB shadow RAM 156871d10453SEric Joyner * except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD 156971d10453SEric Joyner * is customer specific and unknown. Therefore, this function skips all maximum 157071d10453SEric Joyner * possible size of VPD (1kB). 157171d10453SEric Joyner */ 1572f2635e84SEric Joyner static int ice_calc_sr_checksum(struct ice_hw *hw, u16 *checksum) 157371d10453SEric Joyner { 157471d10453SEric Joyner u16 pcie_alt_module = 0; 157571d10453SEric Joyner u16 checksum_local = 0; 157671d10453SEric Joyner u16 vpd_module; 1577f2635e84SEric Joyner int status = 0; 157871d10453SEric Joyner void *vmem; 157971d10453SEric Joyner u16 *data; 158071d10453SEric Joyner u16 i; 158171d10453SEric Joyner 158271d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 158371d10453SEric Joyner 158471d10453SEric Joyner vmem = ice_calloc(hw, ICE_SR_SECTOR_SIZE_IN_WORDS, sizeof(u16)); 158571d10453SEric Joyner if (!vmem) 158671d10453SEric Joyner return ICE_ERR_NO_MEMORY; 158771d10453SEric Joyner data = (u16 *)vmem; 158871d10453SEric Joyner 158971d10453SEric Joyner /* read pointer to VPD area */ 159071d10453SEric Joyner status = ice_read_sr_word_aq(hw, ICE_SR_VPD_PTR, &vpd_module); 159171d10453SEric Joyner if (status) 159271d10453SEric Joyner goto ice_calc_sr_checksum_exit; 159371d10453SEric Joyner 159471d10453SEric Joyner /* read pointer to PCIe Alt Auto-load module */ 159571d10453SEric Joyner status = ice_read_sr_word_aq(hw, ICE_SR_PCIE_ALT_AUTO_LOAD_PTR, 159671d10453SEric Joyner &pcie_alt_module); 159771d10453SEric Joyner if (status) 159871d10453SEric Joyner goto ice_calc_sr_checksum_exit; 159971d10453SEric Joyner 160071d10453SEric Joyner /* Calculate SW checksum that covers the whole 64kB shadow RAM 160171d10453SEric Joyner * except the VPD and PCIe ALT Auto-load modules 160271d10453SEric Joyner */ 1603d08b8680SEric Joyner for (i = 0; i < hw->flash.sr_words; i++) { 160471d10453SEric Joyner /* Read SR page */ 160571d10453SEric Joyner if ((i % ICE_SR_SECTOR_SIZE_IN_WORDS) == 0) { 160671d10453SEric Joyner u16 words = ICE_SR_SECTOR_SIZE_IN_WORDS; 160771d10453SEric Joyner 160871d10453SEric Joyner status = ice_read_sr_buf_aq(hw, i, &words, data); 1609f2635e84SEric Joyner if (status) 161071d10453SEric Joyner goto ice_calc_sr_checksum_exit; 161171d10453SEric Joyner } 161271d10453SEric Joyner 161371d10453SEric Joyner /* Skip Checksum word */ 161471d10453SEric Joyner if (i == ICE_SR_SW_CHECKSUM_WORD) 161571d10453SEric Joyner continue; 161671d10453SEric Joyner /* Skip VPD module (convert byte size to word count) */ 16177d7af7f8SEric Joyner if (i >= (u32)vpd_module && 16187d7af7f8SEric Joyner i < ((u32)vpd_module + ICE_SR_VPD_SIZE_WORDS)) 161971d10453SEric Joyner continue; 162071d10453SEric Joyner /* Skip PCIe ALT module (convert byte size to word count) */ 16217d7af7f8SEric Joyner if (i >= (u32)pcie_alt_module && 16227d7af7f8SEric Joyner i < ((u32)pcie_alt_module + ICE_SR_PCIE_ALT_SIZE_WORDS)) 162371d10453SEric Joyner continue; 162471d10453SEric Joyner 162571d10453SEric Joyner checksum_local += data[i % ICE_SR_SECTOR_SIZE_IN_WORDS]; 162671d10453SEric Joyner } 162771d10453SEric Joyner 162871d10453SEric Joyner *checksum = (u16)ICE_SR_SW_CHECKSUM_BASE - checksum_local; 162971d10453SEric Joyner 163071d10453SEric Joyner ice_calc_sr_checksum_exit: 163171d10453SEric Joyner ice_free(hw, vmem); 163271d10453SEric Joyner return status; 163371d10453SEric Joyner } 163471d10453SEric Joyner 163571d10453SEric Joyner /** 163671d10453SEric Joyner * ice_update_sr_checksum - Updates the Shadow RAM SW checksum 163771d10453SEric Joyner * @hw: pointer to hardware structure 163871d10453SEric Joyner * 163971d10453SEric Joyner * NVM ownership must be acquired before calling this function and released 164071d10453SEric Joyner * on ARQ completion event reception by caller. 164171d10453SEric Joyner * This function will commit SR to NVM. 164271d10453SEric Joyner */ 1643f2635e84SEric Joyner int ice_update_sr_checksum(struct ice_hw *hw) 164471d10453SEric Joyner { 164571d10453SEric Joyner __le16 le_sum; 164671d10453SEric Joyner u16 checksum; 1647f2635e84SEric Joyner int status; 164871d10453SEric Joyner 164971d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 165071d10453SEric Joyner 165171d10453SEric Joyner status = ice_calc_sr_checksum(hw, &checksum); 165271d10453SEric Joyner if (!status) { 165371d10453SEric Joyner le_sum = CPU_TO_LE16(checksum); 165471d10453SEric Joyner status = ice_write_sr_aq(hw, ICE_SR_SW_CHECKSUM_WORD, 1, 165571d10453SEric Joyner &le_sum, true); 165671d10453SEric Joyner } 165771d10453SEric Joyner return status; 165871d10453SEric Joyner } 165971d10453SEric Joyner 166071d10453SEric Joyner /** 166171d10453SEric Joyner * ice_validate_sr_checksum - Validate Shadow RAM SW checksum 166271d10453SEric Joyner * @hw: pointer to hardware structure 166371d10453SEric Joyner * @checksum: calculated checksum 166471d10453SEric Joyner * 166571d10453SEric Joyner * Performs checksum calculation and validates the Shadow RAM SW checksum. 166671d10453SEric Joyner * If the caller does not need checksum, the value can be NULL. 166771d10453SEric Joyner */ 1668f2635e84SEric Joyner int ice_validate_sr_checksum(struct ice_hw *hw, u16 *checksum) 166971d10453SEric Joyner { 167071d10453SEric Joyner u16 checksum_local; 167171d10453SEric Joyner u16 checksum_sr; 1672f2635e84SEric Joyner int status; 167371d10453SEric Joyner 167471d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 167571d10453SEric Joyner 167671d10453SEric Joyner status = ice_acquire_nvm(hw, ICE_RES_READ); 167771d10453SEric Joyner if (!status) { 167871d10453SEric Joyner status = ice_calc_sr_checksum(hw, &checksum_local); 167971d10453SEric Joyner ice_release_nvm(hw); 168071d10453SEric Joyner if (status) 168171d10453SEric Joyner return status; 168271d10453SEric Joyner } else { 168371d10453SEric Joyner return status; 168471d10453SEric Joyner } 168571d10453SEric Joyner 168671d10453SEric Joyner ice_read_sr_word(hw, ICE_SR_SW_CHECKSUM_WORD, &checksum_sr); 168771d10453SEric Joyner 168871d10453SEric Joyner /* Verify read checksum from EEPROM is the same as 168971d10453SEric Joyner * calculated checksum 169071d10453SEric Joyner */ 169171d10453SEric Joyner if (checksum_local != checksum_sr) 169271d10453SEric Joyner status = ICE_ERR_NVM_CHECKSUM; 169371d10453SEric Joyner 169471d10453SEric Joyner /* If the user cares, return the calculated checksum */ 169571d10453SEric Joyner if (checksum) 169671d10453SEric Joyner *checksum = checksum_local; 169771d10453SEric Joyner 169871d10453SEric Joyner return status; 169971d10453SEric Joyner } 170071d10453SEric Joyner 170171d10453SEric Joyner /** 170271d10453SEric Joyner * ice_nvm_validate_checksum 170371d10453SEric Joyner * @hw: pointer to the HW struct 170471d10453SEric Joyner * 170571d10453SEric Joyner * Verify NVM PFA checksum validity (0x0706) 170671d10453SEric Joyner */ 1707f2635e84SEric Joyner int ice_nvm_validate_checksum(struct ice_hw *hw) 170871d10453SEric Joyner { 170971d10453SEric Joyner struct ice_aqc_nvm_checksum *cmd; 171071d10453SEric Joyner struct ice_aq_desc desc; 1711f2635e84SEric Joyner int status; 171271d10453SEric Joyner 171371d10453SEric Joyner status = ice_acquire_nvm(hw, ICE_RES_READ); 171471d10453SEric Joyner if (status) 171571d10453SEric Joyner return status; 171671d10453SEric Joyner 171771d10453SEric Joyner cmd = &desc.params.nvm_checksum; 171871d10453SEric Joyner 171971d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_checksum); 172071d10453SEric Joyner cmd->flags = ICE_AQC_NVM_CHECKSUM_VERIFY; 172171d10453SEric Joyner 172271d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 172371d10453SEric Joyner ice_release_nvm(hw); 172471d10453SEric Joyner 172571d10453SEric Joyner if (!status) 172671d10453SEric Joyner if (LE16_TO_CPU(cmd->checksum) != ICE_AQC_NVM_CHECKSUM_CORRECT) 172771d10453SEric Joyner status = ICE_ERR_NVM_CHECKSUM; 172871d10453SEric Joyner 172971d10453SEric Joyner return status; 173071d10453SEric Joyner } 173171d10453SEric Joyner 173271d10453SEric Joyner /** 1733d08b8680SEric Joyner * ice_nvm_recalculate_checksum 1734d08b8680SEric Joyner * @hw: pointer to the HW struct 1735d08b8680SEric Joyner * 1736d08b8680SEric Joyner * Recalculate NVM PFA checksum (0x0706) 1737d08b8680SEric Joyner */ 1738f2635e84SEric Joyner int ice_nvm_recalculate_checksum(struct ice_hw *hw) 1739d08b8680SEric Joyner { 1740d08b8680SEric Joyner struct ice_aqc_nvm_checksum *cmd; 1741d08b8680SEric Joyner struct ice_aq_desc desc; 1742f2635e84SEric Joyner int status; 1743d08b8680SEric Joyner 1744d08b8680SEric Joyner status = ice_acquire_nvm(hw, ICE_RES_READ); 1745d08b8680SEric Joyner if (status) 1746d08b8680SEric Joyner return status; 1747d08b8680SEric Joyner 1748d08b8680SEric Joyner cmd = &desc.params.nvm_checksum; 1749d08b8680SEric Joyner 1750d08b8680SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_checksum); 1751d08b8680SEric Joyner cmd->flags = ICE_AQC_NVM_CHECKSUM_RECALC; 1752d08b8680SEric Joyner 1753d08b8680SEric Joyner status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 1754d08b8680SEric Joyner 1755d08b8680SEric Joyner ice_release_nvm(hw); 1756d08b8680SEric Joyner 1757d08b8680SEric Joyner return status; 1758d08b8680SEric Joyner } 1759d08b8680SEric Joyner 1760d08b8680SEric Joyner /** 1761d08b8680SEric Joyner * ice_nvm_write_activate 1762d08b8680SEric Joyner * @hw: pointer to the HW struct 17638923de59SPiotr Kubaj * @cmd_flags: flags for write activate command 17648923de59SPiotr Kubaj * @response_flags: response indicators from firmware 1765d08b8680SEric Joyner * 1766d08b8680SEric Joyner * Update the control word with the required banks' validity bits 1767d08b8680SEric Joyner * and dumps the Shadow RAM to flash (0x0707) 17688923de59SPiotr Kubaj * 17698923de59SPiotr Kubaj * cmd_flags controls which banks to activate, the preservation level to use 17708923de59SPiotr Kubaj * when activating the NVM bank, and whether an EMP reset is required for 17718923de59SPiotr Kubaj * activation. 17728923de59SPiotr Kubaj * 17738923de59SPiotr Kubaj * Note that the 16bit cmd_flags value is split between two separate 1 byte 17748923de59SPiotr Kubaj * flag values in the descriptor. 17758923de59SPiotr Kubaj * 17768923de59SPiotr Kubaj * On successful return of the firmware command, the response_flags variable 17778923de59SPiotr Kubaj * is updated with the flags reported by firmware indicating certain status, 17788923de59SPiotr Kubaj * such as whether EMP reset is enabled. 1779d08b8680SEric Joyner */ 1780f2635e84SEric Joyner int ice_nvm_write_activate(struct ice_hw *hw, u16 cmd_flags, u8 *response_flags) 1781d08b8680SEric Joyner { 1782d08b8680SEric Joyner struct ice_aqc_nvm *cmd; 1783d08b8680SEric Joyner struct ice_aq_desc desc; 1784f2635e84SEric Joyner int err; 1785d08b8680SEric Joyner 1786d08b8680SEric Joyner cmd = &desc.params.nvm; 1787d08b8680SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_write_activate); 1788d08b8680SEric Joyner 17899e54973fSEric Joyner cmd->cmd_flags = (u8)(cmd_flags & 0xFF); 17909e54973fSEric Joyner cmd->offset_high = (u8)((cmd_flags >> 8) & 0xFF); 1791d08b8680SEric Joyner 17929e54973fSEric Joyner err = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 17939e54973fSEric Joyner if (!err && response_flags) 17948923de59SPiotr Kubaj *response_flags = cmd->cmd_flags; 17958923de59SPiotr Kubaj 17969e54973fSEric Joyner return err; 1797d08b8680SEric Joyner } 1798d08b8680SEric Joyner 1799d08b8680SEric Joyner /** 1800d08b8680SEric Joyner * ice_get_nvm_minsrevs - Get the Minimum Security Revision values from flash 1801d08b8680SEric Joyner * @hw: pointer to the HW struct 1802d08b8680SEric Joyner * @minsrevs: structure to store NVM and OROM minsrev values 1803d08b8680SEric Joyner * 1804d08b8680SEric Joyner * Read the Minimum Security Revision TLV and extract the revision values from 1805d08b8680SEric Joyner * the flash image into a readable structure for processing. 1806d08b8680SEric Joyner */ 1807f2635e84SEric Joyner int 1808d08b8680SEric Joyner ice_get_nvm_minsrevs(struct ice_hw *hw, struct ice_minsrev_info *minsrevs) 1809d08b8680SEric Joyner { 1810d08b8680SEric Joyner struct ice_aqc_nvm_minsrev data; 1811f2635e84SEric Joyner int status; 1812d08b8680SEric Joyner u16 valid; 1813d08b8680SEric Joyner 1814d08b8680SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 1815d08b8680SEric Joyner 1816d08b8680SEric Joyner status = ice_acquire_nvm(hw, ICE_RES_READ); 1817d08b8680SEric Joyner if (status) 1818d08b8680SEric Joyner return status; 1819d08b8680SEric Joyner 1820d08b8680SEric Joyner status = ice_aq_read_nvm(hw, ICE_AQC_NVM_MINSREV_MOD_ID, 0, sizeof(data), 1821d08b8680SEric Joyner &data, true, false, NULL); 1822d08b8680SEric Joyner 1823d08b8680SEric Joyner ice_release_nvm(hw); 1824d08b8680SEric Joyner 1825d08b8680SEric Joyner if (status) 1826d08b8680SEric Joyner return status; 1827d08b8680SEric Joyner 1828d08b8680SEric Joyner valid = LE16_TO_CPU(data.validity); 1829d08b8680SEric Joyner 1830d08b8680SEric Joyner /* Extract NVM minimum security revision */ 1831d08b8680SEric Joyner if (valid & ICE_AQC_NVM_MINSREV_NVM_VALID) { 1832d08b8680SEric Joyner u16 minsrev_l, minsrev_h; 1833d08b8680SEric Joyner 1834d08b8680SEric Joyner minsrev_l = LE16_TO_CPU(data.nvm_minsrev_l); 1835d08b8680SEric Joyner minsrev_h = LE16_TO_CPU(data.nvm_minsrev_h); 1836d08b8680SEric Joyner 1837d08b8680SEric Joyner minsrevs->nvm = minsrev_h << 16 | minsrev_l; 1838d08b8680SEric Joyner minsrevs->nvm_valid = true; 1839d08b8680SEric Joyner } 1840d08b8680SEric Joyner 1841d08b8680SEric Joyner /* Extract the OROM minimum security revision */ 1842d08b8680SEric Joyner if (valid & ICE_AQC_NVM_MINSREV_OROM_VALID) { 1843d08b8680SEric Joyner u16 minsrev_l, minsrev_h; 1844d08b8680SEric Joyner 1845d08b8680SEric Joyner minsrev_l = LE16_TO_CPU(data.orom_minsrev_l); 1846d08b8680SEric Joyner minsrev_h = LE16_TO_CPU(data.orom_minsrev_h); 1847d08b8680SEric Joyner 1848d08b8680SEric Joyner minsrevs->orom = minsrev_h << 16 | minsrev_l; 1849d08b8680SEric Joyner minsrevs->orom_valid = true; 1850d08b8680SEric Joyner } 1851d08b8680SEric Joyner 1852f2635e84SEric Joyner return 0; 1853d08b8680SEric Joyner } 1854d08b8680SEric Joyner 1855d08b8680SEric Joyner /** 1856d08b8680SEric Joyner * ice_update_nvm_minsrevs - Update minimum security revision TLV data in flash 1857d08b8680SEric Joyner * @hw: pointer to the HW struct 1858d08b8680SEric Joyner * @minsrevs: minimum security revision information 1859d08b8680SEric Joyner * 1860d08b8680SEric Joyner * Update the NVM or Option ROM minimum security revision fields in the PFA 1861d08b8680SEric Joyner * area of the flash. Reads the minsrevs->nvm_valid and minsrevs->orom_valid 1862d08b8680SEric Joyner * fields to determine what update is being requested. If the valid bit is not 1863d08b8680SEric Joyner * set for that module, then the associated minsrev will be left as is. 1864d08b8680SEric Joyner */ 1865f2635e84SEric Joyner int 1866d08b8680SEric Joyner ice_update_nvm_minsrevs(struct ice_hw *hw, struct ice_minsrev_info *minsrevs) 1867d08b8680SEric Joyner { 1868d08b8680SEric Joyner struct ice_aqc_nvm_minsrev data; 1869f2635e84SEric Joyner int status; 1870d08b8680SEric Joyner 1871d08b8680SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 1872d08b8680SEric Joyner 1873d08b8680SEric Joyner if (!minsrevs->nvm_valid && !minsrevs->orom_valid) { 1874d08b8680SEric Joyner ice_debug(hw, ICE_DBG_NVM, "At least one of NVM and OROM MinSrev must be valid"); 1875d08b8680SEric Joyner return ICE_ERR_PARAM; 1876d08b8680SEric Joyner } 1877d08b8680SEric Joyner 1878d08b8680SEric Joyner status = ice_acquire_nvm(hw, ICE_RES_WRITE); 1879d08b8680SEric Joyner if (status) 1880d08b8680SEric Joyner return status; 1881d08b8680SEric Joyner 1882d08b8680SEric Joyner /* Get current data */ 1883d08b8680SEric Joyner status = ice_aq_read_nvm(hw, ICE_AQC_NVM_MINSREV_MOD_ID, 0, sizeof(data), 1884d08b8680SEric Joyner &data, true, false, NULL); 1885d08b8680SEric Joyner if (status) 1886d08b8680SEric Joyner goto exit_release_res; 1887d08b8680SEric Joyner 1888d08b8680SEric Joyner if (minsrevs->nvm_valid) { 1889d08b8680SEric Joyner data.nvm_minsrev_l = CPU_TO_LE16(minsrevs->nvm & 0xFFFF); 1890d08b8680SEric Joyner data.nvm_minsrev_h = CPU_TO_LE16(minsrevs->nvm >> 16); 1891d08b8680SEric Joyner data.validity |= CPU_TO_LE16(ICE_AQC_NVM_MINSREV_NVM_VALID); 1892d08b8680SEric Joyner } 1893d08b8680SEric Joyner 1894d08b8680SEric Joyner if (minsrevs->orom_valid) { 1895d08b8680SEric Joyner data.orom_minsrev_l = CPU_TO_LE16(minsrevs->orom & 0xFFFF); 1896d08b8680SEric Joyner data.orom_minsrev_h = CPU_TO_LE16(minsrevs->orom >> 16); 1897d08b8680SEric Joyner data.validity |= CPU_TO_LE16(ICE_AQC_NVM_MINSREV_OROM_VALID); 1898d08b8680SEric Joyner } 1899d08b8680SEric Joyner 1900d08b8680SEric Joyner /* Update flash data */ 1901d08b8680SEric Joyner status = ice_aq_update_nvm(hw, ICE_AQC_NVM_MINSREV_MOD_ID, 0, sizeof(data), &data, 19028923de59SPiotr Kubaj false, ICE_AQC_NVM_SPECIAL_UPDATE, NULL); 1903d08b8680SEric Joyner if (status) 1904d08b8680SEric Joyner goto exit_release_res; 1905d08b8680SEric Joyner 1906d08b8680SEric Joyner /* Dump the Shadow RAM to the flash */ 19078923de59SPiotr Kubaj status = ice_nvm_write_activate(hw, 0, NULL); 1908d08b8680SEric Joyner 1909d08b8680SEric Joyner exit_release_res: 1910d08b8680SEric Joyner ice_release_nvm(hw); 1911d08b8680SEric Joyner 1912d08b8680SEric Joyner return status; 1913d08b8680SEric Joyner } 1914d08b8680SEric Joyner 1915d08b8680SEric Joyner /** 191671d10453SEric Joyner * ice_nvm_access_get_features - Return the NVM access features structure 191771d10453SEric Joyner * @cmd: NVM access command to process 191871d10453SEric Joyner * @data: storage for the driver NVM features 191971d10453SEric Joyner * 192071d10453SEric Joyner * Fill in the data section of the NVM access request with a copy of the NVM 192171d10453SEric Joyner * features structure. 192271d10453SEric Joyner */ 1923f2635e84SEric Joyner int 192471d10453SEric Joyner ice_nvm_access_get_features(struct ice_nvm_access_cmd *cmd, 192571d10453SEric Joyner union ice_nvm_access_data *data) 192671d10453SEric Joyner { 192771d10453SEric Joyner /* The provided data_size must be at least as large as our NVM 192871d10453SEric Joyner * features structure. A larger size should not be treated as an 19297d7af7f8SEric Joyner * error, to allow future extensions to the features structure to 193071d10453SEric Joyner * work on older drivers. 193171d10453SEric Joyner */ 193271d10453SEric Joyner if (cmd->data_size < sizeof(struct ice_nvm_features)) 193371d10453SEric Joyner return ICE_ERR_NO_MEMORY; 193471d10453SEric Joyner 193571d10453SEric Joyner /* Initialize the data buffer to zeros */ 193671d10453SEric Joyner ice_memset(data, 0, cmd->data_size, ICE_NONDMA_MEM); 193771d10453SEric Joyner 193871d10453SEric Joyner /* Fill in the features data */ 193971d10453SEric Joyner data->drv_features.major = ICE_NVM_ACCESS_MAJOR_VER; 194071d10453SEric Joyner data->drv_features.minor = ICE_NVM_ACCESS_MINOR_VER; 194171d10453SEric Joyner data->drv_features.size = sizeof(struct ice_nvm_features); 194271d10453SEric Joyner data->drv_features.features[0] = ICE_NVM_FEATURES_0_REG_ACCESS; 194371d10453SEric Joyner 1944f2635e84SEric Joyner return 0; 194571d10453SEric Joyner } 194671d10453SEric Joyner 194771d10453SEric Joyner /** 194871d10453SEric Joyner * ice_nvm_access_get_module - Helper function to read module value 194971d10453SEric Joyner * @cmd: NVM access command structure 195071d10453SEric Joyner * 195171d10453SEric Joyner * Reads the module value out of the NVM access config field. 195271d10453SEric Joyner */ 195371d10453SEric Joyner u32 ice_nvm_access_get_module(struct ice_nvm_access_cmd *cmd) 195471d10453SEric Joyner { 195571d10453SEric Joyner return ((cmd->config & ICE_NVM_CFG_MODULE_M) >> ICE_NVM_CFG_MODULE_S); 195671d10453SEric Joyner } 195771d10453SEric Joyner 195871d10453SEric Joyner /** 195971d10453SEric Joyner * ice_nvm_access_get_flags - Helper function to read flags value 196071d10453SEric Joyner * @cmd: NVM access command structure 196171d10453SEric Joyner * 196271d10453SEric Joyner * Reads the flags value out of the NVM access config field. 196371d10453SEric Joyner */ 196471d10453SEric Joyner u32 ice_nvm_access_get_flags(struct ice_nvm_access_cmd *cmd) 196571d10453SEric Joyner { 196671d10453SEric Joyner return ((cmd->config & ICE_NVM_CFG_FLAGS_M) >> ICE_NVM_CFG_FLAGS_S); 196771d10453SEric Joyner } 196871d10453SEric Joyner 196971d10453SEric Joyner /** 197071d10453SEric Joyner * ice_nvm_access_get_adapter - Helper function to read adapter info 197171d10453SEric Joyner * @cmd: NVM access command structure 197271d10453SEric Joyner * 197371d10453SEric Joyner * Read the adapter info value out of the NVM access config field. 197471d10453SEric Joyner */ 197571d10453SEric Joyner u32 ice_nvm_access_get_adapter(struct ice_nvm_access_cmd *cmd) 197671d10453SEric Joyner { 197771d10453SEric Joyner return ((cmd->config & ICE_NVM_CFG_ADAPTER_INFO_M) >> 197871d10453SEric Joyner ICE_NVM_CFG_ADAPTER_INFO_S); 197971d10453SEric Joyner } 198071d10453SEric Joyner 198171d10453SEric Joyner /** 198271d10453SEric Joyner * ice_validate_nvm_rw_reg - Check than an NVM access request is valid 198371d10453SEric Joyner * @cmd: NVM access command structure 198471d10453SEric Joyner * 198571d10453SEric Joyner * Validates that an NVM access structure is request to read or write a valid 198671d10453SEric Joyner * register offset. First validates that the module and flags are correct, and 198771d10453SEric Joyner * then ensures that the register offset is one of the accepted registers. 198871d10453SEric Joyner */ 1989f2635e84SEric Joyner static int 199071d10453SEric Joyner ice_validate_nvm_rw_reg(struct ice_nvm_access_cmd *cmd) 199171d10453SEric Joyner { 199271d10453SEric Joyner u32 module, flags, offset; 199371d10453SEric Joyner u16 i; 199471d10453SEric Joyner 199571d10453SEric Joyner module = ice_nvm_access_get_module(cmd); 199671d10453SEric Joyner flags = ice_nvm_access_get_flags(cmd); 199771d10453SEric Joyner offset = cmd->offset; 199871d10453SEric Joyner 199971d10453SEric Joyner /* Make sure the module and flags indicate a read/write request */ 200071d10453SEric Joyner if (module != ICE_NVM_REG_RW_MODULE || 200171d10453SEric Joyner flags != ICE_NVM_REG_RW_FLAGS || 200271d10453SEric Joyner cmd->data_size != FIELD_SIZEOF(union ice_nvm_access_data, regval)) 200371d10453SEric Joyner return ICE_ERR_PARAM; 200471d10453SEric Joyner 200571d10453SEric Joyner switch (offset) { 200671d10453SEric Joyner case GL_HICR: 200771d10453SEric Joyner case GL_HICR_EN: /* Note, this register is read only */ 200871d10453SEric Joyner case GL_FWSTS: 200971d10453SEric Joyner case GL_MNG_FWSM: 201071d10453SEric Joyner case GLGEN_CSR_DEBUG_C: 201171d10453SEric Joyner case GLGEN_RSTAT: 201271d10453SEric Joyner case GLPCI_LBARCTRL: 201356429daeSEric Joyner case GL_MNG_DEF_DEVID: 201471d10453SEric Joyner case GLNVM_GENS: 201571d10453SEric Joyner case GLNVM_FLA: 201671d10453SEric Joyner case PF_FUNC_RID: 2017f2635e84SEric Joyner return 0; 201871d10453SEric Joyner default: 201971d10453SEric Joyner break; 202071d10453SEric Joyner } 202171d10453SEric Joyner 202256429daeSEric Joyner for (i = 0; i <= GL_HIDA_MAX_INDEX; i++) 202371d10453SEric Joyner if (offset == (u32)GL_HIDA(i)) 2024f2635e84SEric Joyner return 0; 202571d10453SEric Joyner 202656429daeSEric Joyner for (i = 0; i <= GL_HIBA_MAX_INDEX; i++) 202771d10453SEric Joyner if (offset == (u32)GL_HIBA(i)) 2028f2635e84SEric Joyner return 0; 202971d10453SEric Joyner 203071d10453SEric Joyner /* All other register offsets are not valid */ 203171d10453SEric Joyner return ICE_ERR_OUT_OF_RANGE; 203271d10453SEric Joyner } 203371d10453SEric Joyner 203471d10453SEric Joyner /** 203571d10453SEric Joyner * ice_nvm_access_read - Handle an NVM read request 203671d10453SEric Joyner * @hw: pointer to the HW struct 203771d10453SEric Joyner * @cmd: NVM access command to process 203871d10453SEric Joyner * @data: storage for the register value read 203971d10453SEric Joyner * 204071d10453SEric Joyner * Process an NVM access request to read a register. 204171d10453SEric Joyner */ 2042f2635e84SEric Joyner int 204371d10453SEric Joyner ice_nvm_access_read(struct ice_hw *hw, struct ice_nvm_access_cmd *cmd, 204471d10453SEric Joyner union ice_nvm_access_data *data) 204571d10453SEric Joyner { 2046f2635e84SEric Joyner int status; 204771d10453SEric Joyner 204871d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 204971d10453SEric Joyner 205071d10453SEric Joyner /* Always initialize the output data, even on failure */ 205171d10453SEric Joyner ice_memset(data, 0, cmd->data_size, ICE_NONDMA_MEM); 205271d10453SEric Joyner 205371d10453SEric Joyner /* Make sure this is a valid read/write access request */ 205471d10453SEric Joyner status = ice_validate_nvm_rw_reg(cmd); 205571d10453SEric Joyner if (status) 205671d10453SEric Joyner return status; 205771d10453SEric Joyner 205871d10453SEric Joyner ice_debug(hw, ICE_DBG_NVM, "NVM access: reading register %08x\n", 205971d10453SEric Joyner cmd->offset); 206071d10453SEric Joyner 206171d10453SEric Joyner /* Read the register and store the contents in the data field */ 206271d10453SEric Joyner data->regval = rd32(hw, cmd->offset); 206371d10453SEric Joyner 2064f2635e84SEric Joyner return 0; 206571d10453SEric Joyner } 206671d10453SEric Joyner 206771d10453SEric Joyner /** 206871d10453SEric Joyner * ice_nvm_access_write - Handle an NVM write request 206971d10453SEric Joyner * @hw: pointer to the HW struct 207071d10453SEric Joyner * @cmd: NVM access command to process 207171d10453SEric Joyner * @data: NVM access data to write 207271d10453SEric Joyner * 207371d10453SEric Joyner * Process an NVM access request to write a register. 207471d10453SEric Joyner */ 2075f2635e84SEric Joyner int 207671d10453SEric Joyner ice_nvm_access_write(struct ice_hw *hw, struct ice_nvm_access_cmd *cmd, 207771d10453SEric Joyner union ice_nvm_access_data *data) 207871d10453SEric Joyner { 2079f2635e84SEric Joyner int status; 208071d10453SEric Joyner 208171d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 208271d10453SEric Joyner 208371d10453SEric Joyner /* Make sure this is a valid read/write access request */ 208471d10453SEric Joyner status = ice_validate_nvm_rw_reg(cmd); 208571d10453SEric Joyner if (status) 208671d10453SEric Joyner return status; 208771d10453SEric Joyner 208871d10453SEric Joyner /* Reject requests to write to read-only registers */ 2089f2635e84SEric Joyner if (hw->mac_type == ICE_MAC_E830) { 2090f2635e84SEric Joyner if (cmd->offset == E830_GL_HICR_EN) 209171d10453SEric Joyner return ICE_ERR_OUT_OF_RANGE; 2092f2635e84SEric Joyner } else { 2093f2635e84SEric Joyner if (cmd->offset == GL_HICR_EN) 2094f2635e84SEric Joyner return ICE_ERR_OUT_OF_RANGE; 209571d10453SEric Joyner } 209671d10453SEric Joyner 2097f2635e84SEric Joyner if (cmd->offset == GLGEN_RSTAT) 2098f2635e84SEric Joyner return ICE_ERR_OUT_OF_RANGE; 2099f2635e84SEric Joyner 21007d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_NVM, "NVM access: writing register %08x with value %08x\n", 210171d10453SEric Joyner cmd->offset, data->regval); 210271d10453SEric Joyner 210371d10453SEric Joyner /* Write the data field to the specified register */ 210471d10453SEric Joyner wr32(hw, cmd->offset, data->regval); 210571d10453SEric Joyner 2106f2635e84SEric Joyner return 0; 210771d10453SEric Joyner } 210871d10453SEric Joyner 210971d10453SEric Joyner /** 211071d10453SEric Joyner * ice_handle_nvm_access - Handle an NVM access request 211171d10453SEric Joyner * @hw: pointer to the HW struct 211271d10453SEric Joyner * @cmd: NVM access command info 211371d10453SEric Joyner * @data: pointer to read or return data 211471d10453SEric Joyner * 211571d10453SEric Joyner * Process an NVM access request. Read the command structure information and 211671d10453SEric Joyner * determine if it is valid. If not, report an error indicating the command 211771d10453SEric Joyner * was invalid. 211871d10453SEric Joyner * 211971d10453SEric Joyner * For valid commands, perform the necessary function, copying the data into 212071d10453SEric Joyner * the provided data buffer. 212171d10453SEric Joyner */ 2122f2635e84SEric Joyner int 212371d10453SEric Joyner ice_handle_nvm_access(struct ice_hw *hw, struct ice_nvm_access_cmd *cmd, 212471d10453SEric Joyner union ice_nvm_access_data *data) 212571d10453SEric Joyner { 212671d10453SEric Joyner u32 module, flags, adapter_info; 212771d10453SEric Joyner 212871d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 212971d10453SEric Joyner 213071d10453SEric Joyner /* Extended flags are currently reserved and must be zero */ 213171d10453SEric Joyner if ((cmd->config & ICE_NVM_CFG_EXT_FLAGS_M) != 0) 213271d10453SEric Joyner return ICE_ERR_PARAM; 213371d10453SEric Joyner 213471d10453SEric Joyner /* Adapter info must match the HW device ID */ 213571d10453SEric Joyner adapter_info = ice_nvm_access_get_adapter(cmd); 213671d10453SEric Joyner if (adapter_info != hw->device_id) 213771d10453SEric Joyner return ICE_ERR_PARAM; 213871d10453SEric Joyner 213971d10453SEric Joyner switch (cmd->command) { 214071d10453SEric Joyner case ICE_NVM_CMD_READ: 214171d10453SEric Joyner module = ice_nvm_access_get_module(cmd); 214271d10453SEric Joyner flags = ice_nvm_access_get_flags(cmd); 214371d10453SEric Joyner 214471d10453SEric Joyner /* Getting the driver's NVM features structure shares the same 214571d10453SEric Joyner * command type as reading a register. Read the config field 214671d10453SEric Joyner * to determine if this is a request to get features. 214771d10453SEric Joyner */ 214871d10453SEric Joyner if (module == ICE_NVM_GET_FEATURES_MODULE && 214971d10453SEric Joyner flags == ICE_NVM_GET_FEATURES_FLAGS && 215071d10453SEric Joyner cmd->offset == 0) 215171d10453SEric Joyner return ice_nvm_access_get_features(cmd, data); 215271d10453SEric Joyner else 215371d10453SEric Joyner return ice_nvm_access_read(hw, cmd, data); 215471d10453SEric Joyner case ICE_NVM_CMD_WRITE: 215571d10453SEric Joyner return ice_nvm_access_write(hw, cmd, data); 215671d10453SEric Joyner default: 215771d10453SEric Joyner return ICE_ERR_PARAM; 215871d10453SEric Joyner } 215971d10453SEric Joyner } 216071d10453SEric Joyner 2161f2635e84SEric Joyner /** 2162f2635e84SEric Joyner * ice_nvm_sanitize_operate - Clear the user data 2163f2635e84SEric Joyner * @hw: pointer to the HW struct 2164f2635e84SEric Joyner * 2165f2635e84SEric Joyner * Clear user data from NVM using AQ command (0x070C). 2166f2635e84SEric Joyner * 2167f2635e84SEric Joyner * Return: the exit code of the operation. 2168f2635e84SEric Joyner */ 2169f2635e84SEric Joyner s32 ice_nvm_sanitize_operate(struct ice_hw *hw) 2170f2635e84SEric Joyner { 2171f2635e84SEric Joyner s32 status; 2172f2635e84SEric Joyner u8 values; 2173f2635e84SEric Joyner 2174f2635e84SEric Joyner u8 cmd_flags = ICE_AQ_NVM_SANITIZE_REQ_OPERATE | 2175f2635e84SEric Joyner ICE_AQ_NVM_SANITIZE_OPERATE_SUBJECT_CLEAR; 2176f2635e84SEric Joyner 2177f2635e84SEric Joyner status = ice_nvm_sanitize(hw, cmd_flags, &values); 2178f2635e84SEric Joyner if (status) 2179f2635e84SEric Joyner return status; 2180f2635e84SEric Joyner if ((!(values & ICE_AQ_NVM_SANITIZE_OPERATE_HOST_CLEAN_DONE) && 2181f2635e84SEric Joyner !(values & ICE_AQ_NVM_SANITIZE_OPERATE_BMC_CLEAN_DONE)) || 2182f2635e84SEric Joyner ((values & ICE_AQ_NVM_SANITIZE_OPERATE_HOST_CLEAN_DONE) && 2183f2635e84SEric Joyner !(values & ICE_AQ_NVM_SANITIZE_OPERATE_HOST_CLEAN_SUCCESS)) || 2184f2635e84SEric Joyner ((values & ICE_AQ_NVM_SANITIZE_OPERATE_BMC_CLEAN_DONE) && 2185f2635e84SEric Joyner !(values & ICE_AQ_NVM_SANITIZE_OPERATE_BMC_CLEAN_SUCCESS))) 2186f2635e84SEric Joyner return ICE_ERR_AQ_ERROR; 2187f2635e84SEric Joyner 2188f2635e84SEric Joyner return ICE_SUCCESS; 2189f2635e84SEric Joyner } 2190f2635e84SEric Joyner 2191f2635e84SEric Joyner /** 2192f2635e84SEric Joyner * ice_nvm_sanitize - Sanitize NVM 2193f2635e84SEric Joyner * @hw: pointer to the HW struct 2194f2635e84SEric Joyner * @cmd_flags: flag to the ACI command 2195f2635e84SEric Joyner * @values: values returned from the command 2196f2635e84SEric Joyner * 2197f2635e84SEric Joyner * Sanitize NVM using AQ command (0x070C). 2198f2635e84SEric Joyner * 2199f2635e84SEric Joyner * Return: the exit code of the operation. 2200f2635e84SEric Joyner */ 2201f2635e84SEric Joyner s32 ice_nvm_sanitize(struct ice_hw *hw, u8 cmd_flags, u8 *values) 2202f2635e84SEric Joyner { 2203f2635e84SEric Joyner struct ice_aqc_nvm_sanitization *cmd; 2204f2635e84SEric Joyner struct ice_aq_desc desc; 2205f2635e84SEric Joyner s32 status; 2206f2635e84SEric Joyner 2207f2635e84SEric Joyner cmd = &desc.params.sanitization; 2208f2635e84SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_sanitization); 2209f2635e84SEric Joyner cmd->cmd_flags = cmd_flags; 2210f2635e84SEric Joyner 2211f2635e84SEric Joyner status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 2212f2635e84SEric Joyner if (values) 2213f2635e84SEric Joyner *values = cmd->values; 2214f2635e84SEric Joyner 2215f2635e84SEric Joyner return status; 2216f2635e84SEric Joyner } 2217