1f31e4b6fSAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0 2f31e4b6fSAnirudh Venkataramanan /* Copyright (c) 2018, Intel Corporation. */ 3f31e4b6fSAnirudh Venkataramanan 4f31e4b6fSAnirudh Venkataramanan #include "ice_common.h" 5f31e4b6fSAnirudh Venkataramanan 6f31e4b6fSAnirudh Venkataramanan /** 7f31e4b6fSAnirudh Venkataramanan * ice_aq_read_nvm 8f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 9f31e4b6fSAnirudh Venkataramanan * @module_typeid: module pointer location in words from the NVM beginning 10f31e4b6fSAnirudh Venkataramanan * @offset: byte offset from the module beginning 11f31e4b6fSAnirudh Venkataramanan * @length: length of the section to be read (in bytes from the offset) 12f31e4b6fSAnirudh Venkataramanan * @data: command buffer (size [bytes] = length) 13f31e4b6fSAnirudh Venkataramanan * @last_command: tells if this is the last command in a series 14e9450990SJacob Keller * @read_shadow_ram: tell if this is a shadow RAM read 15f31e4b6fSAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 16f31e4b6fSAnirudh Venkataramanan * 17f31e4b6fSAnirudh Venkataramanan * Read the NVM using the admin queue commands (0x0701) 18f31e4b6fSAnirudh Venkataramanan */ 19f31e4b6fSAnirudh Venkataramanan static enum ice_status 2043c89b16SAnirudh Venkataramanan ice_aq_read_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset, u16 length, 21e9450990SJacob Keller void *data, bool last_command, bool read_shadow_ram, 22e9450990SJacob Keller struct ice_sq_cd *cd) 23f31e4b6fSAnirudh Venkataramanan { 24f31e4b6fSAnirudh Venkataramanan struct ice_aq_desc desc; 25f31e4b6fSAnirudh Venkataramanan struct ice_aqc_nvm *cmd; 26f31e4b6fSAnirudh Venkataramanan 27f31e4b6fSAnirudh Venkataramanan cmd = &desc.params.nvm; 28f31e4b6fSAnirudh Venkataramanan 2981f07491SJacob Keller if (offset > ICE_AQC_NVM_MAX_OFFSET) 30f31e4b6fSAnirudh Venkataramanan return ICE_ERR_PARAM; 31f31e4b6fSAnirudh Venkataramanan 32f31e4b6fSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_read); 33f31e4b6fSAnirudh Venkataramanan 34e9450990SJacob Keller if (!read_shadow_ram && module_typeid == ICE_AQC_NVM_START_POINT) 35e9450990SJacob Keller cmd->cmd_flags |= ICE_AQC_NVM_FLASH_ONLY; 36e9450990SJacob Keller 37f31e4b6fSAnirudh Venkataramanan /* If this is the last command in a series, set the proper flag. */ 38f31e4b6fSAnirudh Venkataramanan if (last_command) 39f31e4b6fSAnirudh Venkataramanan cmd->cmd_flags |= ICE_AQC_NVM_LAST_CMD; 4043c89b16SAnirudh Venkataramanan cmd->module_typeid = cpu_to_le16(module_typeid); 4143c89b16SAnirudh Venkataramanan cmd->offset_low = cpu_to_le16(offset & 0xFFFF); 4243c89b16SAnirudh Venkataramanan cmd->offset_high = (offset >> 16) & 0xFF; 43f31e4b6fSAnirudh Venkataramanan cmd->length = cpu_to_le16(length); 44f31e4b6fSAnirudh Venkataramanan 45f31e4b6fSAnirudh Venkataramanan return ice_aq_send_cmd(hw, &desc, data, length, cd); 46f31e4b6fSAnirudh Venkataramanan } 47f31e4b6fSAnirudh Venkataramanan 48f31e4b6fSAnirudh Venkataramanan /** 49e9450990SJacob Keller * ice_read_flat_nvm - Read portion of NVM by flat offset 50e9450990SJacob Keller * @hw: pointer to the HW struct 51e9450990SJacob Keller * @offset: offset from beginning of NVM 52e9450990SJacob Keller * @length: (in) number of bytes to read; (out) number of bytes actually read 53e9450990SJacob Keller * @data: buffer to return data in (sized to fit the specified length) 54e9450990SJacob Keller * @read_shadow_ram: if true, read from shadow RAM instead of NVM 55e9450990SJacob Keller * 56e9450990SJacob Keller * Reads a portion of the NVM, as a flat memory space. This function correctly 57e9450990SJacob Keller * breaks read requests across Shadow RAM sectors and ensures that no single 58e9450990SJacob Keller * read request exceeds the maximum 4Kb read for a single AdminQ command. 59e9450990SJacob Keller * 60e9450990SJacob Keller * Returns a status code on failure. Note that the data pointer may be 61e9450990SJacob Keller * partially updated if some reads succeed before a failure. 62e9450990SJacob Keller */ 63e9450990SJacob Keller enum ice_status 64e9450990SJacob Keller ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data, 65e9450990SJacob Keller bool read_shadow_ram) 66e9450990SJacob Keller { 67e9450990SJacob Keller enum ice_status status; 68e9450990SJacob Keller u32 inlen = *length; 69e9450990SJacob Keller u32 bytes_read = 0; 70e9450990SJacob Keller bool last_cmd; 71e9450990SJacob Keller 72e9450990SJacob Keller *length = 0; 73e9450990SJacob Keller 74e9450990SJacob Keller /* Verify the length of the read if this is for the Shadow RAM */ 75e9450990SJacob Keller if (read_shadow_ram && ((offset + inlen) > (hw->nvm.sr_words * 2u))) { 76e9450990SJacob Keller ice_debug(hw, ICE_DBG_NVM, 77e9450990SJacob Keller "NVM error: requested offset is beyond Shadow RAM limit\n"); 78e9450990SJacob Keller return ICE_ERR_PARAM; 79e9450990SJacob Keller } 80e9450990SJacob Keller 81e9450990SJacob Keller do { 82e9450990SJacob Keller u32 read_size, sector_offset; 83e9450990SJacob Keller 84e9450990SJacob Keller /* ice_aq_read_nvm cannot read more than 4Kb at a time. 85e9450990SJacob Keller * Additionally, a read from the Shadow RAM may not cross over 86e9450990SJacob Keller * a sector boundary. Conveniently, the sector size is also 87e9450990SJacob Keller * 4Kb. 88e9450990SJacob Keller */ 89e9450990SJacob Keller sector_offset = offset % ICE_AQ_MAX_BUF_LEN; 90e9450990SJacob Keller read_size = min_t(u32, ICE_AQ_MAX_BUF_LEN - sector_offset, 91e9450990SJacob Keller inlen - bytes_read); 92e9450990SJacob Keller 93e9450990SJacob Keller last_cmd = !(bytes_read + read_size < inlen); 94e9450990SJacob Keller 95e9450990SJacob Keller status = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, 96e9450990SJacob Keller offset, read_size, 97e9450990SJacob Keller data + bytes_read, last_cmd, 98e9450990SJacob Keller read_shadow_ram, NULL); 99e9450990SJacob Keller if (status) 100e9450990SJacob Keller break; 101e9450990SJacob Keller 102e9450990SJacob Keller bytes_read += read_size; 103e9450990SJacob Keller offset += read_size; 104e9450990SJacob Keller } while (!last_cmd); 105e9450990SJacob Keller 106e9450990SJacob Keller *length = bytes_read; 107e9450990SJacob Keller return status; 108e9450990SJacob Keller } 109e9450990SJacob Keller 110e9450990SJacob Keller /** 111544cd2acSCudzilo, Szymon T * ice_aq_update_nvm 112544cd2acSCudzilo, Szymon T * @hw: pointer to the HW struct 113544cd2acSCudzilo, Szymon T * @module_typeid: module pointer location in words from the NVM beginning 114544cd2acSCudzilo, Szymon T * @offset: byte offset from the module beginning 115544cd2acSCudzilo, Szymon T * @length: length of the section to be written (in bytes from the offset) 116544cd2acSCudzilo, Szymon T * @data: command buffer (size [bytes] = length) 117544cd2acSCudzilo, Szymon T * @last_command: tells if this is the last command in a series 118544cd2acSCudzilo, Szymon T * @command_flags: command parameters 119544cd2acSCudzilo, Szymon T * @cd: pointer to command details structure or NULL 120544cd2acSCudzilo, Szymon T * 121544cd2acSCudzilo, Szymon T * Update the NVM using the admin queue commands (0x0703) 122544cd2acSCudzilo, Szymon T */ 123544cd2acSCudzilo, Szymon T enum ice_status 124544cd2acSCudzilo, Szymon T ice_aq_update_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset, 125544cd2acSCudzilo, Szymon T u16 length, void *data, bool last_command, u8 command_flags, 126544cd2acSCudzilo, Szymon T struct ice_sq_cd *cd) 127544cd2acSCudzilo, Szymon T { 128544cd2acSCudzilo, Szymon T struct ice_aq_desc desc; 129544cd2acSCudzilo, Szymon T struct ice_aqc_nvm *cmd; 130544cd2acSCudzilo, Szymon T 131544cd2acSCudzilo, Szymon T cmd = &desc.params.nvm; 132544cd2acSCudzilo, Szymon T 133544cd2acSCudzilo, Szymon T /* In offset the highest byte must be zeroed. */ 134544cd2acSCudzilo, Szymon T if (offset & 0xFF000000) 135544cd2acSCudzilo, Szymon T return ICE_ERR_PARAM; 136544cd2acSCudzilo, Szymon T 137544cd2acSCudzilo, Szymon T ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_write); 138544cd2acSCudzilo, Szymon T 139544cd2acSCudzilo, Szymon T cmd->cmd_flags |= command_flags; 140544cd2acSCudzilo, Szymon T 141544cd2acSCudzilo, Szymon T /* If this is the last command in a series, set the proper flag. */ 142544cd2acSCudzilo, Szymon T if (last_command) 143544cd2acSCudzilo, Szymon T cmd->cmd_flags |= ICE_AQC_NVM_LAST_CMD; 144544cd2acSCudzilo, Szymon T cmd->module_typeid = cpu_to_le16(module_typeid); 145544cd2acSCudzilo, Szymon T cmd->offset_low = cpu_to_le16(offset & 0xFFFF); 146544cd2acSCudzilo, Szymon T cmd->offset_high = (offset >> 16) & 0xFF; 147544cd2acSCudzilo, Szymon T cmd->length = cpu_to_le16(length); 148544cd2acSCudzilo, Szymon T 149544cd2acSCudzilo, Szymon T desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 150544cd2acSCudzilo, Szymon T 151544cd2acSCudzilo, Szymon T return ice_aq_send_cmd(hw, &desc, data, length, cd); 152544cd2acSCudzilo, Szymon T } 153544cd2acSCudzilo, Szymon T 154544cd2acSCudzilo, Szymon T /** 155544cd2acSCudzilo, Szymon T * ice_aq_erase_nvm 156544cd2acSCudzilo, Szymon T * @hw: pointer to the HW struct 157544cd2acSCudzilo, Szymon T * @module_typeid: module pointer location in words from the NVM beginning 158544cd2acSCudzilo, Szymon T * @cd: pointer to command details structure or NULL 159544cd2acSCudzilo, Szymon T * 160544cd2acSCudzilo, Szymon T * Erase the NVM sector using the admin queue commands (0x0702) 161544cd2acSCudzilo, Szymon T */ 162544cd2acSCudzilo, Szymon T enum ice_status 163544cd2acSCudzilo, Szymon T ice_aq_erase_nvm(struct ice_hw *hw, u16 module_typeid, struct ice_sq_cd *cd) 164544cd2acSCudzilo, Szymon T { 165544cd2acSCudzilo, Szymon T struct ice_aq_desc desc; 166544cd2acSCudzilo, Szymon T struct ice_aqc_nvm *cmd; 167544cd2acSCudzilo, Szymon T 168544cd2acSCudzilo, Szymon T cmd = &desc.params.nvm; 169544cd2acSCudzilo, Szymon T 170544cd2acSCudzilo, Szymon T ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_erase); 171544cd2acSCudzilo, Szymon T 172544cd2acSCudzilo, Szymon T cmd->module_typeid = cpu_to_le16(module_typeid); 173544cd2acSCudzilo, Szymon T cmd->length = cpu_to_le16(ICE_AQC_NVM_ERASE_LEN); 174544cd2acSCudzilo, Szymon T cmd->offset_low = 0; 175544cd2acSCudzilo, Szymon T cmd->offset_high = 0; 176544cd2acSCudzilo, Szymon T 177544cd2acSCudzilo, Szymon T return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 178544cd2acSCudzilo, Szymon T } 179544cd2acSCudzilo, Szymon T 180544cd2acSCudzilo, Szymon T /** 181f31e4b6fSAnirudh Venkataramanan * ice_read_sr_word_aq - Reads Shadow RAM via AQ 182f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the HW structure 183f31e4b6fSAnirudh Venkataramanan * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) 184f31e4b6fSAnirudh Venkataramanan * @data: word read from the Shadow RAM 185f31e4b6fSAnirudh Venkataramanan * 186e9450990SJacob Keller * Reads one 16 bit word from the Shadow RAM using ice_read_flat_nvm. 187f31e4b6fSAnirudh Venkataramanan */ 188f31e4b6fSAnirudh Venkataramanan static enum ice_status 189f31e4b6fSAnirudh Venkataramanan ice_read_sr_word_aq(struct ice_hw *hw, u16 offset, u16 *data) 190f31e4b6fSAnirudh Venkataramanan { 191e9450990SJacob Keller u32 bytes = sizeof(u16); 192f31e4b6fSAnirudh Venkataramanan enum ice_status status; 1932efefb56SJacob Keller __le16 data_local; 194f31e4b6fSAnirudh Venkataramanan 195e9450990SJacob Keller /* Note that ice_read_flat_nvm takes into account the 4Kb AdminQ and 196e9450990SJacob Keller * Shadow RAM sector restrictions necessary when reading from the NVM. 197e9450990SJacob Keller */ 198e9450990SJacob Keller status = ice_read_flat_nvm(hw, offset * sizeof(u16), &bytes, 199e9450990SJacob Keller (u8 *)&data_local, true); 200e9450990SJacob Keller if (status) 201f31e4b6fSAnirudh Venkataramanan return status; 202e9450990SJacob Keller 203e9450990SJacob Keller *data = le16_to_cpu(data_local); 204e9450990SJacob Keller return 0; 205f31e4b6fSAnirudh Venkataramanan } 206f31e4b6fSAnirudh Venkataramanan 207f31e4b6fSAnirudh Venkataramanan /** 208f31e4b6fSAnirudh Venkataramanan * ice_acquire_nvm - Generic request for acquiring the NVM ownership 209f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the HW structure 210f31e4b6fSAnirudh Venkataramanan * @access: NVM access type (read or write) 211f31e4b6fSAnirudh Venkataramanan * 212f31e4b6fSAnirudh Venkataramanan * This function will request NVM ownership. 213f31e4b6fSAnirudh Venkataramanan */ 21484a24798SJesse Brandeburg enum ice_status 2153968540bSAnirudh Venkataramanan ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access) 216f31e4b6fSAnirudh Venkataramanan { 217f31e4b6fSAnirudh Venkataramanan if (hw->nvm.blank_nvm_mode) 218f31e4b6fSAnirudh Venkataramanan return 0; 219f31e4b6fSAnirudh Venkataramanan 220ff2b1321SDan Nowlin return ice_acquire_res(hw, ICE_NVM_RES_ID, access, ICE_NVM_TIMEOUT); 221f31e4b6fSAnirudh Venkataramanan } 222f31e4b6fSAnirudh Venkataramanan 223f31e4b6fSAnirudh Venkataramanan /** 224f31e4b6fSAnirudh Venkataramanan * ice_release_nvm - Generic request for releasing the NVM ownership 225f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the HW structure 226f31e4b6fSAnirudh Venkataramanan * 227f31e4b6fSAnirudh Venkataramanan * This function will release NVM ownership. 228f31e4b6fSAnirudh Venkataramanan */ 22984a24798SJesse Brandeburg void ice_release_nvm(struct ice_hw *hw) 230f31e4b6fSAnirudh Venkataramanan { 231f31e4b6fSAnirudh Venkataramanan if (hw->nvm.blank_nvm_mode) 232f31e4b6fSAnirudh Venkataramanan return; 233f31e4b6fSAnirudh Venkataramanan 234f31e4b6fSAnirudh Venkataramanan ice_release_res(hw, ICE_NVM_RES_ID); 235f31e4b6fSAnirudh Venkataramanan } 236f31e4b6fSAnirudh Venkataramanan 237f31e4b6fSAnirudh Venkataramanan /** 238f31e4b6fSAnirudh Venkataramanan * ice_read_sr_word - Reads Shadow RAM word and acquire NVM if necessary 239f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the HW structure 240f31e4b6fSAnirudh Venkataramanan * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) 241f31e4b6fSAnirudh Venkataramanan * @data: word read from the Shadow RAM 242f31e4b6fSAnirudh Venkataramanan * 243f31e4b6fSAnirudh Venkataramanan * Reads one 16 bit word from the Shadow RAM using the ice_read_sr_word_aq. 244f31e4b6fSAnirudh Venkataramanan */ 245769c500dSAkeem G Abodunrin enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data) 246f31e4b6fSAnirudh Venkataramanan { 247f31e4b6fSAnirudh Venkataramanan enum ice_status status; 248f31e4b6fSAnirudh Venkataramanan 249f31e4b6fSAnirudh Venkataramanan status = ice_acquire_nvm(hw, ICE_RES_READ); 250f31e4b6fSAnirudh Venkataramanan if (!status) { 251f31e4b6fSAnirudh Venkataramanan status = ice_read_sr_word_aq(hw, offset, data); 252f31e4b6fSAnirudh Venkataramanan ice_release_nvm(hw); 253f31e4b6fSAnirudh Venkataramanan } 254f31e4b6fSAnirudh Venkataramanan 255f31e4b6fSAnirudh Venkataramanan return status; 256f31e4b6fSAnirudh Venkataramanan } 257f31e4b6fSAnirudh Venkataramanan 258f31e4b6fSAnirudh Venkataramanan /** 259e961b679SJacob Keller * ice_get_pfa_module_tlv - Reads sub module TLV from NVM PFA 260e961b679SJacob Keller * @hw: pointer to hardware structure 261e961b679SJacob Keller * @module_tlv: pointer to module TLV to return 262e961b679SJacob Keller * @module_tlv_len: pointer to module TLV length to return 263e961b679SJacob Keller * @module_type: module type requested 264e961b679SJacob Keller * 265e961b679SJacob Keller * Finds the requested sub module TLV type from the Preserved Field 266e961b679SJacob Keller * Area (PFA) and returns the TLV pointer and length. The caller can 267e961b679SJacob Keller * use these to read the variable length TLV value. 268e961b679SJacob Keller */ 269ea78ce4dSPaul Greenwalt enum ice_status 270e961b679SJacob Keller ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len, 271e961b679SJacob Keller u16 module_type) 272e961b679SJacob Keller { 273e961b679SJacob Keller enum ice_status status; 274e961b679SJacob Keller u16 pfa_len, pfa_ptr; 275e961b679SJacob Keller u16 next_tlv; 276e961b679SJacob Keller 277e961b679SJacob Keller status = ice_read_sr_word(hw, ICE_SR_PFA_PTR, &pfa_ptr); 278e961b679SJacob Keller if (status) { 279e961b679SJacob Keller ice_debug(hw, ICE_DBG_INIT, "Preserved Field Array pointer.\n"); 280e961b679SJacob Keller return status; 281e961b679SJacob Keller } 282e961b679SJacob Keller status = ice_read_sr_word(hw, pfa_ptr, &pfa_len); 283e961b679SJacob Keller if (status) { 284e961b679SJacob Keller ice_debug(hw, ICE_DBG_INIT, "Failed to read PFA length.\n"); 285e961b679SJacob Keller return status; 286e961b679SJacob Keller } 287e961b679SJacob Keller /* Starting with first TLV after PFA length, iterate through the list 288e961b679SJacob Keller * of TLVs to find the requested one. 289e961b679SJacob Keller */ 290e961b679SJacob Keller next_tlv = pfa_ptr + 1; 291e961b679SJacob Keller while (next_tlv < pfa_ptr + pfa_len) { 292e961b679SJacob Keller u16 tlv_sub_module_type; 293e961b679SJacob Keller u16 tlv_len; 294e961b679SJacob Keller 295e961b679SJacob Keller /* Read TLV type */ 296e961b679SJacob Keller status = ice_read_sr_word(hw, next_tlv, &tlv_sub_module_type); 297e961b679SJacob Keller if (status) { 298e961b679SJacob Keller ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV type.\n"); 299e961b679SJacob Keller break; 300e961b679SJacob Keller } 301e961b679SJacob Keller /* Read TLV length */ 302e961b679SJacob Keller status = ice_read_sr_word(hw, next_tlv + 1, &tlv_len); 303e961b679SJacob Keller if (status) { 304e961b679SJacob Keller ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV length.\n"); 305e961b679SJacob Keller break; 306e961b679SJacob Keller } 307e961b679SJacob Keller if (tlv_sub_module_type == module_type) { 308e961b679SJacob Keller if (tlv_len) { 309e961b679SJacob Keller *module_tlv = next_tlv; 310e961b679SJacob Keller *module_tlv_len = tlv_len; 311e961b679SJacob Keller return 0; 312e961b679SJacob Keller } 313e961b679SJacob Keller return ICE_ERR_INVAL_SIZE; 314e961b679SJacob Keller } 315e961b679SJacob Keller /* Check next TLV, i.e. current TLV pointer + length + 2 words 316e961b679SJacob Keller * (for current TLV's type and length) 317e961b679SJacob Keller */ 318e961b679SJacob Keller next_tlv = next_tlv + tlv_len + 2; 319e961b679SJacob Keller } 320e961b679SJacob Keller /* Module does not exist */ 321e961b679SJacob Keller return ICE_ERR_DOES_NOT_EXIST; 322e961b679SJacob Keller } 323e961b679SJacob Keller 324e961b679SJacob Keller /** 325e961b679SJacob Keller * ice_read_pba_string - Reads part number string from NVM 326e961b679SJacob Keller * @hw: pointer to hardware structure 327e961b679SJacob Keller * @pba_num: stores the part number string from the NVM 328e961b679SJacob Keller * @pba_num_size: part number string buffer length 329e961b679SJacob Keller * 330e961b679SJacob Keller * Reads the part number string from the NVM. 331e961b679SJacob Keller */ 332e961b679SJacob Keller enum ice_status 333e961b679SJacob Keller ice_read_pba_string(struct ice_hw *hw, u8 *pba_num, u32 pba_num_size) 334e961b679SJacob Keller { 335e961b679SJacob Keller u16 pba_tlv, pba_tlv_len; 336e961b679SJacob Keller enum ice_status status; 337e961b679SJacob Keller u16 pba_word, pba_size; 338e961b679SJacob Keller u16 i; 339e961b679SJacob Keller 340e961b679SJacob Keller status = ice_get_pfa_module_tlv(hw, &pba_tlv, &pba_tlv_len, 341e961b679SJacob Keller ICE_SR_PBA_BLOCK_PTR); 342e961b679SJacob Keller if (status) { 343e961b679SJacob Keller ice_debug(hw, ICE_DBG_INIT, "Failed to read PBA Block TLV.\n"); 344e961b679SJacob Keller return status; 345e961b679SJacob Keller } 346e961b679SJacob Keller 347e961b679SJacob Keller /* pba_size is the next word */ 348e961b679SJacob Keller status = ice_read_sr_word(hw, (pba_tlv + 2), &pba_size); 349e961b679SJacob Keller if (status) { 350e961b679SJacob Keller ice_debug(hw, ICE_DBG_INIT, "Failed to read PBA Section size.\n"); 351e961b679SJacob Keller return status; 352e961b679SJacob Keller } 353e961b679SJacob Keller 354e961b679SJacob Keller if (pba_tlv_len < pba_size) { 355e961b679SJacob Keller ice_debug(hw, ICE_DBG_INIT, "Invalid PBA Block TLV size.\n"); 356e961b679SJacob Keller return ICE_ERR_INVAL_SIZE; 357e961b679SJacob Keller } 358e961b679SJacob Keller 359e961b679SJacob Keller /* Subtract one to get PBA word count (PBA Size word is included in 360e961b679SJacob Keller * total size) 361e961b679SJacob Keller */ 362e961b679SJacob Keller pba_size--; 363e961b679SJacob Keller if (pba_num_size < (((u32)pba_size * 2) + 1)) { 364e961b679SJacob Keller ice_debug(hw, ICE_DBG_INIT, "Buffer too small for PBA data.\n"); 365e961b679SJacob Keller return ICE_ERR_PARAM; 366e961b679SJacob Keller } 367e961b679SJacob Keller 368e961b679SJacob Keller for (i = 0; i < pba_size; i++) { 369e961b679SJacob Keller status = ice_read_sr_word(hw, (pba_tlv + 2 + 1) + i, &pba_word); 370e961b679SJacob Keller if (status) { 371e961b679SJacob Keller ice_debug(hw, ICE_DBG_INIT, "Failed to read PBA Block word %d.\n", i); 372e961b679SJacob Keller return status; 373e961b679SJacob Keller } 374e961b679SJacob Keller 375e961b679SJacob Keller pba_num[(i * 2)] = (pba_word >> 8) & 0xFF; 376e961b679SJacob Keller pba_num[(i * 2) + 1] = pba_word & 0xFF; 377e961b679SJacob Keller } 378e961b679SJacob Keller pba_num[(pba_size * 2)] = '\0'; 379e961b679SJacob Keller 380e961b679SJacob Keller return status; 381e961b679SJacob Keller } 382e961b679SJacob Keller 383e961b679SJacob Keller /** 384d4e87444SJacob Keller * ice_get_orom_ver_info - Read Option ROM version information 385d4e87444SJacob Keller * @hw: pointer to the HW struct 386d4e87444SJacob Keller * 387d4e87444SJacob Keller * Read the Combo Image version data from the Boot Configuration TLV and fill 388d4e87444SJacob Keller * in the option ROM version data. 389d4e87444SJacob Keller */ 390d4e87444SJacob Keller static enum ice_status ice_get_orom_ver_info(struct ice_hw *hw) 391d4e87444SJacob Keller { 392d4e87444SJacob Keller u16 combo_hi, combo_lo, boot_cfg_tlv, boot_cfg_tlv_len; 393d4e87444SJacob Keller struct ice_orom_info *orom = &hw->nvm.orom; 394d4e87444SJacob Keller enum ice_status status; 395d4e87444SJacob Keller u32 combo_ver; 396d4e87444SJacob Keller 397d4e87444SJacob Keller status = ice_get_pfa_module_tlv(hw, &boot_cfg_tlv, &boot_cfg_tlv_len, 398d4e87444SJacob Keller ICE_SR_BOOT_CFG_PTR); 399d4e87444SJacob Keller if (status) { 400d4e87444SJacob Keller ice_debug(hw, ICE_DBG_INIT, 401d4e87444SJacob Keller "Failed to read Boot Configuration Block TLV.\n"); 402d4e87444SJacob Keller return status; 403d4e87444SJacob Keller } 404d4e87444SJacob Keller 405d4e87444SJacob Keller /* Boot Configuration Block must have length at least 2 words 406d4e87444SJacob Keller * (Combo Image Version High and Combo Image Version Low) 407d4e87444SJacob Keller */ 408d4e87444SJacob Keller if (boot_cfg_tlv_len < 2) { 409d4e87444SJacob Keller ice_debug(hw, ICE_DBG_INIT, 410d4e87444SJacob Keller "Invalid Boot Configuration Block TLV size.\n"); 411d4e87444SJacob Keller return ICE_ERR_INVAL_SIZE; 412d4e87444SJacob Keller } 413d4e87444SJacob Keller 414d4e87444SJacob Keller status = ice_read_sr_word(hw, (boot_cfg_tlv + ICE_NVM_OROM_VER_OFF), 415d4e87444SJacob Keller &combo_hi); 416d4e87444SJacob Keller if (status) { 417d4e87444SJacob Keller ice_debug(hw, ICE_DBG_INIT, "Failed to read OROM_VER hi.\n"); 418d4e87444SJacob Keller return status; 419d4e87444SJacob Keller } 420d4e87444SJacob Keller 421d4e87444SJacob Keller status = ice_read_sr_word(hw, (boot_cfg_tlv + ICE_NVM_OROM_VER_OFF + 1), 422d4e87444SJacob Keller &combo_lo); 423d4e87444SJacob Keller if (status) { 424d4e87444SJacob Keller ice_debug(hw, ICE_DBG_INIT, "Failed to read OROM_VER lo.\n"); 425d4e87444SJacob Keller return status; 426d4e87444SJacob Keller } 427d4e87444SJacob Keller 428d4e87444SJacob Keller combo_ver = ((u32)combo_hi << 16) | combo_lo; 429d4e87444SJacob Keller 430d4e87444SJacob Keller orom->major = (u8)((combo_ver & ICE_OROM_VER_MASK) >> 431d4e87444SJacob Keller ICE_OROM_VER_SHIFT); 432d4e87444SJacob Keller orom->patch = (u8)(combo_ver & ICE_OROM_VER_PATCH_MASK); 433d4e87444SJacob Keller orom->build = (u16)((combo_ver & ICE_OROM_VER_BUILD_MASK) >> 434d4e87444SJacob Keller ICE_OROM_VER_BUILD_SHIFT); 435d4e87444SJacob Keller 436d4e87444SJacob Keller return 0; 437d4e87444SJacob Keller } 438d4e87444SJacob Keller 439d4e87444SJacob Keller /** 440f45a645fSJacob Keller * ice_get_netlist_ver_info 441f45a645fSJacob Keller * @hw: pointer to the HW struct 442f45a645fSJacob Keller * 443f45a645fSJacob Keller * Get the netlist version information 444f45a645fSJacob Keller */ 445f45a645fSJacob Keller static enum ice_status ice_get_netlist_ver_info(struct ice_hw *hw) 446f45a645fSJacob Keller { 447f45a645fSJacob Keller struct ice_netlist_ver_info *ver = &hw->netlist_ver; 448f45a645fSJacob Keller enum ice_status ret; 449f45a645fSJacob Keller u32 id_blk_start; 450f45a645fSJacob Keller __le16 raw_data; 451f45a645fSJacob Keller u16 data, i; 452f45a645fSJacob Keller u16 *buff; 453f45a645fSJacob Keller 454f45a645fSJacob Keller ret = ice_acquire_nvm(hw, ICE_RES_READ); 455f45a645fSJacob Keller if (ret) 456f45a645fSJacob Keller return ret; 457f45a645fSJacob Keller buff = kcalloc(ICE_AQC_NVM_NETLIST_ID_BLK_LEN, sizeof(*buff), 458f45a645fSJacob Keller GFP_KERNEL); 459f45a645fSJacob Keller if (!buff) { 460f45a645fSJacob Keller ret = ICE_ERR_NO_MEMORY; 461f45a645fSJacob Keller goto exit_no_mem; 462f45a645fSJacob Keller } 463f45a645fSJacob Keller 464f45a645fSJacob Keller /* read module length */ 465f45a645fSJacob Keller ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_LINK_TOPO_NETLIST_MOD_ID, 466f45a645fSJacob Keller ICE_AQC_NVM_LINK_TOPO_NETLIST_LEN_OFFSET * 2, 467f45a645fSJacob Keller ICE_AQC_NVM_LINK_TOPO_NETLIST_LEN, &raw_data, 468f45a645fSJacob Keller false, false, NULL); 469f45a645fSJacob Keller if (ret) 470f45a645fSJacob Keller goto exit_error; 471f45a645fSJacob Keller 472f45a645fSJacob Keller data = le16_to_cpu(raw_data); 473f45a645fSJacob Keller /* exit if length is = 0 */ 474f45a645fSJacob Keller if (!data) 475f45a645fSJacob Keller goto exit_error; 476f45a645fSJacob Keller 477f45a645fSJacob Keller /* read node count */ 478f45a645fSJacob Keller ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_LINK_TOPO_NETLIST_MOD_ID, 479f45a645fSJacob Keller ICE_AQC_NVM_NETLIST_NODE_COUNT_OFFSET * 2, 480f45a645fSJacob Keller ICE_AQC_NVM_NETLIST_NODE_COUNT_LEN, &raw_data, 481f45a645fSJacob Keller false, false, NULL); 482f45a645fSJacob Keller if (ret) 483f45a645fSJacob Keller goto exit_error; 484f45a645fSJacob Keller data = le16_to_cpu(raw_data) & ICE_AQC_NVM_NETLIST_NODE_COUNT_M; 485f45a645fSJacob Keller 486f45a645fSJacob Keller /* netlist ID block starts from offset 4 + node count * 2 */ 487f45a645fSJacob Keller id_blk_start = ICE_AQC_NVM_NETLIST_ID_BLK_START_OFFSET + data * 2; 488f45a645fSJacob Keller 489f45a645fSJacob Keller /* read the entire netlist ID block */ 490f45a645fSJacob Keller ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_LINK_TOPO_NETLIST_MOD_ID, 491f45a645fSJacob Keller id_blk_start * 2, 492f45a645fSJacob Keller ICE_AQC_NVM_NETLIST_ID_BLK_LEN * 2, buff, false, 493f45a645fSJacob Keller false, NULL); 494f45a645fSJacob Keller if (ret) 495f45a645fSJacob Keller goto exit_error; 496f45a645fSJacob Keller 497f45a645fSJacob Keller for (i = 0; i < ICE_AQC_NVM_NETLIST_ID_BLK_LEN; i++) 498f45a645fSJacob Keller buff[i] = le16_to_cpu(((__force __le16 *)buff)[i]); 499f45a645fSJacob Keller 500f45a645fSJacob Keller ver->major = (buff[ICE_AQC_NVM_NETLIST_ID_BLK_MAJOR_VER_HIGH] << 16) | 501f45a645fSJacob Keller buff[ICE_AQC_NVM_NETLIST_ID_BLK_MAJOR_VER_LOW]; 502f45a645fSJacob Keller ver->minor = (buff[ICE_AQC_NVM_NETLIST_ID_BLK_MINOR_VER_HIGH] << 16) | 503f45a645fSJacob Keller buff[ICE_AQC_NVM_NETLIST_ID_BLK_MINOR_VER_LOW]; 504f45a645fSJacob Keller ver->type = (buff[ICE_AQC_NVM_NETLIST_ID_BLK_TYPE_HIGH] << 16) | 505f45a645fSJacob Keller buff[ICE_AQC_NVM_NETLIST_ID_BLK_TYPE_LOW]; 506f45a645fSJacob Keller ver->rev = (buff[ICE_AQC_NVM_NETLIST_ID_BLK_REV_HIGH] << 16) | 507f45a645fSJacob Keller buff[ICE_AQC_NVM_NETLIST_ID_BLK_REV_LOW]; 508f45a645fSJacob Keller ver->cust_ver = buff[ICE_AQC_NVM_NETLIST_ID_BLK_CUST_VER]; 509f45a645fSJacob Keller /* Read the left most 4 bytes of SHA */ 510f45a645fSJacob Keller ver->hash = buff[ICE_AQC_NVM_NETLIST_ID_BLK_SHA_HASH + 15] << 16 | 511f45a645fSJacob Keller buff[ICE_AQC_NVM_NETLIST_ID_BLK_SHA_HASH + 14]; 512f45a645fSJacob Keller 513f45a645fSJacob Keller exit_error: 514f45a645fSJacob Keller kfree(buff); 515f45a645fSJacob Keller exit_no_mem: 516f45a645fSJacob Keller ice_release_nvm(hw); 517f45a645fSJacob Keller return ret; 518f45a645fSJacob Keller } 519f45a645fSJacob Keller 520f45a645fSJacob Keller /** 52181f07491SJacob Keller * ice_discover_flash_size - Discover the available flash size. 52281f07491SJacob Keller * @hw: pointer to the HW struct 52381f07491SJacob Keller * 52481f07491SJacob Keller * The device flash could be up to 16MB in size. However, it is possible that 52581f07491SJacob Keller * the actual size is smaller. Use bisection to determine the accessible size 52681f07491SJacob Keller * of flash memory. 52781f07491SJacob Keller */ 52881f07491SJacob Keller static enum ice_status ice_discover_flash_size(struct ice_hw *hw) 52981f07491SJacob Keller { 53081f07491SJacob Keller u32 min_size = 0, max_size = ICE_AQC_NVM_MAX_OFFSET + 1; 53181f07491SJacob Keller enum ice_status status; 53281f07491SJacob Keller 53381f07491SJacob Keller status = ice_acquire_nvm(hw, ICE_RES_READ); 53481f07491SJacob Keller if (status) 53581f07491SJacob Keller return status; 53681f07491SJacob Keller 53781f07491SJacob Keller while ((max_size - min_size) > 1) { 53881f07491SJacob Keller u32 offset = (max_size + min_size) / 2; 53981f07491SJacob Keller u32 len = 1; 54081f07491SJacob Keller u8 data; 54181f07491SJacob Keller 54281f07491SJacob Keller status = ice_read_flat_nvm(hw, offset, &len, &data, false); 54381f07491SJacob Keller if (status == ICE_ERR_AQ_ERROR && 54481f07491SJacob Keller hw->adminq.sq_last_status == ICE_AQ_RC_EINVAL) { 54581f07491SJacob Keller ice_debug(hw, ICE_DBG_NVM, 54681f07491SJacob Keller "%s: New upper bound of %u bytes\n", 54781f07491SJacob Keller __func__, offset); 54881f07491SJacob Keller status = 0; 54981f07491SJacob Keller max_size = offset; 55081f07491SJacob Keller } else if (!status) { 55181f07491SJacob Keller ice_debug(hw, ICE_DBG_NVM, 55281f07491SJacob Keller "%s: New lower bound of %u bytes\n", 55381f07491SJacob Keller __func__, offset); 55481f07491SJacob Keller min_size = offset; 55581f07491SJacob Keller } else { 55681f07491SJacob Keller /* an unexpected error occurred */ 55781f07491SJacob Keller goto err_read_flat_nvm; 55881f07491SJacob Keller } 55981f07491SJacob Keller } 56081f07491SJacob Keller 56181f07491SJacob Keller ice_debug(hw, ICE_DBG_NVM, 56281f07491SJacob Keller "Predicted flash size is %u bytes\n", max_size); 56381f07491SJacob Keller 56481f07491SJacob Keller hw->nvm.flash_size = max_size; 56581f07491SJacob Keller 56681f07491SJacob Keller err_read_flat_nvm: 56781f07491SJacob Keller ice_release_nvm(hw); 56881f07491SJacob Keller 56981f07491SJacob Keller return status; 57081f07491SJacob Keller } 57181f07491SJacob Keller 57281f07491SJacob Keller /** 573f31e4b6fSAnirudh Venkataramanan * ice_init_nvm - initializes NVM setting 574f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 575f31e4b6fSAnirudh Venkataramanan * 576f31e4b6fSAnirudh Venkataramanan * This function reads and populates NVM settings such as Shadow RAM size, 577f31e4b6fSAnirudh Venkataramanan * max_timeout, and blank_nvm_mode 578f31e4b6fSAnirudh Venkataramanan */ 579f31e4b6fSAnirudh Venkataramanan enum ice_status ice_init_nvm(struct ice_hw *hw) 580f31e4b6fSAnirudh Venkataramanan { 581f31e4b6fSAnirudh Venkataramanan struct ice_nvm_info *nvm = &hw->nvm; 582d4e87444SJacob Keller u16 eetrack_lo, eetrack_hi, ver; 583031f2147SMd Fahad Iqbal Polash enum ice_status status; 584f31e4b6fSAnirudh Venkataramanan u32 fla, gens_stat; 585f31e4b6fSAnirudh Venkataramanan u8 sr_size; 586f31e4b6fSAnirudh Venkataramanan 587f9867df6SAnirudh Venkataramanan /* The SR size is stored regardless of the NVM programming mode 588f31e4b6fSAnirudh Venkataramanan * as the blank mode may be used in the factory line. 589f31e4b6fSAnirudh Venkataramanan */ 590f31e4b6fSAnirudh Venkataramanan gens_stat = rd32(hw, GLNVM_GENS); 591f31e4b6fSAnirudh Venkataramanan sr_size = (gens_stat & GLNVM_GENS_SR_SIZE_M) >> GLNVM_GENS_SR_SIZE_S; 592f31e4b6fSAnirudh Venkataramanan 593f31e4b6fSAnirudh Venkataramanan /* Switching to words (sr_size contains power of 2) */ 594f31e4b6fSAnirudh Venkataramanan nvm->sr_words = BIT(sr_size) * ICE_SR_WORDS_IN_1KB; 595f31e4b6fSAnirudh Venkataramanan 596f31e4b6fSAnirudh Venkataramanan /* Check if we are in the normal or blank NVM programming mode */ 597f31e4b6fSAnirudh Venkataramanan fla = rd32(hw, GLNVM_FLA); 598f31e4b6fSAnirudh Venkataramanan if (fla & GLNVM_FLA_LOCKED_M) { /* Normal programming mode */ 599f31e4b6fSAnirudh Venkataramanan nvm->blank_nvm_mode = false; 600031f2147SMd Fahad Iqbal Polash } else { 601031f2147SMd Fahad Iqbal Polash /* Blank programming mode */ 602f31e4b6fSAnirudh Venkataramanan nvm->blank_nvm_mode = true; 603f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_NVM, 604f31e4b6fSAnirudh Venkataramanan "NVM init error: unsupported blank mode.\n"); 605031f2147SMd Fahad Iqbal Polash return ICE_ERR_NVM_BLANK_MODE; 606f31e4b6fSAnirudh Venkataramanan } 607f31e4b6fSAnirudh Venkataramanan 608d4e87444SJacob Keller status = ice_read_sr_word(hw, ICE_SR_NVM_DEV_STARTER_VER, &ver); 609f31e4b6fSAnirudh Venkataramanan if (status) { 610f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 611f31e4b6fSAnirudh Venkataramanan "Failed to read DEV starter version.\n"); 612f31e4b6fSAnirudh Venkataramanan return status; 613f31e4b6fSAnirudh Venkataramanan } 614d4e87444SJacob Keller nvm->major_ver = (ver & ICE_NVM_VER_HI_MASK) >> ICE_NVM_VER_HI_SHIFT; 615d4e87444SJacob Keller nvm->minor_ver = (ver & ICE_NVM_VER_LO_MASK) >> ICE_NVM_VER_LO_SHIFT; 616f31e4b6fSAnirudh Venkataramanan 617f31e4b6fSAnirudh Venkataramanan status = ice_read_sr_word(hw, ICE_SR_NVM_EETRACK_LO, &eetrack_lo); 618f31e4b6fSAnirudh Venkataramanan if (status) { 619f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, "Failed to read EETRACK lo.\n"); 620f31e4b6fSAnirudh Venkataramanan return status; 621f31e4b6fSAnirudh Venkataramanan } 622f31e4b6fSAnirudh Venkataramanan status = ice_read_sr_word(hw, ICE_SR_NVM_EETRACK_HI, &eetrack_hi); 623f31e4b6fSAnirudh Venkataramanan if (status) { 624f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, "Failed to read EETRACK hi.\n"); 625f31e4b6fSAnirudh Venkataramanan return status; 626f31e4b6fSAnirudh Venkataramanan } 627f31e4b6fSAnirudh Venkataramanan 628031f2147SMd Fahad Iqbal Polash nvm->eetrack = (eetrack_hi << 16) | eetrack_lo; 629f31e4b6fSAnirudh Venkataramanan 63081f07491SJacob Keller status = ice_discover_flash_size(hw); 63181f07491SJacob Keller if (status) { 63281f07491SJacob Keller ice_debug(hw, ICE_DBG_NVM, 63381f07491SJacob Keller "NVM init error: failed to discover flash size.\n"); 63481f07491SJacob Keller return status; 63581f07491SJacob Keller } 63681f07491SJacob Keller 637e36aeec0SBruce Allan switch (hw->device_id) { 6385d9e618cSJacob Keller /* the following devices do not have boot_cfg_tlv yet */ 639e36aeec0SBruce Allan case ICE_DEV_ID_E823C_BACKPLANE: 640e36aeec0SBruce Allan case ICE_DEV_ID_E823C_QSFP: 641e36aeec0SBruce Allan case ICE_DEV_ID_E823C_SFP: 642e36aeec0SBruce Allan case ICE_DEV_ID_E823C_10G_BASE_T: 643e36aeec0SBruce Allan case ICE_DEV_ID_E823C_SGMII: 644e36aeec0SBruce Allan case ICE_DEV_ID_E822C_BACKPLANE: 645e36aeec0SBruce Allan case ICE_DEV_ID_E822C_QSFP: 646e36aeec0SBruce Allan case ICE_DEV_ID_E822C_10G_BASE_T: 647e36aeec0SBruce Allan case ICE_DEV_ID_E822C_SGMII: 648e36aeec0SBruce Allan case ICE_DEV_ID_E822C_SFP: 6492fbfa966SBruce Allan case ICE_DEV_ID_E822L_BACKPLANE: 650e36aeec0SBruce Allan case ICE_DEV_ID_E822L_SFP: 651e36aeec0SBruce Allan case ICE_DEV_ID_E822L_10G_BASE_T: 652e36aeec0SBruce Allan case ICE_DEV_ID_E822L_SGMII: 653e36aeec0SBruce Allan case ICE_DEV_ID_E823L_BACKPLANE: 654e36aeec0SBruce Allan case ICE_DEV_ID_E823L_SFP: 655e36aeec0SBruce Allan case ICE_DEV_ID_E823L_10G_BASE_T: 656e36aeec0SBruce Allan case ICE_DEV_ID_E823L_1GBE: 657e36aeec0SBruce Allan case ICE_DEV_ID_E823L_QSFP: 6585d9e618cSJacob Keller return status; 659e36aeec0SBruce Allan default: 660e36aeec0SBruce Allan break; 661e36aeec0SBruce Allan } 6625d9e618cSJacob Keller 663d4e87444SJacob Keller status = ice_get_orom_ver_info(hw); 664031f2147SMd Fahad Iqbal Polash if (status) { 665d4e87444SJacob Keller ice_debug(hw, ICE_DBG_INIT, "Failed to read Option ROM info.\n"); 666f31e4b6fSAnirudh Venkataramanan return status; 667f31e4b6fSAnirudh Venkataramanan } 6684c98ab55SBruce Allan 669f45a645fSJacob Keller /* read the netlist version information */ 670f45a645fSJacob Keller status = ice_get_netlist_ver_info(hw); 671f45a645fSJacob Keller if (status) 672f45a645fSJacob Keller ice_debug(hw, ICE_DBG_INIT, "Failed to read netlist info.\n"); 673f45a645fSJacob Keller 674031f2147SMd Fahad Iqbal Polash return 0; 675031f2147SMd Fahad Iqbal Polash } 676031f2147SMd Fahad Iqbal Polash 6774c98ab55SBruce Allan /** 6780e674aebSAnirudh Venkataramanan * ice_nvm_validate_checksum 6790e674aebSAnirudh Venkataramanan * @hw: pointer to the HW struct 6800e674aebSAnirudh Venkataramanan * 6810e674aebSAnirudh Venkataramanan * Verify NVM PFA checksum validity (0x0706) 6820e674aebSAnirudh Venkataramanan */ 6830e674aebSAnirudh Venkataramanan enum ice_status ice_nvm_validate_checksum(struct ice_hw *hw) 6840e674aebSAnirudh Venkataramanan { 6850e674aebSAnirudh Venkataramanan struct ice_aqc_nvm_checksum *cmd; 6860e674aebSAnirudh Venkataramanan struct ice_aq_desc desc; 6870e674aebSAnirudh Venkataramanan enum ice_status status; 6880e674aebSAnirudh Venkataramanan 6890e674aebSAnirudh Venkataramanan status = ice_acquire_nvm(hw, ICE_RES_READ); 6900e674aebSAnirudh Venkataramanan if (status) 6910e674aebSAnirudh Venkataramanan return status; 6920e674aebSAnirudh Venkataramanan 6930e674aebSAnirudh Venkataramanan cmd = &desc.params.nvm_checksum; 6940e674aebSAnirudh Venkataramanan 6950e674aebSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_checksum); 6960e674aebSAnirudh Venkataramanan cmd->flags = ICE_AQC_NVM_CHECKSUM_VERIFY; 6970e674aebSAnirudh Venkataramanan 6980e674aebSAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 6990e674aebSAnirudh Venkataramanan ice_release_nvm(hw); 7000e674aebSAnirudh Venkataramanan 7010e674aebSAnirudh Venkataramanan if (!status) 7020e674aebSAnirudh Venkataramanan if (le16_to_cpu(cmd->checksum) != ICE_AQC_NVM_CHECKSUM_CORRECT) 7030e674aebSAnirudh Venkataramanan status = ICE_ERR_NVM_CHECKSUM; 7040e674aebSAnirudh Venkataramanan 7050e674aebSAnirudh Venkataramanan return status; 7060e674aebSAnirudh Venkataramanan } 707544cd2acSCudzilo, Szymon T 708544cd2acSCudzilo, Szymon T /** 709544cd2acSCudzilo, Szymon T * ice_nvm_write_activate 710544cd2acSCudzilo, Szymon T * @hw: pointer to the HW struct 711544cd2acSCudzilo, Szymon T * @cmd_flags: NVM activate admin command bits (banks to be validated) 712544cd2acSCudzilo, Szymon T * 713544cd2acSCudzilo, Szymon T * Update the control word with the required banks' validity bits 714544cd2acSCudzilo, Szymon T * and dumps the Shadow RAM to flash (0x0707) 715544cd2acSCudzilo, Szymon T */ 716544cd2acSCudzilo, Szymon T enum ice_status ice_nvm_write_activate(struct ice_hw *hw, u8 cmd_flags) 717544cd2acSCudzilo, Szymon T { 718544cd2acSCudzilo, Szymon T struct ice_aqc_nvm *cmd; 719544cd2acSCudzilo, Szymon T struct ice_aq_desc desc; 720544cd2acSCudzilo, Szymon T 721544cd2acSCudzilo, Szymon T cmd = &desc.params.nvm; 722544cd2acSCudzilo, Szymon T ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_write_activate); 723544cd2acSCudzilo, Szymon T 724544cd2acSCudzilo, Szymon T cmd->cmd_flags = cmd_flags; 725544cd2acSCudzilo, Szymon T 726544cd2acSCudzilo, Szymon T return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 727544cd2acSCudzilo, Szymon T } 728544cd2acSCudzilo, Szymon T 729544cd2acSCudzilo, Szymon T /** 730544cd2acSCudzilo, Szymon T * ice_aq_nvm_update_empr 731544cd2acSCudzilo, Szymon T * @hw: pointer to the HW struct 732544cd2acSCudzilo, Szymon T * 733544cd2acSCudzilo, Szymon T * Update empr (0x0709). This command allows SW to 734544cd2acSCudzilo, Szymon T * request an EMPR to activate new FW. 735544cd2acSCudzilo, Szymon T */ 736544cd2acSCudzilo, Szymon T enum ice_status ice_aq_nvm_update_empr(struct ice_hw *hw) 737544cd2acSCudzilo, Szymon T { 738544cd2acSCudzilo, Szymon T struct ice_aq_desc desc; 739544cd2acSCudzilo, Szymon T 740544cd2acSCudzilo, Szymon T ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_update_empr); 741544cd2acSCudzilo, Szymon T 742544cd2acSCudzilo, Szymon T return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 743544cd2acSCudzilo, Szymon T } 744544cd2acSCudzilo, Szymon T 745544cd2acSCudzilo, Szymon T /* ice_nvm_set_pkg_data 746544cd2acSCudzilo, Szymon T * @hw: pointer to the HW struct 747544cd2acSCudzilo, Szymon T * @del_pkg_data_flag: If is set then the current pkg_data store by FW 748544cd2acSCudzilo, Szymon T * is deleted. 749544cd2acSCudzilo, Szymon T * If bit is set to 1, then buffer should be size 0. 750544cd2acSCudzilo, Szymon T * @data: pointer to buffer 751544cd2acSCudzilo, Szymon T * @length: length of the buffer 752544cd2acSCudzilo, Szymon T * @cd: pointer to command details structure or NULL 753544cd2acSCudzilo, Szymon T * 754544cd2acSCudzilo, Szymon T * Set package data (0x070A). This command is equivalent to the reception 755544cd2acSCudzilo, Szymon T * of a PLDM FW Update GetPackageData cmd. This command should be sent 756544cd2acSCudzilo, Szymon T * as part of the NVM update as the first cmd in the flow. 757544cd2acSCudzilo, Szymon T */ 758544cd2acSCudzilo, Szymon T 759544cd2acSCudzilo, Szymon T enum ice_status 760544cd2acSCudzilo, Szymon T ice_nvm_set_pkg_data(struct ice_hw *hw, bool del_pkg_data_flag, u8 *data, 761544cd2acSCudzilo, Szymon T u16 length, struct ice_sq_cd *cd) 762544cd2acSCudzilo, Szymon T { 763544cd2acSCudzilo, Szymon T struct ice_aqc_nvm_pkg_data *cmd; 764544cd2acSCudzilo, Szymon T struct ice_aq_desc desc; 765544cd2acSCudzilo, Szymon T 766544cd2acSCudzilo, Szymon T if (length != 0 && !data) 767544cd2acSCudzilo, Szymon T return ICE_ERR_PARAM; 768544cd2acSCudzilo, Szymon T 769544cd2acSCudzilo, Szymon T cmd = &desc.params.pkg_data; 770544cd2acSCudzilo, Szymon T 771544cd2acSCudzilo, Szymon T ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_pkg_data); 772544cd2acSCudzilo, Szymon T desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 773544cd2acSCudzilo, Szymon T 774544cd2acSCudzilo, Szymon T if (del_pkg_data_flag) 775544cd2acSCudzilo, Szymon T cmd->cmd_flags |= ICE_AQC_NVM_PKG_DELETE; 776544cd2acSCudzilo, Szymon T 777544cd2acSCudzilo, Szymon T return ice_aq_send_cmd(hw, &desc, data, length, cd); 778544cd2acSCudzilo, Szymon T } 779544cd2acSCudzilo, Szymon T 780544cd2acSCudzilo, Szymon T /* ice_nvm_pass_component_tbl 781544cd2acSCudzilo, Szymon T * @hw: pointer to the HW struct 782544cd2acSCudzilo, Szymon T * @data: pointer to buffer 783544cd2acSCudzilo, Szymon T * @length: length of the buffer 784544cd2acSCudzilo, Szymon T * @transfer_flag: parameter for determining stage of the update 785544cd2acSCudzilo, Szymon T * @comp_response: a pointer to the response from the 0x070B AQC. 786544cd2acSCudzilo, Szymon T * @comp_response_code: a pointer to the response code from the 0x070B AQC. 787544cd2acSCudzilo, Szymon T * @cd: pointer to command details structure or NULL 788544cd2acSCudzilo, Szymon T * 789544cd2acSCudzilo, Szymon T * Pass component table (0x070B). This command is equivalent to the reception 790544cd2acSCudzilo, Szymon T * of a PLDM FW Update PassComponentTable cmd. This command should be sent once 791544cd2acSCudzilo, Szymon T * per component. It can be only sent after Set Package Data cmd and before 792544cd2acSCudzilo, Szymon T * actual update. FW will assume these commands are going to be sent until 793544cd2acSCudzilo, Szymon T * the TransferFlag is set to End or StartAndEnd. 794544cd2acSCudzilo, Szymon T */ 795544cd2acSCudzilo, Szymon T 796544cd2acSCudzilo, Szymon T enum ice_status 797544cd2acSCudzilo, Szymon T ice_nvm_pass_component_tbl(struct ice_hw *hw, u8 *data, u16 length, 798544cd2acSCudzilo, Szymon T u8 transfer_flag, u8 *comp_response, 799544cd2acSCudzilo, Szymon T u8 *comp_response_code, struct ice_sq_cd *cd) 800544cd2acSCudzilo, Szymon T { 801544cd2acSCudzilo, Szymon T struct ice_aqc_nvm_pass_comp_tbl *cmd; 802544cd2acSCudzilo, Szymon T struct ice_aq_desc desc; 803544cd2acSCudzilo, Szymon T enum ice_status status; 804544cd2acSCudzilo, Szymon T 805544cd2acSCudzilo, Szymon T if (!data || !comp_response || !comp_response_code) 806544cd2acSCudzilo, Szymon T return ICE_ERR_PARAM; 807544cd2acSCudzilo, Szymon T 808544cd2acSCudzilo, Szymon T cmd = &desc.params.pass_comp_tbl; 809544cd2acSCudzilo, Szymon T 810544cd2acSCudzilo, Szymon T ice_fill_dflt_direct_cmd_desc(&desc, 811544cd2acSCudzilo, Szymon T ice_aqc_opc_nvm_pass_component_tbl); 812544cd2acSCudzilo, Szymon T desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 813544cd2acSCudzilo, Szymon T 814544cd2acSCudzilo, Szymon T cmd->transfer_flag = transfer_flag; 815544cd2acSCudzilo, Szymon T status = ice_aq_send_cmd(hw, &desc, data, length, cd); 816544cd2acSCudzilo, Szymon T 817544cd2acSCudzilo, Szymon T if (!status) { 818544cd2acSCudzilo, Szymon T *comp_response = cmd->component_response; 819544cd2acSCudzilo, Szymon T *comp_response_code = cmd->component_response_code; 820544cd2acSCudzilo, Szymon T } 821544cd2acSCudzilo, Szymon T return status; 822544cd2acSCudzilo, Szymon T } 823