diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/dwc_eth_qos.c | 129 | ||||
-rw-r--r-- | drivers/net/dwmac_socfpga.c | 37 | ||||
-rw-r--r-- | drivers/net/e1000.c | 17 | ||||
-rw-r--r-- | drivers/net/ftgmac100.c | 32 | ||||
-rw-r--r-- | drivers/net/ks8851_mll.c | 3 | ||||
-rw-r--r-- | drivers/net/macb.c | 144 | ||||
-rw-r--r-- | drivers/net/macb.h | 6 | ||||
-rw-r--r-- | drivers/net/phy/miiphybb.c | 4 |
8 files changed, 266 insertions, 106 deletions
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 45a1648ad50..944412958d6 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -209,6 +209,7 @@ struct eqos_dma_regs { #define EQOS_DMA_SYSBUS_MODE_BLEN8 BIT(2) #define EQOS_DMA_SYSBUS_MODE_BLEN4 BIT(1) +#define EQOS_DMA_CH0_CONTROL_DSL_SHIFT 18 #define EQOS_DMA_CH0_CONTROL_PBLX8 BIT(16) #define EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT 16 @@ -239,37 +240,15 @@ struct eqos_tegra186_regs { #define EQOS_AUTO_CAL_STATUS_ACTIVE BIT(31) /* Descriptors */ - -#define EQOS_DESCRIPTOR_WORDS 4 -#define EQOS_DESCRIPTOR_SIZE (EQOS_DESCRIPTOR_WORDS * 4) /* We assume ARCH_DMA_MINALIGN >= 16; 16 is the EQOS HW minimum */ #define EQOS_DESCRIPTOR_ALIGN ARCH_DMA_MINALIGN #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, ARCH_DMA_MINALIGN) #define EQOS_BUFFER_ALIGN ARCH_DMA_MINALIGN #define EQOS_MAX_PACKET_SIZE ALIGN(1568, ARCH_DMA_MINALIGN) #define EQOS_RX_BUFFER_SIZE (EQOS_DESCRIPTORS_RX * EQOS_MAX_PACKET_SIZE) -/* - * Warn if the cache-line size is larger than the descriptor size. In such - * cases the driver will likely fail because the CPU needs to flush the cache - * when requeuing RX buffers, therefore descriptors written by the hardware - * may be discarded. Architectures with full IO coherence, such as x86, do not - * experience this issue, and hence are excluded from this condition. - * - * This can be fixed by defining CONFIG_SYS_NONCACHED_MEMORY which will cause - * the driver to allocate descriptors from a pool of non-cached memory. - */ -#if EQOS_DESCRIPTOR_SIZE < ARCH_DMA_MINALIGN -#if !defined(CONFIG_SYS_NONCACHED_MEMORY) && \ - !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) && !defined(CONFIG_X86) -#warning Cache line size is larger than descriptor size -#endif -#endif - struct eqos_desc { u32 des0; u32 des1; @@ -282,12 +261,17 @@ struct eqos_desc { #define EQOS_DESC3_LD BIT(28) #define EQOS_DESC3_BUF1V BIT(24) +#define EQOS_AXI_WIDTH_32 4 +#define EQOS_AXI_WIDTH_64 8 +#define EQOS_AXI_WIDTH_128 16 + struct eqos_config { bool reg_access_always_ok; int mdio_wait; int swr_wait; int config_mac; int config_mac_mdio; + unsigned int axi_bus_width; phy_interface_t (*interface)(struct udevice *dev); struct eqos_ops *ops; }; @@ -330,9 +314,8 @@ struct eqos_priv { int phyaddr; u32 max_speed; void *descs; - struct eqos_desc *tx_descs; - struct eqos_desc *rx_descs; int tx_desc_idx, rx_desc_idx; + unsigned int desc_size; void *tx_dma_buf; void *rx_dma_buf; void *rx_pkt; @@ -358,63 +341,42 @@ struct eqos_priv { * not have the same constraints since they are 1536 bytes large, so they * are unlikely to share cache-lines. */ -static void *eqos_alloc_descs(unsigned int num) +static void *eqos_alloc_descs(struct eqos_priv *eqos, unsigned int num) { -#ifdef CONFIG_SYS_NONCACHED_MEMORY - return (void *)noncached_alloc(EQOS_DESCRIPTORS_SIZE, - EQOS_DESCRIPTOR_ALIGN); -#else - return memalign(EQOS_DESCRIPTOR_ALIGN, EQOS_DESCRIPTORS_SIZE); -#endif + eqos->desc_size = ALIGN(sizeof(struct eqos_desc), + (unsigned int)ARCH_DMA_MINALIGN); + + return memalign(eqos->desc_size, num * eqos->desc_size); } static void eqos_free_descs(void *descs) { -#ifdef CONFIG_SYS_NONCACHED_MEMORY - /* FIXME: noncached_alloc() has no opposite */ -#else free(descs); -#endif } -static void eqos_inval_desc_tegra186(void *desc) +static struct eqos_desc *eqos_get_desc(struct eqos_priv *eqos, + unsigned int num, bool rx) { -#ifndef CONFIG_SYS_NONCACHED_MEMORY - unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1); - unsigned long end = ALIGN(start + EQOS_DESCRIPTOR_SIZE, - ARCH_DMA_MINALIGN); - - invalidate_dcache_range(start, end); -#endif + return eqos->descs + + ((rx ? EQOS_DESCRIPTORS_TX : 0) + num) * eqos->desc_size; } static void eqos_inval_desc_generic(void *desc) { -#ifndef CONFIG_SYS_NONCACHED_MEMORY - unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); - unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE, - ARCH_DMA_MINALIGN); + unsigned long start = (unsigned long)desc; + unsigned long end = ALIGN(start + sizeof(struct eqos_desc), + ARCH_DMA_MINALIGN); invalidate_dcache_range(start, end); -#endif -} - -static void eqos_flush_desc_tegra186(void *desc) -{ -#ifndef CONFIG_SYS_NONCACHED_MEMORY - flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE); -#endif } static void eqos_flush_desc_generic(void *desc) { -#ifndef CONFIG_SYS_NONCACHED_MEMORY - unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); - unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE, - ARCH_DMA_MINALIGN); + unsigned long start = (unsigned long)desc; + unsigned long end = ALIGN(start + sizeof(struct eqos_desc), + ARCH_DMA_MINALIGN); flush_dcache_range(start, end); -#endif } static void eqos_inval_buffer_tegra186(void *buf, size_t size) @@ -1167,6 +1129,7 @@ static int eqos_start(struct udevice *dev) ulong rate; u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl; ulong last_rx_desc; + ulong desc_pad; debug("%s(dev=%p):\n", __func__, dev); @@ -1405,8 +1368,12 @@ static int eqos_start(struct udevice *dev) EQOS_MAX_PACKET_SIZE << EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT); + desc_pad = (eqos->desc_size - sizeof(struct eqos_desc)) / + eqos->config->axi_bus_width; + setbits_le32(&eqos->dma_regs->ch0_control, - EQOS_DMA_CH0_CONTROL_PBLX8); + EQOS_DMA_CH0_CONTROL_PBLX8 | + (desc_pad << EQOS_DMA_CH0_CONTROL_DSL_SHIFT)); /* * Burst length must be < 1/2 FIFO size. @@ -1435,9 +1402,15 @@ static int eqos_start(struct udevice *dev) /* Set up descriptors */ - memset(eqos->descs, 0, EQOS_DESCRIPTORS_SIZE); + memset(eqos->descs, 0, eqos->desc_size * EQOS_DESCRIPTORS_NUM); + + for (i = 0; i < EQOS_DESCRIPTORS_TX; i++) { + struct eqos_desc *tx_desc = eqos_get_desc(eqos, i, false); + eqos->config->ops->eqos_flush_desc(tx_desc); + } + for (i = 0; i < EQOS_DESCRIPTORS_RX; i++) { - struct eqos_desc *rx_desc = &(eqos->rx_descs[i]); + struct eqos_desc *rx_desc = eqos_get_desc(eqos, i, true); rx_desc->des0 = (u32)(ulong)(eqos->rx_dma_buf + (i * EQOS_MAX_PACKET_SIZE)); rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; @@ -1449,12 +1422,14 @@ static int eqos_start(struct udevice *dev) } writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress); - writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address); + writel((ulong)eqos_get_desc(eqos, 0, false), + &eqos->dma_regs->ch0_txdesc_list_address); writel(EQOS_DESCRIPTORS_TX - 1, &eqos->dma_regs->ch0_txdesc_ring_length); writel(0, &eqos->dma_regs->ch0_rxdesc_list_haddress); - writel((ulong)eqos->rx_descs, &eqos->dma_regs->ch0_rxdesc_list_address); + writel((ulong)eqos_get_desc(eqos, 0, true), + &eqos->dma_regs->ch0_rxdesc_list_address); writel(EQOS_DESCRIPTORS_RX - 1, &eqos->dma_regs->ch0_rxdesc_ring_length); @@ -1473,7 +1448,7 @@ static int eqos_start(struct udevice *dev) * that's not distinguishable from none of the descriptors being * available. */ - last_rx_desc = (ulong)&(eqos->rx_descs[(EQOS_DESCRIPTORS_RX - 1)]); + last_rx_desc = (ulong)eqos_get_desc(eqos, EQOS_DESCRIPTORS_RX - 1, true); writel(last_rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); eqos->started = true; @@ -1558,7 +1533,7 @@ static int eqos_send(struct udevice *dev, void *packet, int length) memcpy(eqos->tx_dma_buf, packet, length); eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length); - tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]); + tx_desc = eqos_get_desc(eqos, eqos->tx_desc_idx, false); eqos->tx_desc_idx++; eqos->tx_desc_idx %= EQOS_DESCRIPTORS_TX; @@ -1573,7 +1548,7 @@ static int eqos_send(struct udevice *dev, void *packet, int length) tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length; eqos->config->ops->eqos_flush_desc(tx_desc); - writel((ulong)(&(eqos->tx_descs[eqos->tx_desc_idx])), + writel((ulong)eqos_get_desc(eqos, eqos->tx_desc_idx, false), &eqos->dma_regs->ch0_txdesc_tail_pointer); for (i = 0; i < 1000000; i++) { @@ -1596,7 +1571,7 @@ static int eqos_recv(struct udevice *dev, int flags, uchar **packetp) debug("%s(dev=%p, flags=%x):\n", __func__, dev, flags); - rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); + rx_desc = eqos_get_desc(eqos, eqos->rx_desc_idx, true); eqos->config->ops->eqos_inval_desc(rx_desc); if (rx_desc->des3 & EQOS_DESC3_OWN) { debug("%s: RX packet not available\n", __func__); @@ -1631,7 +1606,7 @@ static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) eqos->config->ops->eqos_inval_buffer(packet, length); - rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); + rx_desc = eqos_get_desc(eqos, eqos->rx_desc_idx, true); rx_desc->des0 = 0; mb(); @@ -1663,17 +1638,12 @@ static int eqos_probe_resources_core(struct udevice *dev) debug("%s(dev=%p):\n", __func__, dev); - eqos->descs = eqos_alloc_descs(EQOS_DESCRIPTORS_TX + - EQOS_DESCRIPTORS_RX); + eqos->descs = eqos_alloc_descs(eqos, EQOS_DESCRIPTORS_NUM); if (!eqos->descs) { debug("%s: eqos_alloc_descs() failed\n", __func__); ret = -ENOMEM; goto err; } - eqos->tx_descs = (struct eqos_desc *)eqos->descs; - eqos->rx_descs = (eqos->tx_descs + EQOS_DESCRIPTORS_TX); - debug("%s: tx_descs=%p, rx_descs=%p\n", __func__, eqos->tx_descs, - eqos->rx_descs); eqos->tx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_MAX_PACKET_SIZE); if (!eqos->tx_dma_buf) { @@ -2083,8 +2053,8 @@ static const struct eth_ops eqos_ops = { }; static struct eqos_ops eqos_tegra186_ops = { - .eqos_inval_desc = eqos_inval_desc_tegra186, - .eqos_flush_desc = eqos_flush_desc_tegra186, + .eqos_inval_desc = eqos_inval_desc_generic, + .eqos_flush_desc = eqos_flush_desc_generic, .eqos_inval_buffer = eqos_inval_buffer_tegra186, .eqos_flush_buffer = eqos_flush_buffer_tegra186, .eqos_probe_resources = eqos_probe_resources_tegra186, @@ -2105,6 +2075,7 @@ static const struct eqos_config __maybe_unused eqos_tegra186_config = { .swr_wait = 10, .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35, + .axi_bus_width = EQOS_AXI_WIDTH_128, .interface = eqos_get_interface_tegra186, .ops = &eqos_tegra186_ops }; @@ -2132,6 +2103,7 @@ static const struct eqos_config __maybe_unused eqos_stm32_config = { .swr_wait = 50, .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV, .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, + .axi_bus_width = EQOS_AXI_WIDTH_64, .interface = eqos_get_interface_stm32, .ops = &eqos_stm32_ops }; @@ -2159,6 +2131,7 @@ struct eqos_config __maybe_unused eqos_imx_config = { .swr_wait = 50, .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, + .axi_bus_width = EQOS_AXI_WIDTH_64, .interface = eqos_get_interface_imx, .ops = &eqos_imx_ops }; diff --git a/drivers/net/dwmac_socfpga.c b/drivers/net/dwmac_socfpga.c index 939f199b1fe..82fdff51dac 100644 --- a/drivers/net/dwmac_socfpga.c +++ b/drivers/net/dwmac_socfpga.c @@ -6,6 +6,8 @@ */ #include <common.h> +#include <asm/arch/secure_reg_helper.h> +#include <asm/arch/system_manager.h> #include <asm/io.h> #include <dm.h> #include <clk.h> @@ -17,8 +19,6 @@ #include <dm/device_compat.h> #include <linux/err.h> -#include <asm/arch/system_manager.h> - struct dwmac_socfpga_plat { struct dw_eth_pdata dw_eth_pdata; void *phy_intf; @@ -64,6 +64,32 @@ static int dwmac_socfpga_of_to_plat(struct udevice *dev) return designware_eth_of_to_plat(dev); } +static int dwmac_socfpga_do_setphy(struct udevice *dev, u32 modereg) +{ + struct dwmac_socfpga_plat *pdata = dev_get_plat(dev); + u32 modemask = SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << pdata->reg_shift; + +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF) + u32 index = ((u64)pdata->phy_intf - socfpga_get_sysmgr_addr() - + SYSMGR_SOC64_EMAC0) >> 2; + + u32 id = SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC0 + index; + + int ret = socfpga_secure_reg_update32(id, + modemask, + modereg << pdata->reg_shift); + if (ret) { + dev_err(dev, "Failed to set PHY register via SMC call\n"); + return ret; + } +#else + clrsetbits_le32(pdata->phy_intf, modemask, + modereg << pdata->reg_shift); +#endif + + return 0; +} + static int dwmac_socfpga_probe(struct udevice *dev) { struct dwmac_socfpga_plat *pdata = dev_get_plat(dev); @@ -71,7 +97,6 @@ static int dwmac_socfpga_probe(struct udevice *dev) struct reset_ctl_bulk reset_bulk; int ret; u32 modereg; - u32 modemask; switch (edata->phy_interface) { case PHY_INTERFACE_MODE_MII: @@ -97,9 +122,9 @@ static int dwmac_socfpga_probe(struct udevice *dev) reset_assert_bulk(&reset_bulk); - modemask = SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << pdata->reg_shift; - clrsetbits_le32(pdata->phy_intf, modemask, - modereg << pdata->reg_shift); + ret = dwmac_socfpga_do_setphy(dev, modereg); + if (ret) + return ret; reset_release_bulk(&reset_bulk); diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 3b3dd104cde..733588302db 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -869,7 +869,6 @@ e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset, return E1000_SUCCESS; } -#ifndef CONFIG_DM_ETH /****************************************************************************** * e1000_write_eeprom_srwr - Write to Shadow Ram using EEWR * @hw: pointer to the HW structure @@ -1035,7 +1034,6 @@ static int32_t e1000_update_eeprom_checksum_i210(struct e1000_hw *hw) out: return ret_val; } -#endif /****************************************************************************** * Verifies that the EEPROM has a valid checksum @@ -5660,13 +5658,24 @@ e1000_poll(struct eth_device *nic) return len ? 1 : 0; } +#endif /* !CONFIG_DM_ETH */ +#ifdef CONFIG_DM_ETH +static int e1000_write_hwaddr(struct udevice *dev) +#else static int e1000_write_hwaddr(struct eth_device *dev) +#endif { #ifndef CONFIG_E1000_NO_NVM - unsigned char *mac = dev->enetaddr; unsigned char current_mac[6]; +#ifdef CONFIG_DM_ETH + struct eth_pdata *plat = dev_get_plat(dev); + struct e1000_hw *hw = dev_get_priv(dev); + u8 *mac = plat->enetaddr; +#else struct e1000_hw *hw = dev->priv; + u8 *mac = dev->enetaddr; +#endif uint16_t data[3]; int ret_val, i; @@ -5700,6 +5709,7 @@ static int e1000_write_hwaddr(struct eth_device *dev) #endif } +#ifndef CONFIG_DM_ETH /************************************************************************** PROBE - Look for an adapter, this routine's visible to the outside You should omit the last argument struct pci_device * for a non-PCI NIC @@ -5926,6 +5936,7 @@ static const struct eth_ops e1000_eth_ops = { .recv = e1000_eth_recv, .stop = e1000_eth_stop, .free_pkt = e1000_free_pkt, + .write_hwaddr = e1000_write_hwaddr, }; static const struct udevice_id e1000_eth_ids[] = { diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c index 69e299d6a3d..0687230b4bb 100644 --- a/drivers/net/ftgmac100.c +++ b/drivers/net/ftgmac100.c @@ -271,6 +271,28 @@ static int ftgmac100_set_mac(struct ftgmac100_data *priv, } /* + * Get MAC address + */ +static int ftgmac100_get_mac(struct ftgmac100_data *priv, + unsigned char *mac) +{ + struct ftgmac100 *ftgmac100 = priv->iobase; + unsigned int maddr = readl(&ftgmac100->mac_madr); + unsigned int laddr = readl(&ftgmac100->mac_ladr); + + debug("%s(%x %x)\n", __func__, maddr, laddr); + + mac[0] = (maddr >> 8) & 0xff; + mac[1] = maddr & 0xff; + mac[2] = (laddr >> 24) & 0xff; + mac[3] = (laddr >> 16) & 0xff; + mac[4] = (laddr >> 8) & 0xff; + mac[5] = laddr & 0xff; + + return 0; +} + +/* * disable transmitter, receiver */ static void ftgmac100_stop(struct udevice *dev) @@ -511,6 +533,14 @@ static int ftgmac100_write_hwaddr(struct udevice *dev) return ftgmac100_set_mac(priv, pdata->enetaddr); } +static int ftgmac_read_hwaddr(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct ftgmac100_data *priv = dev_get_priv(dev); + + return ftgmac100_get_mac(priv, pdata->enetaddr); +} + static int ftgmac100_of_to_plat(struct udevice *dev) { struct eth_pdata *pdata = dev_get_plat(dev); @@ -571,6 +601,8 @@ static int ftgmac100_probe(struct udevice *dev) goto out; } + ftgmac_read_hwaddr(dev); + out: if (ret) clk_release_bulk(&priv->clks); diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c index 91c2d10ffc8..9dd9b33955a 100644 --- a/drivers/net/ks8851_mll.c +++ b/drivers/net/ks8851_mll.c @@ -251,7 +251,8 @@ static int ks_rcv(struct ks_net *ks, uchar *data) } ks_wrreg16(ks, KS_RXQCR, RXQCR_CMD_CNTL | RXQCR_RRXEF); - printf(DRIVERNAME ": bad packet\n"); + printf(DRIVERNAME ": bad packet (sts=0x%04x len=0x%04x)\n", sts, len); + ks->rxfc = 0; return 0; } diff --git a/drivers/net/macb.c b/drivers/net/macb.c index e287c29e69f..2225b33ff65 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -83,7 +83,16 @@ struct macb_dma_desc { u32 ctrl; }; -#define DMA_DESC_BYTES(n) (n * sizeof(struct macb_dma_desc)) +struct macb_dma_desc_64 { + u32 addrh; + u32 unused; +}; + +#define HW_DMA_CAP_32B 0 +#define HW_DMA_CAP_64B 1 + +#define DMA_DESC_SIZE 16 +#define DMA_DESC_BYTES(n) ((n) * DMA_DESC_SIZE) #define MACB_TX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_TX_RING_SIZE)) #define MACB_RX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_RX_RING_SIZE)) #define MACB_TX_DUMMY_DMA_DESC_SIZE (DMA_DESC_BYTES(1)) @@ -137,6 +146,7 @@ struct macb_device { struct macb_config { unsigned int dma_burst_length; + unsigned int hw_dma_cap; int (*clk_init)(struct udevice *dev, ulong rate); }; @@ -307,6 +317,24 @@ static inline void macb_invalidate_rx_buffer(struct macb_device *macb) #if defined(CONFIG_CMD_NET) +static struct macb_dma_desc_64 *macb_64b_desc(struct macb_dma_desc *desc) +{ + return (struct macb_dma_desc_64 *)((void *)desc + + sizeof(struct macb_dma_desc)); +} + +static void macb_set_addr(struct macb_device *macb, struct macb_dma_desc *desc, + ulong addr) +{ + struct macb_dma_desc_64 *desc_64; + + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) { + desc_64 = macb_64b_desc(desc); + desc_64->addrh = upper_32_bits(addr); + } + desc->addr = lower_32_bits(addr); +} + static int _macb_send(struct macb_device *macb, const char *name, void *packet, int length) { @@ -325,8 +353,12 @@ static int _macb_send(struct macb_device *macb, const char *name, void *packet, macb->tx_head++; } + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) + tx_head = tx_head * 2; + macb->tx_ring[tx_head].ctrl = ctrl; - macb->tx_ring[tx_head].addr = paddr; + macb_set_addr(macb, &macb->tx_ring[tx_head], paddr); + barrier(); macb_flush_ring_desc(macb, TX); macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART)); @@ -363,19 +395,28 @@ static void reclaim_rx_buffers(struct macb_device *macb, unsigned int new_tail) { unsigned int i; + unsigned int count; i = macb->rx_tail; macb_invalidate_ring_desc(macb, RX); while (i > new_tail) { - macb->rx_ring[i].addr &= ~MACB_BIT(RX_USED); + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) + count = i * 2; + else + count = i; + macb->rx_ring[count].addr &= ~MACB_BIT(RX_USED); i++; if (i > MACB_RX_RING_SIZE) i = 0; } while (i < new_tail) { - macb->rx_ring[i].addr &= ~MACB_BIT(RX_USED); + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) + count = i * 2; + else + count = i; + macb->rx_ring[count].addr &= ~MACB_BIT(RX_USED); i++; } @@ -390,16 +431,25 @@ static int _macb_recv(struct macb_device *macb, uchar **packetp) void *buffer; int length; u32 status; + u8 flag = false; macb->wrapped = false; for (;;) { macb_invalidate_ring_desc(macb, RX); + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) + next_rx_tail = next_rx_tail * 2; + if (!(macb->rx_ring[next_rx_tail].addr & MACB_BIT(RX_USED))) return -EAGAIN; status = macb->rx_ring[next_rx_tail].ctrl; if (status & MACB_BIT(RX_SOF)) { + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) { + next_rx_tail = next_rx_tail / 2; + flag = true; + } + if (next_rx_tail != macb->rx_tail) reclaim_rx_buffers(macb, next_rx_tail); macb->wrapped = false; @@ -426,11 +476,22 @@ static int _macb_recv(struct macb_device *macb, uchar **packetp) *packetp = buffer; } + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) { + if (!flag) + next_rx_tail = next_rx_tail / 2; + } + if (++next_rx_tail >= MACB_RX_RING_SIZE) next_rx_tail = 0; macb->next_rx_tail = next_rx_tail; return length; } else { + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) { + if (!flag) + next_rx_tail = next_rx_tail / 2; + flag = false; + } + if (++next_rx_tail >= MACB_RX_RING_SIZE) { macb->wrapped = true; next_rx_tail = 0; @@ -470,6 +531,12 @@ static int macb_phy_find(struct macb_device *macb, const char *name) int i; u16 phy_id; + phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1); + if (phy_id != 0xffff) { + printf("%s: PHY present at %d\n", name, macb->phy_addr); + return 0; + } + /* Search for PHY... */ for (i = 0; i < 32; i++) { macb->phy_addr = i; @@ -718,6 +785,7 @@ static int gmac_init_multi_queues(struct macb_device *macb) { int i, num_queues = 1; u32 queue_mask; + unsigned long paddr; /* bit 0 is never set but queue 0 always exists */ queue_mask = gem_readl(macb, DCFG6) & 0xff; @@ -731,10 +799,18 @@ static int gmac_init_multi_queues(struct macb_device *macb) macb->dummy_desc->addr = 0; flush_dcache_range(macb->dummy_desc_dma, macb->dummy_desc_dma + ALIGN(MACB_TX_DUMMY_DMA_DESC_SIZE, PKTALIGN)); - - for (i = 1; i < num_queues; i++) - gem_writel_queue_TBQP(macb, macb->dummy_desc_dma, i - 1); - + paddr = macb->dummy_desc_dma; + + for (i = 1; i < num_queues; i++) { + gem_writel_queue_TBQP(macb, lower_32_bits(paddr), i - 1); + gem_writel_queue_RBQP(macb, lower_32_bits(paddr), i - 1); + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) { + gem_writel_queue_TBQPH(macb, upper_32_bits(paddr), + i - 1); + gem_writel_queue_RBQPH(macb, upper_32_bits(paddr), + i - 1); + } + } return 0; } @@ -760,6 +836,9 @@ static void gmac_configure_dma(struct macb_device *macb) dmacfg &= ~GEM_BIT(ENDIA_DESC); dmacfg &= ~GEM_BIT(ADDR64); + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) + dmacfg |= GEM_BIT(ADDR64); + gem_writel(macb, DMACFG, dmacfg); } @@ -775,6 +854,7 @@ static int _macb_init(struct macb_device *macb, const char *name) unsigned long paddr; int ret; int i; + int count; /* * macb_halt should have been called at some point before now, @@ -786,20 +866,28 @@ static int _macb_init(struct macb_device *macb, const char *name) for (i = 0; i < MACB_RX_RING_SIZE; i++) { if (i == (MACB_RX_RING_SIZE - 1)) paddr |= MACB_BIT(RX_WRAP); - macb->rx_ring[i].addr = paddr; - macb->rx_ring[i].ctrl = 0; + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) + count = i * 2; + else + count = i; + macb->rx_ring[count].ctrl = 0; + macb_set_addr(macb, &macb->rx_ring[count], paddr); paddr += macb->rx_buffer_size; } macb_flush_ring_desc(macb, RX); macb_flush_rx_buffer(macb); for (i = 0; i < MACB_TX_RING_SIZE; i++) { - macb->tx_ring[i].addr = 0; + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) + count = i * 2; + else + count = i; + macb_set_addr(macb, &macb->tx_ring[count], 0); if (i == (MACB_TX_RING_SIZE - 1)) - macb->tx_ring[i].ctrl = MACB_BIT(TX_USED) | + macb->tx_ring[count].ctrl = MACB_BIT(TX_USED) | MACB_BIT(TX_WRAP); else - macb->tx_ring[i].ctrl = MACB_BIT(TX_USED); + macb->tx_ring[count].ctrl = MACB_BIT(TX_USED); } macb_flush_ring_desc(macb, TX); @@ -812,8 +900,12 @@ static int _macb_init(struct macb_device *macb, const char *name) gem_writel(macb, DMACFG, MACB_ZYNQ_GEM_DMACR_INIT); #endif - macb_writel(macb, RBQP, macb->rx_ring_dma); - macb_writel(macb, TBQP, macb->tx_ring_dma); + macb_writel(macb, RBQP, lower_32_bits(macb->rx_ring_dma)); + macb_writel(macb, TBQP, lower_32_bits(macb->tx_ring_dma)); + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) { + macb_writel(macb, RBQPH, upper_32_bits(macb->rx_ring_dma)); + macb_writel(macb, TBQPH, upper_32_bits(macb->tx_ring_dma)); + } if (macb_is_gem(macb)) { /* Initialize DMA properties */ @@ -1217,6 +1309,7 @@ static int macb_enable_clk(struct udevice *dev) static const struct macb_config default_gem_config = { .dma_burst_length = 16, + .hw_dma_cap = HW_DMA_CAP_32B, .clk_init = NULL, }; @@ -1224,11 +1317,12 @@ static int macb_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_plat(dev); struct macb_device *macb = dev_get_priv(dev); + struct ofnode_phandle_args phandle_args; const char *phy_mode; int ret; - phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", - NULL); + phy_mode = dev_read_prop(dev, "phy-mode", NULL); + if (phy_mode) macb->phy_interface = phy_get_interface_by_name(phy_mode); if (macb->phy_interface == -1) { @@ -1236,6 +1330,12 @@ static int macb_eth_probe(struct udevice *dev) return -EINVAL; } + /* Read phyaddr from DT */ + if (!dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, + &phandle_args)) + macb->phy_addr = ofnode_read_u32_default(phandle_args.node, + "reg", -1); + macb->regs = (void *)pdata->iobase; macb->is_big_endian = (cpu_to_be32(0x12345678) == 0x12345678); @@ -1304,13 +1404,21 @@ static int macb_eth_of_to_plat(struct udevice *dev) return macb_late_eth_of_to_plat(dev); } +static const struct macb_config microchip_config = { + .dma_burst_length = 16, + .hw_dma_cap = HW_DMA_CAP_64B, + .clk_init = NULL, +}; + static const struct macb_config sama5d4_config = { .dma_burst_length = 4, + .hw_dma_cap = HW_DMA_CAP_32B, .clk_init = NULL, }; static const struct macb_config sifive_config = { .dma_burst_length = 16, + .hw_dma_cap = HW_DMA_CAP_32B, .clk_init = macb_sifive_clk_init, }; @@ -1324,6 +1432,8 @@ static const struct udevice_id macb_eth_ids[] = { { .compatible = "cdns,zynq-gem" }, { .compatible = "sifive,fu540-c000-gem", .data = (ulong)&sifive_config }, + { .compatible = "microchip,mpfs-mss-gem", + .data = (ulong)µchip_config }, { } }; diff --git a/drivers/net/macb.h b/drivers/net/macb.h index 9b16383eba4..72b84ae96ed 100644 --- a/drivers/net/macb.h +++ b/drivers/net/macb.h @@ -768,5 +768,11 @@ #define GEM_RX_CSUM_CHECKED_MASK 2 #define gem_writel_queue_TBQP(port, value, queue_num) \ writel((value), (port)->regs + GEM_TBQP(queue_num)) +#define gem_writel_queue_TBQPH(port, value, queue_num) \ + writel((value), (port)->regs + GEM_TBQPH(queue_num)) +#define gem_writel_queue_RBQP(port, value, queue_num) \ + writel((value), (port)->regs + GEM_RBQP(queue_num)) +#define gem_writel_queue_RBQPH(port, value, queue_num) \ + writel((value), (port)->regs + GEM_RBQPH(queue_num)) #endif /* __DRIVERS_MACB_H__ */ diff --git a/drivers/net/phy/miiphybb.c b/drivers/net/phy/miiphybb.c index ba97a54c067..59a32c49130 100644 --- a/drivers/net/phy/miiphybb.c +++ b/drivers/net/phy/miiphybb.c @@ -105,7 +105,7 @@ int bb_miiphy_buses_num = sizeof(bb_miiphy_buses) / sizeof(bb_miiphy_buses[0]); #endif -void bb_miiphy_init(void) +int bb_miiphy_init(void) { int i; @@ -124,6 +124,8 @@ void bb_miiphy_init(void) bb_miiphy_buses[i].init(&bb_miiphy_buses[i]); } } + + return 0; } static inline struct bb_miiphy_bus *bb_miiphy_getbus(const char *devname) |