[U-Boot] [PATCH v3 00/11] Add XFI, USXGMII net protocols, use them in Aquantia driver

There are several plaforms that use XFI and/or USXGMII protocols but declare them as XGMII in U-Boot because that's already defined. These protocols are not identical and in some cases specific configuration has to be applied for each of them. This patch series introduces XFI and USXGMII and updates the Aquantia PHY driver to use them, in addition to the existing XGMII.
Currently AQR PHYs rely exclusively on firmware to configure system side protocols as well as a few other parameters, which means that FW has to be replaced on the PHY when switching between SGMII, SGMII-2.5G, XFI, USXGMII. This patch set adds support to the driver to reconfigure the system interface protocol based on the interface selected by the ethernet driver (typically picked up from DT). Additional configuration (mdi-reversal, smb-addr) is also picked up by Aquantia driver from the PHY DT node, if present from a couple of newly defined properties.
The new aquantia DT attributes are documented in a new binding document. Also added a generic PHY node binding document using content from Linux.
And last, update ENETC to use the new interface types.
This patch set supersedes v2: https://patchwork.ozlabs.org/project/uboot/list/?series=124595
Changes in v3: - It seems some Gen1 Aquantia PHYs don't behave well when put in low power and we're not even reconfiguring Gen1 PHYs anyway, so just leave them alone. - Changed subject and description in cover letter. - Other minor changes.
Changes in v2: - Flip USX AN bit both ways as needed, in v1 it was only set for USXGMII but not reset for XFI - Use CONFIG_DM_ETH instead of CONFIG_OF_CONTROL around the codeu using phydev->node - Use variable name interface instead of if_type for consistency with the rest of the code.
Alex Marginean (11): include: phy: define XFI and USXGMII interface types include: phy: add data field for private driver data drivers: net: aquantia: use XFI, USXGMII interface types drivers: net: aquantia: add PHY generation information drivers: net: aquantia: set up SI protocol based on interface type drivers: net: aquantia: set MDI reversal based on DT property drivers: net: aquantia: set SMBus addr based on DT property drivers: net: aquantia: check system interface too when checking for link up doc: bindings: add bindings document for PHY nodes doc: bindings: Aquantia PHY node binding drivers: net: fsl_enetc: use XFI, USXGMII interface type macros
doc/device-tree-bindings/net/aquantia-phy.txt | 25 ++ doc/device-tree-bindings/net/phy.txt | 24 ++ drivers/net/fsl_enetc.c | 2 + drivers/net/phy/aquantia.c | 226 ++++++++++++++++-- include/phy.h | 3 + include/phy_interface.h | 4 + 6 files changed, 265 insertions(+), 19 deletions(-) create mode 100644 doc/device-tree-bindings/net/aquantia-phy.txt create mode 100644 doc/device-tree-bindings/net/phy.txt

