All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 2/5] net: re-add support for the Faraday ftgmac100 controller
Date: Thu, 27 Sep 2018 06:41:50 -0700	[thread overview]
Message-ID: <CAPnjgZ1hV7A+69kDN-h0sm8wtLgKdWAcL44Cf9VoJrnbPUxCTg@mail.gmail.com> (raw)
In-Reply-To: <20180910142148.21436-3-clg@kaod.org>

Hi Cedric,

On 10 September 2018 at 07:21, Cédric Le Goater <clg@kaod.org> wrote:
> The driver is based on the previous one and adds the same support for
> the Faraday ftgmac100 controller with MAC and MDIO bus support for
> RGMII/RMII modes.
>
> Driver model support was added as well as some enhancements and fixes.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  drivers/net/ftgmac100.h | 242 ++++++++++++++++++++
>  drivers/net/ftgmac100.c | 493 ++++++++++++++++++++++++++++++++++++++++
>  drivers/net/Kconfig     |   8 +
>  drivers/net/Makefile    |   1 +
>  4 files changed, 744 insertions(+)
>  create mode 100644 drivers/net/ftgmac100.h
>  create mode 100644 drivers/net/ftgmac100.c

Reviewed-by: Simon Glass <sjg@chromium.org>

Various minor comments below.

