get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/71869/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 71869,
    "url": "https://patches.dpdk.org/api/patches/71869/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20200622064634.70941-3-guinanx.sun@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20200622064634.70941-3-guinanx.sun@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200622064634.70941-3-guinanx.sun@intel.com",
    "date": "2020-06-22T06:45:26",
    "name": "[02/70] net/e1000/base: add initial support for Foxville",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "9d581c90dca9447f3b753f9a71f94fb19f5cd992",
    "submitter": {
        "id": 1476,
        "url": "https://patches.dpdk.org/api/people/1476/?format=api",
        "name": "Guinan Sun",
        "email": "guinanx.sun@intel.com"
    },
    "delegate": {
        "id": 1540,
        "url": "https://patches.dpdk.org/api/users/1540/?format=api",
        "username": "qzhan15",
        "first_name": "Qi",
        "last_name": "Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20200622064634.70941-3-guinanx.sun@intel.com/mbox/",
    "series": [
        {
            "id": 10543,
            "url": "https://patches.dpdk.org/api/series/10543/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=10543",
            "date": "2020-06-22T06:45:24",
            "name": "update e1000 base code",
            "version": 1,
            "mbox": "https://patches.dpdk.org/series/10543/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/71869/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/71869/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 3F872A0350;\n\tMon, 22 Jun 2020 09:05:34 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 591441C1B2;\n\tMon, 22 Jun 2020 09:05:19 +0200 (CEST)",
            "from mga11.intel.com (mga11.intel.com [192.55.52.93])\n by dpdk.org (Postfix) with ESMTP id 5CDAF1C1A5\n for <dev@dpdk.org>; Mon, 22 Jun 2020 09:05:15 +0200 (CEST)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 22 Jun 2020 00:05:14 -0700",
            "from dpdk.sh.intel.com ([10.239.255.83])\n by fmsmga001.fm.intel.com with ESMTP; 22 Jun 2020 00:05:12 -0700"
        ],
        "IronPort-SDR": [
            "\n 5PuXNmF2hx2tpriwP4UL7byNSOQIhoETMlzO/qhCtyDri5FIVSkcBUI+Ofg6AuYYN6cPeExLrt\n 50ycU3xPc35w==",
            "\n rzxS5IVVzK2WET+zBSARTHxqd+xp9fjEWgwT0IZPW6RY80k5FJIdKemPUJlw18x2a4TLJGP+r/\n yfRyHjnPwR0A=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9659\"; a=\"141944682\"",
            "E=Sophos;i=\"5.75,266,1589266800\"; d=\"scan'208\";a=\"141944682\"",
            "E=Sophos;i=\"5.75,266,1589266800\"; d=\"scan'208\";a=\"384408749\""
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "From": "Guinan Sun <guinanx.sun@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "Jeff Guo <jia.guo@intel.com>, Zhao1 Wei <wei.zhao1@intel.com>,\n Guinan Sun <guinanx.sun@intel.com>, Sasha Neftin <sasha.neftin@intel.com>",
        "Date": "Mon, 22 Jun 2020 06:45:26 +0000",
        "Message-Id": "<20200622064634.70941-3-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 02/70] net/e1000/base: add initial support for\n\tFoxville",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Add Foxville device's ID and mac type,\nbind device's ID and MAC type.\nAdd basic Foxville functionality.\nAdd phy ID's for Foxville.\n\nSigned-off-by: Sasha Neftin <sasha.neftin@intel.com>\nSigned-off-by: Guinan Sun <guinanx.sun@intel.com>\n---\n drivers/net/e1000/Makefile             |    1 +\n drivers/net/e1000/base/e1000_82575.c   |   10 +-\n drivers/net/e1000/base/e1000_api.c     |    9 +\n drivers/net/e1000/base/e1000_api.h     |    1 +\n drivers/net/e1000/base/e1000_defines.h |   52 ++\n drivers/net/e1000/base/e1000_hw.h      |   19 +\n drivers/net/e1000/base/e1000_i225.c    | 1119 ++++++++++++++++++++++++\n drivers/net/e1000/base/e1000_i225.h    |  105 +++\n drivers/net/e1000/base/e1000_regs.h    |    6 +\n drivers/net/e1000/base/meson.build     |    1 +\n 10 files changed, 1321 insertions(+), 2 deletions(-)\n create mode 100644 drivers/net/e1000/base/e1000_i225.c\n create mode 100644 drivers/net/e1000/base/e1000_i225.h",
    "diff": "diff --git a/drivers/net/e1000/Makefile b/drivers/net/e1000/Makefile\nindex 9fb038cf0..82e156ecb 100644\n--- a/drivers/net/e1000/Makefile\n+++ b/drivers/net/e1000/Makefile\n@@ -58,6 +58,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_82543.c\n SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_82571.c\n SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_82575.c\n SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_i210.c\n+SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_i225.c\n SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_api.c\n SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_ich8lan.c\n SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_logs.c\ndiff --git a/drivers/net/e1000/base/e1000_82575.c b/drivers/net/e1000/base/e1000_82575.c\nindex 4c3611c6d..35a6ba502 100644\n--- a/drivers/net/e1000/base/e1000_82575.c\n+++ b/drivers/net/e1000/base/e1000_82575.c\n@@ -14,6 +14,7 @@\n \n #include \"e1000_api.h\"\n #include \"e1000_i210.h\"\n+#include \"e1000_i225.h\"\n \n STATIC s32  e1000_init_phy_params_82575(struct e1000_hw *hw);\n STATIC s32  e1000_init_mac_params_82575(struct e1000_hw *hw);\n@@ -430,12 +431,17 @@ STATIC s32 e1000_init_mac_params_82575(struct e1000_hw *hw)\n \tif (mac->type >= e1000_82580)\n \t\tmac->ops.reset_hw = e1000_reset_hw_82580;\n \telse\n-\tmac->ops.reset_hw = e1000_reset_hw_82575;\n+\t\tmac->ops.reset_hw = e1000_reset_hw_82575;\n \t/* hw initialization */\n \tif ((mac->type == e1000_i210) || (mac->type == e1000_i211))\n \t\tmac->ops.init_hw = e1000_init_hw_i210;\n \telse\n-\tmac->ops.init_hw = e1000_init_hw_82575;\n+#ifndef NO_I225_SUPPORT\n+\tif (mac->type == e1000_i225)\n+\t\tmac->ops.init_hw = e1000_init_hw_i225;\n+\telse\n+#endif /* NO_I225_SUPPORT */\n+\t\tmac->ops.init_hw = e1000_init_hw_82575;\n \t/* link setup */\n \tmac->ops.setup_link = e1000_setup_link_generic;\n \t/* physical interface link setup */\ndiff --git a/drivers/net/e1000/base/e1000_api.c b/drivers/net/e1000/base/e1000_api.c\nindex 718952801..90845d477 100644\n--- a/drivers/net/e1000/base/e1000_api.c\n+++ b/drivers/net/e1000/base/e1000_api.c\n@@ -333,6 +333,12 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)\n \tcase E1000_DEV_ID_I211_COPPER:\n \t\tmac->type = e1000_i211;\n \t\tbreak;\n+#ifndef NO_I225_SUPPORT\n+\tcase E1000_DEV_ID_I225_LM:\n+\tcase E1000_DEV_ID_I225_V:\n+\t\tmac->type = e1000_i225;\n+\t\tbreak;\n+#endif /* NO_I225_SUPPORT */\n \tcase E1000_DEV_ID_82576_VF:\n \tcase E1000_DEV_ID_82576_VF_HV:\n \t\tmac->type = e1000_vfadapt;\n@@ -451,6 +457,9 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)\n \tcase e1000_i211:\n \t\te1000_init_function_pointers_i210(hw);\n \t\tbreak;\n+\tcase e1000_i225:\n+\t\te1000_init_function_pointers_i225(hw);\n+\t\tbreak;\n \tcase e1000_vfadapt:\n \t\te1000_init_function_pointers_vf(hw);\n \t\tbreak;\ndiff --git a/drivers/net/e1000/base/e1000_api.h b/drivers/net/e1000/base/e1000_api.h\nindex 3054d5b9d..34e065054 100644\n--- a/drivers/net/e1000/base/e1000_api.h\n+++ b/drivers/net/e1000/base/e1000_api.h\n@@ -20,6 +20,7 @@ extern void e1000_init_function_pointers_vf(struct e1000_hw *hw);\n extern void e1000_power_up_fiber_serdes_link(struct e1000_hw *hw);\n extern void e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw);\n extern void e1000_init_function_pointers_i210(struct e1000_hw *hw);\n+extern void e1000_init_function_pointers_i225(struct e1000_hw *hw);\n \n s32 e1000_set_obff_timer(struct e1000_hw *hw, u32 itr);\n s32 e1000_set_mac_type(struct e1000_hw *hw);\ndiff --git a/drivers/net/e1000/base/e1000_defines.h b/drivers/net/e1000/base/e1000_defines.h\nindex 8831da7ca..ee2ecceee 100644\n--- a/drivers/net/e1000/base/e1000_defines.h\n+++ b/drivers/net/e1000/base/e1000_defines.h\n@@ -843,6 +843,11 @@\n #define E1000_EEE_SU_LPI_CLK_STP\t0x00800000 /* EEE LPI Clock Stop */\n #define E1000_EEE_LP_ADV_DEV_I210\t7          /* EEE LP Adv Device */\n #define E1000_EEE_LP_ADV_ADDR_I210\t61         /* EEE LP Adv Register */\n+#ifndef NO_I225_SUPPORT\n+#define E1000_EEE_LP_ADV_DEV_I225\t7          /* EEE LP Adv Device */\n+#define E1000_EEE_LP_ADV_ADDR_I225\t61         /* EEE LP Adv Register */\n+\n+#endif /* NO_I225_SUPPORT */\n /* PCI Express Control */\n #define E1000_GCR_RXD_NO_SNOOP\t\t0x00000001\n #define E1000_GCR_RXDSCW_NO_SNOOP\t0x00000002\n@@ -1027,6 +1032,12 @@\n /* Firmware code revision field word offset*/\n #define E1000_I210_FW_VER_OFFSET\t328\n \n+#ifndef NO_I225_SUPPORT\n+#define E1000_EECD_FLUPD_I225\t\t0x00800000 /* Update FLASH */\n+#define E1000_EECD_FLUDONE_I225\t\t0x04000000 /* Update FLASH done */\n+#define E1000_EECD_FLASH_DETECTED_I225\t0x00080000 /* FLASH detected */\n+\n+#endif /* NO_I225_SUPPORT */\n #define E1000_NVM_RW_REG_DATA\t16  /* Offset to data in NVM read/write regs */\n #define E1000_NVM_RW_REG_DONE\t2   /* Offset to READ/WRITE done bit */\n #define E1000_NVM_RW_REG_START\t1   /* Start operation */\n@@ -1244,6 +1255,9 @@\n #define I82580_I_PHY_ID\t\t0x015403A0\n #define I350_I_PHY_ID\t\t0x015403B0\n #define I210_I_PHY_ID\t\t0x01410C00\n+#ifndef NO_I225_SUPPORT\n+#define I225_I_PHY_ID\t\t0x67C9DC00\n+#endif /* NO_I225_SUPPORT */\n #define IGP04E1000_E_PHY_ID\t0x02A80391\n #define BCM54616_E_PHY_ID\t0x03625D10\n #define M88_VENDOR\t\t0x0141\n@@ -1454,6 +1468,43 @@\n #define I210_TXPBSIZE_DEFAULT\t\t0x04000014 /* TXPBSIZE default */\n \n \n+#ifndef NO_I225_SUPPORT\n+#define I225_RXPBSIZE_DEFAULT\t\t0x000000A2 /* RXPBSIZE default */\n+#define I225_TXPBSIZE_DEFAULT\t\t0x04000014 /* TXPBSIZE default */\n+#define E1000_RXPBS_SIZE_I225_MASK\t0x0000003F /* Rx packet buffer size */\n+#define E1000_TXPB0S_SIZE_I225_MASK\t0x0000003F /* Tx packet buffer 0 size */\n+#define E1000_STM_OPCODE\t\t0xDB00\n+#define E1000_EEPROM_FLASH_SIZE_WORD\t0x11\n+#define INVM_DWORD_TO_RECORD_TYPE(invm_dword) \\\n+\t(u8)((invm_dword) & 0x7)\n+#define INVM_DWORD_TO_WORD_ADDRESS(invm_dword) \\\n+\t(u8)(((invm_dword) & 0x0000FE00) >> 9)\n+#define INVM_DWORD_TO_WORD_DATA(invm_dword) \\\n+\t(u16)(((invm_dword) & 0xFFFF0000) >> 16)\n+#define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS\t8\n+#define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS\t1\n+#define E1000_INVM_ULT_BYTES_SIZE\t\t8\n+#define E1000_INVM_RECORD_SIZE_IN_BYTES\t4\n+#define E1000_INVM_VER_FIELD_ONE\t\t0x1FF8\n+#define E1000_INVM_VER_FIELD_TWO\t\t0x7FE000\n+#define E1000_INVM_IMGTYPE_FIELD\t\t0x1F800000\n+\n+#define E1000_INVM_MAJOR_MASK\t0x3F0\n+#define E1000_INVM_MINOR_MASK\t0xF\n+#define E1000_INVM_MAJOR_SHIFT\t4\n+\n+/* PLL Defines */\n+#define E1000_PCI_PMCSR\t\t0x44\n+#define E1000_PCI_PMCSR_D3\t\t0x03\n+#define E1000_MAX_PLL_TRIES\t\t5\n+#define E1000_PHY_PLL_UNCONF\t\t0xFF\n+#define E1000_PHY_PLL_FREQ_PAGE\t0xFC0000\n+#define E1000_PHY_PLL_FREQ_REG\t\t0x000E\n+#define E1000_INVM_DEFAULT_AL\t\t0x202F\n+#define E1000_INVM_AUTOLOAD\t\t0x0A\n+#define E1000_INVM_PLL_WO_VAL\t\t0x0010\n+\n+#endif /* NO_I225_SUPPORT */\n /* Proxy Filter Control */\n #define E1000_PROXYFC_D0\t\t0x00000001 /* Enable offload in D0 */\n #define E1000_PROXYFC_EX\t\t0x00000004 /* Directed exact proxy */\n@@ -1476,6 +1527,7 @@\n /* Lan ID bit field offset in status register */\n #define E1000_STATUS_LAN_ID_OFFSET\t2\n #define E1000_VFTA_ENTRIES\t\t128\n+\n #ifndef E1000_UNUSEDARG\n #define E1000_UNUSEDARG\n #endif /* E1000_UNUSEDARG */\ndiff --git a/drivers/net/e1000/base/e1000_hw.h b/drivers/net/e1000/base/e1000_hw.h\nindex 9793b724e..a47fa9822 100644\n--- a/drivers/net/e1000/base/e1000_hw.h\n+++ b/drivers/net/e1000/base/e1000_hw.h\n@@ -155,6 +155,10 @@ struct e1000_hw;\n #define E1000_DEV_ID_I210_COPPER_FLASHLESS\t0x157B\n #define E1000_DEV_ID_I210_SERDES_FLASHLESS\t0x157C\n #define E1000_DEV_ID_I211_COPPER\t\t0x1539\n+#ifndef NO_I225_SUPPORT\n+#define E1000_DEV_ID_I225_LM\t\t\t0x15F2\n+#define E1000_DEV_ID_I225_V\t\t\t0x15F3\n+#endif /* NO_I225_SUPPORT */\n #define E1000_DEV_ID_I354_BACKPLANE_1GBPS\t0x1F40\n #define E1000_DEV_ID_I354_SGMII\t\t\t0x1F41\n #define E1000_DEV_ID_I354_BACKPLANE_2_5GBPS\t0x1F45\n@@ -214,6 +218,9 @@ enum e1000_mac_type {\n \te1000_i354,\n \te1000_i210,\n \te1000_i211,\n+#ifndef NO_I225_SUPPORT\n+\te1000_i225,\n+#endif /* NO_I225_SUPPORT */\n \te1000_vfadapt,\n \te1000_vfadapt_i350,\n \te1000_num_macs  /* List is 1-based, so subtract 1 for true count. */\n@@ -348,6 +355,17 @@ enum e1000_serdes_link_state {\n \te1000_serdes_link_forced_up\n };\n \n+#ifndef NO_I225_SUPPORT\n+enum e1000_invm_structure_type {\n+\te1000_invm_unitialized_structure\t\t= 0x00,\n+\te1000_invm_word_autoload_structure\t\t= 0x01,\n+\te1000_invm_csr_autoload_structure\t\t= 0x02,\n+\te1000_invm_phy_register_autoload_structure\t= 0x03,\n+\te1000_invm_rsa_key_sha256_structure\t\t= 0x04,\n+\te1000_invm_invalidated_structure\t\t= 0x0f,\n+};\n+\n+#endif /* NO_I225_SUPPORT */\n #define __le16 u16\n #define __le32 u32\n #define __le64 u64\n@@ -1008,6 +1026,7 @@ struct e1000_hw {\n #include \"e1000_ich8lan.h\"\n #include \"e1000_82575.h\"\n #include \"e1000_i210.h\"\n+#include \"e1000_i225.h\"\n \n /* These functions must be implemented by drivers */\n void e1000_pci_clear_mwi(struct e1000_hw *hw);\ndiff --git a/drivers/net/e1000/base/e1000_i225.c b/drivers/net/e1000/base/e1000_i225.c\nnew file mode 100644\nindex 000000000..4ba6c45be\n--- /dev/null\n+++ b/drivers/net/e1000/base/e1000_i225.c\n@@ -0,0 +1,1119 @@\n+#ifndef NO_API_SUPPORT\n+#include \"e1000_api.h\"\n+#else\n+#include \"e1000_hw.h\"\n+#endif /* NO_API_SUPPORT */\n+#ifndef EXTERNAL_RELEASE\n+#ifdef WPP_TRACING_ENABLED\n+#include <e1000_i225.tmh>\n+#endif /* WPP_TRACING_ENABLED */\n+#endif /* EXTERNAL_RELEASE */\n+\n+STATIC s32 e1000_acquire_nvm_i225(struct e1000_hw *hw);\n+STATIC void e1000_release_nvm_i225(struct e1000_hw *hw);\n+STATIC s32 e1000_get_hw_semaphore_i225(struct e1000_hw *hw);\n+#ifndef QV_RELEASE\n+STATIC s32 __e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,\n+\t\t\t\t  u16 *data);\n+#endif /* QV_RELEASE */\n+STATIC s32 e1000_pool_flash_update_done_i225(struct e1000_hw *hw);\n+STATIC s32 e1000_valid_led_default_i225(struct e1000_hw *hw, u16 *data);\n+\n+/* e1000_acquire_nvm_i225 - Request for access to EEPROM\n+ * @hw: pointer to the HW structure\n+ *\n+ * Acquire the necessary semaphores for exclusive access to the EEPROM.\n+ * Set the EEPROM access request bit and wait for EEPROM access grant bit.\n+ * Return successful if access grant bit set, else clear the request for\n+ * EEPROM access and return -E1000_ERR_NVM (-1).\n+ */\n+STATIC s32 e1000_acquire_nvm_i225(struct e1000_hw *hw)\n+{\n+\ts32 ret_val;\n+\n+\tDEBUGFUNC(\"e1000_acquire_nvm_i225\");\n+\n+\tret_val = e1000_acquire_swfw_sync_i225(hw, E1000_SWFW_EEP_SM);\n+\n+\treturn ret_val;\n+}\n+\n+/* e1000_release_nvm_i225 - Release exclusive access to EEPROM\n+ * @hw: pointer to the HW structure\n+ *\n+ * Stop any current commands to the EEPROM and clear the EEPROM request bit,\n+ * then release the semaphores acquired.\n+ */\n+STATIC void e1000_release_nvm_i225(struct e1000_hw *hw)\n+{\n+\tDEBUGFUNC(\"e1000_release_nvm_i225\");\n+\n+\te1000_release_swfw_sync_i225(hw, E1000_SWFW_EEP_SM);\n+}\n+\n+/* e1000_acquire_swfw_sync_i225 - Acquire SW/FW semaphore\n+ * @hw: pointer to the HW structure\n+ * @mask: specifies which semaphore to acquire\n+ *\n+ * Acquire the SW/FW semaphore to access the PHY or NVM.  The mask\n+ * will also specify which port we're acquiring the lock for.\n+ */\n+s32 e1000_acquire_swfw_sync_i225(struct e1000_hw *hw, u16 mask)\n+{\n+\tu32 swfw_sync;\n+\tu32 swmask = mask;\n+\tu32 fwmask = mask << 16;\n+\ts32 ret_val = E1000_SUCCESS;\n+\ts32 i = 0, timeout = 200; /* FIXME: find real value to use here */\n+\n+\tDEBUGFUNC(\"e1000_acquire_swfw_sync_i225\");\n+\n+\twhile (i < timeout) {\n+\t\tif (e1000_get_hw_semaphore_i225(hw)) {\n+\t\t\tret_val = -E1000_ERR_SWFW_SYNC;\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tswfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);\n+\t\tif (!(swfw_sync & (fwmask | swmask)))\n+\t\t\tbreak;\n+\n+\t\t/* Firmware currently using resource (fwmask)\n+\t\t * or other software thread using resource (swmask)\n+\t\t */\n+\t\te1000_put_hw_semaphore_generic(hw);\n+\t\tmsec_delay_irq(5);\n+\t\ti++;\n+\t}\n+\n+\tif (i == timeout) {\n+\t\tDEBUGOUT(\"Driver can't access resource, SW_FW_SYNC timeout.\\n\");\n+\t\tret_val = -E1000_ERR_SWFW_SYNC;\n+\t\tgoto out;\n+\t}\n+\n+\tswfw_sync |= swmask;\n+\tE1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);\n+\n+\te1000_put_hw_semaphore_generic(hw);\n+\n+out:\n+\treturn ret_val;\n+}\n+\n+/* e1000_release_swfw_sync_i225 - Release SW/FW semaphore\n+ * @hw: pointer to the HW structure\n+ * @mask: specifies which semaphore to acquire\n+ *\n+ * Release the SW/FW semaphore used to access the PHY or NVM.  The mask\n+ * will also specify which port we're releasing the lock for.\n+ */\n+void e1000_release_swfw_sync_i225(struct e1000_hw *hw, u16 mask)\n+{\n+\tu32 swfw_sync;\n+\n+\tDEBUGFUNC(\"e1000_release_swfw_sync_i225\");\n+\n+\twhile (e1000_get_hw_semaphore_i225(hw) != E1000_SUCCESS)\n+\t\t; /* Empty */\n+\n+\tswfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);\n+\tswfw_sync &= ~mask;\n+\tE1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);\n+\n+\te1000_put_hw_semaphore_generic(hw);\n+}\n+\n+/* e1000_get_hw_semaphore_i225 - Acquire hardware semaphore\n+ * @hw: pointer to the HW structure\n+ *\n+ * Acquire the HW semaphore to access the PHY or NVM\n+ */\n+STATIC s32 e1000_get_hw_semaphore_i225(struct e1000_hw *hw)\n+{\n+\tu32 swsm;\n+\ts32 timeout = hw->nvm.word_size + 1;\n+\ts32 i = 0;\n+\n+\tDEBUGFUNC(\"e1000_get_hw_semaphore_i225\");\n+\n+\t/* Get the SW semaphore */\n+\twhile (i < timeout) {\n+\t\tswsm = E1000_READ_REG(hw, E1000_SWSM);\n+\t\tif (!(swsm & E1000_SWSM_SMBI))\n+\t\t\tbreak;\n+\n+\t\tusec_delay(50);\n+\t\ti++;\n+\t}\n+\n+\tif (i == timeout) {\n+\t\t/* In rare circumstances, the SW semaphore may already be held\n+\t\t * unintentionally. Clear the semaphore once before giving up.\n+\t\t */\n+\t\tif (hw->dev_spec._82575.clear_semaphore_once) {\n+\t\t\thw->dev_spec._82575.clear_semaphore_once = false;\n+\t\t\te1000_put_hw_semaphore_generic(hw);\n+\t\t\tfor (i = 0; i < timeout; i++) {\n+\t\t\t\tswsm = E1000_READ_REG(hw, E1000_SWSM);\n+\t\t\t\tif (!(swsm & E1000_SWSM_SMBI))\n+\t\t\t\t\tbreak;\n+\n+\t\t\t\tusec_delay(50);\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* If we do not have the semaphore here, we have to give up. */\n+\t\tif (i == timeout) {\n+\t\t\tDEBUGOUT(\"Driver can't access device -\\n\");\n+\t\t\tDEBUGOUT(\"SMBI bit is set.\\n\");\n+\t\t\treturn -E1000_ERR_NVM;\n+\t\t}\n+\t}\n+\n+\t/* Get the FW semaphore. */\n+\tfor (i = 0; i < timeout; i++) {\n+\t\tswsm = E1000_READ_REG(hw, E1000_SWSM);\n+\t\tE1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI);\n+\n+\t\t/* Semaphore acquired if bit latched */\n+\t\tif (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI)\n+\t\t\tbreak;\n+\n+\t\tusec_delay(50);\n+\t}\n+\n+\tif (i == timeout) {\n+\t\t/* Release semaphores */\n+\t\te1000_put_hw_semaphore_generic(hw);\n+\t\tDEBUGOUT(\"Driver can't access the NVM\\n\");\n+\t\treturn -E1000_ERR_NVM;\n+\t}\n+\n+\treturn E1000_SUCCESS;\n+}\n+\n+/* e1000_read_nvm_srrd_i225 - Reads Shadow Ram using EERD register\n+ * @hw: pointer to the HW structure\n+ * @offset: offset of word in the Shadow Ram to read\n+ * @words: number of words to read\n+ * @data: word read from the Shadow Ram\n+ *\n+ * Reads a 16 bit word from the Shadow Ram using the EERD register.\n+ * Uses necessary synchronization semaphores.\n+ */\n+s32 e1000_read_nvm_srrd_i225(struct e1000_hw *hw, u16 offset, u16 words,\n+\t\t\t     u16 *data)\n+{\n+\ts32 status = E1000_SUCCESS;\n+\tu16 i, count;\n+\n+\tDEBUGFUNC(\"e1000_read_nvm_srrd_i225\");\n+\n+\t/* We cannot hold synchronization semaphores for too long,\n+\t * because of forceful takeover procedure. However it is more efficient\n+\t * to read in bursts than synchronizing access for each word.\n+\t */\n+\tfor (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {\n+\t\tcount = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?\n+\t\t\tE1000_EERD_EEWR_MAX_COUNT : (words - i);\n+\t\tif (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {\n+\t\t\tstatus = e1000_read_nvm_eerd(hw, offset, count,\n+\t\t\t\t\t\t     data + i);\n+\t\t\thw->nvm.ops.release(hw);\n+\t\t} else {\n+\t\t\tstatus = E1000_ERR_SWFW_SYNC;\n+\t\t}\n+\n+\t\tif (status != E1000_SUCCESS)\n+\t\t\tbreak;\n+\t}\n+\n+\treturn status;\n+}\n+\n+/* e1000_write_nvm_srwr_i225 - Write to Shadow RAM using EEWR\n+ * @hw: pointer to the HW structure\n+ * @offset: offset within the Shadow RAM to be written to\n+ * @words: number of words to write\n+ * @data: 16 bit word(s) to be written to the Shadow RAM\n+ *\n+ * Writes data to Shadow RAM at offset using EEWR register.\n+ *\n+ * If e1000_update_nvm_checksum is not called after this function , the\n+ * data will not be committed to FLASH and also Shadow RAM will most likely\n+ * contain an invalid checksum.\n+ *\n+ * If error code is returned, data and Shadow RAM may be inconsistent - buffer\n+ * partially written.\n+ */\n+s32 e1000_write_nvm_srwr_i225(struct e1000_hw *hw, u16 offset, u16 words,\n+\t\t\t      u16 *data)\n+{\n+\ts32 status = E1000_SUCCESS;\n+\tu16 i, count;\n+\n+\tDEBUGFUNC(\"e1000_write_nvm_srwr_i225\");\n+\n+\t/* We cannot hold synchronization semaphores for too long,\n+\t * because of forceful takeover procedure. However it is more efficient\n+\t * to write in bursts than synchronizing access for each word.\n+\t */\n+\tfor (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {\n+\t\tcount = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?\n+\t\t\tE1000_EERD_EEWR_MAX_COUNT : (words - i);\n+\t\tif (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {\n+\t\t\tstatus = __e1000_write_nvm_srwr(hw, offset, count,\n+\t\t\t\t\t\t\tdata + i);\n+\t\t\thw->nvm.ops.release(hw);\n+\t\t} else {\n+\t\t\tstatus = E1000_ERR_SWFW_SYNC;\n+\t\t}\n+\n+\t\tif (status != E1000_SUCCESS)\n+\t\t\tbreak;\n+\t}\n+\n+\treturn status;\n+}\n+\n+/* __e1000_write_nvm_srwr - Write to Shadow Ram using EEWR\n+ * @hw: pointer to the HW structure\n+ * @offset: offset within the Shadow Ram to be written to\n+ * @words: number of words to write\n+ * @data: 16 bit word(s) to be written to the Shadow Ram\n+ *\n+ * Writes data to Shadow Ram at offset using EEWR register.\n+ *\n+ * If e1000_update_nvm_checksum is not called after this function , the\n+ * Shadow Ram will most likely contain an invalid checksum.\n+ */\n+STATIC s32 __e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,\n+\t\t\t\t  u16 *data)\n+{\n+\tstruct e1000_nvm_info *nvm = &hw->nvm;\n+\tu32 i, k, eewr = 0;\n+\tu32 attempts = 100000;\n+\ts32 ret_val = E1000_SUCCESS;\n+\n+\tDEBUGFUNC(\"__e1000_write_nvm_srwr\");\n+\n+\t/* A check for invalid values:  offset too large, too many words,\n+\t * too many words for the offset, and not enough words.\n+\t */\n+\tif ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||\n+\t    (words == 0)) {\n+\t\tDEBUGOUT(\"nvm parameter(s) out of bounds\\n\");\n+\t\tret_val = -E1000_ERR_NVM;\n+\t\tgoto out;\n+\t}\n+\n+\tfor (i = 0; i < words; i++) {\n+\t\teewr = ((offset + i) << E1000_NVM_RW_ADDR_SHIFT) |\n+\t\t\t(data[i] << E1000_NVM_RW_REG_DATA) |\n+\t\t\tE1000_NVM_RW_REG_START;\n+\n+\t\tE1000_WRITE_REG(hw, E1000_SRWR, eewr);\n+\n+\t\tfor (k = 0; k < attempts; k++) {\n+\t\t\tif (E1000_NVM_RW_REG_DONE &\n+\t\t\t    E1000_READ_REG(hw, E1000_SRWR)) {\n+\t\t\t\tret_val = E1000_SUCCESS;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tusec_delay(5);\n+\t\t}\n+\n+\t\tif (ret_val != E1000_SUCCESS) {\n+\t\t\tDEBUGOUT(\"Shadow RAM write EEWR timed out\\n\");\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+out:\n+\treturn ret_val;\n+}\n+\n+/* e1000_read_invm_word_i225 - Reads OTP\n+ * @hw: pointer to the HW structure\n+ * @address: the word address (aka eeprom offset) to read\n+ * @data: pointer to the data read\n+ *\n+ * Reads 16-bit words from the OTP. Return error when the word is not\n+ * stored in OTP.\n+ */\n+STATIC s32 e1000_read_invm_word_i225(struct e1000_hw *hw, u8 address, u16 *data)\n+{\n+\ts32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;\n+\tu32 invm_dword;\n+\tu16 i;\n+\tu8 record_type, word_address;\n+\n+\tDEBUGFUNC(\"e1000_read_invm_word_i225\");\n+\n+\tfor (i = 0; i < E1000_INVM_SIZE; i++) {\n+\t\tinvm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i));\n+\t\t/* Get record type */\n+\t\trecord_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);\n+\t\tif (record_type == e1000_invm_unitialized_structure)\n+\t\t\tbreak;\n+\t\tif (record_type == e1000_invm_csr_autoload_structure)\n+\t\t\ti += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;\n+\t\tif (record_type == e1000_invm_rsa_key_sha256_structure)\n+\t\t\ti += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;\n+\t\tif (record_type == e1000_invm_word_autoload_structure) {\n+\t\t\tword_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);\n+\t\t\tif (word_address == address) {\n+\t\t\t\t*data = INVM_DWORD_TO_WORD_DATA(invm_dword);\n+\t\t\t\tDEBUGOUT2(\"Read INVM Word 0x%02x = %x\",\n+\t\t\t\t\t  address, *data);\n+\t\t\t\tstatus = E1000_SUCCESS;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+\tif (status != E1000_SUCCESS)\n+\t\tDEBUGOUT1(\"Requested word 0x%02x not found in OTP\\n\", address);\n+\treturn status;\n+}\n+\n+/* e1000_read_invm_i225 - Read invm wrapper function for I225\n+ * @hw: pointer to the HW structure\n+ * @address: the word address (aka eeprom offset) to read\n+ * @data: pointer to the data read\n+ *\n+ * Wrapper function to return data formerly found in the NVM.\n+ */\n+STATIC s32 e1000_read_invm_i225(struct e1000_hw *hw, u16 offset,\n+\t\t\t\tu16 E1000_UNUSEDARG words, u16 *data)\n+{\n+\ts32 ret_val = E1000_SUCCESS;\n+\n+\tUNREFERENCED_1PARAMETER(words);\n+\n+\tDEBUGFUNC(\"e1000_read_invm_i225\");\n+\n+\t/* Only the MAC addr is required to be present in the iNVM */\n+\tswitch (offset) {\n+\tcase NVM_MAC_ADDR:\n+\t\tret_val = e1000_read_invm_word_i225(hw, (u8)offset, &data[0]);\n+\t\tret_val |= e1000_read_invm_word_i225(hw, (u8)offset + 1,\n+\t\t\t\t\t\t     &data[1]);\n+\t\tret_val |= e1000_read_invm_word_i225(hw, (u8)offset + 2,\n+\t\t\t\t\t\t     &data[2]);\n+\t\tif (ret_val != E1000_SUCCESS)\n+\t\t\tDEBUGOUT(\"MAC Addr not found in iNVM\\n\");\n+\t\tbreak;\n+\tcase NVM_INIT_CTRL_2:\n+\t\tret_val = e1000_read_invm_word_i225(hw, (u8)offset, data);\n+\t\tif (ret_val != E1000_SUCCESS) {\n+\t\t\t*data = NVM_INIT_CTRL_2_DEFAULT_I225;\n+\t\t\tret_val = E1000_SUCCESS;\n+\t\t}\n+\t\tbreak;\n+\tcase NVM_INIT_CTRL_4:\n+\t\tret_val = e1000_read_invm_word_i225(hw, (u8)offset, data);\n+\t\tif (ret_val != E1000_SUCCESS) {\n+\t\t\t*data = NVM_INIT_CTRL_4_DEFAULT_I225;\n+\t\t\tret_val = E1000_SUCCESS;\n+\t\t}\n+\t\tbreak;\n+\tcase NVM_LED_1_CFG:\n+\t\tret_val = e1000_read_invm_word_i225(hw, (u8)offset, data);\n+\t\tif (ret_val != E1000_SUCCESS) {\n+\t\t\t*data = NVM_LED_1_CFG_DEFAULT_I225;\n+\t\t\tret_val = E1000_SUCCESS;\n+\t\t}\n+\t\tbreak;\n+\tcase NVM_LED_0_2_CFG:\n+\t\tret_val = e1000_read_invm_word_i225(hw, (u8)offset, data);\n+\t\tif (ret_val != E1000_SUCCESS) {\n+\t\t\t*data = NVM_LED_0_2_CFG_DEFAULT_I225;\n+\t\t\tret_val = E1000_SUCCESS;\n+\t\t}\n+\t\tbreak;\n+\tcase NVM_ID_LED_SETTINGS:\n+\t\tret_val = e1000_read_invm_word_i225(hw, (u8)offset, data);\n+\t\tif (ret_val != E1000_SUCCESS) {\n+\t\t\t*data = ID_LED_RESERVED_FFFF;\n+\t\t\tret_val = E1000_SUCCESS;\n+\t\t}\n+\t\tbreak;\n+\tcase NVM_SUB_DEV_ID:\n+\t\t*data = hw->subsystem_device_id;\n+\t\tbreak;\n+\tcase NVM_SUB_VEN_ID:\n+\t\t*data = hw->subsystem_vendor_id;\n+\t\tbreak;\n+\tcase NVM_DEV_ID:\n+\t\t*data = hw->device_id;\n+\t\tbreak;\n+\tcase NVM_VEN_ID:\n+\t\t*data = hw->vendor_id;\n+\t\tbreak;\n+\tdefault:\n+\t\tDEBUGOUT1(\"NVM word 0x%02x is not mapped.\\n\", offset);\n+\t\t*data = NVM_RESERVED_WORD;\n+\t\tbreak;\n+\t}\n+\treturn ret_val;\n+}\n+\n+#if defined(NVM_VERSION_SUPPORT) || defined(QV_RELEASE)\n+/* e1000_read_invm_version_i225 - Reads iNVM version and image type\n+ * @hw: pointer to the HW structure\n+ * @invm_ver: version structure for the version read\n+ *\n+ * Reads iNVM version and image type.\n+ */\n+s32 e1000_read_invm_version_i225(struct e1000_hw *hw,\n+\t\t\t\t struct e1000_fw_version *invm_ver)\n+{\n+\tu32 *record = NULL;\n+\tu32 *next_record = NULL;\n+\tu32 i = 0;\n+\tu32 invm_dword = 0;\n+\tu32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE /\n+\t\t\t\t\t     E1000_INVM_RECORD_SIZE_IN_BYTES);\n+\tu32 buffer[E1000_INVM_SIZE];\n+\ts32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;\n+\tu16 version = 0;\n+\n+\tDEBUGFUNC(\"e1000_read_invm_version_i225\");\n+\n+\t/* Read iNVM memory */\n+\tfor (i = 0; i < E1000_INVM_SIZE; i++) {\n+\t\tinvm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i));\n+\t\tbuffer[i] = invm_dword;\n+\t}\n+\n+\t/* Read version number */\n+\tfor (i = 1; i < invm_blocks; i++) {\n+\t\trecord = &buffer[invm_blocks - i];\n+\t\tnext_record = &buffer[invm_blocks - i + 1];\n+\n+\t\t/* Check if we have first version location used */\n+\t\tif ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) {\n+\t\t\tversion = 0;\n+\t\t\tstatus = E1000_SUCCESS;\n+\t\t\tbreak;\n+\t\t}\n+\t\t/* Check if we have second version location used */\n+\t\telse if ((i == 1) &&\n+\t\t\t ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) {\n+\t\t\tversion = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;\n+\t\t\tstatus = E1000_SUCCESS;\n+\t\t\tbreak;\n+\t\t}\n+\t\t/* Check if we have odd version location\n+\t\t * used and it is the last one used\n+\t\t */\n+\t\telse if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) &&\n+\t\t\t  ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) &&\n+\t\t\t   (i != 1))) {\n+\t\t\tversion = (*next_record & E1000_INVM_VER_FIELD_TWO)\n+\t\t\t\t  >> 13;\n+\t\t\tstatus = E1000_SUCCESS;\n+\t\t\tbreak;\n+\t\t}\n+\t\t/* Check if we have even version location\n+\t\t * used and it is the last one used\n+\t\t */\n+\t\telse if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) &&\n+\t\t\t ((*record & 0x3) == 0)) {\n+\t\t\tversion = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;\n+\t\t\tstatus = E1000_SUCCESS;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (status == E1000_SUCCESS) {\n+\t\tinvm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK)\n+\t\t\t\t\t>> E1000_INVM_MAJOR_SHIFT;\n+\t\tinvm_ver->invm_minor = version & E1000_INVM_MINOR_MASK;\n+\t}\n+\t/* Read Image Type */\n+\tfor (i = 1; i < invm_blocks; i++) {\n+\t\trecord = &buffer[invm_blocks - i];\n+\t\tnext_record = &buffer[invm_blocks - i + 1];\n+\n+\t\t/* Check if we have image type in first location used */\n+\t\tif ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) {\n+\t\t\tinvm_ver->invm_img_type = 0;\n+\t\t\tstatus = E1000_SUCCESS;\n+\t\t\tbreak;\n+\t\t}\n+\t\t/* Check if we have image type in first location used */\n+\t\telse if ((((*record & 0x3) == 0) &&\n+\t\t\t  ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) ||\n+\t\t\t    ((((*record & 0x3) != 0) && (i != 1)))) {\n+\t\t\tinvm_ver->invm_img_type =\n+\t\t\t\t(*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23;\n+\t\t\tstatus = E1000_SUCCESS;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\treturn status;\n+}\n+\n+#endif /* NVM_VERSION_SUPPORT or QV_RELEASE */\n+/* e1000_validate_nvm_checksum_i225 - Validate EEPROM checksum\n+ * @hw: pointer to the HW structure\n+ *\n+ * Calculates the EEPROM checksum by reading/adding each word of the EEPROM\n+ * and then verifies that the sum of the EEPROM is equal to 0xBABA.\n+ */\n+s32 e1000_validate_nvm_checksum_i225(struct e1000_hw *hw)\n+{\n+\ts32 status = E1000_SUCCESS;\n+\ts32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);\n+\n+\tDEBUGFUNC(\"e1000_validate_nvm_checksum_i225\");\n+\n+\tif (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {\n+\t\t/* Replace the read function with semaphore grabbing with\n+\t\t * the one that skips this for a while.\n+\t\t * We have semaphore taken already here.\n+\t\t */\n+\t\tread_op_ptr = hw->nvm.ops.read;\n+\t\thw->nvm.ops.read = e1000_read_nvm_eerd;\n+\n+\t\tstatus = e1000_validate_nvm_checksum_generic(hw);\n+\n+\t\t/* Revert original read operation. */\n+\t\thw->nvm.ops.read = read_op_ptr;\n+\n+\t\thw->nvm.ops.release(hw);\n+\t} else {\n+\t\tstatus = E1000_ERR_SWFW_SYNC;\n+\t}\n+\n+\treturn status;\n+}\n+\n+/* e1000_update_nvm_checksum_i225 - Update EEPROM checksum\n+ * @hw: pointer to the HW structure\n+ *\n+ * Updates the EEPROM checksum by reading/adding each word of the EEPROM\n+ * up to the checksum.  Then calculates the EEPROM checksum and writes the\n+ * value to the EEPROM. Next commit EEPROM data onto the Flash.\n+ */\n+s32 e1000_update_nvm_checksum_i225(struct e1000_hw *hw)\n+{\n+\ts32 ret_val;\n+\tu16 checksum = 0;\n+\tu16 i, nvm_data;\n+\n+\tDEBUGFUNC(\"e1000_update_nvm_checksum_i225\");\n+\n+\t/* Read the first word from the EEPROM. If this times out or fails, do\n+\t * not continue or we could be in for a very long wait while every\n+\t * EEPROM read fails\n+\t */\n+\tret_val = e1000_read_nvm_eerd(hw, 0, 1, &nvm_data);\n+\tif (ret_val != E1000_SUCCESS) {\n+\t\tDEBUGOUT(\"EEPROM read failed\\n\");\n+\t\tgoto out;\n+\t}\n+\n+\tif (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {\n+\t\t/* Do not use hw->nvm.ops.write, hw->nvm.ops.read\n+\t\t * because we do not want to take the synchronization\n+\t\t * semaphores twice here.\n+\t\t */\n+\n+\t\tfor (i = 0; i < NVM_CHECKSUM_REG; i++) {\n+\t\t\tret_val = e1000_read_nvm_eerd(hw, i, 1, &nvm_data);\n+\t\t\tif (ret_val) {\n+\t\t\t\thw->nvm.ops.release(hw);\n+\t\t\t\tDEBUGOUT(\"NVM Read Error while updating\\n\");\n+\t\t\t\tDEBUGOUT(\"checksum.\\n\");\n+\t\t\t\tgoto out;\n+\t\t\t}\n+\t\t\tchecksum += nvm_data;\n+\t\t}\n+\t\tchecksum = (u16)NVM_SUM - checksum;\n+\t\tret_val = __e1000_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,\n+\t\t\t\t\t\t &checksum);\n+\t\tif (ret_val != E1000_SUCCESS) {\n+\t\t\thw->nvm.ops.release(hw);\n+\t\t\tDEBUGOUT(\"NVM Write Error while updating checksum.\\n\");\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\thw->nvm.ops.release(hw);\n+\n+\t\tret_val = e1000_update_flash_i225(hw);\n+\t} else {\n+\t\tret_val = E1000_ERR_SWFW_SYNC;\n+\t}\n+out:\n+\treturn ret_val;\n+}\n+\n+/* e1000_get_flash_presence_i225 - Check if flash device is detected.\n+ * @hw: pointer to the HW structure\n+ */\n+bool e1000_get_flash_presence_i225(struct e1000_hw *hw)\n+{\n+\tu32 eec = 0;\n+\tbool ret_val = false;\n+\n+\tDEBUGFUNC(\"e1000_get_flash_presence_i225\");\n+\n+\teec = E1000_READ_REG(hw, E1000_EECD);\n+\n+\tif (eec & E1000_EECD_FLASH_DETECTED_I225)\n+\t\tret_val = true;\n+\n+\treturn ret_val;\n+}\n+\n+/* e1000_update_flash_i225 - Commit EEPROM to the flash\n+ * @hw: pointer to the HW structure\n+ */\n+s32 e1000_update_flash_i225(struct e1000_hw *hw)\n+{\n+\ts32 ret_val;\n+\tu32 flup;\n+\n+\tDEBUGFUNC(\"e1000_update_flash_i225\");\n+\n+\tret_val = e1000_pool_flash_update_done_i225(hw);\n+\tif (ret_val == -E1000_ERR_NVM) {\n+\t\tDEBUGOUT(\"Flash update time out\\n\");\n+\t\tgoto out;\n+\t}\n+\n+\tflup = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD_I225;\n+\tE1000_WRITE_REG(hw, E1000_EECD, flup);\n+\n+\tret_val = e1000_pool_flash_update_done_i225(hw);\n+\tif (ret_val == E1000_SUCCESS)\n+\t\tDEBUGOUT(\"Flash update complete\\n\");\n+\telse\n+\t\tDEBUGOUT(\"Flash update time out\\n\");\n+\n+out:\n+\treturn ret_val;\n+}\n+\n+/* e1000_pool_flash_update_done_i225 - Pool FLUDONE status.\n+ * @hw: pointer to the HW structure\n+ */\n+s32 e1000_pool_flash_update_done_i225(struct e1000_hw *hw)\n+{\n+\ts32 ret_val = -E1000_ERR_NVM;\n+\tu32 i, reg;\n+\n+\tDEBUGFUNC(\"e1000_pool_flash_update_done_i225\");\n+\n+\tfor (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {\n+\t\treg = E1000_READ_REG(hw, E1000_EECD);\n+\t\tif (reg & E1000_EECD_FLUDONE_I225) {\n+\t\t\tret_val = E1000_SUCCESS;\n+\t\t\tbreak;\n+\t\t}\n+\t\tusec_delay(5);\n+\t}\n+\n+\treturn ret_val;\n+}\n+\n+/* e1000_init_nvm_params_i225 - Initialize i225 NVM function pointers\n+ * @hw: pointer to the HW structure\n+ *\n+ * Initialize the i225/i211 NVM parameters and function pointers.\n+ */\n+STATIC s32 e1000_init_nvm_params_i225(struct e1000_hw *hw)\n+{\n+\ts32 ret_val;\n+\tstruct e1000_nvm_info *nvm = &hw->nvm;\n+\n+\tDEBUGFUNC(\"e1000_init_nvm_params_i225\");\n+\n+\tret_val = e1000_init_nvm_params_82575(hw);\n+\tnvm->ops.acquire = e1000_acquire_nvm_i225;\n+\tnvm->ops.release = e1000_release_nvm_i225;\n+\tnvm->ops.valid_led_default = e1000_valid_led_default_i225;\n+\tif (e1000_get_flash_presence_i225(hw)) {\n+\t\thw->nvm.type = e1000_nvm_flash_hw;\n+\t\tnvm->ops.read    = e1000_read_nvm_srrd_i225;\n+\t\tnvm->ops.write   = e1000_write_nvm_srwr_i225;\n+\t\tnvm->ops.validate = e1000_validate_nvm_checksum_i225;\n+\t\tnvm->ops.update   = e1000_update_nvm_checksum_i225;\n+\t} else {\n+\t\thw->nvm.type = e1000_nvm_invm;\n+\t\tnvm->ops.read     = e1000_read_invm_i225;\n+#ifndef NO_NULL_OPS_SUPPORT\n+\t\tnvm->ops.write    = e1000_null_write_nvm;\n+\t\tnvm->ops.validate = e1000_null_ops_generic;\n+\t\tnvm->ops.update   = e1000_null_ops_generic;\n+#else\n+\t\tnvm->ops.write    = NULL;\n+\t\tnvm->ops.validate = NULL;\n+\t\tnvm->ops.update   = NULL;\n+#endif /* NO_NULL_OPS_SUPPORT */\n+\t}\n+\treturn ret_val;\n+}\n+\n+#ifdef I225_LTR_SUPPORT\n+/* e1000_set_ltr_i225 - Set Latency Tolerance Reporting thresholds.\n+ * @hw: pointer to the HW structure\n+ * @link: bool indicating link status\n+ *\n+ * Set the LTR thresholds based on the link speed (Mbps), EEE, and DMAC\n+ * settings, otherwise specify that there is no LTR requirement.\n+ */\n+STATIC s32 e1000_set_ltr_i225(struct e1000_hw *hw, bool link)\n+{\n+\tu16 speed, duplex;\n+\tu32 tw_system, ltrc, ltrv, ltr_min, ltr_max, scale_min, scale_max;\n+\ts32 size;\n+\n+\tDEBUGFUNC(\"e1000_set_ltr_i225\");\n+\n+\t/* If we do not have link, LTR thresholds are zero. */\n+\tif (link) {\n+\t\thw->mac.ops.get_link_up_info(hw, &speed, &duplex);\n+\n+\t\t/* Check if using copper interface with EEE enabled or if the\n+\t\t * link speed is 10 Mbps.\n+\t\t */\n+\t\tif ((hw->phy.media_type == e1000_media_type_copper) &&\n+\t\t    !(hw->dev_spec._82575.eee_disable) &&\n+\t\t     (speed != SPEED_10)) {\n+\t\t\t/* EEE enabled, so send LTRMAX threshold. */\n+\t\t\tltrc = E1000_READ_REG(hw, E1000_LTRC) |\n+\t\t\t\tE1000_LTRC_EEEMS_EN;\n+\t\t\tE1000_WRITE_REG(hw, E1000_LTRC, ltrc);\n+\n+\t\t\t/* Calculate tw_system (nsec). */\n+\t\t\tif (speed == SPEED_100) {\n+\t\t\t\ttw_system = ((E1000_READ_REG(hw, E1000_EEE_SU) &\n+\t\t\t\t\t     E1000_TW_SYSTEM_100_MASK) >>\n+\t\t\t\t\t     E1000_TW_SYSTEM_100_SHIFT) * 500;\n+\t\t\t} else {\n+\t\t\t\ttw_system = (E1000_READ_REG(hw, E1000_EEE_SU) &\n+\t\t\t\t\t     E1000_TW_SYSTEM_1000_MASK) * 500;\n+\t\t\t\t}\n+\t\t} else {\n+\t\t\ttw_system = 0;\n+\t\t\t}\n+\n+\t\t/* Get the Rx packet buffer size. */\n+\t\tsize = E1000_READ_REG(hw, E1000_RXPBS) &\n+\t\t\tE1000_RXPBS_SIZE_I225_MASK;\n+\n+\t\t/* Calculations vary based on DMAC settings. */\n+\t\tif (E1000_READ_REG(hw, E1000_DMACR) & E1000_DMACR_DMAC_EN) {\n+\t\t\tsize -= (E1000_READ_REG(hw, E1000_DMACR) &\n+\t\t\t\t E1000_DMACR_DMACTHR_MASK) >>\n+\t\t\t\t E1000_DMACR_DMACTHR_SHIFT;\n+\t\t\t/* Convert size to bits. */\n+\t\t\tsize *= 1024 * 8;\n+\t\t} else {\n+\t\t\t/* Convert size to bytes, subtract the MTU, and then\n+\t\t\t * convert the size to bits.\n+\t\t\t */\n+\t\t\tsize *= 1024;\n+\t\t\tsize -= hw->dev_spec._82575.mtu;\n+\t\t\tsize *= 8;\n+\t\t}\n+\n+\t\tif (size < 0) {\n+\t\t\tDEBUGOUT1(\"Invalid effective Rx buffer size %d\\n\",\n+\t\t\t\t  size);\n+\t\t\treturn -E1000_ERR_CONFIG;\n+\t\t}\n+\n+\t\t/* Calculate the thresholds. Since speed is in Mbps, simplify\n+\t\t * the calculation by multiplying size/speed by 1000 for result\n+\t\t * to be in nsec before dividing by the scale in nsec. Set the\n+\t\t * scale such that the LTR threshold fits in the register.\n+\t\t */\n+\t\tltr_min = (1000 * size) / speed;\n+\t\tltr_max = ltr_min + tw_system;\n+\t\tscale_min = (ltr_min / 1024) < 1024 ? E1000_LTRMINV_SCALE_1024 :\n+\t\t\t    E1000_LTRMINV_SCALE_32768;\n+\t\tscale_max = (ltr_max / 1024) < 1024 ? E1000_LTRMAXV_SCALE_1024 :\n+\t\t\t    E1000_LTRMAXV_SCALE_32768;\n+\t\tltr_min /= scale_min == E1000_LTRMINV_SCALE_1024 ? 1024 : 32768;\n+\t\tltr_max /= scale_max == E1000_LTRMAXV_SCALE_1024 ? 1024 : 32768;\n+\n+\t\t/* Only write the LTR thresholds if they differ from before. */\n+\t\tltrv = E1000_READ_REG(hw, E1000_LTRMINV);\n+\t\tif (ltr_min != (ltrv & E1000_LTRMINV_LTRV_MASK)) {\n+\t\t\tltrv = E1000_LTRMINV_LSNP_REQ | ltr_min |\n+\t\t\t      (scale_min << E1000_LTRMINV_SCALE_SHIFT);\n+\t\t\tE1000_WRITE_REG(hw, E1000_LTRMINV, ltrv);\n+\t\t}\n+\n+\t\tltrv = E1000_READ_REG(hw, E1000_LTRMAXV);\n+\t\tif (ltr_max != (ltrv & E1000_LTRMAXV_LTRV_MASK)) {\n+\t\t\tltrv = E1000_LTRMAXV_LSNP_REQ | ltr_max |\n+\t\t\t      (scale_min << E1000_LTRMAXV_SCALE_SHIFT);\n+\t\t\tE1000_WRITE_REG(hw, E1000_LTRMAXV, ltrv);\n+\t\t}\n+\t}\n+\n+\treturn E1000_SUCCESS;\n+}\n+\n+/* e1000_check_for_link_i225 - Check for link\n+ * @hw: pointer to the HW structure\n+ *\n+ * Checks to see of the link status of the hardware has changed.  If a\n+ * change in link status has been detected, then we read the PHY registers\n+ * to get the current speed/duplex if link exists.\n+ */\n+s32 e1000_check_for_link_i225(struct e1000_hw *hw)\n+{\n+\tstruct e1000_mac_info *mac = &hw->mac;\n+\ts32 ret_val;\n+\tbool link = false;\n+\n+\tDEBUGFUNC(\"e1000_check_for_link_i225\");\n+\n+\tif (hw->phy.media_type != e1000_media_type_copper) {\n+\t\tu16 speed, duplex;\n+\n+\t\tret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed,\n+\t\t\t\t\t\t\t       &duplex);\n+\t\t/* Use this flag to determine if link needs to be checked or\n+\t\t * not.  If we have link clear the flag so that we do not\n+\t\t * continue to check for link.\n+\t\t */\n+\t\thw->mac.get_link_status = !hw->mac.serdes_has_link;\n+\n+\t\tlink = hw->mac.serdes_has_link;\n+\t} else {\n+\t\t/* We only want to go out to the PHY registers to see if\n+\t\t * Auto-Neg has completed and/or if our link status has\n+\t\t * changed.  The get_link_status flag is set upon receiving\n+\t\t * a Link Status Change or Rx Sequence Error interrupt.\n+\t\t */\n+\t\tif (!mac->get_link_status) {\n+\t\t\tret_val = E1000_SUCCESS;\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\t/* First we want to see if the MII Status Register reports\n+\t\t * link.  If so, then we want to get the current speed/duplex\n+\t\t * of the PHY.\n+\t\t */\n+\t\tret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);\n+\t\tif (ret_val)\n+\t\t\tgoto out;\n+\n+\t\tif (!link)\n+\t\t\tgoto out; /* No link detected */\n+\n+\t\tmac->get_link_status = false;\n+\n+\t\t/* Check if there was DownShift, must be checked\n+\t\t * immediately after link-up\n+\t\t */\n+\t\te1000_check_downshift_generic(hw);\n+\n+\t\t/* If we are forcing speed/duplex, then we simply return since\n+\t\t * we have already determined whether we have link or not.\n+\t\t */\n+\t\tif (!mac->autoneg) {\n+\t\t\tret_val = -E1000_ERR_CONFIG;\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\t/* Auto-Neg is enabled.  Auto Speed Detection takes care\n+\t\t * of MAC speed/duplex configuration.  So we only need to\n+\t\t * configure Collision Distance in the MAC.\n+\t\t */\n+\t\tmac->ops.config_collision_dist(hw);\n+\n+\t\t/* Configure Flow Control now that Auto-Neg has completed.\n+\t\t * First, we need to restore the desired flow control\n+\t\t * settings because we may have had to re-autoneg with a\n+\t\t * different link partner.\n+\t\t */\n+\t\tret_val = e1000_config_fc_after_link_up_generic(hw);\n+\t\tif (ret_val)\n+\t\t\tDEBUGOUT(\"Error configuring flow control\\n\");\n+\t}\n+\n+out:\n+\t/* Now that we are aware of our link settings, we can set the LTR\n+\t * thresholds.\n+\t */\n+\tret_val = e1000_set_ltr_i225(hw, link);\n+\n+\treturn ret_val;\n+}\n+\n+#endif /* I225_LTR_SUPPORT */\n+/* e1000_init_function_pointers_i225 - Init func ptrs.\n+ * @hw: pointer to the HW structure\n+ *\n+ * Called to initialize all function pointers and parameters.\n+ */\n+void e1000_init_function_pointers_i225(struct e1000_hw *hw)\n+{\n+\te1000_init_function_pointers_82575(hw);\n+\thw->nvm.ops.init_params = e1000_init_nvm_params_i225;\n+}\n+\n+/* e1000_valid_led_default_i225 - Verify a valid default LED config\n+ * @hw: pointer to the HW structure\n+ * @data: pointer to the NVM (EEPROM)\n+ *\n+ * Read the EEPROM for the current default LED configuration.  If the\n+ * LED configuration is not valid, set to a valid LED configuration.\n+ */\n+STATIC s32 e1000_valid_led_default_i225(struct e1000_hw *hw, u16 *data)\n+{\n+\ts32 ret_val;\n+\n+\tDEBUGFUNC(\"e1000_valid_led_default_i225\");\n+\n+\tret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);\n+\tif (ret_val) {\n+\t\tDEBUGOUT(\"NVM Read Error\\n\");\n+\t\tgoto out;\n+\t}\n+\n+\tif (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {\n+\t\tswitch (hw->phy.media_type) {\n+\t\tcase e1000_media_type_internal_serdes:\n+\t\t\t*data = ID_LED_DEFAULT_I225_SERDES;\n+\t\t\tbreak;\n+\t\tcase e1000_media_type_copper:\n+\t\tdefault:\n+\t\t\t*data = ID_LED_DEFAULT_I225;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+#ifndef QV_RELEASE\n+out:\n+#endif /* QV_RELEASE */\n+\treturn ret_val;\n+}\n+\n+/* e1000_pll_workaround_i225\n+ * @hw: pointer to the HW structure\n+ *\n+ * Works around an errata in the PLL circuit where it occasionally\n+ * provides the wrong clock frequency after power up.\n+ */\n+STATIC s32 e1000_pll_workaround_i225(struct e1000_hw *hw)\n+{\n+\ts32 ret_val;\n+\tu32 wuc, mdicnfg, ctrl, ctrl_ext, reg_val;\n+\tu16 nvm_word, phy_word, pci_word, tmp_nvm;\n+\tint i;\n+\n+\t/* Get PHY semaphore */\n+\thw->phy.ops.acquire(hw);\n+\t/* Get and set needed register values */\n+\twuc = E1000_READ_REG(hw, E1000_WUC);\n+\tmdicnfg = E1000_READ_REG(hw, E1000_MDICNFG);\n+\treg_val = mdicnfg & ~E1000_MDICNFG_EXT_MDIO;\n+\tE1000_WRITE_REG(hw, E1000_MDICNFG, reg_val);\n+\n+\t/* Get data from NVM, or set default */\n+\tret_val = e1000_read_invm_word_i225(hw, E1000_INVM_AUTOLOAD,\n+\t\t\t\t\t    &nvm_word);\n+\tif (ret_val != E1000_SUCCESS)\n+\t\tnvm_word = E1000_INVM_DEFAULT_AL;\n+\ttmp_nvm = nvm_word | E1000_INVM_PLL_WO_VAL;\n+\tfor (i = 0; i < E1000_MAX_PLL_TRIES; i++) {\n+\t\t/* check current state directly from internal PHY */\n+\t\te1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, 0xFC);\n+\t\tusec_delay(20);\n+\t\te1000_read_phy_reg_mdic(hw, E1000_PHY_PLL_FREQ_REG, &phy_word);\n+\t\tusec_delay(20);\n+\t\te1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, 0);\n+\t\tif ((phy_word & E1000_PHY_PLL_UNCONF)\n+\t\t    != E1000_PHY_PLL_UNCONF) {\n+\t\t\tret_val = E1000_SUCCESS;\n+\t\t} else {\n+\t\t\tret_val = -E1000_ERR_PHY;\n+\t\t}\n+\t\t/* directly reset the internal PHY */\n+\t\tctrl = E1000_READ_REG(hw, E1000_CTRL);\n+\t\tE1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST);\n+\n+\t\tctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);\n+\t\tctrl_ext |= (E1000_CTRL_EXT_PHYPDEN | E1000_CTRL_EXT_SDLPE);\n+\t\tE1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);\n+\n+\t\tE1000_WRITE_REG(hw, E1000_WUC, 0);\n+\t\treg_val = (E1000_INVM_AUTOLOAD << 4) | (tmp_nvm << 16);\n+\t\tE1000_WRITE_REG(hw, E1000_EEARBC_I225, reg_val);\n+\n+\t\te1000_read_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);\n+\t\tpci_word |= E1000_PCI_PMCSR_D3;\n+\t\te1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);\n+\t\tmsec_delay(1);\n+\t\tpci_word &= ~E1000_PCI_PMCSR_D3;\n+\t\te1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);\n+\t\treg_val = (E1000_INVM_AUTOLOAD << 4) | (nvm_word << 16);\n+\t\tE1000_WRITE_REG(hw, E1000_EEARBC_I225, reg_val);\n+\n+\t\t/* restore WUC register */\n+\t\tE1000_WRITE_REG(hw, E1000_WUC, wuc);\n+\t}\n+\t/* restore MDICNFG setting */\n+\tE1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg);\n+\t/* Release PHY semaphore */\n+\thw->phy.ops.release(hw);\n+\treturn ret_val;\n+}\n+\n+/* e1000_get_cfg_done_i225 - Read config done bit\n+ * @hw: pointer to the HW structure\n+ *\n+ * Read the management control register for the config done bit for\n+ * completion status.  NOTE: silicon which is EEPROM-less will fail trying\n+ * to read the config done bit, so an error is *ONLY* logged and returns\n+ * E1000_SUCCESS.  If we were to return with error, EEPROM-less silicon\n+ * would not be able to be reset or change link.\n+ */\n+STATIC s32 e1000_get_cfg_done_i225(struct e1000_hw *hw)\n+{\n+\ts32 timeout = PHY_CFG_TIMEOUT;\n+\tu32 mask = E1000_NVM_CFG_DONE_PORT_0;\n+\n+\tDEBUGFUNC(\"e1000_get_cfg_done_i225\");\n+\n+\twhile (timeout) {\n+\t\tif (E1000_READ_REG(hw, E1000_EEMNGCTL_I225) & mask)\n+\t\t\tbreak;\n+\t\tmsec_delay(1);\n+\t\ttimeout--;\n+\t}\n+\tif (!timeout)\n+\t\tDEBUGOUT(\"MNG configuration cycle has not completed.\\n\");\n+\n+\treturn E1000_SUCCESS;\n+}\n+\n+/* e1000_init_hw_i225 - Init hw for I225\n+ * @hw: pointer to the HW structure\n+ *\n+ * Called to initialize hw for i225 hw family.\n+ */\n+s32 e1000_init_hw_i225(struct e1000_hw *hw)\n+{\n+\ts32 ret_val;\n+\n+\tDEBUGFUNC(\"e1000_init_hw_i225\");\n+\tif ((hw->mac.type >= e1000_i225) &&\n+\t    !(e1000_get_flash_presence_i225(hw))) {\n+\t\tret_val = e1000_pll_workaround_i225(hw);\n+\t\tif (ret_val != E1000_SUCCESS)\n+\t\t\treturn ret_val;\n+\t}\n+\thw->phy.ops.get_cfg_done = e1000_get_cfg_done_i225;\n+\tret_val = e1000_init_hw_82575(hw);\n+\treturn ret_val;\n+}\ndiff --git a/drivers/net/e1000/base/e1000_i225.h b/drivers/net/e1000/base/e1000_i225.h\nnew file mode 100644\nindex 000000000..f13a7bbde\n--- /dev/null\n+++ b/drivers/net/e1000/base/e1000_i225.h\n@@ -0,0 +1,105 @@\n+#ifndef _E1000_I225_H_\n+#define _E1000_I225_H_\n+\n+bool e1000_get_flash_presence_i225(struct e1000_hw *hw);\n+s32 e1000_update_flash_i225(struct e1000_hw *hw);\n+s32 e1000_update_nvm_checksum_i225(struct e1000_hw *hw);\n+s32 e1000_validate_nvm_checksum_i225(struct e1000_hw *hw);\n+s32 e1000_write_nvm_srwr_i225(struct e1000_hw *hw, u16 offset,\n+\t\t\t      u16 words, u16 *data);\n+s32 e1000_read_nvm_srrd_i225(struct e1000_hw *hw, u16 offset,\n+\t\t\t     u16 words, u16 *data);\n+s32 e1000_read_invm_version_i225(struct e1000_hw *hw,\n+\t\t\t\t struct e1000_fw_version *invm_ver);\n+s32 e1000_set_flsw_flash_burst_counter_i225(struct e1000_hw *hw,\n+\t\t\t\t\t    u32 burst_counter);\n+s32 e1000_write_erase_flash_command_i225(struct e1000_hw *hw, u32 opcode,\n+\t\t\t\t\t u32 address);\n+s32 e1000_acquire_swfw_sync_i225(struct e1000_hw *hw, u16 mask);\n+void e1000_release_swfw_sync_i225(struct e1000_hw *hw, u16 mask);\n+s32 e1000_init_hw_i225(struct e1000_hw *hw);\n+s32 e1000_setup_copper_link_i225(struct e1000_hw *hw);\n+s32 e1000_set_d0_lplu_state_i225(struct e1000_hw *hw, bool active);\n+s32 e1000_set_d3_lplu_state_i225(struct e1000_hw *hw, bool active);\n+s32 e1000_set_eee_i225(struct e1000_hw *hw, bool adv2p5G, bool adv1G,\n+\t\t       bool adv100M);\n+\n+#define ID_LED_DEFAULT_I225\t\t((ID_LED_OFF1_ON2  << 8) | \\\n+\t\t\t\t\t (ID_LED_DEF1_DEF2 <<  4) | \\\n+\t\t\t\t\t (ID_LED_OFF1_OFF2))\n+#define ID_LED_DEFAULT_I225_SERDES\t((ID_LED_DEF1_DEF2 << 8) | \\\n+\t\t\t\t\t (ID_LED_DEF1_DEF2 <<  4) | \\\n+\t\t\t\t\t (ID_LED_OFF1_ON2))\n+\n+/* NVM offset defaults for I225 devices */\n+#define NVM_INIT_CTRL_2_DEFAULT_I225\t0X7243\n+#define NVM_INIT_CTRL_4_DEFAULT_I225\t0x00C1\n+#define NVM_LED_1_CFG_DEFAULT_I225\t0x0184\n+#define NVM_LED_0_2_CFG_DEFAULT_I225\t0x200C\n+\n+#define E1000_MRQC_ENABLE_RSS_4Q\t\t0x00000002\n+#define E1000_MRQC_ENABLE_VMDQ\t\t\t0x00000003\n+#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q\t\t0x00000005\n+#define E1000_MRQC_RSS_FIELD_IPV4_UDP\t\t0x00400000\n+#define E1000_MRQC_RSS_FIELD_IPV6_UDP\t\t0x00800000\n+#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX\t0x01000000\n+#define E1000_I225_SHADOW_RAM_SIZE\t\t4096\n+#define E1000_I225_ERASE_CMD_OPCODE\t\t0x02000000\n+#define E1000_I225_WRITE_CMD_OPCODE\t\t0x01000000\n+#define E1000_FLSWCTL_DONE\t\t\t0x40000000\n+#define E1000_FLSWCTL_CMDV\t\t\t0x10000000\n+\n+/* SRRCTL bit definitions */\n+#define E1000_SRRCTL_BSIZEHDRSIZE_MASK\t\t0x00000F00\n+#define E1000_SRRCTL_DESCTYPE_LEGACY\t\t0x00000000\n+#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT\t\t0x04000000\n+#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS\t0x0A000000\n+#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION\t0x06000000\n+#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000\n+#define E1000_SRRCTL_DESCTYPE_MASK\t\t0x0E000000\n+#define E1000_SRRCTL_DROP_EN\t\t\t0x80000000\n+#define E1000_SRRCTL_BSIZEPKT_MASK\t\t0x0000007F\n+#define E1000_SRRCTL_BSIZEHDR_MASK\t\t0x00003F00\n+\n+#define E1000_RXDADV_RSSTYPE_MASK\t0x0000000F\n+#define E1000_RXDADV_RSSTYPE_SHIFT\t12\n+#define E1000_RXDADV_HDRBUFLEN_MASK\t0x7FE0\n+#define E1000_RXDADV_HDRBUFLEN_SHIFT\t5\n+#define E1000_RXDADV_SPLITHEADER_EN\t0x00001000\n+#define E1000_RXDADV_SPH\t\t0x8000\n+#define E1000_RXDADV_STAT_TS\t\t0x10000 /* Pkt was time stamped */\n+#define E1000_RXDADV_ERR_HBO\t\t0x00800000\n+\n+/* RSS Hash results */\n+#define E1000_RXDADV_RSSTYPE_NONE\t0x00000000\n+#define E1000_RXDADV_RSSTYPE_IPV4_TCP\t0x00000001\n+#define E1000_RXDADV_RSSTYPE_IPV4\t0x00000002\n+#define E1000_RXDADV_RSSTYPE_IPV6_TCP\t0x00000003\n+#define E1000_RXDADV_RSSTYPE_IPV6_EX\t0x00000004\n+#define E1000_RXDADV_RSSTYPE_IPV6\t0x00000005\n+#define E1000_RXDADV_RSSTYPE_IPV6_TCP_EX 0x00000006\n+#define E1000_RXDADV_RSSTYPE_IPV4_UDP\t0x00000007\n+#define E1000_RXDADV_RSSTYPE_IPV6_UDP\t0x00000008\n+#define E1000_RXDADV_RSSTYPE_IPV6_UDP_EX 0x00000009\n+\n+/* RSS Packet Types as indicated in the receive descriptor */\n+#define E1000_RXDADV_PKTTYPE_ILMASK\t0x000000F0\n+#define E1000_RXDADV_PKTTYPE_TLMASK\t0x00000F00\n+#define E1000_RXDADV_PKTTYPE_NONE\t0x00000000\n+#define E1000_RXDADV_PKTTYPE_IPV4\t0x00000010 /* IPV4 hdr present */\n+#define E1000_RXDADV_PKTTYPE_IPV4_EX\t0x00000020 /* IPV4 hdr + extensions */\n+#define E1000_RXDADV_PKTTYPE_IPV6\t0x00000040 /* IPV6 hdr present */\n+#define E1000_RXDADV_PKTTYPE_IPV6_EX\t0x00000080 /* IPV6 hdr + extensions */\n+#define E1000_RXDADV_PKTTYPE_TCP\t0x00000100 /* TCP hdr present */\n+#define E1000_RXDADV_PKTTYPE_UDP\t0x00000200 /* UDP hdr present */\n+#define E1000_RXDADV_PKTTYPE_SCTP\t0x00000400 /* SCTP hdr present */\n+#define E1000_RXDADV_PKTTYPE_NFS\t0x00000800 /* NFS hdr present */\n+\n+#define E1000_RXDADV_PKTTYPE_IPSEC_ESP\t0x00001000 /* IPSec ESP */\n+#define E1000_RXDADV_PKTTYPE_IPSEC_AH\t0x00002000 /* IPSec AH */\n+#define E1000_RXDADV_PKTTYPE_LINKSEC\t0x00004000 /* LinkSec Encap */\n+#define E1000_RXDADV_PKTTYPE_ETQF\t0x00008000 /* PKTTYPE is ETQF index */\n+#define E1000_RXDADV_PKTTYPE_ETQF_MASK\t0x00000070 /* ETQF has 8 indices */\n+#define E1000_RXDADV_PKTTYPE_ETQF_SHIFT\t4 /* Right-shift 4 bits */\n+\n+#endif\ndiff --git a/drivers/net/e1000/base/e1000_regs.h b/drivers/net/e1000/base/e1000_regs.h\nindex b072c5c1d..1f8736f35 100644\n--- a/drivers/net/e1000/base/e1000_regs.h\n+++ b/drivers/net/e1000/base/e1000_regs.h\n@@ -85,8 +85,14 @@\n #define E1000_IOSFPC\t0x00F28  /* TX corrupted data  */\n #define E1000_EEMNGCTL\t0x01010  /* MNG EEprom Control */\n #define E1000_EEMNGCTL_I210\t0x01010  /* i210 MNG EEprom Mode Control */\n+#ifndef NO_I225_SUPPORT\n+#define E1000_EEMNGCTL_I225\t0x01010  /* i225 MNG EEprom Mode Control */\n+#endif /* NO_I225_SUPPORT */\n #define E1000_EEARBC\t0x01024  /* EEPROM Auto Read Bus Control */\n #define E1000_EEARBC_I210\t0x12024 /* EEPROM Auto Read Bus Control */\n+#ifndef NO_I225_SUPPORT\n+#define E1000_EEARBC_I225\t0x12024 /* EEPROM Auto Read Bus Control */\n+#endif /* NO_I225_SUPPORT */\n #define E1000_FLASHT\t0x01028  /* FLASH Timer Register */\n #define E1000_EEWR\t0x0102C  /* EEPROM Write Register - RW */\n #define E1000_FLSWCTL\t0x01030  /* FLASH control register */\ndiff --git a/drivers/net/e1000/base/meson.build b/drivers/net/e1000/base/meson.build\nindex 5e1716def..d13c32033 100644\n--- a/drivers/net/e1000/base/meson.build\n+++ b/drivers/net/e1000/base/meson.build\n@@ -11,6 +11,7 @@ sources = [\n \t'e1000_82575.c',\n \t'e1000_api.c',\n \t'e1000_i210.c',\n+\t'e1000_i225.c',\n \t'e1000_ich8lan.c',\n \t'e1000_mac.c',\n \t'e1000_manage.c',\n",
    "prefixes": [
        "02/70"
    ]
}