diff mbox series

[12/14] net: axienet: Autodetect 64-bit DMA capability

Message ID 20200110115415.75683-13-andre.przywara@arm.com (mailing list archive)
State New, archived
Headers show
Series net: axienet: Error handling, SGMII and 64-bit DMA fixes | expand

Commit Message

Andre Przywara Jan. 10, 2020, 11:54 a.m. UTC
When newer revisions of the Axienet IP are configured for a 64-bit bus,
we *need* to write to the MSB part of the an address registers,
otherwise the IP won't recognise this as a DMA start condition.
This is even true when the actual DMA address comes from the lower 4 GB.

To autodetect this configuration, at probe time we write all 1's to such
an MSB register, and see if any bits stick. If this is configured for a
32-bit bus, those MSB registers are RES0, so reading back 0 indicates
that no MSB writes are necessary.
On the other hands reading anything other than 0 indicated the need to
write the MSB registers, so we set the respective flag.

For now this leaves the actual DMA mask at 32-bit, as we can't reliably
detect the actually wired number of address lines beyond 32.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/net/ethernet/xilinx/xilinx_axienet.h  |  1 +
 .../net/ethernet/xilinx/xilinx_axienet_main.c | 27 +++++++++++++++++++
 2 files changed, 28 insertions(+)

Comments

Andrew Lunn Jan. 10, 2020, 2:08 p.m. UTC | #1
> To autodetect this configuration, at probe time we write all 1's to such
> an MSB register, and see if any bits stick.

So there is no register you can read containing the IP version?

   Andrew
Andre Przywara Jan. 10, 2020, 2:13 p.m. UTC | #2
On Fri, 10 Jan 2020 15:08:52 +0100
Andrew Lunn <andrew@lunn.ch> wrote:

Hi Andrew,

thanks for having a look!

> > To autodetect this configuration, at probe time we write all 1's to such
> > an MSB register, and see if any bits stick.  
> 
> So there is no register you can read containing the IP version?

There is, and I actually read this before doing this check. But the 64-bit DMA capability is optional even in this revision. It depends on what you give it as the address width. If you say 32, the IP config tool disables the 64-bit capability completely, so it stays compatible with older revisions.
Anything beyond 32 will enable the MSB register and will also require you to write to them.

Cheers,
Andre
Andrew Lunn Jan. 10, 2020, 2:22 p.m. UTC | #3
On Fri, Jan 10, 2020 at 02:13:03PM +0000, Andre Przywara wrote:
> On Fri, 10 Jan 2020 15:08:52 +0100
> Andrew Lunn <andrew@lunn.ch> wrote:
> 
> Hi Andrew,
> 
> thanks for having a look!
> 
> > > To autodetect this configuration, at probe time we write all 1's to such
> > > an MSB register, and see if any bits stick.  
> > 
> > So there is no register you can read containing the IP version?
> 
> There is, and I actually read this before doing this check. But the 64-bit DMA capability is optional even in this revision. It depends on what you give it as the address width. If you say 32, the IP config tool disables the 64-bit capability completely, so it stays compatible with older revisions.
> Anything beyond 32 will enable the MSB register and will also require you to write to them.

