From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id B18ABA0350; Mon, 22 Jun 2020 09:14:07 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 43D851D5AB; Mon, 22 Jun 2020 09:06:52 +0200 (CEST) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by dpdk.org (Postfix) with ESMTP id 192EF1D58B for ; Mon, 22 Jun 2020 09:06:48 +0200 (CEST) IronPort-SDR: ugDbQcZhU/ghXYl/h9slHl4c7QuFqD9g6l0GYmjEItcT1/zOdLyPPRgOICkw+iEgXFOqnlJAQ7 yjRe5tzyDXxA== X-IronPort-AV: E=McAfee;i="6000,8403,9659"; a="141944926" X-IronPort-AV: E=Sophos;i="5.75,266,1589266800"; d="scan'208";a="141944926" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jun 2020 00:06:48 -0700 IronPort-SDR: ASqO4vggXdCIF0seil9WVvYLL7YAorZvvjaqidu6DWKtLg1BME3NwB5WtR7TLdBhX7u2QS0Puq TRK6MMIJBpXQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,266,1589266800"; d="scan'208";a="384409154" Received: from dpdk.sh.intel.com ([10.239.255.83]) by fmsmga001.fm.intel.com with ESMTP; 22 Jun 2020 00:06:46 -0700 From: Guinan Sun To: dev@dpdk.org Cc: Jeff Guo , Zhao1 Wei , Guinan Sun , Lotem Leder Date: Mon, 22 Jun 2020 06:46:12 +0000 Message-Id: <20200622064634.70941-49-guinanx.sun@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200622064634.70941-1-guinanx.sun@intel.com> References: <20200622064634.70941-1-guinanx.sun@intel.com> Subject: [dpdk-dev] [PATCH 48/70] net/e1000/base: support I225 update NVM flow X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" As long as I225 firmware is valid and operational, it is responsible for updating the NVM. If FW is not valid, it is up to the SW to update the NVM while making sure to check which sector is valid and update accordingly. Signed-off-by: Lotem Leder Signed-off-by: Guinan Sun --- drivers/net/e1000/base/e1000_defines.h | 5 +- drivers/net/e1000/base/e1000_i225.c | 166 +++++++++++++++++++++++-- drivers/net/e1000/base/e1000_regs.h | 6 +- 3 files changed, 160 insertions(+), 17 deletions(-) diff --git a/drivers/net/e1000/base/e1000_defines.h b/drivers/net/e1000/base/e1000_defines.h index 985c8924b..80a8645e3 100644 --- a/drivers/net/e1000/base/e1000_defines.h +++ b/drivers/net/e1000/base/e1000_defines.h @@ -1124,14 +1124,15 @@ /* Firmware code revision field word offset*/ #define E1000_I210_FW_VER_OFFSET 328 -#ifndef NO_I225_SUPPORT #define E1000_EECD_FLUPD_I225 0x00800000 /* Update FLASH */ #define E1000_EECD_FLUDONE_I225 0x04000000 /* Update FLASH done */ #define E1000_EECD_FLASH_DETECTED_I225 0x00080000 /* FLASH detected */ #define E1000_FLUDONE_ATTEMPTS 20000 #define E1000_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */ +#define E1000_EECD_SEC1VAL_I225 0x02000000 /* Sector One Valid */ +#define E1000_FLSECU_BLK_SW_ACCESS_I225 0x00000004 /* Block SW access */ +#define E1000_FWSM_FW_VALID_I225 0x8000 /* FW valid bit */ -#endif /* NO_I225_SUPPORT */ #define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM read/write regs */ #define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ #define E1000_NVM_RW_REG_START 1 /* Start operation */ diff --git a/drivers/net/e1000/base/e1000_i225.c b/drivers/net/e1000/base/e1000_i225.c index ef47f1810..089bc7a2a 100644 --- a/drivers/net/e1000/base/e1000_i225.c +++ b/drivers/net/e1000/base/e1000_i225.c @@ -840,31 +840,171 @@ bool e1000_get_flash_presence_i225(struct e1000_hw *hw) return ret_val; } +/* e1000_set_flsw_flash_burst_counter_i225 - sets FLSW NVM Burst + * Counter in FLSWCNT register. + * + * @hw: pointer to the HW structure + * @burst_counter: size in bytes of the Flash burst to read or write + */ +s32 e1000_set_flsw_flash_burst_counter_i225(struct e1000_hw *hw, + u32 burst_counter) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_set_flsw_flash_burst_counter_i225"); + + /* Validate input data */ + if (burst_counter < E1000_I225_SHADOW_RAM_SIZE) { + /* Write FLSWCNT - burst counter */ + E1000_WRITE_REG(hw, E1000_I225_FLSWCNT, burst_counter); + } else { + ret_val = E1000_ERR_INVALID_ARGUMENT; + } + + return ret_val; +} + +/* e1000_write_erase_flash_command_i225 - write/erase to a sector + * region on a given address. + * + * @hw: pointer to the HW structure + * @opcode: opcode to be used for the write command + * @address: the offset to write into the FLASH image + */ +s32 e1000_write_erase_flash_command_i225(struct e1000_hw *hw, u32 opcode, + u32 address) +{ + u32 flswctl = 0; + s32 timeout = E1000_NVM_GRANT_ATTEMPTS; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_write_erase_flash_command_i225"); + + flswctl = E1000_READ_REG(hw, E1000_I225_FLSWCTL); + /* Polling done bit on FLSWCTL register */ + while (timeout) { + if (flswctl & E1000_FLSWCTL_DONE) + break; + usec_delay(5); + flswctl = E1000_READ_REG(hw, E1000_I225_FLSWCTL); + timeout--; + } + + if (!timeout) { + DEBUGOUT("Flash transaction was not done\n"); + return -E1000_ERR_NVM; + } + + /* Build and issue command on FLSWCTL register */ + flswctl = address | opcode; + E1000_WRITE_REG(hw, E1000_I225_FLSWCTL, flswctl); + + /* Check if issued command is valid on FLSWCTL register */ + flswctl = E1000_READ_REG(hw, E1000_I225_FLSWCTL); + if (!(flswctl & E1000_FLSWCTL_CMDV)) { + DEBUGOUT("Write flash command failed\n"); + ret_val = E1000_ERR_INVALID_ARGUMENT; + } + + return ret_val; +} + /* e1000_update_flash_i225 - Commit EEPROM to the flash + * if fw_valid_bit is set, FW is active. setting FLUPD bit in EEC + * register makes the FW load the internal shadow RAM into the flash. + * Otherwise, fw_valid_bit is 0. if FL_SECU.block_prtotected_sw = 0 + * then FW is not active so the SW is responsible shadow RAM dump. + * * @hw: pointer to the HW structure */ s32 e1000_update_flash_i225(struct e1000_hw *hw) { - s32 ret_val; + u16 current_offset_data = 0; + u32 block_sw_protect = 1; + u16 base_address = 0x0; + u32 i, fw_valid_bit; + u16 current_offset; + s32 ret_val = 0; u32 flup; DEBUGFUNC("e1000_update_flash_i225"); - ret_val = e1000_pool_flash_update_done_i225(hw); - if (ret_val == -E1000_ERR_NVM) { - DEBUGOUT("Flash update time out\n"); - goto out; - } + block_sw_protect = E1000_READ_REG(hw, E1000_I225_FLSECU) & + E1000_FLSECU_BLK_SW_ACCESS_I225; + fw_valid_bit = E1000_READ_REG(hw, E1000_FWSM) & + E1000_FWSM_FW_VALID_I225; + if (fw_valid_bit) { + ret_val = e1000_pool_flash_update_done_i225(hw); + if (ret_val == -E1000_ERR_NVM) { + DEBUGOUT("Flash update time out\n"); + goto out; + } - flup = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD_I225; - E1000_WRITE_REG(hw, E1000_EECD, flup); + flup = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD_I225; + E1000_WRITE_REG(hw, E1000_EECD, flup); - ret_val = e1000_pool_flash_update_done_i225(hw); - if (ret_val == E1000_SUCCESS) - DEBUGOUT("Flash update complete\n"); - else - DEBUGOUT("Flash update time out\n"); + ret_val = e1000_pool_flash_update_done_i225(hw); + if (ret_val == E1000_SUCCESS) + DEBUGOUT("Flash update complete\n"); + else + DEBUGOUT("Flash update time out\n"); + } else if (!block_sw_protect) { + /* FW is not active and security protection is disabled. + * therefore, SW is in charge of shadow RAM dump. + * Check which sector is valid. if sector 0 is valid, + * base address remains 0x0. otherwise, sector 1 is + * valid and it's base address is 0x1000 + */ + if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_SEC1VAL_I225) + base_address = 0x1000; + + /* Valid sector erase */ + ret_val = e1000_write_erase_flash_command_i225(hw, + E1000_I225_ERASE_CMD_OPCODE, + base_address); + if (!ret_val) { + DEBUGOUT("Sector erase failed\n"); + goto out; + } + current_offset = base_address; + + /* Write */ + for (i = 0; i < E1000_I225_SHADOW_RAM_SIZE / 2; i++) { + /* Set burst write length */ + ret_val = e1000_set_flsw_flash_burst_counter_i225(hw, + 0x2); + if (ret_val != E1000_SUCCESS) + break; + + /* Set address and opcode */ + ret_val = e1000_write_erase_flash_command_i225(hw, + E1000_I225_WRITE_CMD_OPCODE, + 2 * current_offset); + if (ret_val != E1000_SUCCESS) + break; + + ret_val = e1000_read_nvm_eerd(hw, current_offset, + 1, ¤t_offset_data); + if (ret_val) { + DEBUGOUT("Failed to read from EEPROM\n"); + goto out; + } + + /* Write CurrentOffseData to FLSWDATA register */ + E1000_WRITE_REG(hw, E1000_I225_FLSWDATA, + current_offset_data); + current_offset++; + + /* Wait till operation has finished */ + ret_val = e1000_poll_eerd_eewr_done(hw, + E1000_NVM_POLL_READ); + if (ret_val) + break; + + usec_delay(1000); + } + } out: return ret_val; } diff --git a/drivers/net/e1000/base/e1000_regs.h b/drivers/net/e1000/base/e1000_regs.h index 9428322f3..2d94e7294 100644 --- a/drivers/net/e1000/base/e1000_regs.h +++ b/drivers/net/e1000/base/e1000_regs.h @@ -31,9 +31,11 @@ #define E1000_SCTL 0x00024 /* SerDes Control - RW */ #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ -#if !defined(EXTERNAL_RELEASE) || defined(ULP_SUPPORT) #define E1000_FEXT 0x0002C /* Future Extended - RW */ -#endif /* !EXTERNAL_RELEASE || ULP_SUPPORT */ +#define E1000_I225_FLSWCTL 0x12048 /* FLASH control register */ +#define E1000_I225_FLSWDATA 0x1204C /* FLASH data register */ +#define E1000_I225_FLSWCNT 0x12050 /* FLASH Access Counter */ +#define E1000_I225_FLSECU 0x12114 /* FLASH Security */ #define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ #define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */ #define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ -- 2.17.1