[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