Drivers currently use XGMII for XFI and USXGMII and, where needed, use other information to identify the actual protocol on the board. With these two defined drivers can now rely on DT phy-mode property.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com --- include/phy_interface.h | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/include/phy_interface.h b/include/phy_interface.h index c6823189f8..73f3a3679c 100644 --- a/include/phy_interface.h +++ b/include/phy_interface.h @@ -31,6 +31,8 @@ typedef enum { PHY_INTERFACE_MODE_XLAUI, PHY_INTERFACE_MODE_CAUI2, PHY_INTERFACE_MODE_CAUI4, + PHY_INTERFACE_MODE_XFI, + PHY_INTERFACE_MODE_USXGMII, PHY_INTERFACE_MODE_NONE, /* Must be last */
PHY_INTERFACE_MODE_COUNT, @@ -58,6 +60,8 @@ static const char * const phy_interface_strings[] = { [PHY_INTERFACE_MODE_XLAUI] = "xlaui4", [PHY_INTERFACE_MODE_CAUI2] = "caui2", [PHY_INTERFACE_MODE_CAUI4] = "caui4", + [PHY_INTERFACE_MODE_XFI] = "xfi", + [PHY_INTERFACE_MODE_USXGMII] = "usxgmii", [PHY_INTERFACE_MODE_NONE] = "", };

On Thu, Nov 14, 2019 at 10:31 AM Alex Marginean alexandru.marginean@nxp.com wrote:
Drivers currently use XGMII for XFI and USXGMII and, where needed, use other information to identify the actual protocol on the board. With these two defined drivers can now rely on DT phy-mode property.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com
Acked-by: Joe Hershberger joe.hershberger@ni.com

This is useful to carry custom information between the driver structure associated with a specific HW and the driver code.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com --- include/phy.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/include/phy.h b/include/phy.h index e50f56b6eb..6ace9b3a0c 100644 --- a/include/phy.h +++ b/include/phy.h @@ -115,6 +115,9 @@ struct phy_driver { u16 val);
struct list_head list; + + /* driver private data */ + ulong data; };
struct phy_device {

On Thu, Nov 14, 2019 at 10:30 AM Alex Marginean alexandru.marginean@nxp.com wrote:
This is useful to carry custom information between the driver structure associated with a specific HW and the driver code.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com
Acked-by: Joe Hershberger joe.hershberger@ni.com

The PHY supports XFI and USXGMII, the notable difference being that USX AN is enabled for USXGMII. Legacy code uses XGMII for any 10G proto and detects whether USX AN should be enabled or not using a PHY status register. Keep that functionality too, so we don't break existing drivers.
Signed-off-by: Razvan Ionut Cirjan razvanionut.cirjan@nxp.com Signed-off-by: Alex Marginean alexandru.marginean@nxp.com --- drivers/net/phy/aquantia.c | 47 ++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 14 deletions(-)
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 465ec2d342..7be1a40608 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -256,8 +256,10 @@ static int aquantia_upload_firmware(struct phy_device *phydev)
int aquantia_config(struct phy_device *phydev) { + int interface = phydev->interface; u32 val, id, rstatus, fault; u32 reg_val1 = 0; + int usx_an = 0;
id = phy_read(phydev, MDIO_MMD_VEND1, GLOBAL_FIRMWARE_ID); rstatus = phy_read(phydev, MDIO_MMD_VEND1, GLOBAL_RSTATUS_1); @@ -278,17 +280,34 @@ int aquantia_config(struct phy_device *phydev) if (ret != 0) return ret; } + /* + * for backward compatibility convert XGMII into either XFI or USX based + * on FW config + */ + if (interface == PHY_INTERFACE_MODE_XGMII) { + reg_val1 = phy_read(phydev, MDIO_MMD_PHYXS, + AQUANTIA_SYSTEM_INTERFACE_SR); + if ((reg_val1 & AQUANTIA_SI_IN_USE_MASK) == AQUANTIA_SI_USXGMII) + interface = PHY_INTERFACE_MODE_USXGMII; + else + interface = PHY_INTERFACE_MODE_XFI; + }
val = phy_read(phydev, MDIO_MMD_PMAPMD, MII_BMCR);
- if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: /* 1000BASE-T mode */ phydev->advertising = SUPPORTED_1000baseT_Full; phydev->supported = phydev->advertising;
val = (val & ~AQUNTIA_SPEED_LSB_MASK) | AQUNTIA_SPEED_MSB_MASK; phy_write(phydev, MDIO_MMD_PMAPMD, MII_BMCR, val); - } else if (phydev->interface == PHY_INTERFACE_MODE_XGMII) { + break; + case PHY_INTERFACE_MODE_USXGMII: + usx_an = 1; + /* FALLTHROUGH */ + case PHY_INTERFACE_MODE_XFI: /* 10GBASE-T mode */ phydev->advertising = SUPPORTED_10000baseT_Full; phydev->supported = phydev->advertising; @@ -299,40 +318,40 @@ int aquantia_config(struct phy_device *phydev) AQUNTIA_SPEED_LSB_MASK | AQUNTIA_SPEED_MSB_MASK);
- val = phy_read(phydev, MDIO_MMD_PHYXS, - AQUANTIA_SYSTEM_INTERFACE_SR); /* If SI is USXGMII then start USXGMII autoneg */ - if ((val & AQUANTIA_SI_IN_USE_MASK) == AQUANTIA_SI_USXGMII) { - reg_val1 = phy_read(phydev, MDIO_MMD_PHYXS, - AQUANTIA_VENDOR_PROVISIONING_REG); + reg_val1 = phy_read(phydev, MDIO_MMD_PHYXS, + AQUANTIA_VENDOR_PROVISIONING_REG);
+ if (usx_an) { reg_val1 |= AQUANTIA_USX_AUTONEG_CONTROL_ENA; - - phy_write(phydev, MDIO_MMD_PHYXS, - AQUANTIA_VENDOR_PROVISIONING_REG, - reg_val1); printf("%s: system interface USXGMII\n", phydev->dev->name); } else { + reg_val1 &= ~AQUANTIA_USX_AUTONEG_CONTROL_ENA; printf("%s: system interface XFI\n", phydev->dev->name); }
- } else if (phydev->interface == PHY_INTERFACE_MODE_SGMII_2500) { + phy_write(phydev, MDIO_MMD_PHYXS, + AQUANTIA_VENDOR_PROVISIONING_REG, reg_val1); + break; + case PHY_INTERFACE_MODE_SGMII_2500: /* 2.5GBASE-T mode */ phydev->advertising = SUPPORTED_1000baseT_Full; phydev->supported = phydev->advertising;
phy_write(phydev, MDIO_MMD_AN, AQUNTIA_10G_CTL, 1); phy_write(phydev, MDIO_MMD_AN, AQUNTIA_VENDOR_P1, 0x9440); - } else if (phydev->interface == PHY_INTERFACE_MODE_MII) { + break; + case PHY_INTERFACE_MODE_MII: /* 100BASE-TX mode */ phydev->advertising = SUPPORTED_100baseT_Full; phydev->supported = phydev->advertising;
val = (val & ~AQUNTIA_SPEED_MSB_MASK) | AQUNTIA_SPEED_LSB_MASK; phy_write(phydev, MDIO_MMD_PMAPMD, MII_BMCR, val); - } + break; + };
val = phy_read(phydev, MDIO_MMD_VEND1, AQUANTIA_RESERVED_STATUS); reg_val1 = phy_read(phydev, MDIO_MMD_VEND1, AQUANTIA_FIRMWARE_ID);

