diff options
Diffstat (limited to 'drivers/net/designware_eqos.c')
-rw-r--r-- | drivers/net/designware_eqos.c | 264 |
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)); |