]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
net: ftgmac100: Add Aspeed AST2700 support
authorJacky Chou <jacky_chou@aspeedtech.com>
Mon, 8 Jul 2024 06:07:18 +0000 (14:07 +0800)
committerLeo Yu-Chi Liang <ycliang@andestech.com>
Wed, 11 Sep 2024 12:34:43 +0000 (20:34 +0800)
Add support of Aspeed AST2700 SoC.  AST2700 is based on ARM64 so modify
the DMA address related code to fit both ARM and ARM64.  Besides, the
RMII/RGMII mode control register is moved from SCU500 to MAC50 so
initialize the register in ftgmac100_start correspondingly.

Signed-off-by: Jacky Chou <jacky_chou@aspeedtech.com>
Acked-by: Leo Yu-Chi Liang <ycliang@andestech.com>
drivers/net/ftgmac100.c
drivers/net/ftgmac100.h

index 9d64125bfcb8ac8f060c9e0c107c705e2f723eb5..f5ea2e72d1bbd401faefffaee0d118b61e253fdf 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/printk.h>
+#include <linux/bitfield.h>
 
 #include "ftgmac100.h"
 
 enum ftgmac100_model {
        FTGMAC100_MODEL_FARADAY,
        FTGMAC100_MODEL_ASPEED,
+       FTGMAC100_MODEL_ASPEED_AST2700,
+};
+
+union ftgmac100_dma_addr {
+       dma_addr_t addr;
+       struct {
+               u32 lo;
+               u32 hi;
+       };
 };
 
 /**
@@ -96,6 +106,8 @@ struct ftgmac100_data {
        /* End of RX/TX ring buffer bits. Depend on model */
        u32 rxdes0_edorr_mask;
        u32 txdes0_edotr_mask;
+
+       bool is_ast2700;
 };
 
 /*
@@ -320,6 +332,7 @@ static int ftgmac100_start(struct udevice *dev)
        struct eth_pdata *plat = dev_get_plat(dev);
        struct ftgmac100_data *priv = dev_get_priv(dev);
        struct ftgmac100 *ftgmac100 = priv->iobase;
+       union ftgmac100_dma_addr dma_addr = {.hi = 0, .lo = 0};
        struct phy_device *phydev = priv->phydev;
        unsigned int maccr, dblac, desc_size;
        ulong start, end;
@@ -341,6 +354,7 @@ static int ftgmac100_start(struct udevice *dev)
        priv->rx_index = 0;
 
        for (i = 0; i < PKTBUFSTX; i++) {
+               priv->txdes[i].txdes2 = 0;
                priv->txdes[i].txdes3 = 0;
                priv->txdes[i].txdes0 = 0;
        }
@@ -351,7 +365,14 @@ static int ftgmac100_start(struct udevice *dev)
        flush_dcache_range(start, end);
 
        for (i = 0; i < PKTBUFSRX; i++) {
-               priv->rxdes[i].rxdes3 = (unsigned int)net_rx_packets[i];
+               unsigned int ip_align = 0;
+
+               dma_addr.addr = (dma_addr_t)net_rx_packets[i];
+               priv->rxdes[i].rxdes2 = FIELD_PREP(FTGMAC100_RXDES2_RXBUF_BADR_HI, dma_addr.hi);
+               /* For IP alignment */
+               if ((dma_addr.lo & (PKTALIGN - 1)) == 0)
+                       ip_align = 2;
+               priv->rxdes[i].rxdes3 = dma_addr.lo + ip_align;
                priv->rxdes[i].rxdes0 = 0;
        }
        priv->rxdes[PKTBUFSRX - 1].rxdes0 = priv->rxdes0_edorr_mask;
@@ -361,10 +382,14 @@ static int ftgmac100_start(struct udevice *dev)
        flush_dcache_range(start, end);
 
        /* transmit ring */
-       writel((u32)priv->txdes, &ftgmac100->txr_badr);
+       dma_addr.addr = (dma_addr_t)priv->txdes;
+       writel(dma_addr.lo, &ftgmac100->txr_badr);
+       writel(dma_addr.hi, &ftgmac100->txr_badr_hi);
 
        /* receive ring */
-       writel((u32)priv->rxdes, &ftgmac100->rxr_badr);
+       dma_addr.addr = (dma_addr_t)priv->rxdes;
+       writel(dma_addr.lo, &ftgmac100->rxr_badr);
+       writel(dma_addr.hi, &ftgmac100->rxr_badr_hi);
 
        /* Configure TX/RX decsriptor size
         * This size is calculated based on cache line.
@@ -393,6 +418,10 @@ static int ftgmac100_start(struct udevice *dev)
                FTGMAC100_MACCR_RX_RUNT |
                FTGMAC100_MACCR_RX_BROADPKT;
 
+       if (priv->is_ast2700 && (priv->phydev->interface == PHY_INTERFACE_MODE_RMII ||
+                                priv->phydev->interface == PHY_INTERFACE_MODE_NCSI))
+               maccr |= FTGMAC100_MACCR_RMII_ENABLE;
+
        writel(maccr, &ftgmac100->maccr);
 
        ret = phy_startup(phydev);
@@ -450,9 +479,11 @@ static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
        ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
        ulong des_end = des_start +
                roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
-       ulong data_start = curr_des->rxdes3;
+       union ftgmac100_dma_addr data_start = { .lo = 0, .hi = 0 };
        ulong data_end;
 
+       data_start.hi = FIELD_GET(FTGMAC100_RXDES2_RXBUF_BADR_HI, curr_des->rxdes2);
+       data_start.lo = curr_des->rxdes3;
        invalidate_dcache_range(des_start, des_end);
 
        if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY))
@@ -472,9 +503,9 @@ static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
               __func__, priv->rx_index, rxlen);
 
        /* Invalidate received data */
