[PATCH v1 02/42] net/e1000/base: add initial support for i225

Anatoly Burakov anatoly.burakov at intel.com
Fri Jan 31 13:58:15 CET 2025


Add basic init, and PHY/MAC type support for i225 series NICs. This is
mostly identical to IGC driver, with some minor differences due to the
way IGC driver was originally generated.

Signed-off-by: Anatoly Burakov <anatoly.burakov at intel.com>
---
 drivers/net/intel/e1000/base/e1000_api.c     |  20 ++
 drivers/net/intel/e1000/base/e1000_api.h     |   1 +
 drivers/net/intel/e1000/base/e1000_defines.h |   2 +
 drivers/net/intel/e1000/base/e1000_hw.h      |  19 ++
 drivers/net/intel/e1000/base/e1000_i225.c    | 211 +++++++++++++++++++
 drivers/net/intel/e1000/base/e1000_i225.h    |  10 +
 drivers/net/intel/e1000/base/e1000_phy.c     |   4 +
 drivers/net/intel/e1000/base/e1000_regs.h    |   1 +
 drivers/net/intel/e1000/base/meson.build     |   1 +
 9 files changed, 269 insertions(+)
 create mode 100644 drivers/net/intel/e1000/base/e1000_i225.c
 create mode 100644 drivers/net/intel/e1000/base/e1000_i225.h

diff --git a/drivers/net/intel/e1000/base/e1000_api.c b/drivers/net/intel/e1000/base/e1000_api.c
index 6697b4b64f..1a7a737637 100644
--- a/drivers/net/intel/e1000/base/e1000_api.c
+++ b/drivers/net/intel/e1000/base/e1000_api.c
@@ -354,6 +354,23 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
 	case E1000_DEV_ID_82576_VF_HV:
 		mac->type = e1000_vfadapt;
 		break;
+	case E1000_DEV_ID_I225_LM:
+	case E1000_DEV_ID_I225_LMVP:
+	case E1000_DEV_ID_I225_V:
+	case E1000_DEV_ID_I225_K:
+	case E1000_DEV_ID_I225_I:
+	case E1000_DEV_ID_I225_IT:
+	case E1000_DEV_ID_I220_V:
+	case E1000_DEV_ID_I225_BLANK_NVM:
+	case E1000_DEV_ID_I226_LM:
+	case E1000_DEV_ID_I226_V:
+	case E1000_DEV_ID_I226_IT:
+	case E1000_DEV_ID_I226_K:
+	case E1000_DEV_ID_I221_V:
+	case E1000_DEV_ID_I226_LMVP:
+	case E1000_DEV_ID_I226_BLANK_NVM:
+		mac->type = e1000_i225;
+		break;
 	case E1000_DEV_ID_I350_VF:
 	case E1000_DEV_ID_I350_VF_HV:
 		mac->type = e1000_vfadapt_i350;
@@ -470,6 +487,9 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
 	case e1000_i211:
 		e1000_init_function_pointers_i210(hw);
 		break;
+	case e1000_i225:
+		e1000_init_function_pointers_i225(hw);
+		break;
 	case e1000_vfadapt:
 		e1000_init_function_pointers_vf(hw);
 		break;
