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

2019-10-11 Thread Florin Laurentiu Chiculita
Hi Alex,

> -Original Message-
> From: U-Boot  On Behalf Of Alex Marginean
> Sent: Thursday, August 8, 2019 7:45 PM
> To: u-boot@lists.denx.de
> Cc: Joe Hershberger ; Razvan Ionut Cirjan
> 
> 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 
> Signed-off-by: Alex Marginean 
> ---
>  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_READYBIT(0)
>  #define AQUANTIA_VENDOR_PROVISIONING_REG 0xC441
>  #define AQUANTIA_FIRMWARE_ID0x20
>  #define AQUANTIA_RESERVED_STATUS0xc885
> @@ -33,6 +34,9 @@
>  #define AQUANTIA_SI_USXGMII  0x0018
> 
>  /* registers in MDIO_MMD_VEND1 region */
> +#define AQUANTIA_VND1_GLOBAL_SC0x000
> +#define  AQUANTIA_VND1_GLOBAL_SC_LPBIT(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_100M1
> +#define  AQUANTIA_VND1_GSTART_RATE_1G  2
> +#define  AQUANTIA_VND1_GSTART_RATE_10G 3
> +#define  AQUANTIA_VND1_GSTART_RATE_2_5G4
> +#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
> 0x3FFE  #define IRAM_BASE_ADDR 0x4000 @@ -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,

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

2019-08-08 Thread Alex Marginean
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 
Signed-off-by: Alex Marginean 
---
 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_READYBIT(0)
 #define AQUANTIA_VENDOR_PROVISIONING_REG 0xC441
 #define AQUANTIA_FIRMWARE_ID0x20
 #define AQUANTIA_RESERVED_STATUS0xc885
@@ -33,6 +34,9 @@
 #define AQUANTIA_SI_USXGMII  0x0018
 
 /* registers in MDIO_MMD_VEND1 region */
+#define AQUANTIA_VND1_GLOBAL_SC0x000
+#define  AQUANTIA_VND1_GLOBAL_SC_LPBIT(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_100M1
+#define  AQUANTIA_VND1_GSTART_RATE_1G  2
+#define  AQUANTIA_VND1_GSTART_RATE_10G 3
+#define  AQUANTIA_VND1_GSTART_RATE_2_5G4
+#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 0x3FFE
 #define IRAM_BASE_ADDR 0x4000
@@ -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;