RE: [RFC PATCH 1/1] net: xilinx: handle internal PHY/PCS

2022-09-12 Thread Katakam, Harini
Hi Nikita,


> > > >
> > > > +   if (pcsdev) {
> > > > +   /* It looks like we need a bit of delay for core
> > > > to come up
> > > > +* may be we could poll MgtRdy or PhyRstCmplt bit
> > > > +* in 0x0010, but 1 msec is no a big deal.
> > > > +*/
> > > > +   udelay(1000);
> > > > +   ret = phywrite(priv, pcsdev->addr, MII_BMCR,
> > > > +   BMCR_ANENABLE | BMCR_FULLDPLX |
> > > BMCR_SPEED1000);
> >
> > Thanks for the patch.
> > Could you please confirm that BMCR_ISOLATE is also being handled in
> > the autonegotiation path? For ex., the equivalent in linux can be
> > found here:
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tre
> > e/drivers/net/phy/phylink.c#n3050
> 
> For linux BMCR_ISOLATE is cleared and BMCR_ANENABLE is set (if mode is
> MLO_AN_INBAND which is definitely our case) in
> phylink_mii_c22_pcs_config.
> 
> In current patch BMCR_ISOLATE is cleared by write, may be indeed
> something like:
> phyread(priv, pcsdev->addr, MII_BMCR, &val); val &= ~(BMCR_ISOLATE); val
> |= BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000; phywrite(priv,
> pcsdev->addr, MII_BMCR, val);
> 
> Whould make more sense.

Thanks, yes it is cleared by the explicit value written. That's fine.
The read-modify-write snippet you mentioned above is just good to have.

> 
> >
> > Could you also please handle the SGMII/1000BaseX standard selection in
> > the PCS PMA IP? For reference, please see:
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tre
> > e/drivers/net/ethernet/xilinx/xilinx_axienet_main.c#n1619
> 
> You mean to handle "xlnx,switch-x-sgmii" device tree property in same
> manner as linux does? No problem then.

Yes, thanks.

Regards,
Harini


Re: [RFC PATCH 1/1] net: xilinx: handle internal PHY/PCS

2022-09-02 Thread Nikita Shubin
Hello Harini!

Sorry for long response time.

On Wed, 24 Aug 2022 12:51:08 +
"Katakam, Harini"  wrote:


> Hi Nikita,
> 
> > -Original Message-
> > From: Simek, Michal 
> > Sent: Thursday, August 11, 2022 1:16 PM
> > To: Nikita Shubin ; Agarwal, Swati
> > ; Pandey, Radhey Shyam
> > 
> > Cc: li...@yadro.com; Nikita Shubin ; Joe
> > Hershberger ; Ramon Fried
> > ; u-boot@lists.denx.de
> > Subject: Re: [RFC PATCH 1/1] net: xilinx: handle internal PHY/PCS
> > 
> > Hi Nikita,
> > 
> > On 8/2/22 12:53, Nikita Shubin wrote:  
> > > From: Nikita Shubin 
> > >
> > > In SGMII/1000BaseX Xilinx AXI Ethernet may also have an Internal
> > > PHY (PCS) in addition to external PHY, in that case we should
> > > also set at least BMCR_ANENABLE.
> > >
> > > PCS are not visible until axinet bringup, so init should be done
> > > after, controller is brought up, then we should poll
> > > BMSR_ANEGCOMPLETE prior to polling the external PHY.
> > >
> > > The PCS handling relies on "pcs-handle" device tree handle which
> > > serves the similar purpose in Linux device tree.
> > >
> > > Signed-off-by: Nikita Shubin 
> > > ---  
> 
> > > @@ -540,6 +565,20 @@ static int axiemac_start(struct udevice *dev)
> > >   return -1;
> > >   }
> > >
> > > + if (pcsdev) {
> > > + /* It looks like we need a bit of delay for core
> > > to come up
> > > +  * may be we could poll MgtRdy or PhyRstCmplt bit
> > > +  * in 0x0010, but 1 msec is no a big deal.
> > > +  */
> > > + udelay(1000);
> > > + ret = phywrite(priv, pcsdev->addr, MII_BMCR,
> > > + BMCR_ANENABLE | BMCR_FULLDPLX |  
> > BMCR_SPEED1000);  
> 
> Thanks for the patch.
> Could you please confirm that BMCR_ISOLATE is also being handled in
> the autonegotiation path? For ex., the equivalent in linux can be
> found here:
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/phy/phylink.c#n3050

For linux BMCR_ISOLATE is cleared and BMCR_ANENABLE is set (if mode is
MLO_AN_INBAND which is definitely our case) in
phylink_mii_c22_pcs_config. 

In current patch BMCR_ISOLATE is cleared by write, may be indeed
something like:
phyread(priv, pcsdev->addr, MII_BMCR, &val);
val &= ~(BMCR_ISOLATE);
val |= BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000;
phywrite(priv, pcsdev->addr, MII_BMCR, val);

Whould make more sense.

> 
> Could you also please handle the SGMII/1000BaseX standard selection
> in the PCS PMA IP? For reference, please see:
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/xilinx/xilinx_axienet_main.c#n1619

You mean to handle "xlnx,switch-x-sgmii" device tree property in same
manner as linux does? No problem then.

Yours,
Nikita Shubin.


> 
> Regards,
> Harini



RE: [RFC PATCH 1/1] net: xilinx: handle internal PHY/PCS

2022-08-24 Thread Katakam, Harini
Hi Nikita,

> -Original Message-
> From: Simek, Michal 
> Sent: Thursday, August 11, 2022 1:16 PM
> To: Nikita Shubin ; Agarwal, Swati
> ; Pandey, Radhey Shyam
> 
> Cc: li...@yadro.com; Nikita Shubin ; Joe
> Hershberger ; Ramon Fried
> ; u-boot@lists.denx.de
> Subject: Re: [RFC PATCH 1/1] net: xilinx: handle internal PHY/PCS
> 
> Hi Nikita,
> 
> On 8/2/22 12:53, Nikita Shubin wrote:
> > From: Nikita Shubin 
> >
> > In SGMII/1000BaseX Xilinx AXI Ethernet may also have an Internal PHY
> > (PCS) in addition to external PHY, in that case we should also set at
> > least BMCR_ANENABLE.
> >
> > PCS are not visible until axinet bringup, so init should be done
> > after, controller is brought up, then we should poll BMSR_ANEGCOMPLETE
> > prior to polling the external PHY.
> >
> > The PCS handling relies on "pcs-handle" device tree handle which
> > serves the similar purpose in Linux device tree.
> >
> > Signed-off-by: Nikita Shubin 
> > ---

> > @@ -540,6 +565,20 @@ static int axiemac_start(struct udevice *dev)
> > return -1;
> > }
> >
> > +   if (pcsdev) {
> > +   /* It looks like we need a bit of delay for core to come up
> > +* may be we could poll MgtRdy or PhyRstCmplt bit
> > +* in 0x0010, but 1 msec is no a big deal.
> > +*/
> > +   udelay(1000);
> > +   ret = phywrite(priv, pcsdev->addr, MII_BMCR,
> > +   BMCR_ANENABLE | BMCR_FULLDPLX |
> BMCR_SPEED1000);

Thanks for the patch.
Could you please confirm that BMCR_ISOLATE is also being handled in
the autonegotiation path? For ex., the equivalent in linux can be found
here:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/phy/phylink.c#n3050

Could you also please handle the SGMII/1000BaseX standard selection
in the PCS PMA IP? For reference, please see:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/xilinx/xilinx_axienet_main.c#n1619

Regards,
Harini


Re: [RFC PATCH 1/1] net: xilinx: handle internal PHY/PCS

2022-08-11 Thread Michal Simek

Hi Nikita,

On 8/2/22 12:53, Nikita Shubin wrote:

From: Nikita Shubin 

In SGMII/1000BaseX Xilinx AXI Ethernet may also have an
Internal PHY (PCS) in addition to external PHY, in that case
we should also set at least BMCR_ANENABLE.

PCS are not visible until axinet bringup, so init should be done after,
controller is brought up, then we should poll BMSR_ANEGCOMPLETE
prior to polling the external PHY.

The PCS handling relies on "pcs-handle" device tree handle which serves
the similar purpose in Linux device tree.

Signed-off-by: Nikita Shubin 
---
  drivers/net/xilinx_axi_emac.c | 50 +--
  1 file changed, 48 insertions(+), 2 deletions(-)

diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index 04277b1269..edbcf6fae3 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -84,6 +84,9 @@ DECLARE_GLOBAL_DATA_PTR;
  #define DMAALIGN  128
  #define XXV_MIN_PKT_SIZE  60
  
+/* Xilinx internal PCS PHY ID */

+#define XILINX_PHY_ID  0x01740c00
+
  static u8 rxframe[PKTSIZE_ALIGN] __attribute((aligned(DMAALIGN)));
  static u8 txminframe[XXV_MIN_PKT_SIZE] __attribute((aligned(DMAALIGN)));
  
@@ -108,6 +111,7 @@ struct axidma_plat {

struct axidma_reg *dmatx;
struct axidma_reg *dmarx;
int phyaddr;
+   int pcsaddr;
u8 eth_hasnobuf;
int phy_of_handle;
enum emac_variant mactype;
@@ -118,9 +122,11 @@ struct axidma_priv {
struct axidma_reg *dmatx;
struct axidma_reg *dmarx;
int phyaddr;
+   int pcsaddr;
struct axi_regs *iobase;
phy_interface_t interface;
struct phy_device *phydev;
+   struct phy_device *pcsdev;
struct mii_dev *bus;
u8 eth_hasnobuf;
int phy_of_handle;
@@ -285,6 +291,7 @@ static int axiemac_phy_init(struct udevice *dev)
struct axidma_priv *priv = dev_get_priv(dev);
struct axi_regs *regs = priv->iobase;
struct phy_device *phydev;
+   struct phy_device *pcsdev;
  
  	u32 supported = SUPPORTED_10baseT_Half |

SUPPORTED_10baseT_Full |
@@ -324,6 +331,15 @@ static int axiemac_phy_init(struct udevice *dev)
priv->phydev->node = offset_to_ofnode(priv->phy_of_handle);
phy_config(phydev);
  
+	/* Creating PCS phy here, but it shouldn't be accessed before axiemac_start */

+   if (priv->pcsaddr != -1) {
+   pcsdev = phy_device_create(priv->bus, priv->pcsaddr,
+   XILINX_PHY_ID, false);
+   pcsdev->dev = dev;
+   priv->pcsdev = pcsdev;
+   printf("axiemac: registered PCS phy, 0x%x\n", priv->pcsaddr);
+   }
+
return 0;
  }
  
@@ -335,6 +351,7 @@ static int setup_phy(struct udevice *dev)

struct axidma_priv *priv = dev_get_priv(dev);
struct axi_regs *regs = priv->iobase;
struct phy_device *phydev = priv->phydev;
+   struct phy_device *pcsdev = priv->pcsdev;
  
  	if (priv->interface == PHY_INTERFACE_MODE_SGMII) {

/*
@@ -353,6 +370,12 @@ static int setup_phy(struct udevice *dev)
}
}
  
+	if (pcsdev && genphy_update_link(pcsdev)) {

+   printf("axiemac: could not initialize PCS %s\n",
+   pcsdev->dev->name);
+   return 0;
+   }
+
if (phy_startup(phydev)) {
printf("axiemac: could not initialize PHY %s\n",
   phydev->dev->name);
@@ -520,7 +543,9 @@ static void axi_dma_init(struct axidma_priv *priv)
  static int axiemac_start(struct udevice *dev)
  {
struct axidma_priv *priv = dev_get_priv(dev);
+   struct phy_device *pcsdev = priv->pcsdev;
u32 temp;
+   int ret;
  
  	debug("axiemac: Init started\n");

/*
@@ -540,6 +565,20 @@ static int axiemac_start(struct udevice *dev)
return -1;
}
  
+	if (pcsdev) {

+   /* It looks like we need a bit of delay for core to come up
+* may be we could poll MgtRdy or PhyRstCmplt bit
+* in 0x0010, but 1 msec is no a big deal.
+*/
+   udelay(1000);
+   ret = phywrite(priv, pcsdev->addr, MII_BMCR,
+   BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000);
+   if (ret) {
+   printf("%s: failed to init PCS\n", __func__);
+   return -1;
+   }
+   }
+
/* Disable all RX interrupts before RxBD space setup */
temp = readl(&priv->dmarx->control);
temp &= ~XAXIDMA_IRQ_ALL_MASK;
@@ -781,6 +820,7 @@ static int axi_emac_probe(struct udevice *dev)
priv->phyaddr = plat->phyaddr;
priv->phy_of_handle = plat->phy_of_handle;
priv->interface = pdata->phy_interface;
+   priv->pcsaddr = plat->pcsaddr;
  
  		if (IS_