Hello

I have some minor comments below

Le 15/05/2016 11:41, Amit Singh Tomar a écrit :
> This patch add EMAC driver support for H3/A83T/A64 SoCs.
> 
> It has been tested on Oragnepipc(H3) board that has internal PHY.

A little typo

> 
> Signed-off-by: Amit Singh Tomar <amittome...@gmail.com>
> ---
>  arch/arm/dts/sun8i-h3-orangepi-pc.dts |   10 +
>  arch/arm/dts/sun8i-h3.dtsi            |    7 +
>  drivers/net/Kconfig                   |    8 +
>  drivers/net/Makefile                  |    1 +
>  drivers/net/sun8i_emac.c              |  678 
> +++++++++++++++++++++++++++++++++
>  5 files changed, 704 insertions(+)
>  create mode 100644 drivers/net/sun8i_emac.c
> 
> diff --git a/arch/arm/dts/sun8i-h3-orangepi-pc.dts 
> b/arch/arm/dts/sun8i-h3-orangepi-pc.dts
> index 30ccca0..3a40fb8 100644
> --- a/arch/arm/dts/sun8i-h3-orangepi-pc.dts
> +++ b/arch/arm/dts/sun8i-h3-orangepi-pc.dts
> @@ -173,3 +173,13 @@
>       /* USB VBUS is always on */
>       status = "okay";
>  };
> +
> +&emac {
> +     phy = <&phy1>;
> +     phy-mode = "mii";
> +     status = "okay";
> +
> +     phy1: ethernet-phy@1 {
> +             reg = <1>;
> +       };
> +};
> diff --git a/arch/arm/dts/sun8i-h3.dtsi b/arch/arm/dts/sun8i-h3.dtsi
> index c2f63c5..1e403e3 100644
> --- a/arch/arm/dts/sun8i-h3.dtsi
> +++ b/arch/arm/dts/sun8i-h3.dtsi
> @@ -616,6 +616,13 @@
>                       status = "disabled";
>               };
>  
> +             emac: ethernet@01c30000 {
> +                        compatible = "allwinner,sun8i-h3-emac";
> +                        reg = <0x01c30000 0x10000>;

10000 is too high

> +                        #address-cells = <1>;
> +                        #size-cells = <0>;
> +                };
> +
>               gic: interrupt-controller@01c81000 {
>                       compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
>                       reg = <0x01c81000 0x1000>,
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 91b7690..3c21810 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -46,6 +46,14 @@ menuconfig NETDEVICES
>  
>  if NETDEVICES
>  
> +config SUN8I_EMAC
> +        bool "Allwinner Sun8i Ethernet MAC support"
> +        depends on DM_ETH
> +        select PHYLIB
> +        help
> +          This driver supports the  Allwinner based SUN8I Ethernet MAC.It can

Space after dot. Try also to keep a minimum of alphabetical order of config.

> +       be found in Allwinners H3/A64/A83T based SoCs.
> +
>  config ALTERA_TSE
>       bool "Altera Triple-Speed Ethernet MAC support"
>       depends on DM_ETH
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index fbedd04..f78fdc5 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -74,3 +74,4 @@ obj-$(CONFIG_FSL_MC_ENET) += ldpaa_eth/
>  obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o
>  obj-$(CONFIG_VSC9953) += vsc9953.o
>  obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o
> +obj-$(CONFIG_SUN8I_EMAC) = sun8i_emac.o

You could put it just after the other sunxi driver

> diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
> new file mode 100644
> index 0000000..0858235
> --- /dev/null
> +++ b/drivers/net/sun8i_emac.c
> @@ -0,0 +1,678 @@
> +/*
> + * (C) Copyright 2016
> + * Author: Amit Singh Tomar, amittome...@gmail.com
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + *
> + * Ethernet driver for H3/A64 based SoC

You forgot A83T

> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <linux/err.h>
> +#include <malloc.h>
> +#include <miiphy.h>
> +#include <net.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/gpio.h>

Sort also headers

> +
> +#define SUN8I_AHB2_EPHY 0x02c8
> +
> +#define AHB2_CFG_REG 0x005c
> +
> +#define BUS_SOFT_RST_REG0 0x02c0
> +#define BUS_SOFT_RST_REG2 0x02c8
> +
> +#define EPHY_RST (0x1 << 2)
> +#define EMAC_RST (0x1 << 17)
> +
> +#define SUN8I_CCU_BASE 0x01c20000
> +#define SUN8I_SCTL_BASE 0x01c00000
> +
> +#define SCTL_EMAC_TX_CLK_SRC_MII ((1 << 1) | (1 << 0))
> +#define SCTL_EMAC_EPIT_MII (1 << 2)
> +#define SCTL_EMAC_CLK_SEL (1 << 18) /* 25 Mhz */

Use BIT()

> +
> +#define MDIO_CMD_MII_BUSY       BIT(0)
> +#define MDIO_CMD_MII_WRITE      BIT(1)
> +
> +#define MDIO_CMD_MII_PHY_REG_ADDR_MASK  0x000001f0
> +#define MDIO_CMD_MII_PHY_REG_ADDR_SHIFT 4
> +#define MDIO_CMD_MII_PHY_ADDR_MASK      0x0001f000
> +#define MDIO_CMD_MII_PHY_ADDR_SHIFT     12
> +
> +#define CONFIG_TX_DESCR_NUM     128
> +#define CONFIG_RX_DESCR_NUM     128
> +#define CONFIG_ETH_BUFSIZE      1522

I do not know the memory pressure on uboot but the number of descriptors could 
be less since uboot seems to not have any scattergather for network (so 64 or 
perhaps 32 could be enought)

> +
> +#define TX_TOTAL_BUFSIZE        (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM)
> +#define RX_TOTAL_BUFSIZE        (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM)
> +
> +#define REG_DEFAULT_VALUE    0x58000
> +#define REG_DEFAULT_MASK     GENMASK(31, 15)
> +
> +#define REG_PHY_ADDR_SHIFT   20
> +#define REG_PHY_ADDR_MASK    GENMASK(4, 0)
> +#define REG_LED_POL          BIT(17) /* 1: active low, 0: active high */
> +#define REG_SHUTDOWN         BIT(16) /* 1: shutdown, 0: power up */
> +#define REG_PHY_SELECT               BIT(15) /* 1: internal PHY, 0: external 
> PHY */
> +
> +#define CONFIG_MDIO_TIMEOUT     (3 * CONFIG_SYS_HZ)
> +
> +#define  AHB_GATE_OFFSET_GMAC 17
> +#define  AHB_GATE_OFFSET_EPHY 0
> +
> +#define SUN8I_GPD8_GMAC 4
> +
> +/* H3/A64 EMAC Register Base */
> +#define SUN8I_EMAC_BASE 0x01c30000
> +
> +/* H3/A64 EMAC Register's offset */
> +#define      CTL0            0x00
> +#define CTL1         0x04
> +#define INT_STA              0x08
> +#define INT_EN               0x0c
> +#define TX_CTL0              0x10
> +#define TX_CTL1              0x14
> +#define      TX_FLOW_CTL     0x1c
> +#define      TX_DMA_DESC     0x20

It seems you have mixed space and tab

> +#define RX_CTL0              0x24
> +#define RX_CTL1              0x28
> +#define RX_DMA_DESC  0x34
> +#define      MII_CMD         0x48
> +#define      MII_DATA        0x4c
> +#define      ADDR0_HIGH      0x50
> +#define      ADDR0_LOW       0x54
> +#define TX_DMA_STA   0xb0
> +#define      TX_CUR_DESC     0xb4
> +#define TX_CUR_BUF      0xb8
> +#define RX_DMA_STA   0xc0
> +#define RX_CUR_DESC  0xc4

Perhaps prefixing all register with SUN8I_EMAC or just EMAC/GMAC could be 
better.

> +
> +/* CCM Register base */
> +#define SUN8I_CCM_BASE 0x01c20000
> +
> +/* CCM Register offset */
> +#define      CLK_GATING_REG0         0x60
> +#define CLK_GATING_REG1              0x64
> +#define CLK_GATING_REG2              0x68
> +#define CLK_GATING_REG3              0x6c
> +#define CLK_GATING_REG4              0x70
> +
> +/* System Control Register base */
> +#define SUN8I_SCTL_BASE 0x01c00000
> +
> +/* System Control Register's offset */
> +#define VER_REG 0x24
> +#define EMAC_CLK_REG 0x30
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct emac_dma_desc {
> +     u32 status;
> +     u32 st;
> +     void *buf_addr;
> +     struct emac_dma_desc *next;
> +} __aligned(ARCH_DMA_MINALIGN);
> +
> +struct emac_eth_dev {
> +     struct emac_dma_desc rx_chain[CONFIG_TX_DESCR_NUM];
> +     struct emac_dma_desc tx_chain[CONFIG_RX_DESCR_NUM];
> +     char rxbuffer[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
> +     char txbuffer[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
> +
> +     u32 interface;
> +     u32 phyaddr;
> +     u32 link;
> +     u32 speed;
> +     u32 duplex;
> +     u32 phy_configured;
> +     u32 tx_currdescnum;
> +     u32 rx_currdescnum;
> +     u32 addr;
> +     u32 tx_slot;
> +     void *mac_reg;
> +     void *sysctl_reg;
> +     void *ccu_reg;
> +     struct phy_device *phydev;
> +     struct mii_dev *bus;
> +};
> +
> +static int sun8i_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
> +{
> +     struct emac_eth_dev *priv = bus->priv;
> +     ulong start;
> +     u32 miiaddr = 0;
> +     int timeout = CONFIG_MDIO_TIMEOUT;
> +
> +     miiaddr &= ~MDIO_CMD_MII_WRITE;
> +     miiaddr &= ~MDIO_CMD_MII_PHY_REG_ADDR_MASK;
> +     miiaddr |= (reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) &
> +             MDIO_CMD_MII_PHY_REG_ADDR_MASK;
> +
> +     miiaddr &= ~MDIO_CMD_MII_PHY_ADDR_MASK;
> +
> +     miiaddr |= (addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) &
> +             MDIO_CMD_MII_PHY_ADDR_MASK;
> +
> +     miiaddr |= MDIO_CMD_MII_BUSY;
> +
> +     writel(miiaddr, priv->mac_reg + MII_CMD);
> +
> +     start = get_timer(0);
> +     while (get_timer(start) < timeout) {
> +             if (!(readl(priv->mac_reg + MII_CMD) & MDIO_CMD_MII_BUSY))
> +                     return readl(priv->mac_reg + MII_DATA);
> +             udelay(10);
> +     };
> +
> +     return -1;
> +}
> +
> +static int sun8i_mdio_write(struct mii_dev *bus, int addr, int devad, int 
> reg,
> +             u16 val)
> +{
> +     struct emac_eth_dev *priv = bus->priv;
> +     ulong start;
> +     u32 miiaddr = 0;
> +     int ret = -1, timeout = CONFIG_MDIO_TIMEOUT;
> +
> +     miiaddr &= ~MDIO_CMD_MII_PHY_REG_ADDR_MASK;
> +     miiaddr |= (reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) &
> +             MDIO_CMD_MII_PHY_REG_ADDR_MASK;
> +
> +     miiaddr &= ~MDIO_CMD_MII_PHY_ADDR_MASK;
> +     miiaddr |= (addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) &
> +             MDIO_CMD_MII_PHY_ADDR_MASK;
> +
> +     miiaddr |= MDIO_CMD_MII_WRITE;
> +     miiaddr |= MDIO_CMD_MII_BUSY;
> +
> +     writel(miiaddr, priv->mac_reg + MII_CMD);
> +     writel(val, priv->mac_reg + MII_DATA);
> +
> +     start = get_timer(0);
> +     while (get_timer(start) < timeout) {
> +             if (!(readl(priv->mac_reg + MII_CMD) & MDIO_CMD_MII_BUSY)) {
> +                     ret = 0;
> +                     break;
> +             }
> +             udelay(10);
> +     };
> +
> +     return ret;
> +}
> +
> +static int _sun8i_write_hwaddr(struct emac_eth_dev *priv, u8 *mac_id)
> +{
> +     u32 macid_lo, macid_hi;
> +
> +     macid_lo = mac_id[0] + (mac_id[1] << 8) + (mac_id[2] << 16) +
> +             (mac_id[3] << 24);
> +     macid_hi = mac_id[4] + (mac_id[5] << 8);
> +
> +     writel(macid_hi, priv->mac_reg + ADDR0_HIGH);
> +     writel(macid_lo, priv->mac_reg + ADDR0_LOW);
> +
> +     return 0;
> +}
> +
> +static int sun8i_phy_init(struct emac_eth_dev *priv, void *dev)
> +{
> +     struct phy_device *phydev;
> +     u32 val;
> +
> +     /* H3 based SoC has an Internal PHY that needs
> +        to be configured and powered up before use
> +      */
> +
> +     val = readl(priv->sysctl_reg + EMAC_CLK_REG);
> +     val = (val & ~REG_DEFAULT_MASK) | REG_DEFAULT_VALUE;
> +
> +     val |= priv->phyaddr << REG_PHY_ADDR_SHIFT;
> +     val &= ~REG_SHUTDOWN;
> +     val |= REG_PHY_SELECT;
> +
> +     setbits_le32((priv->sysctl_reg + EMAC_CLK_REG), (1 << 13));
> +     writel(val, (priv->sysctl_reg + EMAC_CLK_REG));
> +
> +     phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
> +     if (!phydev)
> +             return -ENODEV;
> +
> +     phy_connect_dev(phydev, dev);
> +
> +     priv->phydev = phydev;
> +     phy_config(phydev);
> +
> +     return 0;
> +}
> +
> +static void sun8i_adjust_link(struct emac_eth_dev *priv,
> +             struct phy_device *phydev)
> +{
> +     u32 v;
> +     v = readl(priv->mac_reg + CTL0);
> +
> +     if (phydev->duplex)
> +             v |= BIT(0);
> +     else
> +             v &= ~BIT(0);
> +
> +     v &= ~0x0C;
> +
> +     switch (phydev->speed) {
> +     case 1000:
> +             break;
> +     case 100:
> +             v |= BIT(2);
> +             v |= BIT(3);
> +             break;
> +     case 10:
> +             v |= BIT(3);
> +             break;
> +     }
> +     writel(v, priv->mac_reg + CTL0);
> +}
> +
> +static void rx_descs_init(struct emac_eth_dev *priv)
> +{
> +     struct emac_dma_desc *desc_table_p = &priv->rx_chain[0];
> +     char *rxbuffs = &priv->rxbuffer[0];
> +     struct emac_dma_desc *desc_p;
> +     u32 idx;
> +
> +     /* flush Rx buffers */
> +     flush_dcache_range((unsigned int)rxbuffs, (unsigned int)rxbuffs +
> +                     RX_TOTAL_BUFSIZE);
> +
> +     for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
> +             desc_p = &desc_table_p[idx];
> +             desc_p->buf_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE];
> +             desc_p->next = &desc_table_p[idx + 1];
> +             desc_p->st |= CONFIG_ETH_BUFSIZE;
> +             desc_p->status = BIT(31);
> +     }
> +
> +     /* Correcting the last pointer of the chain */
> +     desc_p->next = &desc_table_p[0];
> +
> +     flush_dcache_range((unsigned int)priv->rx_chain,
> +                         (unsigned int)priv->rx_chain +
> +                          sizeof(priv->rx_chain));
> +
> +     writel((ulong)&desc_table_p[0], (priv->mac_reg + RX_DMA_DESC));
> +     priv->rx_currdescnum = 0;
> +}
> +
> +static void tx_descs_init(struct emac_eth_dev *priv)
> +{
> +     struct emac_dma_desc *desc_table_p = &priv->tx_chain[0];
> +     char *txbuffs = &priv->txbuffer[0];
> +     struct emac_dma_desc *desc_p;
> +     u32 idx;
> +
> +     for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) {
> +             desc_p = &desc_table_p[idx];
> +             desc_p->buf_addr = &txbuffs[idx * CONFIG_ETH_BUFSIZE];
> +             desc_p->next = &desc_table_p[idx + 1];
> +             desc_p->status = (1 << 31);

You forgot a BIT()

> +             desc_p->st = 0;
> +     }
> +
> +     /* Correcting the last pointer of the chain */
> +     desc_p->next = &desc_table_p[0];
> +
> +     /* Flush all Tx buffer descriptors */
> +     flush_dcache_range((unsigned int)priv->tx_chain,
> +                     (unsigned int)priv->tx_chain +
> +                     sizeof(priv->tx_chain));
> +
> +     writel((ulong)&desc_table_p[0], priv->mac_reg + TX_DMA_DESC);
> +     priv->tx_currdescnum = 0;
> +}
> +
> +static int _sun8i_emac_eth_init(struct emac_eth_dev *priv, u8 *enetaddr)
> +{
> +     u32 reg, v;
> +     int timeout = 100;
> +
> +     reg = readl((priv->mac_reg + CTL1));
> +
> +     if (!(reg & 0x1)) {
> +             /* Soft reset MAC */
> +             setbits_le32((priv->mac_reg + CTL1), 0x1 << 0);

The <<0 is useless

> +             do {
> +                     reg = readl(priv->mac_reg + CTL1);
> +             } while ((reg & 0x01) != 0 &&  (--timeout));
> +             if (!timeout) {
> +                     printf("%s: Timeout\n", __func__);
> +                     return -1;
> +
> +             }
> +
> +     }
> +
> +     /* Rewrite mac address after reset */
> +     _sun8i_write_hwaddr(priv, enetaddr);
> +
> +     v = readl(priv->mac_reg + TX_CTL1);
> +     /* TX_MD Transmission starts after a full frame located in TX DMA FIFO*/
> +     v |= BIT(1);
> +     writel(v, priv->mac_reg + TX_CTL1);
> +
> +     v = readl(priv->mac_reg + RX_CTL1);
> +     /* RX_MD RX DMA reads data from RX DMA FIFO to host memory after a
> +      * complete frame has been written to RX DMA FIFO
> +      */
> +     v |= BIT(1);
> +     writel(v, priv->mac_reg + RX_CTL1);
> +
> +     /* DMA */
> +     writel(8 << 24 , priv->mac_reg + CTL1);
> +
> +     /* Initialize rx/tx descriptors */
> +     rx_descs_init(priv);
> +     tx_descs_init(priv);
> +
> +     /*Start up the PHY */
> +     if (phy_startup(priv->phydev)) {
> +             printf("Could not initialize PHY %s\n",
> +                             priv->phydev->dev->name);
> +             return -1;
> +     }
> +
> +     sun8i_adjust_link(priv, priv->phydev);
> +
> +     /* Start RX DMA */
> +     v = readl(priv->mac_reg + RX_CTL1);
> +     v |= BIT(30);
> +     writel(v, priv->mac_reg + RX_CTL1);
> +     /* Start TX DMA */
> +     v = readl(priv->mac_reg + TX_CTL1);
> +     v |= BIT(30);
> +     writel(v, priv->mac_reg + TX_CTL1);
> +
> +     /* Enable RX/TX */
> +     setbits_le32(priv->mac_reg + RX_CTL0, 0x1 << 31);
> +     setbits_le32(priv->mac_reg + TX_CTL0, 0x1 << 31);

BIT() again

> +
> +     return 0;
> +}
> +
> +static void sun8i_emac_board_setup(struct emac_eth_dev *priv)
> +{
> +     priv->ccu_reg = (void *)SUN8I_CCU_BASE;
> +     priv->sysctl_reg = (void *)SUN8I_SCTL_BASE;
> +     int pin;
> +
> +     /* Set clock gating for emac */
> +     setbits_le32((priv->ccu_reg + CLK_GATING_REG0),
> +                   0x1 << AHB_GATE_OFFSET_GMAC);
> +
> +     /* Set clock gating for ephy */
> +     setbits_le32((priv->ccu_reg + CLK_GATING_REG4),
> +                   0x1 << AHB_GATE_OFFSET_EPHY);
> +
> +     /* Set Tx clock source as MII with rate 25 MZ */
> +     clrbits_le32((priv->sysctl_reg + EMAC_CLK_REG),
> +                   SCTL_EMAC_TX_CLK_SRC_MII |
> +                   SCTL_EMAC_EPIT_MII | SCTL_EMAC_CLK_SEL);
> +
> +     /* Set EMAC clock */
> +     setbits_le32((priv->ccu_reg + AHB2_CFG_REG), (0x1 << 1) | (0x1 << 0));
> +
> +     /* Deassert EPHY */
> +     setbits_le32((priv->ccu_reg + BUS_SOFT_RST_REG2), EPHY_RST);
> +
> +     /* De-assert EMAC */
> +     setbits_le32((priv->ccu_reg + BUS_SOFT_RST_REG0), EMAC_RST);
> +
> +     /* Pin mux setting for emac */
> +     for (pin = SUNXI_GPD(8); pin <= SUNXI_GPD(22); pin++)
> +             sunxi_gpio_set_cfgpin(pin, SUN8I_GPD8_GMAC);
> +}
> +
> +static int _sun8i_eth_recv(struct emac_eth_dev *priv, uchar **packetp)
> +{
> +     u32 status, desc_num = priv->rx_currdescnum;
> +     struct emac_dma_desc *desc_p = &priv->rx_chain[desc_num];
> +     int length = -EAGAIN;
> +     uint32_t desc_start = (uint32_t)desc_p;
> +     uint32_t desc_end = desc_start +
> +             roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
> +
> +     uint32_t data_start = (uint32_t)desc_p->buf_addr;
> +     uint32_t data_end;
> +
> +     /* Invalidate entire buffer descriptor */
> +     invalidate_dcache_range(desc_start, desc_end);
> +
> +     status = desc_p->status;
> +
> +     /* Check for DMA own bit */
> +     if (!(status & BIT(31))) {
> +             length = (desc_p->status >> 16) & 0x3FFF;
> +             data_end = data_start + length;
> +             /* Invalidate received data */
> +             invalidate_dcache_range(rounddown(data_start,
> +                                               ARCH_DMA_MINALIGN),
> +                                     roundup(data_end,
> +                                             ARCH_DMA_MINALIGN));
> +             *packetp = desc_p->buf_addr;
> +     }
> +     return length;
> +}

