Re: [U-Boot] [PATCH v2 2/3] net: add higmacv300 Ethernet driver for HiSilicon platform
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
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
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
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
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, +