>
> diff --git a/drivers/net/ftgmac100.h b/drivers/net/ftgmac100.h
> new file mode 100644
> index 000000000000..9a789e4d5bee
> --- /dev/null
> +++ b/drivers/net/ftgmac100.h
> @@ -0,0 +1,242 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Faraday FTGMAC100 Ethernet
> + *
> + * (C) Copyright 2010 Faraday Technology
> + * Po-Yu Chuang <ratbert@faraday-tech.com>
> + *
> + * (C) Copyright 2010 Andes Technology
> + * Macpaul Lin <macpaul@andestech.com>
> + */
> +
> +#ifndef __FTGMAC100_H
> +#define __FTGMAC100_H
> +
> +/* The registers offset table of ftgmac100 */
> +struct ftgmac100 {
> +       unsigned int    isr;            /* 0x00 */
> +       unsigned int    ier;            /* 0x04 */
> +       unsigned int    mac_madr;       /* 0x08 */
> +       unsigned int    mac_ladr;       /* 0x0c */
> +       unsigned int    maht0;          /* 0x10 */
> +       unsigned int    maht1;          /* 0x14 */
> +       unsigned int    txpd;           /* 0x18 */
> +       unsigned int    rxpd;           /* 0x1c */
> +       unsigned int    txr_badr;       /* 0x20 */
> +       unsigned int    rxr_badr;       /* 0x24 */
> +       unsigned int    hptxpd;         /* 0x28 */
> +       unsigned int    hptxpd_badr;    /* 0x2c */
> +       unsigned int    itc;            /* 0x30 */
> +       unsigned int    aptc;           /* 0x34 */
> +       unsigned int    dblac;          /* 0x38 */
> +       unsigned int    dmafifos;       /* 0x3c */
> +       unsigned int    revr;           /* 0x40 */
> +       unsigned int    fear;           /* 0x44 */
> +       unsigned int    tpafcr;         /* 0x48 */
> +       unsigned int    rbsr;           /* 0x4c */
> +       unsigned int    maccr;          /* 0x50 */
> +       unsigned int    macsr;          /* 0x54 */
> +       unsigned int    tm;             /* 0x58 */
> +       unsigned int    resv1;          /* 0x5c */ /* not defined in spec */
> +       unsigned int    phycr;          /* 0x60 */
> +       unsigned int    phydata;        /* 0x64 */
> +       unsigned int    fcr;            /* 0x68 */
> +       unsigned int    bpr;            /* 0x6c */
> +       unsigned int    wolcr;          /* 0x70 */
> +       unsigned int    wolsr;          /* 0x74 */
> +       unsigned int    wfcrc;          /* 0x78 */
> +       unsigned int    resv2;          /* 0x7c */ /* not defined in spec */
> +       unsigned int    wfbm1;          /* 0x80 */
> +       unsigned int    wfbm2;          /* 0x84 */
> +       unsigned int    wfbm3;          /* 0x88 */
> +       unsigned int    wfbm4;          /* 0x8c */
> +       unsigned int    nptxr_ptr;      /* 0x90 */
> +       unsigned int    hptxr_ptr;      /* 0x94 */
> +       unsigned int    rxr_ptr;        /* 0x98 */
> +       unsigned int    resv3;          /* 0x9c */ /* not defined in spec */
> +       unsigned int    tx;             /* 0xa0 */
> +       unsigned int    tx_mcol_scol;   /* 0xa4 */
> +       unsigned int    tx_ecol_fail;   /* 0xa8 */
> +       unsigned int    tx_lcol_und;    /* 0xac */
> +       unsigned int    rx;             /* 0xb0 */
> +       unsigned int    rx_bc;          /* 0xb4 */
> +       unsigned int    rx_mc;          /* 0xb8 */
> +       unsigned int    rx_pf_aep;      /* 0xbc */
> +       unsigned int    rx_runt;        /* 0xc0 */
> +       unsigned int    rx_crcer_ftl;   /* 0xc4 */
> +       unsigned int    rx_col_lost;    /* 0xc8 */
> +};
> +
> +/*
> + * Interrupt status register & interrupt enable register
> + */
> +#define FTGMAC100_INT_RPKT_BUF         BIT(0)
> +#define FTGMAC100_INT_RPKT_FIFO                BIT(1)
> +#define FTGMAC100_INT_NO_RXBUF         BIT(2)
> +#define FTGMAC100_INT_RPKT_LOST                BIT(3)
> +#define FTGMAC100_INT_XPKT_ETH         BIT(4)
> +#define FTGMAC100_INT_XPKT_FIFO                BIT(5)
> +#define FTGMAC100_INT_NO_NPTXBUF       BIT(6)
> +#define FTGMAC100_INT_XPKT_LOST                BIT(7)
> +#define FTGMAC100_INT_AHB_ERR          BIT(8)
> +#define FTGMAC100_INT_PHYSTS_CHG       BIT(9)
> +#define FTGMAC100_INT_NO_HPTXBUF       BIT(10)
> +
> +/*
> + * Interrupt timer control register
> + */
> +#define FTGMAC100_ITC_RXINT_CNT(x)     (((x) & 0xf) << 0)
> +#define FTGMAC100_ITC_RXINT_THR(x)     (((x) & 0x7) << 4)
> +#define FTGMAC100_ITC_RXINT_TIME_SEL   BIT(7)
> +#define FTGMAC100_ITC_TXINT_CNT(x)     (((x) & 0xf) << 8)
> +#define FTGMAC100_ITC_TXINT_THR(x)     (((x) & 0x7) << 12)
> +#define FTGMAC100_ITC_TXINT_TIME_SEL   BIT(15)
> +
> +/*
> + * Automatic polling timer control register
> + */
> +#define FTGMAC100_APTC_RXPOLL_CNT(x)   (((x) & 0xf) << 0)
> +#define FTGMAC100_APTC_RXPOLL_TIME_SEL BIT(4)
> +#define FTGMAC100_APTC_TXPOLL_CNT(x)   (((x) & 0xf) << 8)
> +#define FTGMAC100_APTC_TXPOLL_TIME_SEL BIT(12)
> +
> +/*
> + * DMA burst length and arbitration control register
> + */
> +#define FTGMAC100_DBLAC_RXFIFO_LTHR(x) (((x) & 0x7) << 0)
> +#define FTGMAC100_DBLAC_RXFIFO_HTHR(x) (((x) & 0x7) << 3)
> +#define FTGMAC100_DBLAC_RX_THR_EN      BIT(6)
> +#define FTGMAC100_DBLAC_RXBURST_SIZE(x)        (((x) & 0x3) << 8)
> +#define FTGMAC100_DBLAC_TXBURST_SIZE(x)        (((x) & 0x3) << 10)
> +#define FTGMAC100_DBLAC_RXDES_SIZE(x)  (((x) & 0xf) << 12)
> +#define FTGMAC100_DBLAC_TXDES_SIZE(x)  (((x) & 0xf) << 16)
> +#define FTGMAC100_DBLAC_IFG_CNT(x)     (((x) & 0x7) << 20)
> +#define FTGMAC100_DBLAC_IFG_INC                BIT(23)
> +
> +/*
> + * DMA FIFO status register
> + */
> +#define FTGMAC100_DMAFIFOS_RXDMA1_SM(dmafifos) ((dmafifos) & 0xf)
> +#define FTGMAC100_DMAFIFOS_RXDMA2_SM(dmafifos) (((dmafifos) >> 4) & 0xf)
> +#define FTGMAC100_DMAFIFOS_RXDMA3_SM(dmafifos) (((dmafifos) >> 8) & 0x7)
> +#define FTGMAC100_DMAFIFOS_TXDMA1_SM(dmafifos) (((dmafifos) >> 12) & 0xf)
> +#define FTGMAC100_DMAFIFOS_TXDMA2_SM(dmafifos) (((dmafifos) >> 16) & 0x3)
> +#define FTGMAC100_DMAFIFOS_TXDMA3_SM(dmafifos) (((dmafifos) >> 18) & 0xf)
> +#define FTGMAC100_DMAFIFOS_RXFIFO_EMPTY                BIT(26)
> +#define FTGMAC100_DMAFIFOS_TXFIFO_EMPTY                BIT(27)
> +#define FTGMAC100_DMAFIFOS_RXDMA_GRANT         BIT(28)
> +#define FTGMAC100_DMAFIFOS_TXDMA_GRANT         BIT(29)
> +#define FTGMAC100_DMAFIFOS_RXDMA_REQ           BIT(30)
> +#define FTGMAC100_DMAFIFOS_TXDMA_REQ           BIT(31)
> +
> +/*
> + * Receive buffer size register
> + */
> +#define FTGMAC100_RBSR_SIZE(x)         ((x) & 0x3fff)
> +
> +/*
> + * MAC control register
> + */
> +#define FTGMAC100_MACCR_TXDMA_EN       BIT(0)
> +#define FTGMAC100_MACCR_RXDMA_EN       BIT(1)
> +#define FTGMAC100_MACCR_TXMAC_EN       BIT(2)
> +#define FTGMAC100_MACCR_RXMAC_EN       BIT(3)
> +#define FTGMAC100_MACCR_RM_VLAN                BIT(4)
> +#define FTGMAC100_MACCR_HPTXR_EN       BIT(5)
> +#define FTGMAC100_MACCR_LOOP_EN                BIT(6)
> +#define FTGMAC100_MACCR_ENRX_IN_HALFTX BIT(7)
> +#define FTGMAC100_MACCR_FULLDUP                BIT(8)
> +#define FTGMAC100_MACCR_GIGA_MODE      BIT(9)
> +#define FTGMAC100_MACCR_CRC_APD                BIT(10)
> +#define FTGMAC100_MACCR_RX_RUNT                BIT(12)
> +#define FTGMAC100_MACCR_JUMBO_LF       BIT(13)
> +#define FTGMAC100_MACCR_RX_ALL         BIT(14)
> +#define FTGMAC100_MACCR_HT_MULTI_EN    BIT(15)
> +#define FTGMAC100_MACCR_RX_MULTIPKT    BIT(16)
> +#define FTGMAC100_MACCR_RX_BROADPKT    BIT(17)
> +#define FTGMAC100_MACCR_DISCARD_CRCERR BIT(18)
> +#define FTGMAC100_MACCR_FAST_MODE      BIT(19)
> +#define FTGMAC100_MACCR_SW_RST         BIT(31)
> +
> +/*
> + * PHY control register
> + */
> +#define FTGMAC100_PHYCR_MDC_CYCTHR_MASK        0x3f
> +#define FTGMAC100_PHYCR_MDC_CYCTHR(x)  ((x) & 0x3f)
> +#define FTGMAC100_PHYCR_PHYAD(x)       (((x) & 0x1f) << 16)
> +#define FTGMAC100_PHYCR_REGAD(x)       (((x) & 0x1f) << 21)
> +#define FTGMAC100_PHYCR_MIIRD          BIT(26)
> +#define FTGMAC100_PHYCR_MIIWR          BIT(27)
> +
> +/*
> + * PHY data register
> + */
> +#define FTGMAC100_PHYDATA_MIIWDATA(x)          ((x) & 0xffff)
> +#define FTGMAC100_PHYDATA_MIIRDATA(phydata)    (((phydata) >> 16) & 0xffff)
> +
> +/*
> + * Transmit descriptor, aligned to 16 bytes
> + */
> +struct ftgmac100_txdes {
> +       unsigned int    txdes0;
> +       unsigned int    txdes1;
> +       unsigned int    txdes2; /* not used by HW */
> +       unsigned int    txdes3; /* TXBUF_BADR */
> +} __aligned(16);
> +
> +#define FTGMAC100_TXDES0_TXBUF_SIZE(x) ((x) & 0x3fff)
> +#define FTGMAC100_TXDES0_EDOTR         BIT(15)
> +#define FTGMAC100_TXDES0_CRC_ERR       BIT(19)
> +#define FTGMAC100_TXDES0_LTS           BIT(28)
> +#define FTGMAC100_TXDES0_FTS           BIT(29)
> +#define FTGMAC100_TXDES0_TXDMA_OWN     BIT(31)
> +
> +#define FTGMAC100_TXDES1_VLANTAG_CI(x) ((x) & 0xffff)
> +#define FTGMAC100_TXDES1_INS_VLANTAG   BIT(16)
> +#define FTGMAC100_TXDES1_TCP_CHKSUM    BIT(17)
> +#define FTGMAC100_TXDES1_UDP_CHKSUM    BIT(18)
> +#define FTGMAC100_TXDES1_IP_CHKSUM     BIT(19)
> +#define FTGMAC100_TXDES1_LLC           BIT(22)
> +#define FTGMAC100_TXDES1_TX2FIC                BIT(30)
> +#define FTGMAC100_TXDES1_TXIC          BIT(31)
> +
> +/*
> + * Receive descriptor, aligned to 16 bytes
> + */
> +struct ftgmac100_rxdes {
> +       unsigned int    rxdes0;
> +       unsigned int    rxdes1;
> +       unsigned int    rxdes2; /* not used by HW */
> +       unsigned int    rxdes3; /* RXBUF_BADR */
> +} __aligned(16);
> +
> +#define FTGMAC100_RXDES0_VDBC(x)       ((x) & 0x3fff)
> +#define FTGMAC100_RXDES0_EDORR         BIT(15)
> +#define FTGMAC100_RXDES0_MULTICAST     BIT(16)
> +#define FTGMAC100_RXDES0_BROADCAST     BIT(17)
> +#define FTGMAC100_RXDES0_RX_ERR                BIT(18)
> +#define FTGMAC100_RXDES0_CRC_ERR       BIT(19)
> +#define FTGMAC100_RXDES0_FTL           BIT(20)
> +#define FTGMAC100_RXDES0_RUNT          BIT(21)
> +#define FTGMAC100_RXDES0_RX_ODD_NB     BIT(22)
> +#define FTGMAC100_RXDES0_FIFO_FULL     BIT(23)
> +#define FTGMAC100_RXDES0_PAUSE_OPCODE  BIT(24)
> +#define FTGMAC100_RXDES0_PAUSE_FRAME   BIT(25)
> +#define FTGMAC100_RXDES0_LRS           BIT(28)
> +#define FTGMAC100_RXDES0_FRS           BIT(29)
> +#define FTGMAC100_RXDES0_RXPKT_RDY     BIT(31)
> +
> +#define FTGMAC100_RXDES1_VLANTAG_CI    0xffff
> +#define FTGMAC100_RXDES1_PROT_MASK     (0x3 << 20)
> +#define FTGMAC100_RXDES1_PROT_NONIP    (0x0 << 20)
> +#define FTGMAC100_RXDES1_PROT_IP       (0x1 << 20)
> +#define FTGMAC100_RXDES1_PROT_TCPIP    (0x2 << 20)
> +#define FTGMAC100_RXDES1_PROT_UDPIP    (0x3 << 20)
> +#define FTGMAC100_RXDES1_LLC           BIT(22)
> +#define FTGMAC100_RXDES1_DF            BIT(23)
> +#define FTGMAC100_RXDES1_VLANTAG_AVAIL BIT(24)
> +#define FTGMAC100_RXDES1_TCP_CHKSUM_ERR        BIT(25)
> +#define FTGMAC100_RXDES1_UDP_CHKSUM_ERR        BIT(26)
> +#define FTGMAC100_RXDES1_IP_CHKSUM_ERR BIT(27)
> +
> +#endif /* __FTGMAC100_H */
> diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c
> new file mode 100644
> index 000000000000..8d7bf5b9b351
> --- /dev/null
> +++ b/drivers/net/ftgmac100.c
> @@ -0,0 +1,493 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Faraday FTGMAC100 Ethernet
> + *
> + * (C) Copyright 2009 Faraday Technology
> + * Po-Yu Chuang <ratbert@faraday-tech.com>
> + *
> + * (C) Copyright 2010 Andes Technology
> + * Macpaul Lin <macpaul@andestech.com>
> + *
> + * Copyright (C) 2018, IBM Corporation.
> + */
> +
> +#include <clk.h>
> +#include <miiphy.h>
> +#include <net.h>
> +#include <asm/io.h>
> +
> +#include "ftgmac100.h"
> +
> +#define ETH_ZLEN               60
> +#define CFG_XBUF_SIZE          1536