So you are saying there is no way to enumerate the synthesised
configuration of the IP. Great :-(

Do Xilinx at least document you can discover the DMA size by writing
into these upper bits? Does Xilinx own 'vendor crap' driver do this?

Thanks
	Andrew
Andre Przywara Jan. 10, 2020, 3:08 p.m. UTC | #4
On Fri, 10 Jan 2020 15:22:50 +0100
Andrew Lunn <andrew@lunn.ch> wrote:

Hi,

> On Fri, Jan 10, 2020 at 02:13:03PM +0000, Andre Przywara wrote:
> > On Fri, 10 Jan 2020 15:08:52 +0100
> > Andrew Lunn <andrew@lunn.ch> wrote:
> > 
> > Hi Andrew,
> > 
> > thanks for having a look!
> >   
> > > > To autodetect this configuration, at probe time we write all 1's to such
> > > > an MSB register, and see if any bits stick.    
> > > 
> > > So there is no register you can read containing the IP version?  
> > 
> > There is, and I actually read this before doing this check. But the 64-bit DMA capability is optional even in this revision. It depends on what you give it as the address width. If you say 32, the IP config tool disables the 64-bit capability completely, so it stays compatible with older revisions.
> > Anything beyond 32 will enable the MSB register and will also require you to write to them.  
> 
> So you are saying there is no way to enumerate the synthesised
> configuration of the IP. Great :-(

Apparently not.

> Do Xilinx at least document you can discover the DMA size by writing
> into these upper bits? Does Xilinx own 'vendor crap' driver do this?

So far I couldn't be bothered to put my asbestos trousers on and go into BSP land ;-)
Now quickly browsing the linux-xlnx github repo suggests they make this MSB register access dependent on CONFIG_PHYS_ADDR_T_64BIT. Which would mean:
- A 32-bit kernel on a device configured for >32 bit DMA would not work.
- They always write to the MSB registers on 64-bit and (L)PAE kernels.

The DMA mask is set to the value of the xlnx,addrwidth, in a similar way I did it in the next patch. Minus the safety check for the 64-bit DMA capability.

I got this idea of probing when I saw that those registers are marked as "Reserved" in earlier revisions of the documentation. I couldn't find an exact definition of "Reserved" in that manual, though.
Then I confirmed that behaviour by testing this on an image configured for only a 32 bit wide address bus, where those registers are apparently hardwired to zero.

So if you were hoping for an official blessing, I have to disappoint you ;-)

We could rely completely on the addrwidth property, at the price of it not working when the IP is configured for >32 bits, but the addrwidth property is missing or erroneously set to 32. But I think their:
struct xxx { ....
	phys_addr_t next;	/* Physical address of next buffer descriptor */
#ifndef CONFIG_PHYS_ADDR_T_64BIT
	u32 reserved1;
#endif

construct is broken, and we should not copy this. Also they do writeq to this register, not sure that's the right thing to do.

Cheers,
Andre.
Andrew Lunn Jan. 10, 2020, 3:22 p.m. UTC | #5
> So far I couldn't be bothered to put my asbestos trousers on and go
> into BSP land ;-)

Are you in Cambridge? 7 degrees, so you can pop outside to cool off a
bit :-)

> So if you were hoping for an official blessing, I have to disappoint you ;-)

Well, everything you have done is at least sensible. The patches have
also drawn the interest of Radhey. Let see if he says this is safe for
IP version 0.0 through to 7.1.

   Andrew
Radhey Shyam Pandey Jan. 14, 2020, 5:03 p.m. UTC | #6
> -----Original Message-----
> From: Andre Przywara <andre.przywara@arm.com>
> Sent: Friday, January 10, 2020 5:24 PM
> To: David S . Miller <davem@davemloft.net>; Radhey Shyam Pandey
> <radheys@xilinx.com>
> Cc: Michal Simek <michals@xilinx.com>; Robert Hancock
> <hancock@sedsystems.ca>; netdev@vger.kernel.org; linux-arm-
> kernel@lists.infradead.org; linux-kernel@vger.kernel.org
> Subject: [PATCH 12/14] net: axienet: Autodetect 64-bit DMA capability
> 
> When newer revisions of the Axienet IP are configured for a 64-bit bus,
I assume in design axidma address width is set to 64-bits. 
If not, please provide an overview of the design connections.

> we *need* to write to the MSB part of the an address registers,
> otherwise the IP won't recognise this as a DMA start condition.
> This is even true when the actual DMA address comes from the lower 4 GB.
> 
> To autodetect this configuration, at probe time we write all 1's to such
Is reading address width axidma IP user parameter(c_addr_width) from
the design not sufficient to detect configured bus width?