You do not check for any reception error.

> +
> +static int _sun8i_emac_eth_send(struct emac_eth_dev *priv, void *packet,
> +             int len)
> +{
> +     u32 v, desc_num = priv->tx_currdescnum;
> +     struct emac_dma_desc *desc_p = &priv->tx_chain[desc_num];
> +     uint32_t desc_start = (uint32_t)desc_p;
> +     uint32_t desc_end = desc_start +
> +             roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
> +
> +     uint32_t data_start = (uint32_t)desc_p->buf_addr;
> +     uint32_t data_end = data_start +
> +             roundup(len, ARCH_DMA_MINALIGN);
> +
> +     /* Invalidate entire buffer descriptor */
> +     invalidate_dcache_range(desc_start, desc_end);
> +
> +     desc_p->st = len;
> +     /* Mandatory undocumented bit */
> +     desc_p->st |= BIT(24);
> +
> +     memcpy(desc_p->buf_addr, packet, len);

Since I do not see any MTU settings, perhaps you need to check len against 
CONFIG_ETH_BUFSIZE (sunxi_emac.c do this for reception with rx_len > 
EMAC_RX_BUFSIZE)

> +
> +     /* Flush data to be sent */
> +     flush_dcache_range(data_start, data_end);
> +
> +     /* frame end */
> +     desc_p->st |= BIT(30);
> +     desc_p->st |= BIT(31);
> +
> +     /*frame begin */
> +     desc_p->st |= BIT(29);
> +     desc_p->status = BIT(31);
> +
> +     /*Descriptors st and status field has changed, so FLUSH it */
> +     flush_dcache_range(desc_start, desc_end);
> +
> +     /* Move to next Descriptor and wrap around */
> +     if (++desc_num >= CONFIG_TX_DESCR_NUM)
> +             desc_num = 0;
> +     priv->tx_currdescnum = desc_num;
> +
> +     /* Start the DMA */
> +     v = readl(priv->mac_reg + TX_CTL1);
> +     v |= BIT(31);/* mandatory */
> +     v |= BIT(30);/* mandatory */
> +     writel(v, priv->mac_reg + TX_CTL1);
> +
> +     return 0;
> +}
> +
> +static int sun8i_emac_eth_send(struct udevice *dev, void *packet, int length)
> +{
> +     struct emac_eth_dev *priv = dev_get_priv(dev);
> +     return _sun8i_emac_eth_send(priv, packet, length);
> +}
> +
> +static void sun8i_emac_eth_stop(struct udevice *dev)
> +{
> +     struct emac_eth_dev *priv = dev_get_priv(dev);
> +
> +     /* Stop Rx/Tx transmitter */
> +     clrbits_le32(priv->mac_reg + RX_CTL0, BIT(31));
> +     clrbits_le32(priv->mac_reg + TX_CTL0, BIT(31));
> +
> +     /* Stop TX DMA */
> +     clrbits_le32(priv->mac_reg + TX_CTL1, BIT(30));
> +
> +     /* Disable Interrupt, This is required to leave
> +        from U-boot and enter OS in proper Interrupt state */
> +     writel(0, priv->mac_reg + INT_EN);
> +
> +     phy_shutdown(priv->phydev);
> +}

