summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/dwc_eth_qos.c129
-rw-r--r--drivers/net/dwmac_socfpga.c37
-rw-r--r--drivers/net/e1000.c17
-rw-r--r--drivers/net/ftgmac100.c32
-rw-r--r--drivers/net/ks8851_mll.c3
-rw-r--r--drivers/net/macb.c144
-rw-r--r--drivers/net/macb.h6
-rw-r--r--drivers/net/phy/miiphybb.c4
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)&microchip_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)