Comments on these

> +
> +/* RBSR - hw default init value is also 0x640 */
> +#define RBSR_DEFAULT_VALUE     0x640
> +
> +/* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
> +#define PKTBUFSTX              4
> +
> +struct ftgmac100_data {

Comment here and on members

> +       phys_addr_t iobase;
> +
> +       struct ftgmac100_txdes txdes[PKTBUFSTX];
> +       struct ftgmac100_rxdes rxdes[PKTBUFSRX];
> +       int tx_index;
> +       int rx_index;
> +
> +       u32 phyaddr;
> +       struct phy_device *phydev;
> +       struct mii_dev *bus;
> +       u32 phy_mode;
> +       u32 max_speed;
> +};
> +
> +/*
> + * MDC clock cycle threshold
> + *
> + * 20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
> + */
> +#define MDC_CYCTHR              0x34
> +
> +static int ftgmac100_mdio_read(struct mii_dev *bus, int phy_addr, int dev_addr,
> +                              int reg_addr)
> +{
> +       struct ftgmac100_data *priv = bus->priv;

dev_get_priv(bus)

> +       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)priv->iobase;

Can you put the struct ftgmac100 * in priv and avoid the cast each time?

> +       int phycr;
> +       int i;
> +
> +       phycr = MDC_CYCTHR |
> +               FTGMAC100_PHYCR_PHYAD(phy_addr) |
> +               FTGMAC100_PHYCR_REGAD(reg_addr) |
> +               FTGMAC100_PHYCR_MIIRD;
> +
> +       writel(phycr, &ftgmac100->phycr);
> +
> +       for (i = 0; i < 10; i++) {
> +               phycr = readl(&ftgmac100->phycr);
> +
> +               if ((phycr & FTGMAC100_PHYCR_MIIRD) == 0) {
> +                       int data;
> +
> +                       data = readl(&ftgmac100->phydata);
> +                       return FTGMAC100_PHYDATA_MIIRDATA(data);
> +               }
> +
> +               mdelay(10);

This is an extraordinarily long delay. Is this described in the datasheet?

> +       }
> +
> +       pr_err("mdio read timed out\n");
> +       return -1;