> an MSB register, and see if any bits stick. If this is configured for a
> 32-bit bus, those MSB registers are RES0, so reading back 0 indicates
> that no MSB writes are necessary.
> On the other hands reading anything other than 0 indicated the need to
> write the MSB registers, so we set the respective flag.
> 
> For now this leaves the actual DMA mask at 32-bit, as we can't reliably
> detect the actually wired number of address lines beyond 32.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  drivers/net/ethernet/xilinx/xilinx_axienet.h  |  1 +
>  .../net/ethernet/xilinx/xilinx_axienet_main.c | 27 +++++++++++++++++++
>  2 files changed, 28 insertions(+)
> 
> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> index 4aea4c23d3bb..4feaaa02819c 100644
> --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> @@ -161,6 +161,7 @@
>  #define XAE_FCC_OFFSET		0x0000040C /* Flow Control
> Configuration */
>  #define XAE_EMMC_OFFSET		0x00000410 /* EMAC mode
> configuration */
>  #define XAE_PHYC_OFFSET		0x00000414 /* RGMII/SGMII
> configuration */
> +#define XAE_ID_OFFSET		0x000004F8 /* Identification register
> */
>  #define XAE_MDIO_MC_OFFSET	0x00000500 /* MII Management
> Config */
>  #define XAE_MDIO_MCR_OFFSET	0x00000504 /* MII Management
> Control */
>  #define XAE_MDIO_MWD_OFFSET	0x00000508 /* MII Management Write
> Data */
> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> index 133f088d797e..f7f593df0c11 100644
> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> @@ -151,6 +151,9 @@ static void axienet_dma_out_addr(struct axienet_local
> *lp, off_t reg,
>  				 dma_addr_t addr)
>  {
>  	axienet_dma_out32(lp, reg, lower_32_bits(addr));
> +
> +	if (lp->features & XAE_FEATURE_DMA_64BIT)
> +		axienet_dma_out32(lp, reg + 4, upper_32_bits(addr));
>  }
> 
>  static void desc_set_phys_addr(struct axienet_local *lp, dma_addr_t addr,
> @@ -1934,6 +1937,30 @@ static int axienet_probe(struct platform_device
> *pdev)
>  		goto free_netdev;
>  	}
> 
> +	/*
> +	 * Autodetect the need for 64-bit DMA pointers.
> +	 * When the IP is configured for a bus width bigger than 32 bits,
> +	 * writing the MSB registers is mandatory, even if they are all 0.
> +	 * We can detect this case by writing all 1's to one such register
> +	 * and see if that sticks: when the IP is configured for 32 bits
> +	 * only, those registers are RES0.
> +	 * Those MSB registers were introduced in IP v7.1, which we check first.
> +	 */
> +	if ((axienet_ior(lp, XAE_ID_OFFSET) >> 24) >= 0x9) {
> +		void __iomem *desc = lp->dma_regs +
> XAXIDMA_TX_CDESC_OFFSET + 4;
> +
> +		iowrite32(0x0, desc);
> +		if (ioread32(desc) == 0) {	/* sanity check */
> +			iowrite32(0xffffffff, desc);
> +			if (ioread32(desc) > 0) {
> +				lp->features |= XAE_FEATURE_DMA_64BIT;
> +				dev_info(&pdev->dev,
> +					 "autodetected 64-bit DMA range\n");
> +			}
> +			iowrite32(0x0, desc);
> +		}
> +	}
> +
>  	/* Check for Ethernet core IRQ (optional) */
>  	if (lp->eth_irq <= 0)
>  		dev_info(&pdev->dev, "Ethernet core IRQ not defined\n");
> --
> 2.17.1
Andre Przywara Jan. 14, 2020, 5:41 p.m. UTC | #7
On Tue, 14 Jan 2020 17:03:41 +0000
Radhey Shyam Pandey <radheys@xilinx.com> wrote:

