mc : Reduce MC memory size to 128M
[oweals/u-boot.git] / drivers / net / ftgmac100.c
index bf8600814690d64818eeab2e1686176f75ae24f6..92c38a81bd352b9311f7087bc67545c14b0f8a93 100644 (file)
  * Copyright (C) 2018, IBM Corporation.
  */
 
+#include <clk.h>
 #include <dm.h>
 #include <miiphy.h>
 #include <net.h>
+#include <wait_bit.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
 
@@ -28,6 +30,9 @@
 /* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
 #define PKTBUFSTX      4       /* must be power of 2 */
 
+/* Timeout for transmit */
+#define FTGMAC100_TX_TIMEOUT_MS                1000
+
 /* Timeout for a mdio read/write operation */
 #define FTGMAC100_MDIO_TIMEOUT_USEC    10000
 
  */
 #define MDC_CYCTHR                     0x34
 
+/*
+ * ftgmac100 model variants
+ */
+enum ftgmac100_model {
+       FTGMAC100_MODEL_FARADAY,
+       FTGMAC100_MODEL_ASPEED,
+};
+
 /**
  * struct ftgmac100_data - private data for the FTGMAC100 driver
  *
@@ -51,6 +64,9 @@
  * @bus: The mdio bus
  * @phy_mode: The mode of the PHY interface (rgmii, rmii, ...)
  * @max_speed: Maximum speed of Ethernet connection supported by MAC
+ * @clks: The bulk of clocks assigned to the device in the DT
+ * @rxdes0_edorr_mask: The bit number identifying the end of the RX ring buffer
+ * @txdes0_edotr_mask: The bit number identifying the end of the TX ring buffer
  */
 struct ftgmac100_data {
        struct ftgmac100 *iobase;
@@ -65,6 +81,12 @@ struct ftgmac100_data {
        struct mii_dev *bus;
        u32 phy_mode;
        u32 max_speed;
+
+       struct clk_bulk clks;
+
+       /* End of RX/TX ring buffer bits. Depend on model */
+       u32 rxdes0_edorr_mask;
+       u32 txdes0_edotr_mask;
 };
 
 /*
@@ -285,7 +307,7 @@ static int ftgmac100_start(struct udevice *dev)
                priv->txdes[i].txdes3 = 0;
                priv->txdes[i].txdes0 = 0;
        }
-       priv->txdes[PKTBUFSTX - 1].txdes0 = FTGMAC100_TXDES0_EDOTR;
+       priv->txdes[PKTBUFSTX - 1].txdes0 = priv->txdes0_edotr_mask;
 
        start = (ulong)&priv->txdes[0];
        end = start + roundup(sizeof(priv->txdes), ARCH_DMA_MINALIGN);
@@ -295,7 +317,7 @@ static int ftgmac100_start(struct udevice *dev)
                priv->rxdes[i].rxdes3 = (unsigned int)net_rx_packets[i];
                priv->rxdes[i].rxdes0 = 0;
        }
-       priv->rxdes[PKTBUFSRX - 1].rxdes0 = FTGMAC100_RXDES0_EDORR;
+       priv->rxdes[PKTBUFSRX - 1].rxdes0 = priv->rxdes0_edorr_mask;
 
        start = (ulong)&priv->rxdes[0];
        end = start + roundup(sizeof(priv->rxdes), ARCH_DMA_MINALIGN);
@@ -401,6 +423,19 @@ static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
        return rxlen;
 }
 
+static u32 ftgmac100_read_txdesc(const void *desc)
+{
+       const struct ftgmac100_txdes *txdes = desc;
+       ulong des_start = (ulong)txdes;
+       ulong des_end = des_start + roundup(sizeof(*txdes), ARCH_DMA_MINALIGN);
+
+       invalidate_dcache_range(des_start, des_end);
+
+       return txdes->txdes0;
+}
+
+BUILD_WAIT_FOR_BIT(ftgmac100_txdone, u32, ftgmac100_read_txdesc)
+
 /*
  * Send a data block via Ethernet
  */
@@ -414,6 +449,7 @@ static int ftgmac100_send(struct udevice *dev, void *packet, int length)
                roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
        ulong data_start;
        ulong data_end;
+       int rc;
 
        invalidate_dcache_range(des_start, des_end);
 
@@ -434,7 +470,7 @@ static int ftgmac100_send(struct udevice *dev, void *packet, int length)
        flush_dcache_range(data_start, data_end);
 
        /* Only one segment on TXBUF */
-       curr_des->txdes0 &= FTGMAC100_TXDES0_EDOTR;
+       curr_des->txdes0 &= priv->txdes0_edotr_mask;
        curr_des->txdes0 |= FTGMAC100_TXDES0_FTS |
                            FTGMAC100_TXDES0_LTS |
                            FTGMAC100_TXDES0_TXBUF_SIZE(length) |
@@ -446,6 +482,12 @@ static int ftgmac100_send(struct udevice *dev, void *packet, int length)
        /* Start transmit */
        writel(1, &ftgmac100->txpd);
 
+       rc = wait_for_bit_ftgmac100_txdone(curr_des,
+                                          FTGMAC100_TXDES0_TXDMA_OWN, false,
+                                          FTGMAC100_TX_TIMEOUT_MS, true);
+       if (rc)
+               return rc;
+
        debug("%s(): packet sent\n", __func__);
 
        /* Move to next descriptor */
@@ -465,6 +507,7 @@ static int ftgmac100_write_hwaddr(struct udevice *dev)
 static int ftgmac100_ofdata_to_platdata(struct udevice *dev)
 {
        struct eth_pdata *pdata = dev_get_platdata(dev);
+       struct ftgmac100_data *priv = dev_get_priv(dev);
        const char *phy_mode;
 
        pdata->iobase = devfdt_get_addr(dev);
@@ -479,7 +522,15 @@ static int ftgmac100_ofdata_to_platdata(struct udevice *dev)
 
        pdata->max_speed = dev_read_u32_default(dev, "max-speed", 0);
 
-       return 0;
+       if (dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED) {
+               priv->rxdes0_edorr_mask = BIT(30);
+               priv->txdes0_edotr_mask = BIT(30);
+       } else {
+               priv->rxdes0_edorr_mask = BIT(15);
+               priv->txdes0_edotr_mask = BIT(15);
+       }
+
+       return clk_get_bulk(dev, &priv->clks);
 }
 
 static int ftgmac100_probe(struct udevice *dev)
@@ -493,6 +544,10 @@ static int ftgmac100_probe(struct udevice *dev)
        priv->max_speed = pdata->max_speed;
        priv->phy_addr = 0;
 
+       ret = clk_enable_bulk(&priv->clks);
+       if (ret)
+               goto out;
+
        ret = ftgmac100_mdio_init(dev);
        if (ret) {
                dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
@@ -506,6 +561,9 @@ static int ftgmac100_probe(struct udevice *dev)
        }
 
 out:
+       if (ret)
+               clk_release_bulk(&priv->clks);
+
        return ret;
 }
 
@@ -516,6 +574,7 @@ static int ftgmac100_remove(struct udevice *dev)
        free(priv->phydev);
        mdio_unregister(priv->bus);
        mdio_free(priv->bus);
+       clk_release_bulk(&priv->clks);
 
        return 0;
 }
@@ -530,7 +589,8 @@ static const struct eth_ops ftgmac100_ops = {
 };
 
 static const struct udevice_id ftgmac100_ids[] = {
-       { .compatible = "faraday,ftgmac100" },
+       { .compatible = "faraday,ftgmac100",  .data = FTGMAC100_MODEL_FARADAY },
+       { .compatible = "aspeed,ast2500-mac", .data = FTGMAC100_MODEL_ASPEED  },
        { }
 };