-ETIMEDOUT

Same below

> +}
> +
> +static int ftgmac100_mdio_write(struct mii_dev *bus, int phy_addr, int dev_addr,
> +                               int reg_addr, u16 value)
> +{
> +       struct ftgmac100_data *priv = bus->priv;
> +       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)priv->iobase;
> +       int phycr;
> +       int data;
> +       int i;
> +
> +       phycr = MDC_CYCTHR |
> +               FTGMAC100_PHYCR_PHYAD(phy_addr) |
> +               FTGMAC100_PHYCR_REGAD(reg_addr) |
> +               FTGMAC100_PHYCR_MIIWR;
> +
> +       data = FTGMAC100_PHYDATA_MIIWDATA(value);
> +
> +       writel(data, &ftgmac100->phydata);
> +       writel(phycr, &ftgmac100->phycr);
> +
> +       for (i = 0; i < 10; i++) {
> +               phycr = readl(&ftgmac100->phycr);
> +
> +               if ((phycr & FTGMAC100_PHYCR_MIIWR) == 0)
> +                       return 0;
> +
> +               mdelay(1);
> +       }
> +
> +       pr_err("mdio write timed out\n");
> +       return -1;
> +}
> +
> +static int ftgmac100_mdio_init(struct ftgmac100_data *priv, int dev_id)
> +{
> +       struct mii_dev *bus;
> +       int ret;
> +
> +       bus = mdio_alloc();
> +       if (!bus)
> +               return -ENOMEM;
> +
> +       bus->read  = ftgmac100_mdio_read;
> +       bus->write = ftgmac100_mdio_write;
> +       bus->priv  = priv;
> +
> +       ret = mdio_register_seq(bus, dev_id);
> +       if (ret) {
> +               free(bus);
> +               return ret;
> +       }
> +
> +       priv->bus = bus;
> +       return 0;
> +}
> +
> +static int ftgmac100_phy_adjust_link(struct ftgmac100_data *priv)
> +{
> +       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)priv->iobase;
> +       struct phy_device *phydev = priv->phydev;
> +       u32 maccr;
> +
> +       if (!phydev->link) {
> +               dev_err(phydev->dev, "No link\n");
> +               return -ENODEV;

-EREMOTEIO perhaps? You cannot use -ENODEV since there is a device

> +       }
> +
> +       /* read MAC control register and clear related bits */
> +       maccr = readl(&ftgmac100->maccr) &
> +               ~(FTGMAC100_MACCR_GIGA_MODE |
> +                 FTGMAC100_MACCR_FAST_MODE |
> +                 FTGMAC100_MACCR_FULLDUP);
> +
> +       if (phy_interface_is_rgmii(phydev) && phydev->speed == 1000)
> +               maccr |= FTGMAC100_MACCR_GIGA_MODE;
> +
> +       if (phydev->speed == 100)
> +               maccr |= FTGMAC100_MACCR_FAST_MODE;
> +
> +       if (phydev->duplex)
> +               maccr |= FTGMAC100_MACCR_FULLDUP;
> +
> +       /* update MII config into maccr */
> +       writel(maccr, &ftgmac100->maccr);
> +
> +       return 0;
> +}
> +
> +static int ftgmac100_phy_init(struct ftgmac100_data *priv, void *dev)
> +{
> +       struct phy_device *phydev;
> +       int ret;
> +
> +       phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->phy_mode);
> +
> +       phydev->supported &= PHY_GBIT_FEATURES;
> +       if (priv->max_speed) {
> +               ret = phy_set_supported(phydev, priv->max_speed);
> +               if (ret)
> +                       return ret;
> +       }
> +       phydev->advertising = phydev->supported;
> +       priv->phydev = phydev;
> +       phy_config(phydev);
> +
> +       return 0;
> +}
> +
> +static void ftgmac100_reset(struct ftgmac100_data *priv)
> +{
> +       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)priv->iobase;
> +
> +       setbits_le32(&ftgmac100->maccr, FTGMAC100_MACCR_SW_RST);
> +
> +       while (readl(&ftgmac100->maccr) & FTGMAC100_MACCR_SW_RST)
> +               ;
> +}
> +
> +static int ftgmac100_set_mac(struct ftgmac100_data *priv,
> +                            const unsigned char *mac)
> +{
> +       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)priv->iobase;
> +       unsigned int maddr = mac[0] << 8 | mac[1];
> +       unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
> +
> +       writel(maddr, &ftgmac100->mac_madr);
> +       writel(laddr, &ftgmac100->mac_ladr);
> +       return 0;
> +}
> +
> +static void ftgmac100_stop(struct udevice *dev)
> +{
> +       struct ftgmac100_data *priv = dev_get_priv(dev);
> +       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)priv->iobase;
> +
> +       writel(0, &ftgmac100->maccr);
> +
> +       phy_shutdown(priv->phydev);
> +}
> +
> +static int ftgmac100_start(struct udevice *dev)
> +{
> +       struct eth_pdata *plat = dev_get_platdata(dev);
> +       struct ftgmac100_data *priv = dev_get_priv(dev);
> +       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)priv->iobase;
> +       struct phy_device *phydev = priv->phydev;
> +       unsigned int maccr;
> +       int ret;
> +       int i;
> +
> +       ftgmac100_reset(priv);
> +
> +       /* set the ethernet address */
> +       ftgmac100_set_mac(priv, plat->enetaddr);
> +
> +       /* disable all interrupts */
> +       writel(0, &ftgmac100->ier);
> +
> +       /* initialize descriptor tables */
> +       priv->tx_index = 0;
> +       priv->rx_index = 0;
> +
> +       for (i = 0; i < PKTBUFSTX; i++) {
> +               priv->txdes[i].txdes3 = 0;
> +               priv->txdes[i].txdes0 = 0;
> +       }
> +       priv->txdes[PKTBUFSTX - 1].txdes0 = FTGMAC100_TXDES0_EDOTR;
> +
> +       for (i = 0; i < PKTBUFSRX; i++) {
> +               priv->rxdes[i].rxdes3 = (unsigned int)net_rx_packets[i];
> +               priv->rxdes[i].rxdes0 = 0;
> +       }
> +       priv->rxdes[PKTBUFSRX - 1].rxdes0 = FTGMAC100_RXDES0_EDORR;
> +
> +       /* transmit ring */
> +       writel((u32)priv->txdes, &ftgmac100->txr_badr);
> +
> +       /* receive ring */
> +       writel((u32)priv->rxdes, &ftgmac100->rxr_badr);
> +
> +       /* poll receive descriptor automatically */
> +       writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100->aptc);
> +
> +       /* config receive buffer size register */
> +       writel(FTGMAC100_RBSR_SIZE(RBSR_DEFAULT_VALUE), &ftgmac100->rbsr);
> +
> +       /* enable transmitter, receiver */
> +       maccr = FTGMAC100_MACCR_TXMAC_EN |
> +               FTGMAC100_MACCR_RXMAC_EN |
> +               FTGMAC100_MACCR_TXDMA_EN |
> +               FTGMAC100_MACCR_RXDMA_EN |
> +               FTGMAC100_MACCR_CRC_APD |
> +               FTGMAC100_MACCR_FULLDUP |
> +               FTGMAC100_MACCR_RX_RUNT |
> +               FTGMAC100_MACCR_RX_BROADPKT;
> +
> +       writel(maccr, &ftgmac100->maccr);
> +
> +       ret = phy_startup(phydev);
> +       if (ret) {
> +               dev_err(phydev->dev, "Could not start PHY\n");
> +               return ret;
> +       }
> +
> +       ret = ftgmac100_phy_adjust_link(priv);
> +       if (ret) {
> +               dev_err(phydev->dev,  "Could not adjust link\n");
> +               return ret;
> +       }
> +
> +       printf("%s: link up, %d Mbps %s-duplex mac:%pM\n", phydev->dev->name,
> +              phydev->speed, phydev->duplex ? "full" : "half", plat->enetaddr);
> +
> +       return 0;
> +}
> +
> +static int ftgmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
> +{
> +       struct ftgmac100_data *priv = dev_get_priv(dev);
> +       struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
> +       ulong des_start = (ulong)curr_des;
> +       ulong des_end = des_start +
> +               roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
> +
> +       /* Release buffer to DMA and flush descriptor */
> +       curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
> +       flush_dcache_range(des_start, des_end);
> +
> +       /* Move to next descriptor */
> +       priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
> +       return 0;
> +}
> +
> +static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
> +{
> +       struct ftgmac100_data *priv = dev_get_priv(dev);
> +       struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
> +       int length;
> +       ulong des_start = (ulong)curr_des;
> +       ulong des_end = des_start +
> +               roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
> +       ulong data_start = curr_des->rxdes3;
> +       ulong data_end;
> +
> +       invalidate_dcache_range(des_start, des_end);
> +
> +       if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY))
> +               return -EAGAIN;
> +
> +       if (curr_des->rxdes0 & (FTGMAC100_RXDES0_RX_ERR |
> +                               FTGMAC100_RXDES0_CRC_ERR |
> +                               FTGMAC100_RXDES0_FTL |
> +                               FTGMAC100_RXDES0_RUNT |
> +                               FTGMAC100_RXDES0_RX_ODD_NB)) {
> +               return -EAGAIN;
> +       }
> +
> +       length = FTGMAC100_RXDES0_VDBC(curr_des->rxdes0);
> +
> +       /* Invalidate received data */
> +       data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
> +       invalidate_dcache_range(data_start, data_end);
> +       *packetp = (uchar *)data_start;
> +
> +       return length;
> +}
> +
> +static int ftgmac100_send(struct udevice *dev, void *packet, int length)
> +{
> +       struct ftgmac100_data *priv = dev_get_priv(dev);
> +       struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)priv->iobase;
> +       struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
> +       ulong des_start = (ulong)curr_des;
> +       ulong des_end = des_start +
> +               roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
> +       ulong data_start;
> +       ulong data_end;
> +
> +       invalidate_dcache_range(des_start, des_end);
> +
> +       if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
> +               pr_err("no TX descriptor available\n");
> +               return -EPERM;
> +       }
> +
> +       debug("%s(%x, %x)\n", __func__, (int)packet, length);
> +
> +       length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
> +
> +       /* initiate a transmit sequence */
> +       curr_des->txdes3 = (unsigned int)packet;
> +
> +       /* Flush data to be sent */
> +       data_start = curr_des->txdes3;
> +       data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
> +       flush_dcache_range(data_start, data_end);
> +
> +       /* only one descriptor on TXBUF */
> +       curr_des->txdes0 &= FTGMAC100_TXDES0_EDOTR;
> +       curr_des->txdes0 |= FTGMAC100_TXDES0_FTS |
> +               FTGMAC100_TXDES0_LTS |
> +               FTGMAC100_TXDES0_TXBUF_SIZE(length) |
> +               FTGMAC100_TXDES0_TXDMA_OWN;
> +
> +       /* Flush modified buffer descriptor */
> +       flush_dcache_range(des_start, des_end);
> +
> +       debug("%s(): packet sent\n", __func__);
> +
> +       priv->tx_index = (priv->tx_index + 1) % PKTBUFSTX;
> +
> +       /* start transmit */
> +       writel(1, &ftgmac100->txpd);
> +
> +       /* TODO: check TXDMA_OWN bit for xmit timeouts */