-       data_end = data_start + roundup(rxlen, ARCH_DMA_MINALIGN);
-       invalidate_dcache_range(data_start, data_end);
-       *packetp = (uchar *)data_start;
+       data_end = data_start.addr + roundup(rxlen, ARCH_DMA_MINALIGN);
+       invalidate_dcache_range(data_start.addr, data_end);
+       *packetp = (uchar *)data_start.addr;
 
        return rxlen;
 }
@@ -500,6 +531,7 @@ static int ftgmac100_send(struct udevice *dev, void *packet, int length)
        struct ftgmac100_data *priv = dev_get_priv(dev);
        struct ftgmac100 *ftgmac100 = priv->iobase;
        struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
+       union ftgmac100_dma_addr dma_addr;
        ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
        ulong des_end = des_start +
                roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
@@ -518,10 +550,12 @@ static int ftgmac100_send(struct udevice *dev, void *packet, int length)
 
        length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
 
-       curr_des->txdes3 = (unsigned int)packet;
+       dma_addr.addr = (dma_addr_t)packet;
+       curr_des->txdes2 = FIELD_PREP(FTGMAC100_TXDES2_TXBUF_BADR_HI, dma_addr.hi);
+       curr_des->txdes3 = dma_addr.lo;
 
        /* Flush data to be sent */
-       data_start = curr_des->txdes3;
+       data_start = (ulong)dma_addr.addr;
        data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
        flush_dcache_range(data_start, data_end);
 
@@ -584,6 +618,11 @@ static int ftgmac100_of_to_plat(struct udevice *dev)
        if (dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED) {
                priv->rxdes0_edorr_mask = BIT(30);
                priv->txdes0_edotr_mask = BIT(30);
+               priv->is_ast2700 = false;
+       } else if (dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED_AST2700) {
+               priv->rxdes0_edorr_mask = BIT(30);
+               priv->txdes0_edotr_mask = BIT(30);
+               priv->is_ast2700 = true;
        } else {
                priv->rxdes0_edorr_mask = BIT(15);
                priv->txdes0_edotr_mask = BIT(15);
@@ -674,10 +713,11 @@ static const struct eth_ops ftgmac100_ops = {
 };
 
 static const struct udevice_id ftgmac100_ids[] = {
-       { .compatible = "faraday,ftgmac100",  .data = FTGMAC100_MODEL_FARADAY },
-       { .compatible = "aspeed,ast2500-mac", .data = FTGMAC100_MODEL_ASPEED  },
-       { .compatible = "aspeed,ast2600-mac", .data = FTGMAC100_MODEL_ASPEED  },
-       { }
+       { .compatible = "faraday,ftgmac100", .data = FTGMAC100_MODEL_FARADAY },
+       { .compatible = "aspeed,ast2500-mac", .data = FTGMAC100_MODEL_ASPEED },
+       { .compatible = "aspeed,ast2600-mac", .data = FTGMAC100_MODEL_ASPEED },
+       { .compatible = "aspeed,ast2700-mac", .data = FTGMAC100_MODEL_ASPEED_AST2700 },
+       {}
 };
 
 U_BOOT_DRIVER(ftgmac100) = {
index 37c029aded65f3c6a9057b065faadb43c4f07c9a..c38b57c9541733e712c42879829d96f7f45f9652 100644 (file)
@@ -66,6 +66,13 @@ struct ftgmac100 {
        unsigned int    rx_runt;        /* 0xc0 */
        unsigned int    rx_crcer_ftl;   /* 0xc4 */
        unsigned int    rx_col_lost;    /* 0xc8 */
+       unsigned int    reserved[43];   /* 0xcc - 0x174 */
+       unsigned int    txr_badr_lo;    /* 0x178, defined in ast2700 */
+       unsigned int    txr_badr_hi;    /* 0x17c, defined in ast2700 */
+       unsigned int    hptxr_badr_lo;  /* 0x180, defined in ast2700 */
+       unsigned int    hptxr_badr_hi;  /* 0x184, defined in ast2700 */
+       unsigned int    rxr_badr_lo;    /* 0x188, defined in ast2700 */
+       unsigned int    rxr_badr_hi;    /* 0x18c, defined in ast2700 */
 };
 
 /*
@@ -158,6 +165,7 @@ struct ftgmac100 {
 #define FTGMAC100_MACCR_RX_BROADPKT    BIT(17)
 #define FTGMAC100_MACCR_DISCARD_CRCERR BIT(18)
 #define FTGMAC100_MACCR_FAST_MODE      BIT(19)
+#define FTGMAC100_MACCR_RMII_ENABLE    BIT(20) /* defined in ast2700 */
 #define FTGMAC100_MACCR_SW_RST         BIT(31)
 
 /*
@@ -202,6 +210,8 @@ struct ftgmac100_txdes {
 #define FTGMAC100_TXDES1_TX2FIC                BIT(30)
 #define FTGMAC100_TXDES1_TXIC          BIT(31)
 
+#define FTGMAC100_TXDES2_TXBUF_BADR_HI GENMASK(18, 16)
+
 /*
  * Receive descriptor, aligned to 16 bytes
  */
@@ -241,4 +251,6 @@ struct ftgmac100_rxdes {
 #define FTGMAC100_RXDES1_UDP_CHKSUM_ERR        BIT(26)
 #define FTGMAC100_RXDES1_IP_CHKSUM_ERR BIT(27)
 
+#define FTGMAC100_RXDES2_RXBUF_BADR_HI GENMASK(18, 16)
+
 #endif /* __FTGMAC100_H */