Hi,

> > -----Original Message-----
> > From: Andre Przywara <andre.przywara@arm.com>
> > Sent: Friday, January 10, 2020 5:24 PM
> > To: David S . Miller <davem@davemloft.net>; Radhey Shyam Pandey
> > <radheys@xilinx.com>
> > Cc: Michal Simek <michals@xilinx.com>; Robert Hancock
> > <hancock@sedsystems.ca>; netdev@vger.kernel.org; linux-arm-
> > kernel@lists.infradead.org; linux-kernel@vger.kernel.org
> > Subject: [PATCH 12/14] net: axienet: Autodetect 64-bit DMA capability
> > 
> > When newer revisions of the Axienet IP are configured for a 64-bit bus,  
> I assume in design axidma address width is set to 64-bits. 

So I wrote "64-bit bus" here, but really meant: "address bus wider than 32 bits". In our case it's set to 40 bits, because that's how wide the other busses in the system are.
And we have memory from 2GB to 4GB, and from 34GB till 40GB, but not in-between (VExpress/Juno memory layout).

> If not, please provide an overview of the design connections.

The exact parameter name from PG021 is: "Address Width (32-64) / c_addr_width".

> > we *need* to write to the MSB part of the an address registers,
> > otherwise the IP won't recognise this as a DMA start condition.
> > This is even true when the actual DMA address comes from the lower 4 GB.
> > 
> > To autodetect this configuration, at probe time we write all 1's to such  
> Is reading address width axidma IP user parameter(c_addr_width) from
> the design not sufficient to detect configured bus width?

What do you mean by that? Reading from where? Is there a way to access those parameters from a running system?

Cheers,
Andre.

