diff options
| author | 2026-05-05 14:40:40 +0200 | |
|---|---|---|
| committer | 2026-05-05 14:40:40 +0200 | |
| commit | 8c699be3dad7bba87cdda485dc099226cfc2f706 (patch) | |
| tree | 9a28dcea35feb188da5610fdd4eb86771cb0eec6 /drivers | |
| parent | net/sched: speedup tc_dump_qdisc() when tcm_handle is provided (diff) | |
| parent | net: eth: fbnic: Add pma read and write access (diff) | |
Merge branch 'first-series-for-xpcs-based-rsfec-configuration'develdavem/net-next
Mike Marciniszyn says:
====================
first series for xpcs based rsfec configuration
The series:
- Fixes an addr validation error
- Adds MDIO defines associated with RS-FEC
- consolidates the handling of the boilerplat ID registers
into a routine to report id'ish registers and reduces the lines
of code across the entire set of c45 routines.
- adds PMA read/write routines
https://lore.kernel.org/all/20260428172810.175077-2-mike.marciniszyn@gmail.com/
has been removed from the series and submitted to net as
https://lore.kernel.org/all/20260429150049.1643-1-mike.marciniszyn@gmail.com/
pcs reads for DEVS1 and DEVS2 cleaned up 2/3
====================
Link: https://patch.msgid.link/20260430150802.3521-1-mike.marciniszyn@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/net/ethernet/meta/fbnic/fbnic_csr.h | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/meta/fbnic/fbnic_mdio.c | 135 |
2 files changed, 112 insertions, 24 deletions
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h b/drivers/net/ethernet/meta/fbnic/fbnic_csr.h index 81794bd326e1..64b958df7774 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_csr.h @@ -805,6 +805,7 @@ enum { #define FBNIC_CSR_END_PCS 0x10668 /* CSR section delimiter */ #define FBNIC_CSR_START_RSFEC 0x10800 /* CSR section delimiter */ +#define FBNIC_RSFEC_CONTROL(n) (0x10800 + 8 * (n)) /* 0x42000 + 32*n */ /* We have 4 RSFEC engines present in our part, however we are only using 1. * As such only CCW(0) and NCCW(0) will never be non-zero and the other diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c b/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c index 709041f7fc43..7a8727e8f6f2 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c @@ -7,11 +7,50 @@ #include "fbnic.h" #include "fbnic_netdev.h" +/* fbnic MDIO Interface Layout + * + * +-------------------+ + * | MAC | + * +-------------------+ + * | | | | <-- 25GMII, 50GMII, or CGMII + * +-------------------+ + * MMD 3 | PCS | + * +-------------------+ + * | FEC | + * +-------------------+ + * MMD 8 | Separated PMA | + * +-------------------+ + * | | <-- PMD Service Interface + * +-------------------+ + * MMD 1 | PMD | + * +-------------------+ + */ + #define DW_VENDOR BIT(15) #define FBNIC_PCS_VENDOR BIT(9) #define FBNIC_PCS_ZERO_MASK (DW_VENDOR - FBNIC_PCS_VENDOR) static int +fbnic_mdio_ids(int id, int regnum) +{ + /* return correct IDs */ + switch (regnum) { + case MDIO_DEVID1: + return id >> 16; + case MDIO_DEVID2: + return id & 0xffff; + case MDIO_DEVS1: + return MDIO_DEVS_SEP_PMA1 | MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS; + case MDIO_DEVS2: + return 0; + case MDIO_STAT2: + return MDIO_STAT2_DEVPRST_VAL; + } + + return 0; +} + +static int fbnic_mdio_read_pmd(struct fbnic_dev *fbd, int addr, int regnum) { u8 aui = FBNIC_AUI_UNKNOWN; @@ -29,18 +68,6 @@ fbnic_mdio_read_pmd(struct fbnic_dev *fbd, int addr, int regnum) } switch (regnum) { - case MDIO_DEVID1: - ret = MP_FBNIC_XPCS_PMA_100G_ID >> 16; - break; - case MDIO_DEVID2: - ret = MP_FBNIC_XPCS_PMA_100G_ID & 0xffff; - break; - case MDIO_DEVS1: - ret = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS; - break; - case MDIO_STAT2: - ret = MDIO_STAT2_DEVPRST_VAL; - break; case MDIO_PMA_RXDET: /* If training isn't complete default to 0 */ if (fbd->pmd_state != FBNIC_PMD_SEND_DATA) @@ -51,6 +78,7 @@ fbnic_mdio_read_pmd(struct fbnic_dev *fbd, int addr, int regnum) (MDIO_PMD_RXDET_1 / FBNIC_AUI_MODE_R2)); break; default: + ret = fbnic_mdio_ids(MP_FBNIC_XPCS_PMA_100G_ID, regnum); break; } @@ -64,7 +92,7 @@ fbnic_mdio_read_pmd(struct fbnic_dev *fbd, int addr, int regnum) static int fbnic_mdio_read_pcs(struct fbnic_dev *fbd, int addr, int regnum) { - int ret, offset = 0; + int ret, offset = 0, overrides = 0; /* We will need access to both PCS instances to get config info */ if (addr >= 2) @@ -75,18 +103,25 @@ fbnic_mdio_read_pcs(struct fbnic_dev *fbd, int addr, int regnum) return 0; /* Intercept and return correct ID for PCS */ - if (regnum == MDIO_DEVID1) - return DW_XPCS_ID >> 16; - if (regnum == MDIO_DEVID2) - return DW_XPCS_ID & 0xffff; - if (regnum == MDIO_DEVS1) - return MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS; - - /* Swap vendor page bit for FBNIC PCS vendor page bit */ - if (regnum & DW_VENDOR) - offset ^= DW_VENDOR | FBNIC_PCS_VENDOR; + switch (regnum) { + case MDIO_DEVID1 ... MDIO_DEVID2: + ret = fbnic_mdio_ids(DW_XPCS_ID, regnum); + break; + case MDIO_DEVS1: + /* DW IP returns MDIO_DEVS_SEP_PMA1, MDIO_DEVS_PMAPMD, + * and MDIO_DEVS_PCS as 0 + */ + overrides = fbnic_mdio_ids(DW_XPCS_ID, regnum); + fallthrough; + default: + /* Swap vendor page bit for FBNIC PCS vendor page bit */ + if (regnum & DW_VENDOR) + offset ^= DW_VENDOR | FBNIC_PCS_VENDOR; - ret = fbnic_rd32(fbd, FBNIC_PCS_PAGE(addr) + (regnum ^ offset)); + ret = fbnic_rd32(fbd, FBNIC_PCS_PAGE(addr) + (regnum ^ offset)); + ret |= overrides; + break; + } dev_dbg(fbd->dev, "SWMII PCS Rd: Addr: %d RegNum: %d Value: 0x%04x\n", @@ -96,6 +131,32 @@ fbnic_mdio_read_pcs(struct fbnic_dev *fbd, int addr, int regnum) } static int +fbnic_mdio_read_pma(struct fbnic_dev *fbd, int addr, int regnum) +{ + int ret = 0; + + /* We will need access to both PMA instances to get config info */ + if (addr >= 2) + return 0; + + switch (regnum) { + case MDIO_PMA_RSFEC_CTRL ... MDIO_PMA_RSFEC_LANE_MAP: + ret = fbnic_rd32(fbd, FBNIC_RSFEC_CONTROL(addr) + + regnum - MDIO_PMA_RSFEC_CTRL); + break; + default: + ret = fbnic_mdio_ids(MP_FBNIC_XPCS_PMA_100G_ID, regnum); + break; + } + + dev_dbg(fbd->dev, + "SWMII PMA Rd: Addr: %d RegNum: %d Value: 0x%04x\n", + addr, regnum, ret); + + return ret; +} + +static int fbnic_mdio_read_c45(struct mii_bus *bus, int addr, int devnum, int regnum) { struct fbnic_dev *fbd = bus->priv; @@ -106,6 +167,9 @@ fbnic_mdio_read_c45(struct mii_bus *bus, int addr, int devnum, int regnum) if (devnum == MDIO_MMD_PCS) return fbnic_mdio_read_pcs(fbd, addr, regnum); + if (devnum == MDIO_MMD_SEP_PMA1) + return fbnic_mdio_read_pma(fbd, addr, regnum); + return 0; } @@ -139,6 +203,26 @@ fbnic_mdio_write_pcs(struct fbnic_dev *fbd, int addr, int regnum, u16 val) fbnic_wr32(fbd, FBNIC_PCS_PAGE(addr) + regnum, val); } +static void +fbnic_mdio_write_pma(struct fbnic_dev *fbd, int addr, int regnum, u16 val) +{ + dev_dbg(fbd->dev, + "SWMII PMA Wr: Addr: %d RegNum: %d Value: 0x%04x\n", + addr, regnum, val); + + if (addr >= 2) + return; + + switch (regnum) { + case MDIO_PMA_RSFEC_CTRL ... MDIO_PMA_RSFEC_LANE_MAP: + fbnic_wr32(fbd, FBNIC_RSFEC_CONTROL(addr) + + regnum - MDIO_PMA_RSFEC_CTRL, val); + break; + default: + break; + } +} + static int fbnic_mdio_write_c45(struct mii_bus *bus, int addr, int devnum, int regnum, u16 val) @@ -151,6 +235,9 @@ fbnic_mdio_write_c45(struct mii_bus *bus, int addr, int devnum, if (devnum == MDIO_MMD_PCS) fbnic_mdio_write_pcs(fbd, addr, regnum, val); + if (devnum == MDIO_MMD_SEP_PMA1) + fbnic_mdio_write_pma(fbd, addr, regnum, val); + return 0; } |