TODO(email)

Should this TODO actually be done now, perhaps?

> +
> +       return 0;
> +}
> +
> +static int ftgmac100_write_hwaddr(struct udevice *dev)
> +{
> +       struct eth_pdata *pdata = dev_get_platdata(dev);
> +       struct ftgmac100_data *priv = dev_get_priv(dev);
> +
> +       return ftgmac100_set_mac(priv, pdata->enetaddr);
> +}
> +
> +static int ftgmac100_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct eth_pdata *pdata = dev_get_platdata(dev);
> +       const char *phy_mode;
> +
> +       pdata->iobase = devfdt_get_addr(dev);
> +       pdata->phy_interface = -1;
> +       phy_mode = dev_read_string(dev, "phy-mode");
> +       if (phy_mode)
> +               pdata->phy_interface = phy_get_interface_by_name(phy_mode);
> +       if (pdata->phy_interface == -1) {
> +               dev_err(dev, "Invalid PHY interface '%s'\n", phy_mode);
> +               return -EINVAL;
> +       }
> +
> +       pdata->max_speed = dev_read_u32_default(dev, "max-speed", 0);
> +
> +       return 0;
> +}
> +
> +static int ftgmac100_probe(struct udevice *dev)
> +{
> +       struct eth_pdata *pdata = dev_get_platdata(dev);
> +       struct ftgmac100_data *priv = dev_get_priv(dev);
> +       int ret;
> +
> +       priv->iobase = pdata->iobase;
> +       priv->phy_mode = pdata->phy_interface;
> +       priv->max_speed = pdata->max_speed;
> +       priv->phyaddr = 0;
> +
> +       ret = ftgmac100_mdio_init(priv, dev->seq);
> +       if (ret) {
> +               dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
> +               goto out;
> +       }
> +
> +       ret = ftgmac100_phy_init(priv, dev);
> +       if (ret) {
> +               dev_err(dev, "Failed to initialize PHY: %d\n", ret);
> +               goto out;
> +       }
> +
> +out:
> +       return ret;
> +}
> +
> +static int ftgmac100_remove(struct udevice *dev)
> +{
> +       struct ftgmac100_data *priv = dev_get_priv(dev);
> +
> +       free(priv->phydev);
> +       mdio_unregister(priv->bus);
> +       mdio_free(priv->bus);
> +
> +       return 0;
> +}
> +
> +static const struct eth_ops ftgmac100_ops = {
> +       .start  = ftgmac100_start,
> +       .send   = ftgmac100_send,
> +       .recv   = ftgmac100_recv,
> +       .stop   = ftgmac100_stop,
> +       .free_pkt = ftgmac100_free_pkt,
> +       .write_hwaddr = ftgmac100_write_hwaddr,
> +};
> +
> +static const struct udevice_id ftgmac100_ids[] = {
> +       { .compatible = "faraday,ftgmac100" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(ftgmac100) = {
> +       .name   = "ftgmac100",
> +       .id     = UCLASS_ETH,
> +       .of_match = ftgmac100_ids,
> +       .ofdata_to_platdata = ftgmac100_ofdata_to_platdata,
> +       .probe  = ftgmac100_probe,
> +       .remove = ftgmac100_remove,
> +       .ops    = &ftgmac100_ops,
> +       .priv_auto_alloc_size = sizeof(struct ftgmac100_data),
> +       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
> +       .flags  = DM_FLAG_ALLOC_PRIV_DMA,
> +};
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 5441da47d13e..65edb0316e6f 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -186,6 +186,14 @@ config FTMAC100
>         help
>           This MAC is present in Andestech SoCs.
>
> +config FTGMAC100
> +       bool "Ftgmac100 Ethernet Support"
> +       depends on DM_ETH
> +       select PHYLIB
> +       help
> +          This driver supports the Faraday's FTGMAC100 Gigabit SoC
> +          Ethernet.

Do you have any more details you could add here about the mac or what
feature the driver supports?

> +
>  config MVGBE
>         bool "Marvell Orion5x/Kirkwood network interface support"
>         depends on KIRKWOOD || ORION5X
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 4ca4e15bdd71..48a2878071d1 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -26,6 +26,7 @@ obj-$(CONFIG_EP93XX) += ep93xx_eth.o
>  obj-$(CONFIG_ETHOC) += ethoc.o
>  obj-$(CONFIG_FEC_MXC) += fec_mxc.o
>  obj-$(CONFIG_FSLDMAFEC) += fsl_mcdmafec.o mcfmii.o
> +obj-$(CONFIG_FTGMAC100) += ftgmac100.o
>  obj-$(CONFIG_FTMAC110) += ftmac110.o
>  obj-$(CONFIG_FTMAC100) += ftmac100.o
>  obj-$(CONFIG_GMAC_ROCKCHIP) += gmac_rockchip.o
> --
> 2.17.1
>

Regards,
Simon

  parent reply	other threads:[~2018-09-27 13:41 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-10 14:21 [U-Boot] [PATCH 0/5] Support for the Faraday ftgmac100 controller Cédric Le Goater
2018-09-10 14:21 ` [U-Boot] [PATCH 1/5] net: remove the Faraday ftgmac100 controller driver Cédric Le Goater
2018-09-10 14:21 ` [U-Boot] [PATCH 2/5] net: re-add support for the Faraday ftgmac100 controller Cédric Le Goater
2018-09-12  9:27   ` Joel Stanley
2018-09-12 12:05     ` Cédric Le Goater
2018-09-27 13:41   ` Simon Glass [this message]
2018-09-28 12:24     ` Cédric Le Goater
2018-09-10 14:21 ` [U-Boot] [PATCH 3/5] aspeed: ast2500: fix missing break in D2PLL clock enablement Cédric Le Goater
2018-09-12  9:17   ` Joel Stanley
2018-09-27 13:41   ` Simon Glass
2018-09-10 14:21 ` [U-Boot] [PATCH 4/5] net: ftgmac100: add support for Aspeed SoC Cédric Le Goater
2018-09-12  9:19   ` Joel Stanley
2018-09-27 13:41   ` Simon Glass
2018-09-28 12:49     ` Cédric Le Goater
2018-09-10 14:21 ` [U-Boot] [PATCH 5/5] aspeed: Activate ethernet devices on the ast2500 Eval Board Cédric Le Goater
2018-09-11  0:55   ` Joel Stanley
2018-09-11  5:37     ` Cédric Le Goater
2018-09-27 13:41   ` Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAPnjgZ1hV7A+69kDN-h0sm8wtLgKdWAcL44Cf9VoJrnbPUxCTg@mail.gmail.com \
    --to=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.