> > an MSB register, and see if any bits stick. If this is configured for a
> > 32-bit bus, those MSB registers are RES0, so reading back 0 indicates
> > that no MSB writes are necessary.
> > On the other hands reading anything other than 0 indicated the need to
> > write the MSB registers, so we set the respective flag.
> > 
> > For now this leaves the actual DMA mask at 32-bit, as we can't reliably
> > detect the actually wired number of address lines beyond 32.
> > 
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> >  drivers/net/ethernet/xilinx/xilinx_axienet.h  |  1 +
> >  .../net/ethernet/xilinx/xilinx_axienet_main.c | 27 +++++++++++++++++++
> >  2 files changed, 28 insertions(+)
> > 
> > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> > b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> > index 4aea4c23d3bb..4feaaa02819c 100644
> > --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> > @@ -161,6 +161,7 @@
> >  #define XAE_FCC_OFFSET		0x0000040C /* Flow Control
> > Configuration */
> >  #define XAE_EMMC_OFFSET		0x00000410 /* EMAC mode
> > configuration */
> >  #define XAE_PHYC_OFFSET		0x00000414 /* RGMII/SGMII
> > configuration */
> > +#define XAE_ID_OFFSET		0x000004F8 /* Identification register
> > */
> >  #define XAE_MDIO_MC_OFFSET	0x00000500 /* MII Management
> > Config */
> >  #define XAE_MDIO_MCR_OFFSET	0x00000504 /* MII Management
> > Control */
> >  #define XAE_MDIO_MWD_OFFSET	0x00000508 /* MII Management Write
> > Data */
> > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> > b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> > index 133f088d797e..f7f593df0c11 100644
> > --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> > @@ -151,6 +151,9 @@ static void axienet_dma_out_addr(struct axienet_local
> > *lp, off_t reg,
> >  				 dma_addr_t addr)
> >  {
> >  	axienet_dma_out32(lp, reg, lower_32_bits(addr));
> > +
> > +	if (lp->features & XAE_FEATURE_DMA_64BIT)
> > +		axienet_dma_out32(lp, reg + 4, upper_32_bits(addr));
> >  }
> > 
> >  static void desc_set_phys_addr(struct axienet_local *lp, dma_addr_t addr,
> > @@ -1934,6 +1937,30 @@ static int axienet_probe(struct platform_device
> > *pdev)
> >  		goto free_netdev;
> >  	}
> > 
> > +	/*
> > +	 * Autodetect the need for 64-bit DMA pointers.
> > +	 * When the IP is configured for a bus width bigger than 32 bits,
> > +	 * writing the MSB registers is mandatory, even if they are all 0.
> > +	 * We can detect this case by writing all 1's to one such register
> > +	 * and see if that sticks: when the IP is configured for 32 bits
> > +	 * only, those registers are RES0.
> > +	 * Those MSB registers were introduced in IP v7.1, which we check first.
> > +	 */
> > +	if ((axienet_ior(lp, XAE_ID_OFFSET) >> 24) >= 0x9) {
> > +		void __iomem *desc = lp->dma_regs +
> > XAXIDMA_TX_CDESC_OFFSET + 4;
> > +
> > +		iowrite32(0x0, desc);
> > +		if (ioread32(desc) == 0) {	/* sanity check */
> > +			iowrite32(0xffffffff, desc);
> > +			if (ioread32(desc) > 0) {
> > +				lp->features |= XAE_FEATURE_DMA_64BIT;
> > +				dev_info(&pdev->dev,
> > +					 "autodetected 64-bit DMA range\n");
> > +			}
> > +			iowrite32(0x0, desc);
> > +		}
> > +	}
> > +
> >  	/* Check for Ethernet core IRQ (optional) */
> >  	if (lp->eth_irq <= 0)
> >  		dev_info(&pdev->dev, "Ethernet core IRQ not defined\n");
> > --
> > 2.17.1  
>
Radhey Shyam Pandey Jan. 15, 2020, 6:02 a.m. UTC | #8
> -----Original Message-----
> From: Andre Przywara <andre.przywara@arm.com>
> Sent: Tuesday, January 14, 2020 11:12 PM
> To: Radhey Shyam Pandey <radheys@xilinx.com>
> Cc: David S . Miller <davem@davemloft.net>; Michal Simek
> <michals@xilinx.com>; Robert Hancock <hancock@sedsystems.ca>;
> netdev@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux-
> kernel@vger.kernel.org
> Subject: Re: [PATCH 12/14] net: axienet: Autodetect 64-bit DMA capability
> 
> On Tue, 14 Jan 2020 17:03:41 +0000
> Radhey Shyam Pandey <radheys@xilinx.com> wrote:
> 
> Hi,
> 
> > > -----Original Message-----
> > > From: Andre Przywara <andre.przywara@arm.com>
> > > Sent: Friday, January 10, 2020 5:24 PM
> > > To: David S . Miller <davem@davemloft.net>; Radhey Shyam Pandey
> > > <radheys@xilinx.com>
> > > Cc: Michal Simek <michals@xilinx.com>; Robert Hancock
> > > <hancock@sedsystems.ca>; netdev@vger.kernel.org; linux-arm-
> > > kernel@lists.infradead.org; linux-kernel@vger.kernel.org
> > > Subject: [PATCH 12/14] net: axienet: Autodetect 64-bit DMA
> > > capability
> > >
> > > When newer revisions of the Axienet IP are configured for a 64-bit
> > > bus,
> > I assume in design axidma address width is set to 64-bits.
> 
> So I wrote "64-bit bus" here, but really meant: "address bus wider than 32 bits".
> In our case it's set to 40 bits, because that's how wide the other busses in the
> system are.
> And we have memory from 2GB to 4GB, and from 34GB till 40GB, but not in-
> between (VExpress/Juno memory layout).
> 
> > If not, please provide an overview of the design connections.
> 
> The exact parameter name from PG021 is: "Address Width (32-64) /
> c_addr_width".
Thanks. It's right.

