[U-Boot] [PATCH 2/5] net: re-add support for the Faraday ftgmac100 controller

Cédric Le Goater clg at kaod.org
Wed Sep 12 12:05:36 UTC 2018


On 09/12/2018 11:27 AM, Joel Stanley wrote:
> On Mon, 10 Sep 2018 at 23:54, Cédric Le Goater <clg at 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 at kaod.org>
> 
> There are some discrepancies between the datasheet I have and the
> register layout. The rest of the driver looks good.

I kept the original register layout which came with an Andes Technology 
SoCs (I think) as it is compatible with the Aspeed layout. The feature reg 
name differs indeed but for the rest we are fine.

unless we want to fully drop old layout and directly use the one we have 
in Aspeed SoC ?



>> +++ b/drivers/net/ftgmac100.h
> 
>> +       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 */
> 
> The datasheet calls MAC3C DBG_STS: Debug status register. Actually,
> the next few are different too:
> 
> 0x3c: dbg_sts
> 0x40: fear
> 0x44: undocumented
> 
>> +       unsigned int    revr;           /* 0x40 */
>> +       unsigned int    fear;           /* 0x44 */
> 
> From here on it looks good again:
> 
>> +       unsigned int    tpafcr;         /* 0x48 */
>> +       unsigned int    rbsr;           /* 0x4c */
>> +       unsigned int    maccr;          /* 0x50 */
>> +       unsigned int    macsr;          /* 0x54 */
>> +       unsigned int    tm;             /* 0x58 */
> 
> but here it goes wrong again:
> 
> 0x58: undocumented
> 
>> +       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 */
> 
> And from here it gets confusing agian. The definitions you have appear
> to match the Linux driver.
> 
>> +       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 */
> 
> 
>> +static int ftgmac100_start(struct udevice *dev)
>> +{
> 
>> +
>> +       /* 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;
> 
> Just reviewing for differences between this and the kernel driver; the
> kernel driver sets PHY_LINK_LEVEL. Is there a reason u-boot doesn't?

u-boot doesn't, nor does Linux on the EVB. 

Maybe it is related to NCSI ? I will ask around.

Thanks,

C.
 
>> +
>> +       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 */
>> +
>> +       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.
>> +
>>  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
>>
>> _______________________________________________
>> U-Boot mailing list
>> U-Boot at lists.denx.de
>> https://lists.denx.de/listinfo/u-boot



More information about the U-Boot mailing list