diff --git a/drivers/net/intel/e1000/base/e1000_api.h b/drivers/net/intel/e1000/base/e1000_api.h
index 6b38e2b7bb..2466c2fd48 100644
--- a/drivers/net/intel/e1000/base/e1000_api.h
+++ b/drivers/net/intel/e1000/base/e1000_api.h
@@ -19,6 +19,7 @@ extern void e1000_init_function_pointers_vf(struct e1000_hw *hw);
 extern void e1000_power_up_fiber_serdes_link(struct e1000_hw *hw);
 extern void e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw);
 extern void e1000_init_function_pointers_i210(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_i225(struct e1000_hw *hw);
 
 s32 e1000_set_obff_timer(struct e1000_hw *hw, u32 itr);
 s32 e1000_set_mac_type(struct e1000_hw *hw);
diff --git a/drivers/net/intel/e1000/base/e1000_defines.h b/drivers/net/intel/e1000/base/e1000_defines.h
index 97cc2797b2..cdc0703582 100644
--- a/drivers/net/intel/e1000/base/e1000_defines.h
+++ b/drivers/net/intel/e1000/base/e1000_defines.h
@@ -1257,6 +1257,8 @@
 #define IGP04E1000_E_PHY_ID	0x02A80391
 #define BCM54616_E_PHY_ID	0x03625D10
 #define M88_VENDOR		0x0141
+#define I225_I_PHY_ID		0x67C9DC00
+#define I226_LM_PHY_ID		0x67C9DC10
 
 /* M88E1000 Specific Registers */
 #define M88E1000_PHY_SPEC_CTRL		0x10  /* PHY Specific Control Reg */
diff --git a/drivers/net/intel/e1000/base/e1000_hw.h b/drivers/net/intel/e1000/base/e1000_hw.h
index c7e6903ecc..a21cb070e0 100644
--- a/drivers/net/intel/e1000/base/e1000_hw.h
+++ b/drivers/net/intel/e1000/base/e1000_hw.h
@@ -168,6 +168,22 @@ struct e1000_hw;
 #define E1000_DEV_ID_I210_SERDES_FLASHLESS	0x157C
 #define E1000_DEV_ID_I210_SGMII_FLASHLESS	0x15F6
 #define E1000_DEV_ID_I211_COPPER		0x1539
+#define E1000_DEV_ID_I225_LM			0x15F2
+#define E1000_DEV_ID_I225_V			0x15F3
+#define E1000_DEV_ID_I225_K			0x3100
+#define E1000_DEV_ID_I225_K2			0x3101
+#define E1000_DEV_ID_I225_LMVP			0x5502
+#define E1000_DEV_ID_I225_IT			0x0D9F
+#define E1000_DEV_ID_I225_I			0x15F8
+#define E1000_DEV_ID_I220_V			0x15F7
+#define E1000_DEV_ID_I225_BLANK_NVM		0x15FD
+#define E1000_DEV_ID_I226_LM			0x125B
+#define E1000_DEV_ID_I226_V			0x125C
+#define E1000_DEV_ID_I226_IT			0x125D
+#define E1000_DEV_ID_I226_K			0x3102
+#define E1000_DEV_ID_I221_V			0x125E
+#define E1000_DEV_ID_I226_LMVP			0x5503
+#define E1000_DEV_ID_I226_BLANK_NVM		0x125F
 #define E1000_DEV_ID_I354_BACKPLANE_1GBPS	0x1F40
 #define E1000_DEV_ID_I354_SGMII			0x1F41
 #define E1000_DEV_ID_I354_BACKPLANE_2_5GBPS	0x1F45
@@ -229,6 +245,7 @@ enum e1000_mac_type {
 	e1000_i354,
 	e1000_i210,
 	e1000_i211,
+	e1000_i225,
 	e1000_vfadapt,
 	e1000_vfadapt_i350,
 	e1000_num_macs  /* List is 1-based, so subtract 1 for true count. */
@@ -277,6 +294,7 @@ enum e1000_phy_type {
 	e1000_phy_82580,
 	e1000_phy_vf,
 	e1000_phy_i210,
+	e1000_phy_i225,
 };
 
 enum e1000_bus_type {
@@ -1019,6 +1037,7 @@ struct e1000_hw {
 #include "e1000_ich8lan.h"
 #include "e1000_82575.h"
 #include "e1000_i210.h"
+#include "e1000_i225.h"
 #include "e1000_base.h"
 
 /* These functions must be implemented by drivers */
diff --git a/drivers/net/intel/e1000/base/e1000_i225.c b/drivers/net/intel/e1000/base/e1000_i225.c
new file mode 100644
index 0000000000..37acb29034
--- /dev/null
+++ b/drivers/net/intel/e1000/base/e1000_i225.c
@@ -0,0 +1,211 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2024 Intel Corporation
+ */
+
+#include "e1000_api.h"
+
+STATIC s32 e1000_init_mac_params_i225(struct e1000_hw *hw);
+STATIC s32 e1000_init_phy_params_i225(struct e1000_hw *hw);
+STATIC s32 e1000_reset_hw_i225(struct e1000_hw *hw);
+
+/**
+ *  e1000_init_mac_params_i225 - Init MAC func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 e1000_init_mac_params_i225(struct e1000_hw *hw)
+{
+	struct e1000_mac_info *mac = &hw->mac;
+
+	DEBUGFUNC("e1000_init_mac_params_i225");
+
+	/* Initialize function pointer */
+	e1000_init_mac_ops_generic(hw);
+
+	/* Set media type */
+	hw->phy.media_type = e1000_media_type_copper;
+	/* Set mta register count */
+	mac->mta_reg_count = 128;
+	/* Set rar entry count */
+	mac->rar_entry_count = E1000_RAR_ENTRIES_BASE;
+	/* bus type/speed/width */
+	mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic;
+	/* reset */
+	mac->ops.reset_hw = e1000_reset_hw_i225;
+	/* hw initialization */
+	mac->ops.init_hw = e1000_init_hw_i225;
+	/* link setup */
+	mac->ops.setup_link = e1000_setup_link_generic;
+	mac->ops.check_for_link = e1000_check_for_copper_link_generic;
+	/* link info */
+	mac->ops.get_link_up_info = e1000_get_speed_and_duplex_copper_generic;
+
+	/* Set if part includes ASF firmware */
+	mac->asf_firmware_present = true;
+
+	/* multicast address update */
+	mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
+
+	mac->ops.write_vfta = e1000_write_vfta_generic;
+
+	return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_init_phy_params_i225 - Init PHY func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 e1000_init_phy_params_i225(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val = E1000_SUCCESS;
+	u32 ctrl_ext;
+
+	DEBUGFUNC("e1000_init_phy_params_i225");
+
+	phy->ops.read_i2c_byte = e1000_read_i2c_byte_generic;
+	phy->ops.write_i2c_byte = e1000_write_i2c_byte_generic;
+
+	if (hw->phy.media_type != e1000_media_type_copper) {
+		phy->type = e1000_phy_none;
+		goto out;
+	}
+
+	phy->ops.power_up   = e1000_power_up_phy_copper;
+	phy->ops.power_down = e1000_power_down_phy_copper_base;
+
+	phy->reset_delay_us	= 100;
+
+	phy->ops.acquire	= e1000_acquire_phy_base;
+	phy->ops.check_reset_block = e1000_check_reset_block_generic;
+	phy->ops.commit		= e1000_phy_sw_reset_generic;
+	phy->ops.release	= e1000_release_phy_base;
+	phy->ops.reset		= e1000_phy_hw_reset_generic;
+
+	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+
+	/* Make sure the PHY is in a good state. Several people have reported
+	 * firmware leaving the PHY's page select register set to something
+	 * other than the default of zero, which causes the PHY ID read to
+	 * access something other than the intended register.
+	 */
+	ret_val = hw->phy.ops.reset(hw);
+	if (ret_val)
+		goto out;
+
+	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  e1000_reset_hw_i225 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state.
+ **/
+STATIC s32 e1000_reset_hw_i225(struct e1000_hw *hw)
+{
+	u32 ctrl;
+	s32 ret_val;
+
+	DEBUGFUNC("e1000_reset_hw_i225");
+
+	/*
+	 * Prevent the PCI-E bus from sticking if there is no TLP connection
+	 * on the last TLP read/write transaction when MAC is reset.
+	 */
+	ret_val = e1000_disable_pcie_master_generic(hw);
+	if (ret_val)
+		DEBUGOUT("PCI-E Master disable polling has failed.\n");
+
+	DEBUGOUT("Masking off all interrupts\n");
+	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+
+	E1000_WRITE_REG(hw, E1000_RCTL, 0);
+	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
+	E1000_WRITE_FLUSH(hw);
+
+	msec_delay(10);
+
+	ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+	DEBUGOUT("Issuing a global reset to MAC\n");
+	E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
+
+	ret_val = e1000_get_auto_rd_done_generic(hw);
+	if (ret_val) {
+		/*
+		 * When auto config read does not complete, do not
+		 * return with an error. This can happen in situations
+		 * where there is no eeprom and prevents getting link.
+		 */
+		DEBUGOUT("Auto Read Done did not complete\n");
+	}
+
+	/* Clear any pending interrupt events. */
+	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+	E1000_READ_REG(hw, E1000_ICR);
+
+	/* Install any alternate MAC address into RAR0 */
+	ret_val = e1000_check_alt_mac_addr_generic(hw);
+
+	return ret_val;
+}
+
+/* e1000_init_function_pointers_i225 - Init func ptrs.
+ * @hw: pointer to the HW structure
+ *
+ * Called to initialize all function pointers and parameters.
+ */
+void e1000_init_function_pointers_i225(struct e1000_hw *hw)
+{
+	e1000_init_mac_ops_generic(hw);
+	e1000_init_phy_ops_generic(hw);
+	hw->mac.ops.init_params = e1000_init_mac_params_i225;
+	hw->phy.ops.init_params = e1000_init_phy_params_i225;
+}
+
+/* e1000_get_cfg_done_i225 - Read config done bit
+ * @hw: pointer to the HW structure
+ *
+ * Read the management control register for the config done bit for
+ * completion status.  NOTE: silicon which is EEPROM-less will fail trying
+ * to read the config done bit, so an error is *ONLY* logged and returns
+ * E1000_SUCCESS.  If we were to return with error, EEPROM-less silicon
+ * would not be able to be reset or change link.
+ */
+STATIC s32 e1000_get_cfg_done_i225(struct e1000_hw *hw)
+{
+	s32 timeout = PHY_CFG_TIMEOUT;
+	u32 mask = E1000_NVM_CFG_DONE_PORT_0;
+
+	DEBUGFUNC("e1000_get_cfg_done_i225");
+
+	while (timeout) {
+		if (E1000_READ_REG(hw, E1000_EEMNGCTL_I225) & mask)
+			break;
+		msec_delay(1);
+		timeout--;
+	}
+	if (!timeout)
+		DEBUGOUT("MNG configuration cycle has not completed.\n");
+
+	return E1000_SUCCESS;
+}
+
+/* e1000_init_hw_i225 - Init hw for I225
+ * @hw: pointer to the HW structure
+ *
+ * Called to initialize hw for i225 hw family.
+ */
+s32 e1000_init_hw_i225(struct e1000_hw *hw)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("e1000_init_hw_i225");
+
+	hw->phy.ops.get_cfg_done = e1000_get_cfg_done_i225;
+	ret_val = e1000_init_hw_base(hw);
+	return ret_val;
+}
diff --git a/drivers/net/intel/e1000/base/e1000_i225.h b/drivers/net/intel/e1000/base/e1000_i225.h
new file mode 100644
index 0000000000..8e38b75670
--- /dev/null
+++ b/drivers/net/intel/e1000/base/e1000_i225.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2024 Intel Corporation
+ */
+
+#ifndef _E1000_I225_H_
+#define _E1000_I225_H_
+
+s32 e1000_init_hw_i225(struct e1000_hw *hw);
+
+#endif
diff --git a/drivers/net/intel/e1000/base/e1000_phy.c b/drivers/net/intel/e1000/base/e1000_phy.c
index 62d0be5080..4840094066 100644
--- a/drivers/net/intel/e1000/base/e1000_phy.c
+++ b/drivers/net/intel/e1000/base/e1000_phy.c
@@ -3023,6 +3023,10 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
 	case I210_I_PHY_ID:
 		phy_type = e1000_phy_i210;
 		break;
+	case I225_I_PHY_ID:
+	case I226_LM_PHY_ID:
+		phy_type = e1000_phy_i225;
+		break;
 	default:
 		phy_type = e1000_phy_unknown;
 		break;
diff --git a/drivers/net/intel/e1000/base/e1000_regs.h b/drivers/net/intel/e1000/base/e1000_regs.h
index 092d9d71e6..20abeeaa46 100644
--- a/drivers/net/intel/e1000/base/e1000_regs.h
+++ b/drivers/net/intel/e1000/base/e1000_regs.h
@@ -87,6 +87,7 @@
 #define E1000_IOSFPC	0x00F28  /* TX corrupted data  */
 #define E1000_EEMNGCTL	0x01010  /* MNG EEprom Control */
 #define E1000_EEMNGCTL_I210	0x01010  /* i210 MNG EEprom Mode Control */
+#define E1000_EEMNGCTL_I225	0x01010  /* i225 MNG EEprom Mode Control */
 #define E1000_EEARBC	0x01024  /* EEPROM Auto Read Bus Control */
 #define E1000_EEARBC_I210	0x12024 /* EEPROM Auto Read Bus Control */
 #define E1000_FLASHT	0x01028  /* FLASH Timer Register */
diff --git a/drivers/net/intel/e1000/base/meson.build b/drivers/net/intel/e1000/base/meson.build
index e73f3d6d55..033b3af2e2 100644
--- a/drivers/net/intel/e1000/base/meson.build
+++ b/drivers/net/intel/e1000/base/meson.build
@@ -12,6 +12,7 @@ sources = [
         'e1000_82575.c',
         'e1000_api.c',
         'e1000_i210.c',
+        'e1000_i225.c',
         'e1000_ich8lan.c',
         'e1000_mac.c',
         'e1000_manage.c',
-- 
2.43.5



More information about the dev mailing list