* 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>
/* 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
*
* @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;
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;
};
/*
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);
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);
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
*/
roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
ulong data_start;
ulong data_end;
+ int rc;
invalidate_dcache_range(des_start, des_end);
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) |
/* 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 */
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);
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)
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);
}
out:
+ if (ret)
+ clk_release_bulk(&priv->clks);
+
return ret;
}
free(priv->phydev);
mdio_unregister(priv->bus);
mdio_free(priv->bus);
+ clk_release_bulk(&priv->clks);
return 0;
}
};
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 },
{ }
};