diff mbox series

[v2,06/10] net: stmmac: Add Loongson HWIF entry

Message ID 7cae63ede2792cb2a7189f251b282aecbb0945b1.1690439335.git.chenfeiyang@loongson.cn (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series stmmac: Add Loongson platform support | expand

Checks

Context Check Description
netdev/tree_selection success Guessing tree name failed - patch did not apply

Commit Message

Feiyang Chen July 27, 2023, 7:18 a.m. UTC
Add a new entry to HWIF table for Loongson.

Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
---
 drivers/net/ethernet/stmicro/stmmac/common.h  |  3 ++
 .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |  6 +++
 drivers/net/ethernet/stmicro/stmmac/hwif.c    | 48 ++++++++++++++++++-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c | 25 ++++++----
 include/linux/stmmac.h                        |  1 +
 5 files changed, 73 insertions(+), 10 deletions(-)

Comments

Ravi Gunasekaran July 28, 2023, 6:36 a.m. UTC | #1
On 7/27/23 12:48 PM, Feiyang Chen wrote:
> Add a new entry to HWIF table for Loongson.
> 
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> ---
>  drivers/net/ethernet/stmicro/stmmac/common.h  |  3 ++
>  .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |  6 +++
>  drivers/net/ethernet/stmicro/stmmac/hwif.c    | 48 ++++++++++++++++++-
>  .../net/ethernet/stmicro/stmmac/stmmac_main.c | 25 ++++++----
>  include/linux/stmmac.h                        |  1 +
>  5 files changed, 73 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
> index 16e67c18b6f7..267f9a7913ac 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> @@ -29,11 +29,13 @@
>  /* Synopsys Core versions */
>  #define	DWMAC_CORE_3_40		0x34
>  #define	DWMAC_CORE_3_50		0x35
> +#define	DWMAC_CORE_3_70		0x37
>  #define	DWMAC_CORE_4_00		0x40
>  #define DWMAC_CORE_4_10		0x41
>  #define DWMAC_CORE_5_00		0x50
>  #define DWMAC_CORE_5_10		0x51
>  #define DWMAC_CORE_5_20		0x52
> +#define DWLGMAC_CORE_1_00	0x10
>  #define DWXGMAC_CORE_2_10	0x21
>  #define DWXLGMAC_CORE_2_00	0x20
>  
> @@ -547,6 +549,7 @@ int dwmac1000_setup(struct stmmac_priv *priv);
>  int dwmac4_setup(struct stmmac_priv *priv);
>  int dwxgmac2_setup(struct stmmac_priv *priv);
>  int dwxlgmac2_setup(struct stmmac_priv *priv);
> +int dwmac_loongson_setup(struct stmmac_priv *priv);
>  
>  void stmmac_set_mac_addr(void __iomem *ioaddr, const u8 addr[6],
>  			 unsigned int high, unsigned int low);
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> index 7aa450d6a81a..5da5f111d7e0 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> @@ -172,6 +172,12 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
>  		       chan * DMA_CHAN_OFFSET);
>  		writel(upper_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR_HI +
>  		       chan * DMA_CHAN_OFFSET);
> +		if (priv->plat->has_lgmac) {
> +			writel(upper_32_bits(dma_rx_phy),
> +			       ioaddr + DMA_RCV_BASE_ADDR_SHADOW1);
> +			writel(upper_32_bits(dma_rx_phy),
> +			       ioaddr + DMA_RCV_BASE_ADDR_SHADOW2);
> +		}
>  	} else {
>  		/* RX descriptor base address list must be written into DMA CSR3 */
>  		writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR +
> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> index b8ba8f2d8041..b376ac4f80d5 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> @@ -58,7 +58,8 @@ static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
>  		dev_info(priv->device, "Enhanced/Alternate descriptors\n");
>  
>  		/* GMAC older than 3.50 has no extended descriptors */
> -		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
> +		if (priv->synopsys_id >= DWMAC_CORE_3_50 ||
> +		    priv->plat->has_lgmac) {>  			dev_info(priv->device, "Enabled extended descriptors\n");
>  			priv->extend_desc = 1;
>  		} else {
> @@ -104,6 +105,7 @@ static const struct stmmac_hwif_entry {
>  	bool gmac;
>  	bool gmac4;
>  	bool xgmac;
> +	bool lgmac;

Similar to Andrew's comment on dwmac_is_loongson, can lgmac also be
renamed to some other name? 

I believe the 'gmac' and 'xgmac' refer to 1Gbps and 10Gbps which sounds generic,
while 'lgmac' sounds vendor specific. 

>  	u32 min_id;
>  	u32 dev_id;
>  	const struct stmmac_regs_off regs;


[...]

> +	}, {
> +		.gmac = true,
> +		.gmac4 = false,
> +		.xgmac = false,
> +		.lgmac = true,
> +		.min_id = DWLGMAC_CORE_1_00,
> +		.regs = {
> +			.ptp_off = PTP_GMAC3_X_OFFSET,
> +			.mmc_off = MMC_GMAC3_X_OFFSET,
> +		},
> +		.desc = NULL,
> +		.dma = &dwmac1000_dma_ops,
> +		.mac = &dwmac1000_ops,
> +		.hwtimestamp = &stmmac_ptp,
> +		.mode = NULL,
> +		.tc = NULL,
> +		.setup = dwmac_loongson_setup,
> +		.quirks = stmmac_dwmac1_quirks,
> +	}, {
> +		.gmac = true,
> +		.gmac4 = false,
> +		.xgmac = false,
> +		.lgmac = true,
> +		.min_id = DWMAC_CORE_3_50,
> +		.regs = {
> +			.ptp_off = PTP_GMAC3_X_OFFSET,
> +			.mmc_off = MMC_GMAC3_X_OFFSET,
> +		},
> +		.desc = NULL,
> +		.dma = &dwmac1000_dma_ops,
> +		.mac = &dwmac1000_ops,
> +		.hwtimestamp = &stmmac_ptp,
> +		.mode = NULL,
> +		.tc = NULL,
> +		.setup = dwmac1000_setup,
> +		.quirks = stmmac_dwmac1_quirks,
>  	},
>  };
>  
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index e8619853b6d6..829de274e75d 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -3505,17 +3505,21 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
>  {
>  	struct stmmac_priv *priv = netdev_priv(dev);
>  	enum request_irq_err irq_err;
> +	unsigned long flags = 0;
>  	cpumask_t cpu_mask;
>  	int irq_idx = 0;
>  	char *int_name;
>  	int ret;
>  	int i;
>  
> +	if (priv->plat->has_lgmac)
> +		flags |= IRQF_TRIGGER_RISING;

How about introducing a struct member such as "irq_flags"?

> +
>  	/* For common interrupt */
>  	int_name = priv->int_name_mac;
>  	sprintf(int_name, "%s:%s", dev->name, "mac");
>  	ret = request_irq(dev->irq, stmmac_mac_interrupt,
> -			  0, int_name, dev);
> +			  flags, int_name, dev);

[...]

> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index 46bccc34814d..e21076f57205 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -344,5 +344,6 @@ struct plat_stmmacenet_data {
>  	bool has_integrated_pcs;
>  	const struct dwmac_regs *dwmac_regs;
>  	bool dwmac_is_loongson;
> +	int has_lgmac;
>  };
>  #endif
Russell King (Oracle) July 28, 2023, 9:24 a.m. UTC | #2
On Thu, Jul 27, 2023 at 03:18:06PM +0800, Feiyang Chen wrote:
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index e8619853b6d6..829de274e75d 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -3505,17 +3505,21 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
>  {
>  	struct stmmac_priv *priv = netdev_priv(dev);
>  	enum request_irq_err irq_err;
> +	unsigned long flags = 0;
>  	cpumask_t cpu_mask;
>  	int irq_idx = 0;
>  	char *int_name;
>  	int ret;
>  	int i;
>  
> +	if (priv->plat->has_lgmac)
> +		flags |= IRQF_TRIGGER_RISING;

Can this be described in firmware?
Feiyang Chen July 31, 2023, 9:44 a.m. UTC | #3
On Fri, Jul 28, 2023 at 2:36 PM Ravi Gunasekaran <r-gunasekaran@ti.com> wrote:
>
>
>
> On 7/27/23 12:48 PM, Feiyang Chen wrote:
> > Add a new entry to HWIF table for Loongson.
> >
> > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > ---
> >  drivers/net/ethernet/stmicro/stmmac/common.h  |  3 ++
> >  .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |  6 +++
> >  drivers/net/ethernet/stmicro/stmmac/hwif.c    | 48 ++++++++++++++++++-
> >  .../net/ethernet/stmicro/stmmac/stmmac_main.c | 25 ++++++----
> >  include/linux/stmmac.h                        |  1 +
> >  5 files changed, 73 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
> > index 16e67c18b6f7..267f9a7913ac 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> > +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> > @@ -29,11 +29,13 @@
> >  /* Synopsys Core versions */
> >  #define      DWMAC_CORE_3_40         0x34
> >  #define      DWMAC_CORE_3_50         0x35
> > +#define      DWMAC_CORE_3_70         0x37
> >  #define      DWMAC_CORE_4_00         0x40
> >  #define DWMAC_CORE_4_10              0x41
> >  #define DWMAC_CORE_5_00              0x50
> >  #define DWMAC_CORE_5_10              0x51
> >  #define DWMAC_CORE_5_20              0x52
> > +#define DWLGMAC_CORE_1_00    0x10
> >  #define DWXGMAC_CORE_2_10    0x21
> >  #define DWXLGMAC_CORE_2_00   0x20
> >
> > @@ -547,6 +549,7 @@ int dwmac1000_setup(struct stmmac_priv *priv);
> >  int dwmac4_setup(struct stmmac_priv *priv);
> >  int dwxgmac2_setup(struct stmmac_priv *priv);
> >  int dwxlgmac2_setup(struct stmmac_priv *priv);
> > +int dwmac_loongson_setup(struct stmmac_priv *priv);
> >
> >  void stmmac_set_mac_addr(void __iomem *ioaddr, const u8 addr[6],
> >                        unsigned int high, unsigned int low);
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > index 7aa450d6a81a..5da5f111d7e0 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > @@ -172,6 +172,12 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
> >                      chan * DMA_CHAN_OFFSET);
> >               writel(upper_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR_HI +
> >                      chan * DMA_CHAN_OFFSET);
> > +             if (priv->plat->has_lgmac) {
> > +                     writel(upper_32_bits(dma_rx_phy),
> > +                            ioaddr + DMA_RCV_BASE_ADDR_SHADOW1);
> > +                     writel(upper_32_bits(dma_rx_phy),
> > +                            ioaddr + DMA_RCV_BASE_ADDR_SHADOW2);
> > +             }
> >       } else {
> >               /* RX descriptor base address list must be written into DMA CSR3 */
> >               writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR +
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> > index b8ba8f2d8041..b376ac4f80d5 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> > @@ -58,7 +58,8 @@ static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
> >               dev_info(priv->device, "Enhanced/Alternate descriptors\n");
> >
> >               /* GMAC older than 3.50 has no extended descriptors */
> > -             if (priv->synopsys_id >= DWMAC_CORE_3_50) {
> > +             if (priv->synopsys_id >= DWMAC_CORE_3_50 ||
> > +                 priv->plat->has_lgmac) {>                   dev_info(priv->device, "Enabled extended descriptors\n");
> >                       priv->extend_desc = 1;
> >               } else {
> > @@ -104,6 +105,7 @@ static const struct stmmac_hwif_entry {
> >       bool gmac;
> >       bool gmac4;
> >       bool xgmac;
> > +     bool lgmac;
>
> Similar to Andrew's comment on dwmac_is_loongson, can lgmac also be
> renamed to some other name?
>
> I believe the 'gmac' and 'xgmac' refer to 1Gbps and 10Gbps which sounds generic,
> while 'lgmac' sounds vendor specific.
>
> >       u32 min_id;
> >       u32 dev_id;
> >       const struct stmmac_regs_off regs;
>
>
> [...]
>
> > +     }, {
> > +             .gmac = true,
> > +             .gmac4 = false,
> > +             .xgmac = false,
> > +             .lgmac = true,
> > +             .min_id = DWLGMAC_CORE_1_00,
> > +             .regs = {
> > +                     .ptp_off = PTP_GMAC3_X_OFFSET,
> > +                     .mmc_off = MMC_GMAC3_X_OFFSET,
> > +             },
> > +             .desc = NULL,
> > +             .dma = &dwmac1000_dma_ops,
> > +             .mac = &dwmac1000_ops,
> > +             .hwtimestamp = &stmmac_ptp,
> > +             .mode = NULL,
> > +             .tc = NULL,
> > +             .setup = dwmac_loongson_setup,
> > +             .quirks = stmmac_dwmac1_quirks,
> > +     }, {
> > +             .gmac = true,
> > +             .gmac4 = false,
> > +             .xgmac = false,
> > +             .lgmac = true,
> > +             .min_id = DWMAC_CORE_3_50,
> > +             .regs = {
> > +                     .ptp_off = PTP_GMAC3_X_OFFSET,
> > +                     .mmc_off = MMC_GMAC3_X_OFFSET,
> > +             },
> > +             .desc = NULL,
> > +             .dma = &dwmac1000_dma_ops,
> > +             .mac = &dwmac1000_ops,
> > +             .hwtimestamp = &stmmac_ptp,
> > +             .mode = NULL,
> > +             .tc = NULL,
> > +             .setup = dwmac1000_setup,
> > +             .quirks = stmmac_dwmac1_quirks,
> >       },
> >  };
> >
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > index e8619853b6d6..829de274e75d 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > @@ -3505,17 +3505,21 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
> >  {
> >       struct stmmac_priv *priv = netdev_priv(dev);
> >       enum request_irq_err irq_err;
> > +     unsigned long flags = 0;
> >       cpumask_t cpu_mask;
> >       int irq_idx = 0;
> >       char *int_name;
> >       int ret;
> >       int i;
> >
> > +     if (priv->plat->has_lgmac)
> > +             flags |= IRQF_TRIGGER_RISING;
>
> How about introducing a struct member such as "irq_flags"?
>

Hi, Ravi,

OK.

Thanks,
Feiyang

> > +
> >       /* For common interrupt */
> >       int_name = priv->int_name_mac;
> >       sprintf(int_name, "%s:%s", dev->name, "mac");
> >       ret = request_irq(dev->irq, stmmac_mac_interrupt,
> > -                       0, int_name, dev);
> > +                       flags, int_name, dev);
>
> [...]
>
> > diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> > index 46bccc34814d..e21076f57205 100644
> > --- a/include/linux/stmmac.h
> > +++ b/include/linux/stmmac.h
> > @@ -344,5 +344,6 @@ struct plat_stmmacenet_data {
> >       bool has_integrated_pcs;
> >       const struct dwmac_regs *dwmac_regs;
> >       bool dwmac_is_loongson;
> > +     int has_lgmac;
> >  };
> >  #endif
>
> --
> Regards,
> Ravi
Feiyang Chen July 31, 2023, 9:46 a.m. UTC | #4
On Fri, Jul 28, 2023 at 5:24 PM Russell King (Oracle)
<linux@armlinux.org.uk> wrote:
>
> On Thu, Jul 27, 2023 at 03:18:06PM +0800, Feiyang Chen wrote:
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > index e8619853b6d6..829de274e75d 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > @@ -3505,17 +3505,21 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
> >  {
> >       struct stmmac_priv *priv = netdev_priv(dev);
> >       enum request_irq_err irq_err;
> > +     unsigned long flags = 0;
> >       cpumask_t cpu_mask;
> >       int irq_idx = 0;
> >       char *int_name;
> >       int ret;
> >       int i;
> >
> > +     if (priv->plat->has_lgmac)
> > +             flags |= IRQF_TRIGGER_RISING;
>
> Can this be described in firmware?
>

Hi, Russell,

I'm not sure, could you explain what you mean?

Thanks,
Feiyang

> --
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Russell King (Oracle) July 31, 2023, 3:16 p.m. UTC | #5
On Mon, Jul 31, 2023 at 05:46:57PM +0800, Feiyang Chen wrote:
> On Fri, Jul 28, 2023 at 5:24 PM Russell King (Oracle)
> <linux@armlinux.org.uk> wrote:
> >
> > On Thu, Jul 27, 2023 at 03:18:06PM +0800, Feiyang Chen wrote:
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > index e8619853b6d6..829de274e75d 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > @@ -3505,17 +3505,21 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
> > >  {
> > >       struct stmmac_priv *priv = netdev_priv(dev);
> > >       enum request_irq_err irq_err;
> > > +     unsigned long flags = 0;
> > >       cpumask_t cpu_mask;
> > >       int irq_idx = 0;
> > >       char *int_name;
> > >       int ret;
> > >       int i;
> > >
> > > +     if (priv->plat->has_lgmac)
> > > +             flags |= IRQF_TRIGGER_RISING;
> >
> > Can this be described in firmware?
> >
> 
> Hi, Russell,
> 
> I'm not sure, could you explain what you mean?

Modern systems describe the IRQ triggering in firmware for the OS
such as DT. Does your implementation have any firmware that can
do this kind of description for you (e.g. DT, ACPI?)
Feiyang Chen Aug. 3, 2023, 1:33 a.m. UTC | #6
On Mon, Jul 31, 2023 at 11:16 PM Russell King (Oracle)
<linux@armlinux.org.uk> wrote:
>
> On Mon, Jul 31, 2023 at 05:46:57PM +0800, Feiyang Chen wrote:
> > On Fri, Jul 28, 2023 at 5:24 PM Russell King (Oracle)
> > <linux@armlinux.org.uk> wrote:
> > >
> > > On Thu, Jul 27, 2023 at 03:18:06PM +0800, Feiyang Chen wrote:
> > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > > index e8619853b6d6..829de274e75d 100644
> > > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > > @@ -3505,17 +3505,21 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
> > > >  {
> > > >       struct stmmac_priv *priv = netdev_priv(dev);
> > > >       enum request_irq_err irq_err;
> > > > +     unsigned long flags = 0;
> > > >       cpumask_t cpu_mask;
> > > >       int irq_idx = 0;
> > > >       char *int_name;
> > > >       int ret;
> > > >       int i;
> > > >
> > > > +     if (priv->plat->has_lgmac)
> > > > +             flags |= IRQF_TRIGGER_RISING;
> > >
> > > Can this be described in firmware?
> > >
> >
> > Hi, Russell,
> >
> > I'm not sure, could you explain what you mean?
>
> Modern systems describe the IRQ triggering in firmware for the OS
> such as DT. Does your implementation have any firmware that can
> do this kind of description for you (e.g. DT, ACPI?)
>

Hi, Russell,

I see. I think I can get this from DT.

Thanks,
Feiyang

> --
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
diff mbox series

Patch

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 16e67c18b6f7..267f9a7913ac 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -29,11 +29,13 @@ 
 /* Synopsys Core versions */
 #define	DWMAC_CORE_3_40		0x34
 #define	DWMAC_CORE_3_50		0x35
+#define	DWMAC_CORE_3_70		0x37
 #define	DWMAC_CORE_4_00		0x40
 #define DWMAC_CORE_4_10		0x41
 #define DWMAC_CORE_5_00		0x50
 #define DWMAC_CORE_5_10		0x51
 #define DWMAC_CORE_5_20		0x52
+#define DWLGMAC_CORE_1_00	0x10
 #define DWXGMAC_CORE_2_10	0x21
 #define DWXLGMAC_CORE_2_00	0x20
 
@@ -547,6 +549,7 @@  int dwmac1000_setup(struct stmmac_priv *priv);
 int dwmac4_setup(struct stmmac_priv *priv);
 int dwxgmac2_setup(struct stmmac_priv *priv);
 int dwxlgmac2_setup(struct stmmac_priv *priv);
+int dwmac_loongson_setup(struct stmmac_priv *priv);
 
 void stmmac_set_mac_addr(void __iomem *ioaddr, const u8 addr[6],
 			 unsigned int high, unsigned int low);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 7aa450d6a81a..5da5f111d7e0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -172,6 +172,12 @@  static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
 		       chan * DMA_CHAN_OFFSET);
 		writel(upper_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR_HI +
 		       chan * DMA_CHAN_OFFSET);
+		if (priv->plat->has_lgmac) {
+			writel(upper_32_bits(dma_rx_phy),
+			       ioaddr + DMA_RCV_BASE_ADDR_SHADOW1);
+			writel(upper_32_bits(dma_rx_phy),
+			       ioaddr + DMA_RCV_BASE_ADDR_SHADOW2);
+		}
 	} else {
 		/* RX descriptor base address list must be written into DMA CSR3 */
 		writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR +
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index b8ba8f2d8041..b376ac4f80d5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -58,7 +58,8 @@  static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
 		dev_info(priv->device, "Enhanced/Alternate descriptors\n");
 
 		/* GMAC older than 3.50 has no extended descriptors */
-		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
+		if (priv->synopsys_id >= DWMAC_CORE_3_50 ||
+		    priv->plat->has_lgmac) {
 			dev_info(priv->device, "Enabled extended descriptors\n");
 			priv->extend_desc = 1;
 		} else {
@@ -104,6 +105,7 @@  static const struct stmmac_hwif_entry {
 	bool gmac;
 	bool gmac4;
 	bool xgmac;
+	bool lgmac;
 	u32 min_id;
 	u32 dev_id;
 	const struct stmmac_regs_off regs;
@@ -122,6 +124,7 @@  static const struct stmmac_hwif_entry {
 		.gmac = false,
 		.gmac4 = false,
 		.xgmac = false,
+		.lgmac = false,
 		.min_id = 0,
 		.regs = {
 			.ptp_off = PTP_GMAC3_X_OFFSET,
@@ -140,6 +143,7 @@  static const struct stmmac_hwif_entry {
 		.gmac = true,
 		.gmac4 = false,
 		.xgmac = false,
+		.lgmac = false,
 		.min_id = 0,
 		.regs = {
 			.ptp_off = PTP_GMAC3_X_OFFSET,
@@ -158,6 +162,7 @@  static const struct stmmac_hwif_entry {
 		.gmac = false,
 		.gmac4 = true,
 		.xgmac = false,
+		.lgmac = false,
 		.min_id = 0,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -176,6 +181,7 @@  static const struct stmmac_hwif_entry {
 		.gmac = false,
 		.gmac4 = true,
 		.xgmac = false,
+		.lgmac = false,
 		.min_id = DWMAC_CORE_4_00,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -194,6 +200,7 @@  static const struct stmmac_hwif_entry {
 		.gmac = false,
 		.gmac4 = true,
 		.xgmac = false,
+		.lgmac = false,
 		.min_id = DWMAC_CORE_4_10,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -212,6 +219,7 @@  static const struct stmmac_hwif_entry {
 		.gmac = false,
 		.gmac4 = true,
 		.xgmac = false,
+		.lgmac = false,
 		.min_id = DWMAC_CORE_5_10,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -230,6 +238,7 @@  static const struct stmmac_hwif_entry {
 		.gmac = false,
 		.gmac4 = false,
 		.xgmac = true,
+		.lgmac = false,
 		.min_id = DWXGMAC_CORE_2_10,
 		.dev_id = DWXGMAC_ID,
 		.regs = {
@@ -249,6 +258,7 @@  static const struct stmmac_hwif_entry {
 		.gmac = false,
 		.gmac4 = false,
 		.xgmac = true,
+		.lgmac = false,
 		.min_id = DWXLGMAC_CORE_2_00,
 		.dev_id = DWXLGMAC_ID,
 		.regs = {
@@ -264,6 +274,42 @@  static const struct stmmac_hwif_entry {
 		.mmc = &dwxgmac_mmc_ops,
 		.setup = dwxlgmac2_setup,
 		.quirks = stmmac_dwxlgmac_quirks,
+	}, {
+		.gmac = true,
+		.gmac4 = false,
+		.xgmac = false,
+		.lgmac = true,
+		.min_id = DWLGMAC_CORE_1_00,
+		.regs = {
+			.ptp_off = PTP_GMAC3_X_OFFSET,
+			.mmc_off = MMC_GMAC3_X_OFFSET,
+		},
+		.desc = NULL,
+		.dma = &dwmac1000_dma_ops,
+		.mac = &dwmac1000_ops,
+		.hwtimestamp = &stmmac_ptp,
+		.mode = NULL,
+		.tc = NULL,
+		.setup = dwmac_loongson_setup,
+		.quirks = stmmac_dwmac1_quirks,
+	}, {
+		.gmac = true,
+		.gmac4 = false,
+		.xgmac = false,
+		.lgmac = true,
+		.min_id = DWMAC_CORE_3_50,
+		.regs = {
+			.ptp_off = PTP_GMAC3_X_OFFSET,
+			.mmc_off = MMC_GMAC3_X_OFFSET,
+		},
+		.desc = NULL,
+		.dma = &dwmac1000_dma_ops,
+		.mac = &dwmac1000_ops,
+		.hwtimestamp = &stmmac_ptp,
+		.mode = NULL,
+		.tc = NULL,
+		.setup = dwmac1000_setup,
+		.quirks = stmmac_dwmac1_quirks,
 	},
 };
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index e8619853b6d6..829de274e75d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3505,17 +3505,21 @@  static int stmmac_request_irq_multi_msi(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 	enum request_irq_err irq_err;
+	unsigned long flags = 0;
 	cpumask_t cpu_mask;
 	int irq_idx = 0;
 	char *int_name;
 	int ret;
 	int i;
 
+	if (priv->plat->has_lgmac)
+		flags |= IRQF_TRIGGER_RISING;
+
 	/* For common interrupt */
 	int_name = priv->int_name_mac;
 	sprintf(int_name, "%s:%s", dev->name, "mac");
 	ret = request_irq(dev->irq, stmmac_mac_interrupt,
-			  0, int_name, dev);
+			  flags, int_name, dev);
 	if (unlikely(ret < 0)) {
 		netdev_err(priv->dev,
 			   "%s: alloc mac MSI %d (error: %d)\n",
@@ -3532,7 +3536,7 @@  static int stmmac_request_irq_multi_msi(struct net_device *dev)
 		sprintf(int_name, "%s:%s", dev->name, "wol");
 		ret = request_irq(priv->wol_irq,
 				  stmmac_mac_interrupt,
-				  0, int_name, dev);
+				  flags, int_name, dev);
 		if (unlikely(ret < 0)) {
 			netdev_err(priv->dev,
 				   "%s: alloc wol MSI %d (error: %d)\n",
@@ -3550,7 +3554,7 @@  static int stmmac_request_irq_multi_msi(struct net_device *dev)
 		sprintf(int_name, "%s:%s", dev->name, "lpi");
 		ret = request_irq(priv->lpi_irq,
 				  stmmac_mac_interrupt,
-				  0, int_name, dev);
+				  flags, int_name, dev);
 		if (unlikely(ret < 0)) {
 			netdev_err(priv->dev,
 				   "%s: alloc lpi MSI %d (error: %d)\n",
@@ -3568,7 +3572,7 @@  static int stmmac_request_irq_multi_msi(struct net_device *dev)
 		sprintf(int_name, "%s:%s", dev->name, "safety-ce");
 		ret = request_irq(priv->sfty_ce_irq,
 				  stmmac_safety_interrupt,
-				  0, int_name, dev);
+				  flags, int_name, dev);
 		if (unlikely(ret < 0)) {
 			netdev_err(priv->dev,
 				   "%s: alloc sfty ce MSI %d (error: %d)\n",
@@ -3586,7 +3590,7 @@  static int stmmac_request_irq_multi_msi(struct net_device *dev)
 		sprintf(int_name, "%s:%s", dev->name, "safety-ue");
 		ret = request_irq(priv->sfty_ue_irq,
 				  stmmac_safety_interrupt,
-				  0, int_name, dev);
+				  flags, int_name, dev);
 		if (unlikely(ret < 0)) {
 			netdev_err(priv->dev,
 				   "%s: alloc sfty ue MSI %d (error: %d)\n",
@@ -3607,7 +3611,7 @@  static int stmmac_request_irq_multi_msi(struct net_device *dev)
 		sprintf(int_name, "%s:%s-%d", dev->name, "rx", i);
 		ret = request_irq(priv->rx_irq[i],
 				  stmmac_msi_intr_rx,
-				  0, int_name, &priv->dma_conf.rx_queue[i]);
+				  flags, int_name, &priv->dma_conf.rx_queue[i]);
 		if (unlikely(ret < 0)) {
 			netdev_err(priv->dev,
 				   "%s: alloc rx-%d  MSI %d (error: %d)\n",
@@ -3632,7 +3636,7 @@  static int stmmac_request_irq_multi_msi(struct net_device *dev)
 		sprintf(int_name, "%s:%s-%d", dev->name, "tx", i);
 		ret = request_irq(priv->tx_irq[i],
 				  stmmac_msi_intr_tx,
-				  0, int_name, &priv->dma_conf.tx_queue[i]);
+				  flags, int_name, &priv->dma_conf.tx_queue[i]);
 		if (unlikely(ret < 0)) {
 			netdev_err(priv->dev,
 				   "%s: alloc tx-%d  MSI %d (error: %d)\n",
@@ -6057,8 +6061,10 @@  static u16 stmmac_select_queue(struct net_device *dev, struct sk_buff *skb,
 			       struct net_device *sb_dev)
 {
 	int gso = skb_shinfo(skb)->gso_type;
+	struct stmmac_priv *priv = netdev_priv(dev);
 
-	if (gso & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6 | SKB_GSO_UDP_L4)) {
+	if ((gso & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6 | SKB_GSO_UDP_L4)) ||
+	    priv->plat->has_lgmac) {
 		/*
 		 * There is no way to determine the number of TSO/USO
 		 * capable Queues. Let's use always the Queue 0
@@ -6936,7 +6942,8 @@  static int stmmac_hw_init(struct stmmac_priv *priv)
 	 * riwt_off field from the platform.
 	 */
 	if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
-	    (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
+	    (priv->plat->has_xgmac) || (priv->plat->has_lgmac)) &&
+	    (!priv->plat->riwt_off)) {
 		priv->use_riwt = 1;
 		dev_info(priv->device,
 			 "Enable RX Mitigation via HW Watchdog Timer\n");
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 46bccc34814d..e21076f57205 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -344,5 +344,6 @@  struct plat_stmmacenet_data {
 	bool has_integrated_pcs;
 	const struct dwmac_regs *dwmac_regs;
 	bool dwmac_is_loongson;
+	int has_lgmac;
 };
 #endif