Add hardware support for the AMD P100a platform featuring the ethernet controller PCI device ID 0x1122. Platform-specific changes include: 1. PCI device ID and register configuration: - Add XGBE_P100a_PCI_DEVICE_ID (0x1122) for recognition - Configure platform-specific XPCS window registers - Disable CDR workaround and RRC for this platform 2. XPCS window offset calculation fix: The P100a platform uses a different memory mapping scheme for XPCS register access. The offset calculation differs between platforms: - Older platforms (YC): offset = base + (addr & mask) The address is masked first, then added to the window base. - P100a: offset = (base + addr) & mask The full address is added to base first, then masked. This is critical because using the wrong calculation causes register reads/writes to access incorrect addresses, leading to incorrect behaviour. 3. 2.5G speed mode handling: P100a uses XGMII mode (ss=0x06) for 2.5G instead of GMII mode (ss=0x02) used by older platforms. The MAC version check determines which mode to use. 4. Port speed bits extended: Extend XP_PROP_0_PORT_SPEEDS from 5 bits to 6 bits to support the additional 5G speed capability. 5. Rx adaptation disabled: Rx adaptation is disabled for P100a (MAC version 0x33) as this feature requires further development for this platform. 6. Rate change command for 2.5G: Use XGBE_MB_SUBCMD_2_5G_KX subcommand for 2.5G mode on P100a instead of XGBE_MB_SUBCMD_NONE used on older platforms. Signed-off-by: Raju Rangoju --- drivers/net/ethernet/amd/xgbe/xgbe-common.h | 4 ++- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 33 +++++++++++++++++++-- drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 8 +++++ drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 22 ++++++++++++-- drivers/net/ethernet/amd/xgbe/xgbe.h | 6 +++- 5 files changed, 65 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index 711f295eb777..57cd8d2e1ad7 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h @@ -832,6 +832,8 @@ #define PCS_V2_YC_WINDOW_SELECT 0x18064 #define PCS_V3_RN_WINDOW_DEF 0xf8078 #define PCS_V3_RN_WINDOW_SELECT 0xf807c +#define PCS_P100a_WINDOW_DEF 0x8060 +#define PCS_P100a_WINDOW_SELECT 0x8080 #define PCS_RN_SMN_BASE_ADDR 0x11e00000 #define PCS_RN_PORT_ADDR_SIZE 0x100000 @@ -968,7 +970,7 @@ #define XP_PROP_0_PORT_MODE_INDEX 8 #define XP_PROP_0_PORT_MODE_WIDTH 4 #define XP_PROP_0_PORT_SPEEDS_INDEX 22 -#define XP_PROP_0_PORT_SPEEDS_WIDTH 5 +#define XP_PROP_0_PORT_SPEEDS_WIDTH 6 #define XP_PROP_1_MAX_RX_DMA_INDEX 24 #define XP_PROP_1_MAX_RX_DMA_WIDTH 5 #define XP_PROP_1_MAX_RX_QUEUES_INDEX 8 diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 1a91ec455bee..f1357619097e 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -718,7 +718,7 @@ static void xgbe_disable_ecc_sec(struct xgbe_prv_data *pdata, static int xgbe_set_speed(struct xgbe_prv_data *pdata, int speed) { - unsigned int ss; + unsigned int ss, ver; switch (speed) { case SPEED_10: @@ -728,7 +728,12 @@ static int xgbe_set_speed(struct xgbe_prv_data *pdata, int speed) ss = XGBE_MAC_SS_1G; break; case SPEED_2500: - ss = XGBE_MAC_SS_2_5G_GMII; + /* P100a uses XGMII mode for 2.5G, older platforms use GMII */ + ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER); + if (ver == XGBE_MAC_VER_33) + ss = XGBE_MAC_SS_2_5G_XGMII; + else + ss = XGBE_MAC_SS_2_5G_GMII; break; case SPEED_10000: ss = XGBE_MAC_SS_10G; @@ -1070,6 +1075,8 @@ static void xgbe_get_pcs_index_and_offset(struct xgbe_prv_data *pdata, unsigned int *index, unsigned int *offset) { + unsigned int ver; + /* The PCS registers are accessed using mmio. The underlying * management interface uses indirect addressing to access the MMD * register sets. This requires accessing of the PCS register in two @@ -1081,7 +1088,27 @@ static void xgbe_get_pcs_index_and_offset(struct xgbe_prv_data *pdata, */ mmd_address <<= 1; *index = mmd_address & ~pdata->xpcs_window_mask; - *offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask); + + ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER); + + /* The P100a platform uses a different memory mapping scheme for XPCS + * register access. The offset calculation differs between platforms: + * + * For P100a platforms: The offset is calculated by adding the + * mmd_address to the xpcs_window and then applying the xpcs_window_mask + * For older platforms: The offset is calculated by applying the + * xpcs_window_mask to the mmd_address and then adding it to the + * xpcs_window. + * + * This is critical because using the wrong calculation causes register + * accesses to target the wrong registers, leading to incorrect behavior + */ + if (ver == XGBE_MAC_VER_33) + *offset = (pdata->xpcs_window + mmd_address) & + pdata->xpcs_window_mask; + else + *offset = pdata->xpcs_window + + (mmd_address & pdata->xpcs_window_mask); } static int xgbe_read_mmd_regs_v3(struct xgbe_prv_data *pdata, int prtad, diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c index e3e1dca9856a..f54a5040a493 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c @@ -168,6 +168,14 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0)); if (rdev && rdev->vendor == PCI_VENDOR_ID_AMD) { switch (rdev->device) { + case XGBE_P100a_PCI_DEVICE_ID: + pdata->xpcs_window_def_reg = PCS_P100a_WINDOW_DEF; + pdata->xpcs_window_sel_reg = PCS_P100a_WINDOW_SELECT; + + /* P100a devices do not need rrc and cdr workaround */ + pdata->vdata->an_cdr_workaround = 0; + pdata->vdata->enable_rrc = 0; + break; case XGBE_RV_PCI_DEVICE_ID: pdata->xpcs_window_def_reg = PCS_V2_RV_WINDOW_DEF; pdata->xpcs_window_sel_reg = PCS_V2_RV_WINDOW_SELECT; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index c63ddb12237e..1dbfa9d4360d 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -2132,7 +2132,11 @@ static bool enable_rx_adap(struct xgbe_prv_data *pdata, enum xgbe_mode mode) /* Rx-Adaptation is not supported on older platforms(< 0x30H) */ ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER); - if (ver < 0x30) + if (ver < XGBE_MAC_VER_30) + return false; + + /* Rx adaptation not yet supported on P100a */ + if (ver == XGBE_MAC_VER_33) return false; /* Re-driver models 4223 && 4227 do not support Rx-Adaptation */ @@ -2258,12 +2262,24 @@ static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata) static void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata) { + unsigned int ver; + struct xgbe_phy_data *phy_data = pdata->phy_data; xgbe_phy_set_redrv_mode(pdata); - /* 2.5G/KX */ - xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_SET_2_5G, XGBE_MB_SUBCMD_NONE); + ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER); + + /* + * P100a uses XGMII mode for 2.5G which requires the 2.5G_KX subcommand. + * Older platforms use GMII mode. + */ + if (ver == XGBE_MAC_VER_33) + xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_SET_2_5G, + XGBE_MB_SUBCMD_2_5G_KX); + else + xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_SET_2_5G, + XGBE_MB_SUBCMD_NONE); phy_data->cur_mode = XGBE_MODE_KX_2500; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 32cab96e013c..f1b2954017e6 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -262,6 +262,7 @@ #define XGBE_RV_PCI_DEVICE_ID 0x15d0 #define XGBE_YC_PCI_DEVICE_ID 0x14b5 #define XGBE_RN_PCI_DEVICE_ID 0x1630 +#define XGBE_P100a_PCI_DEVICE_ID 0x1122 /* Generic low and high masks */ #define XGBE_GEN_HI_MASK GENMASK(31, 16) @@ -577,7 +578,10 @@ enum xgbe_mb_subcmd { XGBE_MB_SUBCMD_10MBITS = 0, XGBE_MB_SUBCMD_100MBITS, XGBE_MB_SUBCMD_1G_SGMII, - XGBE_MB_SUBCMD_1G_KX + XGBE_MB_SUBCMD_1G_KX, + + /* 2.5GbE Mode subcommands */ + XGBE_MB_SUBCMD_2_5G_KX = 1 }; struct xgbe_phy { -- 2.34.1