Re: [U-Boot] [PATCH v2 2/3] net: add higmacv300 Ethernet driver for HiSilicon platform

2019-03-07 Thread Shawn Guo
On Wed, Mar 06, 2019 at 08:48:40PM +, Joe Hershberger wrote:
> On Tue, Mar 5, 2019 at 7:42 PM Shawn Guo  wrote:
> >
> > On Tue, Mar 05, 2019 at 11:58:26PM +, Joe Hershberger wrote:
> > > > +static int higmac_recv(struct udevice *dev, int flags, uchar **packetp)
> > > > +{
> > > > +   struct higmac_priv *priv = dev_get_priv(dev);
> > > > +   struct higmac_desc *fqd = priv->rxfq;
> > > > +   struct higmac_desc *bqd = priv->rxbq;
> > > > +   int fqw_pos, fqr_pos, bqw_pos, bqr_pos;
> > > > +   int timeout = 10;
> > > > +   int len = 0;
> > > > +   int space;
> > > > +   int i;
> > > > +
> > > > +   fqw_pos = DESC_CNT(readl(priv->base + RX_FQ_WR_ADDR));
> > > > +   fqr_pos = DESC_CNT(readl(priv->base + RX_FQ_RD_ADDR));
> > > > +
> > > > +   if (fqw_pos >= fqr_pos)
> > > > +   space = RX_DESC_NUM - (fqw_pos - fqr_pos);
> > > > +   else
> > > > +   space = fqr_pos - fqw_pos;
> > > > +
> > > > +   /* Leave one free to distinguish full filled from empty buffer 
> > > > */
> > > > +   for (i = 0; i < space - 1; i++) {
> > > > +   fqd = priv->rxfq + fqw_pos;
> > > > +   invalidate_dcache_range(fqd->buf_addr,
> > > > +   fqd->buf_addr + 
> > > > MAC_MAX_FRAME_SIZE);
> > > > +
> > > > +   if (++fqw_pos >= RX_DESC_NUM)
> > > > +   fqw_pos = 0;
> > > > +
> > > > +   writel(DESC_BYTE(fqw_pos), priv->base + RX_FQ_WR_ADDR);
> > > > +   }
> > > > +
> > > > +   bqr_pos = DESC_CNT(readl(priv->base + RX_BQ_RD_ADDR));
> > > > +   bqd += bqr_pos;
> > > > +   /* BQ is only ever written by GMAC */
> > > > +   invalidate_desc(bqd);
> > > > +
> > > > +   do {
> > > > +   bqw_pos = DESC_CNT(readl(priv->base + RX_BQ_WR_ADDR));
> > > > +   udelay(1);
> > > > +   } while (--timeout && bqw_pos == bqr_pos);
> > >
> > > Did you look into using wait bit macros?
> >
> > I may miss your point, but this is not a loop waiting for some bits set
> > or clear.  It's waiting for a given number.
> 
> OK, I see that, thanks. Should you make these "breakable" in the same
> way that wait_for_bit_* does? The timeout seems quite long.

I assume that you mean the "breakable" as user interaction (CTRL-C)?
I'm not sure 10 us (0.1 s) is so long for user to break.



> > > > +   reset_assert(>rst_phy);
> > > > +   mdelay(30);
> > >
> > > Why is this reasserted?
> >
> > I have to admit this is a bit hackish.  Ideally, the reset sequence
> > should be: deassert -> assert -> deassert.  But this reset signal gets
> > an opposite polarity than others that reset driver handles.  I can add a
> > comment to explain it if you can tolerate this little hack, or I will
> > add polarity support to reset driver to handle this phy reset quirk.
> > Please let me know your preference.
> 
> I would prefer a polarity to be defined in the DT for this reset.

OK, I will implement it in v3.  Thanks for the comment.

Shawn
___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v2 2/3] net: add higmacv300 Ethernet driver for HiSilicon platform