> 
> > > we *need* to write to the MSB part of the an address registers,
> > > otherwise the IP won't recognise this as a DMA start condition.
> > > This is even true when the actual DMA address comes from the lower 4 GB.
> > >
> > > To autodetect this configuration, at probe time we write all 1's to
> > > such
> > Is reading address width axidma IP user parameter(c_addr_width) from
> > the design not sufficient to detect configured bus width?
> 
> What do you mean by that? Reading from where? Is there a way to access those
> parameters from a running system?
Hardware design data i.e IP parameter can be accessed using hsi in-built commands.
Please refer to ug1138-generating-basic-software-platforms.pdf, chapter-4.
The same flow is used in DT,  xilinx device tree generator parses HDF and read IP 
parameters and populate DT binding.

> 
> Cheers,
> Andre.
> 
> > > an MSB register, and see if any bits stick. If this is configured
> > > for a 32-bit bus, those MSB registers are RES0, so reading back 0
> > > indicates that no MSB writes are necessary.
> > > On the other hands reading anything other than 0 indicated the need
> > > to write the MSB registers, so we set the respective flag.
> > >
> > > For now this leaves the actual DMA mask at 32-bit, as we can't
> > > reliably detect the actually wired number of address lines beyond 32.
> > >
> > > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > > ---
> > >  drivers/net/ethernet/xilinx/xilinx_axienet.h  |  1 +
> > > .../net/ethernet/xilinx/xilinx_axienet_main.c | 27
> > > +++++++++++++++++++
> > >  2 files changed, 28 insertions(+)
> > >
> > > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> > > b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> > > index 4aea4c23d3bb..4feaaa02819c 100644
> > > --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> > > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> > > @@ -161,6 +161,7 @@
> > >  #define XAE_FCC_OFFSET		0x0000040C /* Flow Control
> > > Configuration */
> > >  #define XAE_EMMC_OFFSET		0x00000410 /* EMAC mode
> > > configuration */
> > >  #define XAE_PHYC_OFFSET		0x00000414 /* RGMII/SGMII
> > > configuration */
> > > +#define XAE_ID_OFFSET		0x000004F8 /* Identification register
> > > */
> > >  #define XAE_MDIO_MC_OFFSET	0x00000500 /* MII Management
> > > Config */
> > >  #define XAE_MDIO_MCR_OFFSET	0x00000504 /* MII Management
> > > Control */
> > >  #define XAE_MDIO_MWD_OFFSET	0x00000508 /* MII Management Write
> > > Data */
> > > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> > > b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> > > index 133f088d797e..f7f593df0c11 100644
> > > --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> > > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> > > @@ -151,6 +151,9 @@ static void axienet_dma_out_addr(struct
> > > axienet_local *lp, off_t reg,
> > >  				 dma_addr_t addr)
> > >  {
> > >  	axienet_dma_out32(lp, reg, lower_32_bits(addr));
> > > +
> > > +	if (lp->features & XAE_FEATURE_DMA_64BIT)
> > > +		axienet_dma_out32(lp, reg + 4, upper_32_bits(addr));
> > >  }
> > >
> > >  static void desc_set_phys_addr(struct axienet_local *lp, dma_addr_t
> > > addr, @@ -1934,6 +1937,30 @@ static int axienet_probe(struct
> > > platform_device
> > > *pdev)
> > >  		goto free_netdev;
> > >  	}
> > >
> > > +	/*
> > > +	 * Autodetect the need for 64-bit DMA pointers.
> > > +	 * When the IP is configured for a bus width bigger than 32 bits,
> > > +	 * writing the MSB registers is mandatory, even if they are all 0.
> > > +	 * We can detect this case by writing all 1's to one such register
> > > +	 * and see if that sticks: when the IP is configured for 32 bits
> > > +	 * only, those registers are RES0.
> > > +	 * Those MSB registers were introduced in IP v7.1, which we check first.
> > > +	 */
> > > +	if ((axienet_ior(lp, XAE_ID_OFFSET) >> 24) >= 0x9) {
> > > +		void __iomem *desc = lp->dma_regs +
> > > XAXIDMA_TX_CDESC_OFFSET + 4;
> > > +
> > > +		iowrite32(0x0, desc);
> > > +		if (ioread32(desc) == 0) {	/* sanity check */
> > > +			iowrite32(0xffffffff, desc);
> > > +			if (ioread32(desc) > 0) {
> > > +				lp->features |= XAE_FEATURE_DMA_64BIT;
> > > +				dev_info(&pdev->dev,
> > > +					 "autodetected 64-bit DMA range\n");
> > > +			}
> > > +			iowrite32(0x0, desc);
> > > +		}
> > > +	}
> > > +
> > >  	/* Check for Ethernet core IRQ (optional) */
> > >  	if (lp->eth_irq <= 0)
> > >  		dev_info(&pdev->dev, "Ethernet core IRQ not defined\n");
> > > --
> > > 2.17.1
> >
diff mbox series

