Re: [U-Boot] [PATCH 05/11] drivers: net: aquantia: set up SI protocol based on interface type

Hi Alex,
-----Original Message----- From: U-Boot u-boot-bounces@lists.denx.de On Behalf Of Alex Marginean Sent: Thursday, August 8, 2019 7:45 PM To: u-boot@lists.denx.de Cc: Joe Hershberger joe.hershberger@ni.com; Razvan Ionut Cirjan razvanionut.cirjan@nxp.com Subject: [EXT] [U-Boot] [PATCH 05/11] drivers: net: aquantia: set up SI protocol based on interface type
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: Razvan Ionut Cirjan razvanionut.cirjan@nxp.com Signed-off-by: Alex Marginean alexm.osslist@gmail.com
drivers/net/phy/aquantia.c | 109 +++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+)
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 6425ba2021..ab165e76f5 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,72 @@ 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 if_type) {
int i;
/* this code only works on gen2 and gen3 PHYs */
if (phydev->drv->data != AQUANTIA_GEN2 &&
phydev->drv->data != AQUANTIA_GEN3)
return -ENOTSUPP;
if (!aquantia_syscfg[if_type].cnt)
return 0;
/* set the default rate to enable the SI link */
phy_write(phydev, MDIO_MMD_VEND1,
AQUANTIA_VND1_GSTART_RATE,
aquantia_syscfg[if_type].start_rate);
for (i = 0; i <= aquantia_syscfg[if_type].cnt; i++)
phy_write(phydev, MDIO_MMD_VEND1,
AQUANTIA_VND1_GSYSCFG_BASE + i,
aquantia_syscfg[if_type].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 if_type = phydev->interface; @@ -299,6 +389,25 @@ int aquantia_config(struct phy_device *phydev) if_type = PHY_INTERFACE_MODE_XFI; }
Aquantia's Gen1 Quad PHYs have some issues when entering low-power state which is required to reconfigure the system interface or other settings. It is the case of AQR405 ethernet phy. More precisely, bit 1e.c831.f remains set all the time indicating a intense-cpu operation and the phy does not seem to recover. A quick fix would be a check for phydev->drv->data to prevent Gen1 entering low-power mode, with the drawback that they will not benefit from the new added functionality.
if (!aquantia_link_is_up(phydev)) {
/*
* 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
*/
/* 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, if_type);
/* 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);
-- 2.17.1
Cheers, -- Florin Chiculita _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
participants (1)
-
Florin Laurentiu Chiculita