You disable interrupt but I do not see any enabling of it.

> +
> +
> +static int sun8i_emac_eth_start(struct udevice *dev)
> +{
> +     struct eth_pdata *pdata = dev_get_platdata(dev);
> +     return _sun8i_emac_eth_init(dev->priv, pdata->enetaddr);
> +}
> +
> +static int sun8i_mdio_init(const char *name, struct  emac_eth_dev *priv)
> +{
> +     struct mii_dev *bus = mdio_alloc();
> +
> +     if (!bus) {
> +             printf("Failed to allocate MDIO bus\n");
> +             return -ENOMEM;
> +     }
> +
> +     bus->read = sun8i_mdio_read;
> +     bus->write = sun8i_mdio_write;
> +     snprintf(bus->name, sizeof(bus->name), name);
> +     bus->priv = (void *)priv;
> +
> +     return  mdio_register(bus);
> +}
> +
> +static int sun8i_emac_eth_probe(struct udevice *dev)
> +{
> +     struct eth_pdata *pdata = dev_get_platdata(dev);
> +     struct emac_eth_dev *priv = dev_get_priv(dev);
> +
> +     priv->mac_reg = (void *)pdata->iobase;
> +     sun8i_emac_board_setup(priv);
> +
> +     sun8i_mdio_init(dev->name, priv);
> +     priv->bus = miiphy_get_dev_by_name(dev->name);
> +
> +     return sun8i_phy_init(priv, dev);
> +}
> +
> +static int sun8i_eth_write_hwaddr(struct udevice *dev)
> +{
> +     struct eth_pdata *pdata = dev_get_platdata(dev);
> +     struct emac_eth_dev *priv = dev_get_priv(dev);
> +     return _sun8i_write_hwaddr(priv, pdata->enetaddr);
> +}
> +
> +static int sun8i_emac_eth_recv(struct udevice *dev, int flags, uchar 
> **packetp)
> +{
> +     struct emac_eth_dev *priv = dev_get_priv(dev);
> +
> +     return _sun8i_eth_recv(priv, packetp);
> +}
> +
> +static int _sun8i_free_pkt(struct emac_eth_dev *priv)
> +{
> +     u32 desc_num = priv->rx_currdescnum;
> +     struct emac_dma_desc *desc_p = &priv->rx_chain[desc_num];
> +     uint32_t desc_start = (uint32_t)desc_p;
> +     uint32_t desc_end = desc_start +
> +             roundup(sizeof(u32), ARCH_DMA_MINALIGN);
> +
> +     /* Make the current descriptor valid again */
> +     desc_p->status |= BIT(31);
> +
> +     /* Flush Status field of descriptor */
> +     flush_dcache_range(desc_start, desc_end);
> +
> +     /* Move to next desc and wrap-around condition. */
> +     if (++desc_num >= CONFIG_RX_DESCR_NUM)
> +             desc_num = 0;
> +     priv->rx_currdescnum = desc_num;
> +
> +     return 0;
> +}
> +
> +static int sun8i_eth_free_pkt(struct udevice *dev, uchar *packet,
> +             int length)
> +{
> +     struct emac_eth_dev *priv = dev_get_priv(dev);
> +
> +     return _sun8i_free_pkt(priv);
> +}
> +
> +static const struct eth_ops sun8i_emac_eth_ops = {
> +     .start                  = sun8i_emac_eth_start,
> +     .write_hwaddr           = sun8i_eth_write_hwaddr,
> +     .send                   = sun8i_emac_eth_send,
> +     .recv                   = sun8i_emac_eth_recv,
> +     .free_pkt               = sun8i_eth_free_pkt,
> +     .stop                   = sun8i_emac_eth_stop,
> +};
> +
> +static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev)
> +{
> +     struct eth_pdata *pdata = dev_get_platdata(dev);
> +     struct emac_eth_dev *priv = dev_get_priv(dev);
> +     const char *phy_mode;
> +     int offset = 0;
> +     pdata->iobase = dev_get_addr(dev);
> +
> +     pdata->phy_interface = -1;
> +     priv->phyaddr = -1;
> +
> +     offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset,
> +                                     "phy");
> +     if (offset > 0)
> +             priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
> +
> +     phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL);
> +
> +     if (phy_mode)
> +             pdata->phy_interface = phy_get_interface_by_name(phy_mode);
> +     if (pdata->phy_interface == -1) {
> +             printf("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
> +             return -EINVAL;
> +     }
> +
> +     priv->interface = pdata->phy_interface;
> +
> +     return 0;
> +}
> +
> +static const struct udevice_id sun8i_emac_eth_ids[] = {
> +     { .compatible = "allwinner,sun8i-h3-emac" },
> +     { }
> +};
> +
> +U_BOOT_DRIVER(eth_sun8i_emac) = {
> +     .name   = "eth_sun8i_emac",
> +     .id     = UCLASS_ETH,
> +     .of_match = sun8i_emac_eth_ids,
> +     .ofdata_to_platdata = sun8i_emac_eth_ofdata_to_platdata,
> +     .probe  = sun8i_emac_eth_probe,
> +     .ops    = &sun8i_emac_eth_ops,
> +     .priv_auto_alloc_size = sizeof(struct emac_eth_dev),
> +     .platdata_auto_alloc_size = sizeof(struct eth_pdata),
> +     .flags = DM_FLAG_ALLOC_PRIV_DMA,
> +};
> 

Regards

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to