summaryrefslogtreecommitdiffstats
path: root/drivers/net/designware_eqos.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/designware_eqos.c')
-rw-r--r--drivers/net/designware_eqos.c264
1 files changed, 169 insertions, 95 deletions
diff --git a/drivers/net/designware_eqos.c b/drivers/net/designware_eqos.c
index a49239e057..ccce51b6af 100644
--- a/drivers/net/designware_eqos.c
+++ b/drivers/net/designware_eqos.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2016, NVIDIA CORPORATION.
* Copyright (c) 2019, Ahmad Fatoum, Pengutronix
@@ -8,9 +8,12 @@
#include <common.h>
#include <init.h>
+#include <gpio.h>
+#include <linux/gpio/consumer.h>
#include <dma.h>
#include <net.h>
#include <of_net.h>
+#include <of_gpio.h>
#include <linux/iopoll.h>
#include <linux/time.h>
#include <linux/sizes.h>
@@ -23,7 +26,8 @@
struct eqos_mac_regs {
u32 config; /* 0x000 */
u32 ext_config; /* 0x004 */
- u32 unused_004[(0x070 - 0x008) / 4]; /* 0x008 */
+ u32 packet_filter; /* 0x008 */
+ u32 unused_004[(0x070 - 0x00C) / 4]; /* 0x00C */
u32 q0_tx_flow_ctrl; /* 0x070 */
u32 unused_070[(0x090 - 0x074) / 4]; /* 0x074 */
u32 rx_flow_ctrl; /* 0x090 */
@@ -59,6 +63,9 @@ struct eqos_mac_regs {
#define EQOS_MAC_CONFIGURATION_TE BIT(1)
#define EQOS_MAC_CONFIGURATION_RE BIT(0)
+#define EQOS_MAC_PACKET_FILTER_PR BIT(0) /* Promiscuous mode */
+#define EQOS_MAC_PACKET_FILTER_PCF BIT(7) /* Pass Control Frames */
+
#define EQOS_MAC_Q0_TX_FLOW_CTRL_PT_SHIFT 16
#define EQOS_MAC_Q0_TX_FLOW_CTRL_PT_MASK 0xffff
#define EQOS_MAC_Q0_TX_FLOW_CTRL_TFE BIT(1)
@@ -109,6 +116,8 @@ struct eqos_mtl_regs {
#define EQOS_MTL_RXQ0_OPERATION_MODE_RFA_MASK 0x3f
#define EQOS_MTL_RXQ0_OPERATION_MODE_EHFC BIT(7)
#define EQOS_MTL_RXQ0_OPERATION_MODE_RSF BIT(5)
+#define EQOS_MTL_RXQ0_OPERATION_MODE_FEP BIT(4)
+#define EQOS_MTL_RXQ0_OPERATION_MODE_FUP BIT(3)
#define EQOS_MTL_RXQ0_DEBUG_PRXQ_SHIFT 16
#define EQOS_MTL_RXQ0_DEBUG_PRXQ_MASK 0x7fff
@@ -163,8 +172,6 @@ struct eqos_dma_regs {
#define EQOS_DESCRIPTOR_SIZE (EQOS_DESCRIPTOR_WORDS * 4)
/* We assume ARCH_DMA_MINALIGN >= 16; 16 is the EQOS HW minimum */
#define EQOS_DESCRIPTOR_ALIGN 64
-#define EQOS_DESCRIPTORS_TX 4
-#define EQOS_DESCRIPTORS_RX 4
#define EQOS_DESCRIPTORS_NUM (EQOS_DESCRIPTORS_TX + EQOS_DESCRIPTORS_RX)
#define EQOS_DESCRIPTORS_SIZE ALIGN(EQOS_DESCRIPTORS_NUM * \
EQOS_DESCRIPTOR_SIZE, EQOS_DESCRIPTOR_ALIGN)
@@ -189,6 +196,27 @@ struct eqos_desc {
#define MII_BUSY (1 << 0)
+static int eqos_phy_reset(struct device *dev, struct eqos *eqos)
+{
+ struct gpio_desc *phy_reset;
+ u32 delays[3] = { 0, 0, 0 };
+
+ phy_reset = gpiod_get_optional(dev, "snps,reset", GPIOF_OUT_INIT_ACTIVE);
+ if (IS_ERR(phy_reset)) {
+ dev_warn(dev, "Failed to get 'snps,reset' GPIO (ignored)\n");
+ } else if (phy_reset) {
+ of_property_read_u32_array(dev->of_node,
+ "snps,reset-delays-us",
+ delays, ARRAY_SIZE(delays));
+
+ udelay(delays[1]);
+ gpiod_set_value(phy_reset, false);
+ udelay(delays[2]);
+ }
+
+ return 0;
+}
+
static int eqos_mdio_wait_idle(struct eqos *eqos)
{
u32 idle;
@@ -199,70 +227,55 @@ static int eqos_mdio_wait_idle(struct eqos *eqos)
static int eqos_mdio_read(struct mii_bus *bus, int addr, int reg)
{
struct eqos *eqos = bus->priv;
- u32 miiaddr;
+ u32 miiaddr = MII_BUSY;
int ret;
ret = eqos_mdio_wait_idle(eqos);
if (ret) {
- eqos_err(eqos, "MDIO not idle at entry\n");
+ dev_err(&bus->dev, "MDIO not idle at entry\n");
return ret;
}
- miiaddr = readl(&eqos->mac_regs->mdio_address);
- miiaddr &= EQOS_MDIO_ADDR_SKAP | EQOS_MDIO_ADDR_C45E;
- miiaddr |= EQOS_MDIO_ADDR_GOC_READ << EQOS_MDIO_ADDR_GOC_SHIFT;
-
- miiaddr |= EQOS_MDIO_CLK_CSR(eqos->ops->clk_csr);
miiaddr |= EQOS_MDIO_ADDR(addr) | EQOS_MDIO_REG(reg);
- miiaddr |= MII_BUSY;
+ miiaddr |= EQOS_MDIO_CLK_CSR(eqos->ops->clk_csr);
+ miiaddr |= EQOS_MDIO_ADDR_GOC_READ << EQOS_MDIO_ADDR_GOC_SHIFT;
+ writel(0, &eqos->mac_regs->mdio_data);
writel(miiaddr, &eqos->mac_regs->mdio_address);
- udelay(eqos->ops->mdio_wait_us);
-
ret = eqos_mdio_wait_idle(eqos);
if (ret) {
- eqos_err(eqos, "MDIO read didn't complete\n");
+ dev_err(&bus->dev, "MDIO read didn't complete\n");
return ret;
}
return readl(&eqos->mac_regs->mdio_data) & 0xffff;
}
-static int eqos_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val)
+static int eqos_mdio_write(struct mii_bus *bus, int addr, int reg, u16 data)
{
struct eqos *eqos = bus->priv;
- u32 miiaddr = 0;
+ u32 miiaddr = MII_BUSY;
int ret;
ret = eqos_mdio_wait_idle(eqos);
if (ret) {
- eqos_err(eqos, "MDIO not idle at entry\n");
+ dev_err(&bus->dev, "MDIO not idle at entry\n");
return ret;
}
- miiaddr = readl(&eqos->mac_regs->mdio_address);
- miiaddr &= EQOS_MDIO_ADDR_SKAP | EQOS_MDIO_ADDR_C45E;
- miiaddr |= EQOS_MDIO_ADDR_GOC_WRITE << EQOS_MDIO_ADDR_GOC_SHIFT;
-
- miiaddr |= EQOS_MDIO_CLK_CSR(eqos->ops->clk_csr);
miiaddr |= EQOS_MDIO_ADDR(addr) | EQOS_MDIO_REG(reg);
- miiaddr |= MII_BUSY;
-
- writel(val, &eqos->mac_regs->mdio_data);
- writel(addr, &eqos->mac_regs->mdio_address);
+ miiaddr |= EQOS_MDIO_CLK_CSR(eqos->ops->clk_csr);
+ miiaddr |= EQOS_MDIO_ADDR_GOC_WRITE << EQOS_MDIO_ADDR_GOC_SHIFT;
- udelay(eqos->ops->mdio_wait_us);
+ writel(data, &eqos->mac_regs->mdio_data);
+ writel(miiaddr, &eqos->mac_regs->mdio_address);
ret = eqos_mdio_wait_idle(eqos);
- if (ret) {
- eqos_err(eqos, "MDIO read didn't complete\n");
- return ret;
- }
+ if (ret)
+ dev_err(&bus->dev, "MDIO read didn't complete\n");
- /* Needed as a fix for ST-Phy */
- eqos_mdio_read(bus, addr, reg);
- return 0;
+ return ret;
}
@@ -336,6 +349,14 @@ int eqos_set_ethaddr(struct eth_device *edev, const unsigned char *mac)
memcpy(eqos->macaddr, mac, ETH_ALEN);
+ if (!eqos->is_started)
+ return 0;
+
+ /* mac_hi is only partially overwritten by the following code. Part of
+ * this variable is DCS (DMA Channel Select). If this variable is not
+ * zeroed, we may get some random DMA RX channel.
+ */
+ mac_hi = 0;
/* Update the MAC address */
memcpy(&mac_hi, &mac[4], 2);
memcpy(&mac_lo, &mac[0], 4);
@@ -346,6 +367,26 @@ int eqos_set_ethaddr(struct eth_device *edev, const unsigned char *mac)
return 0;
}
+static int eqos_set_promisc(struct eth_device *edev, bool enable)
+{
+ struct eqos *eqos = edev->priv;
+ u32 mask;
+
+ eqos->promisc_enabled = enable;
+
+ if (!eqos->is_started)
+ return 0;
+
+ mask = EQOS_MAC_PACKET_FILTER_PR;
+
+ if (enable)
+ setbits_le32(&eqos->mac_regs->packet_filter, mask);
+ else
+ clrbits_le32(&eqos->mac_regs->packet_filter, mask);
+
+ return 0;
+}
+
/* Get PHY out of power saving mode. If this is needed elsewhere then
* consider making it part of phy-core and adding a resume method to
* the phy device ops. */
@@ -353,6 +394,10 @@ static int phy_resume(struct phy_device *phydev)
{
int bmcr;
+ // Bus will be NULL if a fixed-link is used.
+ if (!phydev->bus)
+ return 0;
+
bmcr = phy_read(phydev, MII_BMCR);
if (bmcr < 0)
return bmcr;
@@ -365,16 +410,25 @@ static int phy_resume(struct phy_device *phydev)
return 0;
}
-int eqos_start(struct eth_device *edev)
+static int eqos_start(struct eth_device *edev)
{
struct eqos *eqos = edev->priv;
u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl;
- unsigned long last_rx_desc;
+ unsigned long last_rx_rf_desc;
unsigned long rate;
u32 mode_set;
int ret;
int i;
+ ret = phy_device_connect(edev, &eqos->miibus, eqos->phy_addr,
+ eqos->ops->adjust_link, 0, eqos->interface);
+ if (ret)
+ return ret;
+
+ /* In some cases where PHY or DSA switch is the clock provider for
+ * EQOS, we need to probe and configure them before issuing software
+ * reset here.
+ */
setbits_le32(&eqos->dma_regs->mode, EQOS_DMA_MODE_SWR);
ret = readl_poll_timeout(&eqos->dma_regs->mode, mode_set,
@@ -385,8 +439,10 @@ int eqos_start(struct eth_device *edev)
return ret;
}
- /* Reset above clears MAC address */
+ /* Reset above clears any previously made configuration */
+ eqos->is_started = true;
eqos_set_ethaddr(edev, eqos->macaddr);
+ eqos_set_promisc(edev, eqos->promisc_enabled);
/* Required for accurate time keeping with EEE counters */
rate = eqos->ops->get_csr_clk_rate(eqos);
@@ -394,17 +450,14 @@ int eqos_start(struct eth_device *edev)
val = (rate / USEC_PER_SEC) - 1; /* -1 because the data sheet says so */
writel(val, &eqos->mac_regs->us_tic_counter);
- ret = phy_device_connect(edev, &eqos->miibus, eqos->phy_addr,
- eqos->ops->adjust_link, 0, eqos->interface);
- if (ret)
- return ret;
-
/* Before we reset the mac, we must insure the PHY is not powered down
* as the dw controller needs all clock domains to be running, including
* the PHY clock, to come out of a mac reset. */
- ret = phy_resume(edev->phydev);
- if (ret)
- return ret;
+ if (edev->phydev) {
+ ret = phy_resume(edev->phydev);
+ if (ret)
+ return ret;
+ }
/* Configure MTL */
@@ -420,7 +473,9 @@ int eqos_start(struct eth_device *edev)
/* Enable Store and Forward mode for RX, since no jumbo frame */
setbits_le32(&eqos->mtl_regs->rxq0_operation_mode,
- EQOS_MTL_RXQ0_OPERATION_MODE_RSF);
+ EQOS_MTL_RXQ0_OPERATION_MODE_RSF |
+ EQOS_MTL_RXQ0_OPERATION_MODE_FEP |
+ EQOS_MTL_RXQ0_OPERATION_MODE_FUP);
/* Transmit/Receive queue fifo size; use all RAM for 1 queue */
val = readl(&eqos->mac_regs->hw_feature1);
@@ -569,9 +624,9 @@ int eqos_start(struct eth_device *edev)
eqos->tx_currdescnum = eqos->rx_currdescnum = 0;
for (i = 0; i < EQOS_DESCRIPTORS_RX; i++) {
- struct eqos_desc *rx_desc = &eqos->rx_descs[i];
+ struct eqos_desc *rx_rf_desc = &eqos->rx_descs[i];
- writel(EQOS_DESC3_BUF1V | EQOS_DESC3_OWN, &rx_desc->des3);
+ writel(EQOS_DESC3_BUF1V | EQOS_DESC3_OWN, &rx_rf_desc->des3);
}
writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress);
@@ -601,28 +656,17 @@ int eqos_start(struct eth_device *edev)
* that's not distinguishable from none of the descriptors being
* available.
*/
- last_rx_desc = (ulong)&eqos->rx_descs[(EQOS_DESCRIPTORS_RX - 1)];
- writel(last_rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
-
- barrier();
-
- eqos->started = true;
+ last_rx_rf_desc = (ulong)&eqos->rx_descs[(EQOS_DESCRIPTORS_RX - 1)];
+ writel(last_rx_rf_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
return 0;
}
-void eqos_stop(struct eth_device *edev)
+static void eqos_stop(struct eth_device *edev)
{
struct eqos *eqos = edev->priv;
int i;
- if (!eqos->started)
- return;
-
- eqos->started = false;
-
- barrier();
-
/* Disable TX DMA */
clrbits_le32(&eqos->dma_regs->ch0_tx_control,
EQOS_DMA_CH0_TX_CONTROL_ST);
@@ -660,7 +704,6 @@ void eqos_stop(struct eth_device *edev)
static int eqos_send(struct eth_device *edev, void *packet, int length)
{
struct eqos *eqos = edev->priv;
- struct device_d *dev = &eqos->netdev.dev;
struct eqos_desc *tx_desc;
dma_addr_t dma;
u32 des3;
@@ -670,8 +713,8 @@ static int eqos_send(struct eth_device *edev, void *packet, int length)
eqos->tx_currdescnum++;
eqos->tx_currdescnum %= EQOS_DESCRIPTORS_TX;
- dma = dma_map_single(dev, packet, length, DMA_TO_DEVICE);
- if (dma_mapping_error(dev, dma))
+ dma = dma_map_single(edev->parent, packet, length, DMA_TO_DEVICE);
+ if (dma_mapping_error(edev->parent, dma))
return -EFAULT;
tx_desc->des0 = (unsigned long)dma;
@@ -690,7 +733,7 @@ static int eqos_send(struct eth_device *edev, void *packet, int length)
!(des3 & EQOS_DESC3_OWN),
100 * USEC_PER_MSEC);
- dma_unmap_single(dev, dma, length, DMA_TO_DEVICE);
+ dma_unmap_single(edev->parent, dma, length, DMA_TO_DEVICE);
if (ret == -ETIMEDOUT)
eqos_dbg(eqos, "TX timeout\n");
@@ -701,33 +744,51 @@ static int eqos_send(struct eth_device *edev, void *packet, int length)
static int eqos_recv(struct eth_device *edev)
{
struct eqos *eqos = edev->priv;
- struct eqos_desc *rx_desc;
+ struct eqos_desc *rx_wbf_desc, *rx_rf_desc;
+ dma_addr_t dma;
void *frame;
int length;
- rx_desc = &eqos->rx_descs[eqos->rx_currdescnum];
- if (readl(&rx_desc->des3) & EQOS_DESC3_OWN)
+ /* We have two types of RX descriptors at some pointer: Read and
+ * Write-Back:
+ * All RX descriptors are prepared by the software and given to the
+ * DMA as "Normal" Descriptors with the content as shown in Receive
+ * Normal Descriptor (Read Format). The DMA reads this descriptor and
+ * after transferring a received packet (or part of) to the buffers
+ * indicated by the descriptor, the Rx DMA will close the descriptor
+ * with the corresponding packet status. The format of this status is
+ * given in the "Receive Normal Descriptor (Write-Back Format)"
+ */
+
+ /* Write-Back Format RX descriptor */
+ rx_wbf_desc = &eqos->rx_descs[eqos->rx_currdescnum];
+ if (readl(&rx_wbf_desc->des3) & EQOS_DESC3_OWN)
return 0;
- frame = phys_to_virt(rx_desc->des0);
- length = rx_desc->des3 & 0x7fff;
+ dma = eqos->dma_rx_buf[eqos->rx_currdescnum];
+ frame = phys_to_virt(dma);
+ length = rx_wbf_desc->des3 & 0x7fff;
- dma_sync_single_for_cpu((unsigned long)frame, length, DMA_FROM_DEVICE);
+ dma_sync_single_for_cpu(edev->parent, (unsigned long)frame,
+ length, DMA_FROM_DEVICE);
net_receive(edev, frame, length);
- dma_sync_single_for_device((unsigned long)frame, length, DMA_FROM_DEVICE);
-
- rx_desc->des0 = (unsigned long)frame;
- rx_desc->des1 = 0;
- rx_desc->des2 = 0;
+ dma_sync_single_for_device(edev->parent, (unsigned long)frame,
+ length, DMA_FROM_DEVICE);
+
+ /* Read Format RX descriptor */
+ rx_rf_desc = &eqos->rx_descs[eqos->rx_currdescnum];
+ rx_rf_desc->des0 = dma;
+ rx_rf_desc->des1 = 0;
+ rx_rf_desc->des2 = 0;
/*
* Make sure that if HW sees the _OWN write below, it will see all the
* writes to the rest of the descriptor too.
*/
- rx_desc->des3 |= EQOS_DESC3_BUF1V;
- rx_desc->des3 |= EQOS_DESC3_OWN;
+ rx_rf_desc->des3 |= EQOS_DESC3_BUF1V;
+ rx_rf_desc->des3 |= EQOS_DESC3_OWN;
barrier();
- writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
+ writel((ulong)rx_rf_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
eqos->rx_currdescnum++;
eqos->rx_currdescnum %= EQOS_DESCRIPTORS_RX;
@@ -737,7 +798,7 @@ static int eqos_recv(struct eth_device *edev)
static int eqos_init_resources(struct eqos *eqos)
{
- struct device_d *dev = eqos->netdev.parent;
+ struct eth_device *edev = &eqos->netdev;
int ret = -ENOMEM;
void *descs;
void *p;
@@ -755,16 +816,17 @@ static int eqos_init_resources(struct eqos *eqos)
goto err_free_desc;
for (i = 0; i < EQOS_DESCRIPTORS_RX; i++) {
- struct eqos_desc *rx_desc = &eqos->rx_descs[i];
+ struct eqos_desc *rx_rf_desc = &eqos->rx_descs[i];
dma_addr_t dma;
- dma = dma_map_single(dev, p, EQOS_MAX_PACKET_SIZE, DMA_FROM_DEVICE);
- if (dma_mapping_error(dev, dma)) {
+ dma = dma_map_single(edev->parent, p, EQOS_MAX_PACKET_SIZE, DMA_FROM_DEVICE);
+ if (dma_mapping_error(edev->parent, dma)) {
ret = -EFAULT;
goto err_free_rx_bufs;
}
- rx_desc->des0 = dma;
+ rx_rf_desc->des0 = dma;
+ eqos->dma_rx_buf[i] = dma;
p += EQOS_MAX_PACKET_SIZE;
}
@@ -780,7 +842,7 @@ err:
return ret;
}
-static int eqos_init(struct device_d *dev, struct eqos *eqos)
+static int eqos_init(struct device *dev, struct eqos *eqos)
{
int ret;
@@ -796,25 +858,26 @@ static int eqos_init(struct device_d *dev, struct eqos *eqos)
return ret;
}
-static void eqos_probe_dt(struct device_d *dev, struct eqos *eqos)
+static void eqos_probe_dt(struct device *dev, struct eqos *eqos)
{
struct device_node *child;
- eqos->interface = of_get_phy_mode(dev->device_node);
+ eqos->interface = of_get_phy_mode(dev->of_node);
eqos->phy_addr = -1;
/* Set MDIO bus device node, if present. */
- for_each_child_of_node(dev->device_node, child) {
+ for_each_child_of_node(dev->of_node, child) {
if (of_device_is_compatible(child, "snps,dwmac-mdio") ||
(child->name && !of_node_cmp(child->name, "mdio"))) {
- eqos->miibus.dev.device_node = child;
+ eqos->miibus.dev.of_node = child;
break;
}
}
}
-int eqos_probe(struct device_d *dev, const struct eqos_ops *ops, void *priv)
+int eqos_probe(struct device *dev, const struct eqos_ops *ops, void *priv)
{
+ struct device_node *np = dev->of_node;
struct mii_bus *miibus;
struct resource *iores;
struct eqos *eqos;
@@ -841,12 +904,13 @@ int eqos_probe(struct device_d *dev, const struct eqos_ops *ops, void *priv)
dev->priv = edev->priv = eqos;
edev->parent = dev;
- edev->open = ops->start;
+ edev->open = eqos_start;
edev->send = eqos_send;
edev->recv = eqos_recv;
- edev->halt = ops->stop;
+ edev->halt = eqos_stop;
edev->get_ethaddr = ops->get_ethaddr;
edev->set_ethaddr = ops->set_ethaddr;
+ edev->set_promisc = eqos_set_promisc;
miibus = &eqos->miibus;
miibus->parent = edev->parent;
@@ -854,10 +918,18 @@ int eqos_probe(struct device_d *dev, const struct eqos_ops *ops, void *priv)
miibus->write = eqos_mdio_write;
miibus->priv = eqos;
+ miibus->dev.of_node = of_get_compatible_child(np, "snps,dwmac-mdio");
+ if (!miibus->dev.of_node)
+ miibus->dev.of_node = of_get_child_by_name(np, "mdio");
+
ret = eqos_init(dev, eqos);
if (ret)
return ret;
+ ret = eqos_phy_reset(dev, eqos);
+ if (ret)
+ return ret;
+
ret = mdiobus_register(miibus);
if (ret)
return ret;
@@ -865,10 +937,12 @@ int eqos_probe(struct device_d *dev, const struct eqos_ops *ops, void *priv)
return eth_register(edev);
}
-void eqos_remove(struct device_d *dev)
+void eqos_remove(struct device *dev)
{
struct eqos *eqos = dev->priv;
+ eth_unregister(&eqos->netdev);
+
mdiobus_unregister(&eqos->miibus);
dma_free(phys_to_virt(eqos->rx_descs[0].des0));