Patch

diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h
index 4aea4c23d3bb..4feaaa02819c 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
@@ -161,6 +161,7 @@ 
 #define XAE_FCC_OFFSET		0x0000040C /* Flow Control Configuration */
 #define XAE_EMMC_OFFSET		0x00000410 /* EMAC mode configuration */
 #define XAE_PHYC_OFFSET		0x00000414 /* RGMII/SGMII configuration */
+#define XAE_ID_OFFSET		0x000004F8 /* Identification register */
 #define XAE_MDIO_MC_OFFSET	0x00000500 /* MII Management Config */
 #define XAE_MDIO_MCR_OFFSET	0x00000504 /* MII Management Control */
 #define XAE_MDIO_MWD_OFFSET	0x00000508 /* MII Management Write Data */
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 133f088d797e..f7f593df0c11 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -151,6 +151,9 @@  static void axienet_dma_out_addr(struct axienet_local *lp, off_t reg,
 				 dma_addr_t addr)
 {
 	axienet_dma_out32(lp, reg, lower_32_bits(addr));
+
+	if (lp->features & XAE_FEATURE_DMA_64BIT)
+		axienet_dma_out32(lp, reg + 4, upper_32_bits(addr));
 }
 
 static void desc_set_phys_addr(struct axienet_local *lp, dma_addr_t addr,
@@ -1934,6 +1937,30 @@  static int axienet_probe(struct platform_device *pdev)
 		goto free_netdev;
 	}
 
+	/*
+	 * Autodetect the need for 64-bit DMA pointers.
+	 * When the IP is configured for a bus width bigger than 32 bits,
+	 * writing the MSB registers is mandatory, even if they are all 0.
+	 * We can detect this case by writing all 1's to one such register
+	 * and see if that sticks: when the IP is configured for 32 bits
+	 * only, those registers are RES0.
+	 * Those MSB registers were introduced in IP v7.1, which we check first.
+	 */
+	if ((axienet_ior(lp, XAE_ID_OFFSET) >> 24) >= 0x9) {
+		void __iomem *desc = lp->dma_regs + XAXIDMA_TX_CDESC_OFFSET + 4;
+
+		iowrite32(0x0, desc);
+		if (ioread32(desc) == 0) {	/* sanity check */
+			iowrite32(0xffffffff, desc);
+			if (ioread32(desc) > 0) {
+				lp->features |= XAE_FEATURE_DMA_64BIT;
+				dev_info(&pdev->dev,
+					 "autodetected 64-bit DMA range\n");
+			}
+			iowrite32(0x0, desc);
+		}
+	}
+
 	/* Check for Ethernet core IRQ (optional) */
 	if (lp->eth_irq <= 0)
 		dev_info(&pdev->dev, "Ethernet core IRQ not defined\n");