On Thu, Nov 14, 2019 at 10:35 AM Alex Marginean alexandru.marginean@nxp.com wrote:
The PHY supports XFI and USXGMII, the notable difference being that USX AN is enabled for USXGMII. Legacy code uses XGMII for any 10G proto and detects whether USX AN should be enabled or not using a PHY status register. Keep that functionality too, so we don't break existing drivers.
Signed-off-by: Razvan Ionut Cirjan razvanionut.cirjan@nxp.com Signed-off-by: Alex Marginean alexandru.marginean@nxp.com
Acked-by: Joe Hershberger joe.hershberger@ni.com

Uses the data field in phy_driver structure to identify the PHY generation. This is useful for custom configuration as non-generic PHY registers are not 100% compatible between generations.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com --- drivers/net/phy/aquantia.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 7be1a40608..c4f11f2860 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -69,6 +69,12 @@ #define VERSION_STRING_OFFSET 0x0200 #define HEADER_OFFSET 0x300
+/* driver private data */ +#define AQUANTIA_NA 0 +#define AQUANTIA_GEN1 1 +#define AQUANTIA_GEN2 2 +#define AQUANTIA_GEN3 3 + #pragma pack(1) struct fw_header { u8 padding[4]; @@ -452,6 +458,7 @@ struct phy_driver aqr105_driver = { .config = &aquantia_config, .startup = &aquantia_startup, .shutdown = &gen10g_shutdown, + .data = AQUANTIA_GEN1, };
struct phy_driver aqr106_driver = { @@ -478,6 +485,7 @@ struct phy_driver aqr107_driver = { .config = &aquantia_config, .startup = &aquantia_startup, .shutdown = &gen10g_shutdown, + .data = AQUANTIA_GEN2, };
struct phy_driver aqr112_driver = { @@ -491,6 +499,7 @@ struct phy_driver aqr112_driver = { .config = &aquantia_config, .startup = &aquantia_startup, .shutdown = &gen10g_shutdown, + .data = AQUANTIA_GEN3, };
struct phy_driver aqr405_driver = { @@ -504,6 +513,7 @@ struct phy_driver aqr405_driver = { .config = &aquantia_config, .startup = &aquantia_startup, .shutdown = &gen10g_shutdown, + .data = AQUANTIA_GEN1, };
struct phy_driver aqr412_driver = { @@ -517,6 +527,7 @@ struct phy_driver aqr412_driver = { .config = &aquantia_config, .startup = &aquantia_startup, .shutdown = &gen10g_shutdown, + .data = AQUANTIA_GEN3, };
int phy_aquantia_init(void)

On Thu, Nov 14, 2019 at 10:32 AM Alex Marginean alexandru.marginean@nxp.com wrote:
Uses the data field in phy_driver structure to identify the PHY generation. This is useful for custom configuration as non-generic PHY registers are not 100% compatible between generations.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com
Acked-by: Joe Hershberger joe.hershberger@ni.com

If PHY is not ready for data by the time _config is called, reconfigure the PHY system interface to use the proper protocol based on phydev->interface, just in case the defaults set by PHY firmware don't match current configuration.
Signed-off-by: Florin Laurentiu Chiculita florinlaurentiu.chiculita@nxp.com Signed-off-by: Alex Marginean alexandru.marginean@nxp.com --- drivers/net/phy/aquantia.c | 107 +++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+)
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index c4f11f2860..97f202afd4 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -21,6 +21,7 @@ #define AQUNTIA_SPEED_MSB_MASK 0x40
#define AQUANTIA_SYSTEM_INTERFACE_SR 0xe812 +#define AQUANTIA_SYSTEM_INTERFACE_SR_READY BIT(0) #define AQUANTIA_VENDOR_PROVISIONING_REG 0xC441 #define AQUANTIA_FIRMWARE_ID 0x20 #define AQUANTIA_RESERVED_STATUS 0xc885 @@ -33,6 +34,9 @@ #define AQUANTIA_SI_USXGMII 0x0018
/* registers in MDIO_MMD_VEND1 region */ +#define AQUANTIA_VND1_GLOBAL_SC 0x000 +#define AQUANTIA_VND1_GLOBAL_SC_LP BIT(0xb) + #define GLOBAL_FIRMWARE_ID 0x20 #define GLOBAL_FAULT 0xc850 #define GLOBAL_RSTATUS_1 0xc885 @@ -60,6 +64,26 @@ #define UP_RUN_STALL_OVERRIDE BIT(6) #define UP_RUN_STALL BIT(0)
+/* + * global start rate, the protocol associated with this speed is used by default + * on SI. + */ +#define AQUANTIA_VND1_GSTART_RATE 0x31a +#define AQUANTIA_VND1_GSTART_RATE_OFF 0 +#define AQUANTIA_VND1_GSTART_RATE_100M 1 +#define AQUANTIA_VND1_GSTART_RATE_1G 2 +#define AQUANTIA_VND1_GSTART_RATE_10G 3 +#define AQUANTIA_VND1_GSTART_RATE_2_5G 4 +#define AQUANTIA_VND1_GSTART_RATE_5G 5 + +/* SYSCFG registers for 100M, 1G, 2.5G, 5G, 10G */ +#define AQUANTIA_VND1_GSYSCFG_BASE 0x31b +#define AQUANTIA_VND1_GSYSCFG_100M 0 +#define AQUANTIA_VND1_GSYSCFG_1G 1 +#define AQUANTIA_VND1_GSYSCFG_2_5G 2 +#define AQUANTIA_VND1_GSYSCFG_5G 3 +#define AQUANTIA_VND1_GSYSCFG_10G 4 + /* addresses of memory segments in the phy */ #define DRAM_BASE_ADDR 0x3FFE0000 #define IRAM_BASE_ADDR 0x40000000 @@ -260,6 +284,68 @@ static int aquantia_upload_firmware(struct phy_device *phydev) } #endif
+struct { + u16 syscfg; + int cnt; + u16 start_rate; +} aquantia_syscfg[PHY_INTERFACE_MODE_COUNT] = { + [PHY_INTERFACE_MODE_SGMII] = {0x04b, AQUANTIA_VND1_GSYSCFG_1G, + AQUANTIA_VND1_GSTART_RATE_1G}, + [PHY_INTERFACE_MODE_SGMII_2500] = {0x144, AQUANTIA_VND1_GSYSCFG_2_5G, + AQUANTIA_VND1_GSTART_RATE_2_5G}, + [PHY_INTERFACE_MODE_XGMII] = {0x100, AQUANTIA_VND1_GSYSCFG_10G, + AQUANTIA_VND1_GSTART_RATE_10G}, + [PHY_INTERFACE_MODE_XFI] = {0x100, AQUANTIA_VND1_GSYSCFG_10G, + AQUANTIA_VND1_GSTART_RATE_10G}, + [PHY_INTERFACE_MODE_USXGMII] = {0x080, AQUANTIA_VND1_GSYSCFG_10G, + AQUANTIA_VND1_GSTART_RATE_10G}, +}; + +static int aquantia_set_proto(struct phy_device *phydev) +{ + int i; + + if (!aquantia_syscfg[phydev->interface].cnt) + return 0; + + /* set the default rate to enable the SI link */ + phy_write(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GSTART_RATE, + aquantia_syscfg[phydev->interface].start_rate); + + /* set selected protocol for all relevant line side link speeds */ + for (i = 0; i <= aquantia_syscfg[phydev->interface].cnt; i++) + phy_write(phydev, MDIO_MMD_VEND1, + AQUANTIA_VND1_GSYSCFG_BASE + i, + aquantia_syscfg[phydev->interface].syscfg); + return 0; +} + +static bool aquantia_link_is_up(struct phy_device *phydev) +{ + u16 reg, regmask; + int devad, regnum; + + /* + * On Gen 2 and 3 we have a bit that indicates that both system and + * line side are ready for data, use that if possible. + */ + if (phydev->drv->data == AQUANTIA_GEN2 || + phydev->drv->data == AQUANTIA_GEN3) { + devad = MDIO_MMD_PHYXS; + regnum = AQUANTIA_SYSTEM_INTERFACE_SR; + regmask = AQUANTIA_SYSTEM_INTERFACE_SR_READY; + } else { + devad = MDIO_MMD_AN; + regnum = MDIO_STAT1; + regmask = MDIO_AN_STAT1_COMPLETE; + } + /* the register should be latched, do a double read */ + phy_read(phydev, devad, regnum); + reg = phy_read(phydev, devad, regnum); + + return !!(reg & regmask); +} + int aquantia_config(struct phy_device *phydev) { int interface = phydev->interface; @@ -299,6 +385,27 @@ int aquantia_config(struct phy_device *phydev) interface = PHY_INTERFACE_MODE_XFI; }
+ /* + * if link is up already we can just use it, otherwise configure + * the protocols in the PHY. If link is down set the system + * interface protocol to use based on phydev->interface + */ + if (!aquantia_link_is_up(phydev) && + (phydev->drv->data == AQUANTIA_GEN2 || + phydev->drv->data == AQUANTIA_GEN3)) { + /* set PHY in low power mode so we can configure protocols */ + phy_write(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GLOBAL_SC, + AQUANTIA_VND1_GLOBAL_SC_LP); + mdelay(10); + + /* configure protocol based on phydev->interface */ + aquantia_set_proto(phydev); + + /* wake PHY back up */ + phy_write(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GLOBAL_SC, 0); + mdelay(10); + } + val = phy_read(phydev, MDIO_MMD_PMAPMD, MII_BMCR);
switch (interface) {

On Thu, Nov 14, 2019 at 10:33 AM Alex Marginean alexandru.marginean@nxp.com wrote:
If PHY is not ready for data by the time _config is called, reconfigure the PHY system interface to use the proper protocol based on phydev->interface, just in case the defaults set by PHY firmware don't match current configuration.
Signed-off-by: Florin Laurentiu Chiculita florinlaurentiu.chiculita@nxp.com Signed-off-by: Alex Marginean alexandru.marginean@nxp.com
Acked-by: Joe Hershberger joe.hershberger@ni.com

MDI pins up to the RJ45 connector may be reversed on the board and the default PHY configuration applied by firmware may or may not match that. Add an optional DT property to configure MDI reversal for this case.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com --- drivers/net/phy/aquantia.c | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 97f202afd4..06532c51d5 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -64,6 +64,13 @@ #define UP_RUN_STALL_OVERRIDE BIT(6) #define UP_RUN_STALL BIT(0)
+#define AQUANTIA_PMA_RX_VENDOR_P1 0xe400 +#define AQUANTIA_PMA_RX_VENDOR_P1_MDI_MSK GENMASK(1, 0) +/* MDI reversal configured through registers */ +#define AQUANTIA_PMA_RX_VENDOR_P1_MDI_CFG BIT(1) +/* MDI reversal enabled */ +#define AQUANTIA_PMA_RX_VENDOR_P1_MDI_REV BIT(0) + /* * global start rate, the protocol associated with this speed is used by default * on SI. @@ -320,6 +327,36 @@ static int aquantia_set_proto(struct phy_device *phydev) return 0; }
+static int aquantia_dts_config(struct phy_device *phydev) +{ +#ifdef CONFIG_DM_ETH + ofnode node = phydev->node; + u32 prop; + u16 reg; + + /* this code only works on gen2 and gen3 PHYs */ + if (phydev->drv->data != AQUANTIA_GEN2 && + phydev->drv->data != AQUANTIA_GEN3) + return -ENOTSUPP; + + if (!ofnode_valid(node)) + return 0; + + if (!ofnode_read_u32(node, "mdi-reversal", &prop)) { + debug("mdi-reversal = %d\n", (int)prop); + reg = phy_read(phydev, MDIO_MMD_PMAPMD, + AQUANTIA_PMA_RX_VENDOR_P1); + reg &= ~AQUANTIA_PMA_RX_VENDOR_P1_MDI_MSK; + reg |= AQUANTIA_PMA_RX_VENDOR_P1_MDI_CFG; + reg |= prop ? AQUANTIA_PMA_RX_VENDOR_P1_MDI_REV : 0; + phy_write(phydev, MDIO_MMD_PMAPMD, AQUANTIA_PMA_RX_VENDOR_P1, + reg); + } + +#endif + return 0; +} + static bool aquantia_link_is_up(struct phy_device *phydev) { u16 reg, regmask; @@ -400,6 +437,8 @@ int aquantia_config(struct phy_device *phydev)
/* configure protocol based on phydev->interface */ aquantia_set_proto(phydev); + /* apply custom configuration based on DT */ + aquantia_dts_config(phydev);
/* wake PHY back up */ phy_write(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GLOBAL_SC, 0);

On Thu, Nov 14, 2019 at 10:34 AM Alex Marginean alexandru.marginean@nxp.com wrote:
MDI pins up to the RJ45 connector may be reversed on the board and the default PHY configuration applied by firmware may or may not match that. Add an optional DT property to configure MDI reversal for this case.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com
Acked-by: Joe Hershberger joe.hershberger@ni.com

Aquantia PHYs have a SMBus interface mostly used for debug. The addresses on this interface are normally set up by PHY firmware, but depending on the board they may end up not being unique. Add an optional DT property used to change SMBus address if needed.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com --- drivers/net/phy/aquantia.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 06532c51d5..151e0ee9e9 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -91,6 +91,9 @@ #define AQUANTIA_VND1_GSYSCFG_5G 3 #define AQUANTIA_VND1_GSYSCFG_10G 4
+#define AQUANTIA_VND1_SMBUS0 0xc485 +#define AQUANTIA_VND1_SMBUS1 0xc495 + /* addresses of memory segments in the phy */ #define DRAM_BASE_ADDR 0x3FFE0000 #define IRAM_BASE_ADDR 0x40000000 @@ -352,6 +355,18 @@ static int aquantia_dts_config(struct phy_device *phydev) phy_write(phydev, MDIO_MMD_PMAPMD, AQUANTIA_PMA_RX_VENDOR_P1, reg); } + if (!ofnode_read_u32(node, "smb-addr", &prop)) { + debug("smb-addr = %x\n", (int)prop); + /* + * there are two addresses here, normally just one bus would + * be in use so we're setting both regs using the same DT + * property. + */ + phy_write(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_SMBUS0, + (u16)(prop << 1)); + phy_write(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_SMBUS1, + (u16)(prop << 1)); + }
#endif return 0;

On Thu, Nov 14, 2019 at 10:31 AM Alex Marginean alexandru.marginean@nxp.com wrote:
Aquantia PHYs have a SMBus interface mostly used for debug. The addresses on this interface are normally set up by PHY firmware, but depending on the board they may end up not being unique. Add an optional DT property used to change SMBus address if needed.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com
Acked-by: Joe Hershberger joe.hershberger@ni.com

In some cases the link on the system interface of the aquantia PHY comes up after the link on line interface. The link state loop only checks the line side, which may result in first packet sent being lost. Use aquantia_link_is_up instead, which checks both system and line side on gen 2/3 PHYs to avoid losing the 1st packet.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com --- drivers/net/phy/aquantia.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 151e0ee9e9..7817d3cb8d 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -540,17 +540,14 @@ int aquantia_startup(struct phy_device *phydev) phydev->duplex = DUPLEX_FULL;
/* if the AN is still in progress, wait till timeout. */ - phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1); - reg = phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1); - if (!(reg & MDIO_AN_STAT1_COMPLETE)) { + if (!aquantia_link_is_up(phydev)) { printf("%s Waiting for PHY auto negotiation to complete", phydev->dev->name); do { udelay(1000); - reg = phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1); if ((i++ % 500) == 0) printf("."); - } while (!(reg & MDIO_AN_STAT1_COMPLETE) && + } while (!aquantia_link_is_up(phydev) && i < (4 * PHY_ANEG_TIMEOUT));
if (i > PHY_ANEG_TIMEOUT)

On Thu, Nov 14, 2019 at 10:32 AM Alex Marginean alexandru.marginean@nxp.com wrote:
In some cases the link on the system interface of the aquantia PHY comes up after the link on line interface. The link state loop only checks the line side, which may result in first packet sent being lost. Use aquantia_link_is_up instead, which checks both system and line side on gen 2/3 PHYs to avoid losing the 1st packet.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com
Acked-by: Joe Hershberger joe.hershberger@ni.com

It defines that PHY nodes must be children on MDIO bus nodes and defines the only required property in U-Boot, reg. This property along with the example provided are copied over from Linux.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com --- doc/device-tree-bindings/net/phy.txt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 doc/device-tree-bindings/net/phy.txt
diff --git a/doc/device-tree-bindings/net/phy.txt b/doc/device-tree-bindings/net/phy.txt new file mode 100644 index 0000000000..6599c667b5 --- /dev/null +++ b/doc/device-tree-bindings/net/phy.txt @@ -0,0 +1,24 @@ +PHY nodes + +If the device tree is used to describe networking interfaces, U-Boot expects a +node for each PHY. Parent node for such a PHY node is expected to correspond to +a MDIO bus and the bus is used to access the PHY. + +Required properties: + + - reg : The ID number for the phy, usually a small integer + +Example: + +ethernet-phy@0 { + compatible = "ethernet-phy-id0141.0e90", "ethernet-phy-ieee802.3-c22"; + interrupt-parent = <&PIC>; + interrupts = <35 IRQ_TYPE_EDGE_RISING>; + reg = <0>; + + resets = <&rst 8>; + reset-names = "phy"; + reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; + reset-assert-us = <1000>; + reset-deassert-us = <2000>; +};

On Thu, Nov 14, 2019 at 10:33 AM Alex Marginean alexandru.marginean@nxp.com wrote:
It defines that PHY nodes must be children on MDIO bus nodes and defines the only required property in U-Boot, reg. This property along with the example provided are copied over from Linux.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com
Acked-by: Joe Hershberger joe.hershberger@ni.com

A couple of optional properties have been introduced for Aquantia PHY allowing the driver to set up wiring related configuration points that are otherwise driven by firmware.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com --- doc/device-tree-bindings/net/aquantia-phy.txt | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 doc/device-tree-bindings/net/aquantia-phy.txt
diff --git a/doc/device-tree-bindings/net/aquantia-phy.txt b/doc/device-tree-bindings/net/aquantia-phy.txt new file mode 100644 index 0000000000..89ce61e05b --- /dev/null +++ b/doc/device-tree-bindings/net/aquantia-phy.txt @@ -0,0 +1,25 @@ +PHY nodes for Aquantia devices. + +This text describes properties that are applicable to Aquantia PHY nodes in +addition to the bindings in phy.txt. + +Aquantia PHYs allow some flexibility in the way they are wired in a system, +they allow MDI pins to be reversed, LEDs linked up in different weays, have an +I2C slave interface that can be used for debug. Normally the configuration +corresponding to these is driven by the PHY firmware with the downside that +a custom firmware is needed for each integration of a PHY. +Several optional bindings are defined that allow these configuration points to +be driven by the PHY driver and reduce dependency on specific FW versions. + +Optional properties: +mdi-reversal: 0 or 1 indicating that reversal must be disabled/enabled. + Firmware default is used if the property is missing. +smb-addr: I2C/SMBus address to use, firmware default is used if the property + is missing. + +Example node: +phy@00 { + reg = <0x00>; + mdi-reversal = <1>; + smb-addr = <0x25>; +};

On Thu, Nov 14, 2019 at 10:34 AM Alex Marginean alexandru.marginean@nxp.com wrote:
A couple of optional properties have been introduced for Aquantia PHY allowing the driver to set up wiring related configuration points that are otherwise driven by firmware.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com
Acked-by: Joe Hershberger joe.hershberger@ni.com

Apply 10G PCS init for USXGMII, XFI interface types.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com --- drivers/net/fsl_enetc.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c index e1713a3337..c94ba240f8 100644 --- a/drivers/net/fsl_enetc.c +++ b/drivers/net/fsl_enetc.c @@ -197,6 +197,8 @@ static void enetc_start_pcs(struct udevice *dev) enetc_init_rgmii(dev); break; case PHY_INTERFACE_MODE_XGMII: + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_XFI: enetc_init_sxgmii(dev); break; };

On Thu, Nov 14, 2019 at 10:31 AM Alex Marginean alexandru.marginean@nxp.com wrote:
Apply 10G PCS init for USXGMII, XFI interface types.
Signed-off-by: Alex Marginean alexandru.marginean@nxp.com
Acked-by: Joe Hershberger joe.hershberger@ni.com
participants (2)
-
Alex Marginean
-
Joe Hershberger