2019-03-06 Thread Joe Hershberger
On Tue, Mar 5, 2019 at 7:42 PM Shawn Guo  wrote:
>
> On Tue, Mar 05, 2019 at 11:58:26PM +, Joe Hershberger wrote:
> > > +static int higmac_recv(struct udevice *dev, int flags, uchar **packetp)
> > > +{
> > > +   struct higmac_priv *priv = dev_get_priv(dev);
> > > +   struct higmac_desc *fqd = priv->rxfq;
> > > +   struct higmac_desc *bqd = priv->rxbq;
> > > +   int fqw_pos, fqr_pos, bqw_pos, bqr_pos;
> > > +   int timeout = 10;
> > > +   int len = 0;
> > > +   int space;
> > > +   int i;
> > > +
> > > +   fqw_pos = DESC_CNT(readl(priv->base + RX_FQ_WR_ADDR));
> > > +   fqr_pos = DESC_CNT(readl(priv->base + RX_FQ_RD_ADDR));
> > > +
> > > +   if (fqw_pos >= fqr_pos)
> > > +   space = RX_DESC_NUM - (fqw_pos - fqr_pos);
> > > +   else
> > > +   space = fqr_pos - fqw_pos;
> > > +
> > > +   /* Leave one free to distinguish full filled from empty buffer */
> > > +   for (i = 0; i < space - 1; i++) {
> > > +   fqd = priv->rxfq + fqw_pos;
> > > +   invalidate_dcache_range(fqd->buf_addr,
> > > +   fqd->buf_addr + 
> > > MAC_MAX_FRAME_SIZE);
> > > +
> > > +   if (++fqw_pos >= RX_DESC_NUM)
> > > +   fqw_pos = 0;
> > > +
> > > +   writel(DESC_BYTE(fqw_pos), priv->base + RX_FQ_WR_ADDR);
> > > +   }
> > > +
> > > +   bqr_pos = DESC_CNT(readl(priv->base + RX_BQ_RD_ADDR));
> > > +   bqd += bqr_pos;
> > > +   /* BQ is only ever written by GMAC */
> > > +   invalidate_desc(bqd);
> > > +
> > > +   do {
> > > +   bqw_pos = DESC_CNT(readl(priv->base + RX_BQ_WR_ADDR));
> > > +   udelay(1);
> > > +   } while (--timeout && bqw_pos == bqr_pos);
> >
> > Did you look into using wait bit macros?
>
> I may miss your point, but this is not a loop waiting for some bits set
> or clear.  It's waiting for a given number.

OK, I see that, thanks. Should you make these "breakable" in the same
way that wait_for_bit_* does? The timeout seems quite long.

>
> >
> > > +
> > > +   if (!timeout)
> > > +   return -ETIMEDOUT;
> > > +
> > > +   if (++bqr_pos >= RX_DESC_NUM)
> > > +   bqr_pos = 0;
> > > +
> > > +   len = bqd->data_len;
> > > +
> > > +   /* CPU should not have touched this buffer since we added it to 
> > > FQ */
> > > +   invalidate_dcache_range(bqd->buf_addr, bqd->buf_addr + len);
> > > +   *packetp = (void *)(unsigned long)bqd->buf_addr;
> > > +
> > > +   /* Record the RX_BQ descriptor that is holding RX data */
> > > +   priv->rxdesc_in_use = bqr_pos;
> > > +
> > > +   return len;
> > > +}
>
> 
>
> > > +static int higmac_hw_init(struct higmac_priv *priv)
> > > +{
> > > +   int ret;
> > > +
> > > +   /* Initialize hardware queues */
> > > +   ret = higmac_init_hw_queue(priv, RX_FQ);
> > > +   if (ret)
> > > +   return ret;
> > > +
> > > +   ret = higmac_init_hw_queue(priv, RX_BQ);
> > > +   if (ret)
> > > +   goto free_rx_fq;
> > > +
> > > +   ret = higmac_init_hw_queue(priv, TX_BQ);
> > > +   if (ret)
> > > +   goto free_rx_bq;
> > > +
> > > +   ret = higmac_init_hw_queue(priv, TX_RQ);
> > > +   if (ret)
> > > +   goto free_tx_bq;
> > > +
> > > +   /* Reset phy */
> > > +   reset_assert(>rst_phy);
> > > +   mdelay(10);
> >
> > I'm surprised the delay here is not a DT parameter.
>
> We do not see the necessity for now.  We can make it a DT parameter when
> we see the real need in the future.

OK

>
> >
> > > +   reset_deassert(>rst_phy);
> > > +   mdelay(30);
> >
> > I'm surprised the delay here is not a DT parameter.
> >
> > > +   reset_assert(>rst_phy);
> > > +   mdelay(30);
> >
> > Why is this reasserted?
>
> I have to admit this is a bit hackish.  Ideally, the reset sequence
> should be: deassert -> assert -> deassert.  But this reset signal gets
> an opposite polarity than others that reset driver handles.  I can add a
> comment to explain it if you can tolerate this little hack, or I will
> add polarity support to reset driver to handle this phy reset quirk.
> Please let me know your preference.

I would prefer a polarity to be defined in the DT for this reset.

>
> >
> > > +
> > > +   return 0;
> > > +
> > > +free_tx_bq:
> > > +   free(priv->txbq);
> > > +free_rx_bq:
> > > +   free(priv->rxbq);
> > > +free_rx_fq:
> > > +   free(priv->rxfq);
> > > +   return ret;
> > > +}
> > > +
> > > +static int higmac_probe(struct udevice *dev)
> > > +{
> > > +   struct higmac_priv *priv = dev_get_priv(dev);
> > > +   struct phy_device *phydev;
> > > +   struct mii_dev *bus;
> > > +   int ret;
> > > +
> > > +   ret = higmac_hw_init(priv);
> > > +   if (ret)
> > > +   return ret;
> > > +
> > > +   bus = mdio_alloc();
> > > +   if (!bus)
> > > +   return 

Re: [U-Boot] [PATCH v2 2/3] net: add higmacv300 Ethernet driver for HiSilicon platform

2019-03-05 Thread Shawn Guo
On Tue, Mar 05, 2019 at 11:58:26PM +, Joe Hershberger wrote:
> > +static int higmac_recv(struct udevice *dev, int flags, uchar **packetp)
> > +{
> > +   struct higmac_priv *priv = dev_get_priv(dev);
> > +   struct higmac_desc *fqd = priv->rxfq;
> > +   struct higmac_desc *bqd = priv->rxbq;
> > +   int fqw_pos, fqr_pos, bqw_pos, bqr_pos;
> > +   int timeout = 10;
> > +   int len = 0;
> > +   int space;
> > +   int i;
> > +
> > +   fqw_pos = DESC_CNT(readl(priv->base + RX_FQ_WR_ADDR));
> > +   fqr_pos = DESC_CNT(readl(priv->base + RX_FQ_RD_ADDR));
> > +
> > +   if (fqw_pos >= fqr_pos)
> > +   space = RX_DESC_NUM - (fqw_pos - fqr_pos);
> > +   else
> > +   space = fqr_pos - fqw_pos;
> > +
> > +   /* Leave one free to distinguish full filled from empty buffer */
> > +   for (i = 0; i < space - 1; i++) {
> > +   fqd = priv->rxfq + fqw_pos;
> > +   invalidate_dcache_range(fqd->buf_addr,
> > +   fqd->buf_addr + MAC_MAX_FRAME_SIZE);
> > +
> > +   if (++fqw_pos >= RX_DESC_NUM)
> > +   fqw_pos = 0;
> > +
> > +   writel(DESC_BYTE(fqw_pos), priv->base + RX_FQ_WR_ADDR);
> > +   }
> > +
> > +   bqr_pos = DESC_CNT(readl(priv->base + RX_BQ_RD_ADDR));
> > +   bqd += bqr_pos;
> > +   /* BQ is only ever written by GMAC */
> > +   invalidate_desc(bqd);
> > +
> > +   do {
> > +   bqw_pos = DESC_CNT(readl(priv->base + RX_BQ_WR_ADDR));
> > +   udelay(1);
> > +   } while (--timeout && bqw_pos == bqr_pos);
> 
> Did you look into using wait bit macros?

I may miss your point, but this is not a loop waiting for some bits set
or clear.  It's waiting for a given number.

> 
> > +
> > +   if (!timeout)
> > +   return -ETIMEDOUT;
> > +
> > +   if (++bqr_pos >= RX_DESC_NUM)
> > +   bqr_pos = 0;
> > +
> > +   len = bqd->data_len;
> > +
> > +   /* CPU should not have touched this buffer since we added it to FQ 
> > */
> > +   invalidate_dcache_range(bqd->buf_addr, bqd->buf_addr + len);
> > +   *packetp = (void *)(unsigned long)bqd->buf_addr;
> > +
> > +   /* Record the RX_BQ descriptor that is holding RX data */
> > +   priv->rxdesc_in_use = bqr_pos;
> > +
> > +   return len;
> > +}



> > +static int higmac_hw_init(struct higmac_priv *priv)
> > +{
> > +   int ret;
> > +
> > +   /* Initialize hardware queues */
> > +   ret = higmac_init_hw_queue(priv, RX_FQ);
> > +   if (ret)
> > +   return ret;
> > +
> > +   ret = higmac_init_hw_queue(priv, RX_BQ);
> > +   if (ret)
> > +   goto free_rx_fq;
> > +
> > +   ret = higmac_init_hw_queue(priv, TX_BQ);
> > +   if (ret)
> > +   goto free_rx_bq;
> > +
> > +   ret = higmac_init_hw_queue(priv, TX_RQ);
> > +   if (ret)
> > +   goto free_tx_bq;
> > +
> > +   /* Reset phy */
> > +   reset_assert(>rst_phy);
> > +   mdelay(10);
> 
> I'm surprised the delay here is not a DT parameter.

We do not see the necessity for now.  We can make it a DT parameter when
we see the real need in the future.

> 
> > +   reset_deassert(>rst_phy);
> > +   mdelay(30);
> 
> I'm surprised the delay here is not a DT parameter.
> 
> > +   reset_assert(>rst_phy);
> > +   mdelay(30);
> 
> Why is this reasserted?

I have to admit this is a bit hackish.  Ideally, the reset sequence
should be: deassert -> assert -> deassert.  But this reset signal gets
an opposite polarity than others that reset driver handles.  I can add a
comment to explain it if you can tolerate this little hack, or I will
add polarity support to reset driver to handle this phy reset quirk.
Please let me know your preference.

> 
> > +
> > +   return 0;
> > +
> > +free_tx_bq:
> > +   free(priv->txbq);
> > +free_rx_bq:
> > +   free(priv->rxbq);
> > +free_rx_fq:
> > +   free(priv->rxfq);
> > +   return ret;
> > +}
> > +
> > +static int higmac_probe(struct udevice *dev)
> > +{
> > +   struct higmac_priv *priv = dev_get_priv(dev);
> > +   struct phy_device *phydev;
> > +   struct mii_dev *bus;
> > +   int ret;
> > +
> > +   ret = higmac_hw_init(priv);
> > +   if (ret)
> > +   return ret;
> > +
> > +   bus = mdio_alloc();
> > +   if (!bus)
> > +   return -ENOMEM;
> > +
> > +   bus->read = higmac_mdio_read;
> > +   bus->write = higmac_mdio_write;
> > +   bus->priv = priv;
> > +   priv->bus = bus;
> > +
> > +   ret = mdio_register_seq(bus, dev->seq);
> > +   if (ret)
> > +   return ret;
> > +
> > +   phydev = phy_connect(bus, priv->phyaddr, dev, priv->phyintf);
> > +   if (!phydev)
> > +   return -ENODEV;
> > +
> > +   phydev->supported &= PHY_GBIT_FEATURES;
> > +   phydev->advertising = phydev->supported;
> > +   

Re: [U-Boot] [PATCH v2 2/3] net: add higmacv300 Ethernet driver for HiSilicon platform

2019-03-05 Thread Joe Hershberger
On Sun, Feb 17, 2019 at 9:39 PM Shawn Guo  wrote:
>
> It adds the driver for HIGMACV300 Ethernet controller found on HiSilicon
> SoCs like Hi3798CV200.  It's based on a downstream U-Boot driver, but
> quite a lot of code gets rewritten and cleaned up to adopt driver model
> and PHY API.
>
> Signed-off-by: Shawn Guo 

Looks pretty good. I have a few  questions / comments below.

> ---
>  drivers/net/Kconfig  |   9 +
>  drivers/net/Makefile |   1 +
>  drivers/net/higmacv300.c | 597 +++
>  3 files changed, 607 insertions(+)
>  create mode 100644 drivers/net/higmacv300.c
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 6a570285aac5..ad1e50c0e8ca 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -525,4 +525,13 @@ config MEDIATEK_ETH
>   This Driver support MediaTek Ethernet GMAC
>   Say Y to enable support for the MediaTek Ethernet GMAC.
>
> +config HIGMACV300_ETH
> +   bool "HiSilicon Gigabit Ethernet Controller"
> +   depends on DM_ETH
> +   select DM_RESET
> +   select PHYLIB
> +   help
> + This driver supports HIGMACV300 Ethernet controller found on
> + HiSilicon SoCs.
> +
>  endif # NETDEVICES
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 51be72b0aa86..8d02a378964b 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -76,3 +76,4 @@ obj-$(CONFIG_SNI_AVE) += sni_ave.o
>  obj-y += ti/
>  obj-$(CONFIG_MEDIATEK_ETH) += mtk_eth.o
>  obj-y += mscc_eswitch/
> +obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
> diff --git a/drivers/net/higmacv300.c b/drivers/net/higmacv300.c
> new file mode 100644
> index ..549c26b19b99
> --- /dev/null
> +++ b/drivers/net/higmacv300.c
> @@ -0,0 +1,597 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019, Linaro Limited
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define STATION_ADDR_LOW   0x
> +#define STATION_ADDR_HIGH  0x0004
> +#define MAC_DUPLEX_HALF_CTRL   0x0008
> +#define PORT_MODE  0x0040
> +#define PORT_EN0x0044
> +#define BIT_TX_EN  BIT(2)
> +#define BIT_RX_EN  BIT(1)
> +#define MODE_CHANGE_EN 0x01b4
> +#define BIT_MODE_CHANGE_EN BIT(0)
> +#define MDIO_SINGLE_CMD0x03c0
> +#define BIT_MDIO_BUSY  BIT(20)
> +#define MDIO_READ  (BIT(17) | BIT_MDIO_BUSY)
> +#define MDIO_WRITE (BIT(16) | BIT_MDIO_BUSY)
> +#define MDIO_SINGLE_DATA   0x03c4
> +#define MDIO_RDATA_STATUS  0x03d0
> +#define BIT_MDIO_RDATA_INVALID BIT(0)
> +#define RX_FQ_START_ADDR   0x0500
> +#define RX_FQ_DEPTH0x0504
> +#define RX_FQ_WR_ADDR  0x0508
> +#define RX_FQ_RD_ADDR  0x050c
> +#define RX_FQ_REG_EN   0x0518
> +#define RX_BQ_START_ADDR   0x0520
> +#define RX_BQ_DEPTH0x0524
> +#define RX_BQ_WR_ADDR  0x0528
> +#define RX_BQ_RD_ADDR  0x052c
> +#define RX_BQ_REG_EN   0x0538
> +#define TX_BQ_START_ADDR   0x0580
> +#define TX_BQ_DEPTH0x0584
> +#define TX_BQ_WR_ADDR  0x0588
> +#define TX_BQ_RD_ADDR  0x058c
> +#define TX_BQ_REG_EN   0x0598
> +#define TX_RQ_START_ADDR   0x05a0
> +#define TX_RQ_DEPTH0x05a4
> +#define TX_RQ_WR_ADDR  0x05a8
> +#define TX_RQ_RD_ADDR  0x05ac
> +#define TX_RQ_REG_EN   0x05b8
> +#define BIT_START_ADDR_EN  BIT(2)
> +#define BIT_DEPTH_EN   BIT(1)
> +#define DESC_WR_RD_ENA 0x05cc
> +#define BIT_RX_OUTCFF_WR   BIT(3)
> +#define BIT_RX_CFF_RD  BIT(2)
> +#define BIT_TX_OUTCFF_WR   BIT(1)
> +#define BIT_TX_CFF_RD  BIT(0)
> +#define BITS_DESC_ENA  (BIT_RX_OUTCFF_WR | BIT_RX_CFF_RD | \
> +BIT_TX_OUTCFF_WR | BIT_TX_CFF_RD)
> +
> +/* MACIF_CTRL */
> +#define RGMII_SPEED_1000   0x2c
> +#define RGMII_SPEED_1000x2f
> +#define RGMII_SPEED_10 0x2d
> +#define MII_SPEED_100  0x0f
> +#define MII_SPEED_10   0x0d
> +#define GMAC_SPEED_10000x05
> +#define GMAC_SPEED_100 0x01
> +#define GMAC_SPEED_10  0x00
> +#define GMAC_FULL_DUPLEX   BIT(4)
> +
> +#define RX_DESC_NUM64
> +#define TX_DESC_NUM2
> +#define DESC_SIZE  32
> +#define DESC_WORD_SHIFT3
> +#define 

[U-Boot] [PATCH v2 2/3] net: add higmacv300 Ethernet driver for HiSilicon platform

2019-02-17 Thread Shawn Guo
It adds the driver for HIGMACV300 Ethernet controller found on HiSilicon
SoCs like Hi3798CV200.  It's based on a downstream U-Boot driver, but
quite a lot of code gets rewritten and cleaned up to adopt driver model
and PHY API.

Signed-off-by: Shawn Guo 
---
 drivers/net/Kconfig  |   9 +
 drivers/net/Makefile |   1 +
 drivers/net/higmacv300.c | 597 +++
 3 files changed, 607 insertions(+)
 create mode 100644 drivers/net/higmacv300.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6a570285aac5..ad1e50c0e8ca 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -525,4 +525,13 @@ config MEDIATEK_ETH
  This Driver support MediaTek Ethernet GMAC
  Say Y to enable support for the MediaTek Ethernet GMAC.
 
+config HIGMACV300_ETH
+   bool "HiSilicon Gigabit Ethernet Controller"
+   depends on DM_ETH
+   select DM_RESET
+   select PHYLIB
+   help
+ This driver supports HIGMACV300 Ethernet controller found on
+ HiSilicon SoCs.
+
 endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 51be72b0aa86..8d02a378964b 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -76,3 +76,4 @@ obj-$(CONFIG_SNI_AVE) += sni_ave.o
 obj-y += ti/
 obj-$(CONFIG_MEDIATEK_ETH) += mtk_eth.o
 obj-y += mscc_eswitch/
+obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
diff --git a/drivers/net/higmacv300.c b/drivers/net/higmacv300.c
new file mode 100644
index ..549c26b19b99
--- /dev/null
+++ b/drivers/net/higmacv300.c
@@ -0,0 +1,597 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019, Linaro Limited
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define STATION_ADDR_LOW   0x
+#define STATION_ADDR_HIGH  0x0004
+#define MAC_DUPLEX_HALF_CTRL   0x0008
+#define PORT_MODE  0x0040
+#define PORT_EN0x0044
+#define BIT_TX_EN  BIT(2)
+#define BIT_RX_EN  BIT(1)
+#define MODE_CHANGE_EN 0x01b4
+#define BIT_MODE_CHANGE_EN BIT(0)
+#define MDIO_SINGLE_CMD0x03c0
+#define BIT_MDIO_BUSY  BIT(20)
+#define MDIO_READ  (BIT(17) | BIT_MDIO_BUSY)
+#define MDIO_WRITE (BIT(16) | BIT_MDIO_BUSY)
+#define MDIO_SINGLE_DATA   0x03c4
+#define MDIO_RDATA_STATUS  0x03d0
+#define BIT_MDIO_RDATA_INVALID BIT(0)
+#define RX_FQ_START_ADDR   0x0500
+#define RX_FQ_DEPTH0x0504
+#define RX_FQ_WR_ADDR  0x0508
+#define RX_FQ_RD_ADDR  0x050c
+#define RX_FQ_REG_EN   0x0518
+#define RX_BQ_START_ADDR   0x0520
+#define RX_BQ_DEPTH0x0524
+#define RX_BQ_WR_ADDR  0x0528
+#define RX_BQ_RD_ADDR  0x052c
+#define RX_BQ_REG_EN   0x0538
+#define TX_BQ_START_ADDR   0x0580
+#define TX_BQ_DEPTH0x0584
+#define TX_BQ_WR_ADDR  0x0588
+#define TX_BQ_RD_ADDR  0x058c
+#define TX_BQ_REG_EN   0x0598
+#define TX_RQ_START_ADDR   0x05a0
+#define TX_RQ_DEPTH0x05a4
+#define TX_RQ_WR_ADDR  0x05a8
+#define TX_RQ_RD_ADDR  0x05ac
+#define TX_RQ_REG_EN   0x05b8
+#define BIT_START_ADDR_EN  BIT(2)
+#define BIT_DEPTH_EN   BIT(1)
+#define DESC_WR_RD_ENA 0x05cc
+#define BIT_RX_OUTCFF_WR   BIT(3)
+#define BIT_RX_CFF_RD  BIT(2)
+#define BIT_TX_OUTCFF_WR   BIT(1)
+#define BIT_TX_CFF_RD  BIT(0)
+#define BITS_DESC_ENA  (BIT_RX_OUTCFF_WR | BIT_RX_CFF_RD | \
+BIT_TX_OUTCFF_WR | BIT_TX_CFF_RD)
+
+/* MACIF_CTRL */
+#define RGMII_SPEED_1000   0x2c
+#define RGMII_SPEED_1000x2f
+#define RGMII_SPEED_10 0x2d
+#define MII_SPEED_100  0x0f
+#define MII_SPEED_10   0x0d
+#define GMAC_SPEED_10000x05
+#define GMAC_SPEED_100 0x01
+#define GMAC_SPEED_10  0x00
+#define GMAC_FULL_DUPLEX   BIT(4)
+
+#define RX_DESC_NUM64
+#define TX_DESC_NUM2
+#define DESC_SIZE  32
+#define DESC_WORD_SHIFT3
+#define DESC_BYTE_SHIFT5
+#define DESC_CNT(n)((n) >> DESC_BYTE_SHIFT)
+#define DESC_BYTE(n)   ((n) << DESC_BYTE_SHIFT)
+#define DESC_VLD_FREE  0
+#define DESC_VLD_BUSY  1
+
+#define MAC_MAX_FRAME_SIZE 1600
+
+enum higmac_queue {
+   RX_FQ,
+   RX_BQ,
+