aboutsummaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/Kconfig23
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/macb.c8
-rw-r--r--drivers/net/mdio_sandbox.c92
-rw-r--r--drivers/net/mscc_eswitch/Makefile10
-rw-r--r--drivers/net/mscc_eswitch/jr2_switch.c119
-rw-r--r--drivers/net/mscc_eswitch/luton_switch.c101
-rw-r--r--drivers/net/mscc_eswitch/mscc_miim.c28
-rw-r--r--drivers/net/mscc_eswitch/mscc_miim.h14
-rw-r--r--drivers/net/mscc_eswitch/ocelot_switch.c104
-rw-r--r--drivers/net/mscc_eswitch/serval_switch.c103
-rw-r--r--drivers/net/mscc_eswitch/servalt_switch.c102
-rw-r--r--drivers/net/phy/cortina.c5
-rw-r--r--drivers/net/phy/ti.c16
-rw-r--r--drivers/net/ti/Kconfig8
-rw-r--r--drivers/net/ti/Makefile1
-rw-r--r--drivers/net/ti/am65-cpsw-nuss.c792
-rw-r--r--drivers/net/ti/cpsw_mdio.c4
-rw-r--r--drivers/net/ti/cpsw_mdio.h2
19 files changed, 998 insertions, 535 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e6a4fdf30e..635f8d72c2 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -11,6 +11,29 @@ config DM_ETH
This is currently implemented in net/eth-uclass.c
Look in include/net.h for details.
+config DM_MDIO
+ bool "Enable Driver Model for MDIO devices"
+ depends on DM_ETH && PHYLIB
+ help
+ Enable driver model for MDIO devices
+
+ Adds UCLASS_MDIO DM class supporting MDIO buses that are probed as
+ stand-alone devices. Useful in particular for systems that support
+ DM_ETH and have a stand-alone MDIO hardware block shared by multiple
+ Ethernet interfaces.
+ This is currently implemented in net/mdio-uclass.c
+ Look in include/miiphy.h for details.
+
+config MDIO_SANDBOX
+ depends on DM_MDIO && SANDBOX
+ default y
+ bool "Sandbox: Mocked MDIO driver"
+ help
+ This driver implements dummy read/write/reset MDIO functions mimicking
+ a bus with a single PHY.
+
+ This driver is used in for testing in test/dm/mdio.c
+
menuconfig NETDEVICES
bool "Network device support"
depends on NET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 8d02a37896..40038427db 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -77,3 +77,4 @@ obj-y += ti/
obj-$(CONFIG_MEDIATEK_ETH) += mtk_eth.o
obj-y += mscc_eswitch/
obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
+obj-$(CONFIG_MDIO_SANDBOX) += mdio_sandbox.o
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index c5560a7111..a7eddd647d 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -613,10 +613,12 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
/* First check for GMAC and that it is GiB capable */
if (gem_is_gigabit_capable(macb)) {
- lpa = macb_mdio_read(macb, MII_STAT1000);
+ lpa = macb_mdio_read(macb, MII_LPA);
- if (lpa & (LPA_1000FULL | LPA_1000HALF)) {
- duplex = ((lpa & LPA_1000FULL) ? 1 : 0);
+ if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL |
+ LPA_1000XHALF)) {
+ duplex = ((lpa & (LPA_1000FULL | LPA_1000XFULL)) ?
+ 1 : 0);
printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n",
name,
diff --git a/drivers/net/mdio_sandbox.c b/drivers/net/mdio_sandbox.c
new file mode 100644
index 0000000000..07515e078c
--- /dev/null
+++ b/drivers/net/mdio_sandbox.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Alex Marginean, NXP
+ */
+
+#include <dm.h>
+#include <errno.h>
+#include <miiphy.h>
+
+#define SANDBOX_PHY_ADDR 5
+#define SANDBOX_PHY_REG 0
+
+struct mdio_sandbox_priv {
+ int enabled;
+ u16 reg;
+};
+
+static int mdio_sandbox_read(struct udevice *dev, int addr, int devad, int reg)
+{
+ struct mdio_sandbox_priv *priv = dev_get_priv(dev);
+
+ if (!priv->enabled)
+ return -ENODEV;
+
+ if (addr != SANDBOX_PHY_ADDR)
+ return -ENODEV;
+ if (devad != MDIO_DEVAD_NONE)
+ return -ENODEV;
+ if (reg != SANDBOX_PHY_REG)
+ return -ENODEV;
+
+ return priv->reg;
+}
+
+static int mdio_sandbox_write(struct udevice *dev, int addr, int devad, int reg,
+ u16 val)
+{
+ struct mdio_sandbox_priv *priv = dev_get_priv(dev);
+
+ if (!priv->enabled)
+ return -ENODEV;
+
+ if (addr != SANDBOX_PHY_ADDR)
+ return -ENODEV;
+ if (devad != MDIO_DEVAD_NONE)
+ return -ENODEV;
+ if (reg != SANDBOX_PHY_REG)
+ return -ENODEV;
+
+ priv->reg = val;
+
+ return 0;
+}
+
+static int mdio_sandbox_reset(struct udevice *dev)
+{
+ struct mdio_sandbox_priv *priv = dev_get_priv(dev);
+
+ priv->reg = 0;
+
+ return 0;
+}
+
+static const struct mdio_ops mdio_sandbox_ops = {
+ .read = mdio_sandbox_read,
+ .write = mdio_sandbox_write,
+ .reset = mdio_sandbox_reset,
+};
+
+static int mdio_sandbox_probe(struct udevice *dev)
+{
+ struct mdio_sandbox_priv *priv = dev_get_priv(dev);
+
+ priv->enabled = 1;
+
+ return 0;
+}
+
+static const struct udevice_id mdio_sandbox_ids[] = {
+ { .compatible = "sandbox,mdio" },
+ { }
+};
+
+U_BOOT_DRIVER(mdio_sandbox) = {
+ .name = "mdio_sandbox",
+ .id = UCLASS_MDIO,
+ .of_match = mdio_sandbox_ids,
+ .probe = mdio_sandbox_probe,
+ .ops = &mdio_sandbox_ops,
+ .priv_auto_alloc_size = sizeof(struct mdio_sandbox_priv),
+};
diff --git a/drivers/net/mscc_eswitch/Makefile b/drivers/net/mscc_eswitch/Makefile
index 02f39a76bb..d583fe9fc4 100644
--- a/drivers/net/mscc_eswitch/Makefile
+++ b/drivers/net/mscc_eswitch/Makefile
@@ -1,6 +1,6 @@
-obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_xfer.o mscc_mac_table.o
-obj-$(CONFIG_MSCC_LUTON_SWITCH) += luton_switch.o mscc_xfer.o mscc_mac_table.o
-obj-$(CONFIG_MSCC_JR2_SWITCH) += jr2_switch.o mscc_xfer.o
-obj-$(CONFIG_MSCC_SERVALT_SWITCH) += servalt_switch.o mscc_xfer.o
-obj-$(CONFIG_MSCC_SERVAL_SWITCH) += serval_switch.o mscc_xfer.o mscc_mac_table.o
+obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_xfer.o mscc_mac_table.o mscc_miim.o
+obj-$(CONFIG_MSCC_LUTON_SWITCH) += luton_switch.o mscc_xfer.o mscc_mac_table.o mscc_miim.o
+obj-$(CONFIG_MSCC_JR2_SWITCH) += jr2_switch.o mscc_xfer.o mscc_miim.o
+obj-$(CONFIG_MSCC_SERVALT_SWITCH) += servalt_switch.o mscc_xfer.o mscc_miim.o
+obj-$(CONFIG_MSCC_SERVAL_SWITCH) += serval_switch.o mscc_xfer.o mscc_mac_table.o mscc_miim.o
diff --git a/drivers/net/mscc_eswitch/jr2_switch.c b/drivers/net/mscc_eswitch/jr2_switch.c
index 60d408f1c7..665517775e 100644
--- a/drivers/net/mscc_eswitch/jr2_switch.c
+++ b/drivers/net/mscc_eswitch/jr2_switch.c
@@ -17,20 +17,7 @@
#include <dt-bindings/mscc/jr2_data.h>
#include "mscc_xfer.h"
-
-#define GCB_MIIM_MII_STATUS 0x0
-#define GCB_MIIM_STAT_BUSY BIT(3)
-#define GCB_MIIM_MII_CMD 0x8
-#define GCB_MIIM_MII_CMD_SCAN BIT(0)
-#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
-#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
-#define GCB_MIIM_MII_CMD_SINGLE_SCAN BIT(3)
-#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
-#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
-#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
-#define GCB_MIIM_MII_CMD_VLD BIT(31)
-#define GCB_MIIM_DATA 0xC
-#define GCB_MIIM_DATA_ERROR (0x3 << 16)
+#include "mscc_miim.h"
#define ANA_AC_RAM_CTRL_RAM_INIT 0x94358
#define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET 0x94370
@@ -279,13 +266,6 @@ struct jr2_private {
struct jr2_phy_port_t ports[MAX_PORT];
};
-struct jr2_miim_dev {
- void __iomem *regs;
- phys_addr_t miim_base;
- unsigned long miim_size;
- struct mii_dev *bus;
-};
-
static const unsigned long jr2_regs_qs[] = {
[MSCC_QS_XTR_RD] = 0x8,
[MSCC_QS_XTR_FLUSH] = 0x18,
@@ -294,99 +274,9 @@ static const unsigned long jr2_regs_qs[] = {
[MSCC_QS_INJ_CTRL] = 0x34,
};
-static struct jr2_miim_dev miim[JR2_MIIM_BUS_COUNT];
+static struct mscc_miim_dev miim[JR2_MIIM_BUS_COUNT];
static int miim_count = -1;
-static int mscc_miim_wait_ready(struct jr2_miim_dev *miim)
-{
- unsigned long deadline;
- u32 val;
-
- deadline = timer_get_us() + 250000;
-
- do {
- val = readl(miim->regs + GCB_MIIM_MII_STATUS);
- } while (timer_get_us() <= deadline && (val & GCB_MIIM_STAT_BUSY));
-
- if (val & GCB_MIIM_STAT_BUSY)
- return -ETIMEDOUT;
-
- return 0;
-}
-
-static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
-{
- struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
- u32 val;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
- miim->regs + GCB_MIIM_MII_CMD);
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- val = readl(miim->regs + GCB_MIIM_DATA);
- if (val & GCB_MIIM_DATA_ERROR) {
- ret = -EIO;
- goto out;
- }
-
- ret = val & 0xFFFF;
- out:
- return ret;
-}
-
-static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
- u16 val)
-{
- struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret < 0)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
- GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
-
- out:
- return ret;
-}
-
-static struct mii_dev *jr2_mdiobus_init(phys_addr_t miim_base,
- unsigned long miim_size)
-{
- struct mii_dev *bus;
-
- bus = mdio_alloc();
- if (!bus)
- return NULL;
-
- ++miim_count;
- sprintf(bus->name, "miim-bus%d", miim_count);
-
- miim[miim_count].regs = ioremap(miim_base, miim_size);
- miim[miim_count].miim_base = miim_base;
- miim[miim_count].miim_size = miim_size;
- bus->priv = &miim[miim_count];
- bus->read = mscc_miim_read;
- bus->write = mscc_miim_write;
-
- if (mdio_register(bus))
- return NULL;
-
- miim[miim_count].bus = bus;
- return bus;
-}
-
static void jr2_cpu_capture_setup(struct jr2_private *priv)
{
/* ASM: No preamble and IFH prefix on CPU injected frames */
@@ -973,7 +863,7 @@ static int jr2_probe(struct udevice *dev)
}
/* Initialize miim buses */
- memset(&miim, 0x0, sizeof(struct jr2_miim_dev) * JR2_MIIM_BUS_COUNT);
+ memset(&miim, 0x0, sizeof(struct mscc_miim_dev) * JR2_MIIM_BUS_COUNT);
/* iterate all the ports and find out on which bus they are */
i = 0;
@@ -1008,7 +898,8 @@ static int jr2_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
- jr2_mdiobus_init(addr_base, addr_size);
+ mscc_mdiobus_init(miim, &miim_count, addr_base,
+ addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
diff --git a/drivers/net/mscc_eswitch/luton_switch.c b/drivers/net/mscc_eswitch/luton_switch.c
index 94852b06e7..dffe81d873 100644
--- a/drivers/net/mscc_eswitch/luton_switch.c
+++ b/drivers/net/mscc_eswitch/luton_switch.c
@@ -17,18 +17,7 @@
#include "mscc_xfer.h"
#include "mscc_mac_table.h"
-
-#define GCB_MIIM_MII_STATUS 0x0
-#define GCB_MIIM_STAT_BUSY BIT(3)
-#define GCB_MIIM_MII_CMD 0x8
-#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
-#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
-#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
-#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
-#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
-#define GCB_MIIM_MII_CMD_VLD BIT(31)
-#define GCB_MIIM_DATA 0xC
-#define GCB_MIIM_DATA_ERROR (0x2 << 16)
+#include "mscc_miim.h"
#define ANA_PORT_VLAN_CFG(x) (0x00 + 0x80 * (x))
#define ANA_PORT_VLAN_CFG_AWARE_ENA BIT(20)
@@ -189,13 +178,6 @@ struct luton_private {
struct luton_phy_port_t ports[MAX_PORT];
};
-struct mscc_miim_dev {
- void __iomem *regs;
- phys_addr_t miim_base;
- unsigned long miim_size;
- struct mii_dev *bus;
-};
-
static const unsigned long luton_regs_qs[] = {
[MSCC_QS_XTR_RD] = 0x18,
[MSCC_QS_XTR_FLUSH] = 0x28,
@@ -213,84 +195,6 @@ static const unsigned long luton_regs_ana_table[] = {
static struct mscc_miim_dev miim[LUTON_MIIM_BUS_COUNT];
static int miim_count = -1;
-static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
-{
- return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS,
- GCB_MIIM_STAT_BUSY, false, 250, false);
-}
-
-static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- u32 val;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
- miim->regs + GCB_MIIM_MII_CMD);
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- val = readl(miim->regs + GCB_MIIM_DATA);
- if (val & GCB_MIIM_DATA_ERROR) {
- ret = -EIO;
- goto out;
- }
-
- ret = val & 0xFFFF;
- out:
- return ret;
-}
-
-static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
- u16 val)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret < 0)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
- GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
- out:
- return ret;
-}
-
-static struct mii_dev *serval_mdiobus_init(phys_addr_t miim_base,
- unsigned long miim_size)
-{
- struct mii_dev *bus;
-
- bus = mdio_alloc();
- if (!bus)
- return NULL;
-
- ++miim_count;
- sprintf(bus->name, "miim-bus%d", miim_count);
-
- miim[miim_count].regs = ioremap(miim_base, miim_size);
- miim[miim_count].miim_base = miim_base;
- miim[miim_count].miim_size = miim_size;
- bus->priv = &miim[miim_count];
- bus->read = mscc_miim_read;
- bus->write = mscc_miim_write;
-
- if (mdio_register(bus))
- return NULL;
-
- miim[miim_count].bus = bus;
- return bus;
-}
-
static void luton_stop(struct udevice *dev)
{
struct luton_private *priv = dev_get_priv(dev);
@@ -760,7 +664,8 @@ static int luton_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
- serval_mdiobus_init(addr_base, addr_size);
+ mscc_mdiobus_init(miim, &miim_count, addr_base,
+ addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
diff --git a/drivers/net/mscc_eswitch/mscc_miim.c b/drivers/net/mscc_eswitch/mscc_miim.c
index 419dcc1dd6..d8ee8df47b 100644
--- a/drivers/net/mscc_eswitch/mscc_miim.c
+++ b/drivers/net/mscc_eswitch/mscc_miim.c
@@ -72,3 +72,31 @@ int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
out:
return ret;
}
+
+struct mii_dev *mscc_mdiobus_init(struct mscc_miim_dev *miim, int *miim_count,
+ phys_addr_t miim_base,
+ unsigned long miim_size)
+{
+ struct mii_dev *bus;
+
+ bus = mdio_alloc();
+
+ if (!bus)
+ return NULL;
+
+ *miim_count += 1;
+ sprintf(bus->name, "miim-bus%d", *miim_count);
+
+ miim[*miim_count].regs = ioremap(miim_base, miim_size);
+ miim[*miim_count].miim_base = miim_base;
+ miim[*miim_count].miim_size = miim_size;
+ bus->priv = &miim[*miim_count];
+ bus->read = mscc_miim_read;
+ bus->write = mscc_miim_write;
+
+ if (mdio_register(bus))
+ return NULL;
+
+ miim[*miim_count].bus = bus;
+ return bus;
+}
diff --git a/drivers/net/mscc_eswitch/mscc_miim.h b/drivers/net/mscc_eswitch/mscc_miim.h
index 0e5d5e3c81..feb1f40ae5 100644
--- a/drivers/net/mscc_eswitch/mscc_miim.h
+++ b/drivers/net/mscc_eswitch/mscc_miim.h
@@ -3,10 +3,22 @@
* Copyright (c) 2018 Microsemi Corporation
*/
+#ifndef _MSCC_MIIM_H_
+#define _MSCC_MIIM_H_
+
struct mscc_miim_dev {
void __iomem *regs;
- void __iomem *phy_regs;
+ phys_addr_t miim_base;
+ unsigned long miim_size;
+ struct mii_dev *bus;
};
int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg);
int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg, u16 val);
+
+struct mii_dev *mscc_mdiobus_init(struct mscc_miim_dev *miim, int *miim_count,
+ phys_addr_t miim_base,
+ unsigned long miim_size);
+
+
+#endif /* _MSCC_MIIM_H_ */
diff --git a/drivers/net/mscc_eswitch/ocelot_switch.c b/drivers/net/mscc_eswitch/ocelot_switch.c
index 5c7e6961be..0ba84ab78a 100644
--- a/drivers/net/mscc_eswitch/ocelot_switch.c
+++ b/drivers/net/mscc_eswitch/ocelot_switch.c
@@ -17,6 +17,7 @@
#include "mscc_xfer.h"
#include "mscc_mac_table.h"
+#include "mscc_miim.h"
#define PHY_CFG 0x0
#define PHY_CFG_ENA 0xF
@@ -25,20 +26,6 @@
#define PHY_STAT 0x4
#define PHY_STAT_SUPERVISOR_COMPLETE BIT(0)
-#define GCB_MIIM_MII_STATUS 0x0
-#define GCB_MIIM_STAT_BUSY BIT(3)
-#define GCB_MIIM_MII_CMD 0x8
-#define GCB_MIIM_MII_CMD_SCAN BIT(0)
-#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
-#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
-#define GCB_MIIM_MII_CMD_SINGLE_SCAN BIT(3)
-#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
-#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
-#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
-#define GCB_MIIM_MII_CMD_VLD BIT(31)
-#define GCB_MIIM_DATA 0xC
-#define GCB_MIIM_DATA_ERROR (0x3 << 16)
-
#define ANA_PORT_VLAN_CFG(x) (0x7000 + 0x100 * (x))
#define ANA_PORT_VLAN_CFG_AWARE_ENA BIT(20)
#define ANA_PORT_VLAN_CFG_POP_CNT(x) ((x) << 18)
@@ -173,13 +160,6 @@ struct ocelot_private {
struct ocelot_phy_port_t ports[MAX_PORT];
};
-struct mscc_miim_dev {
- void __iomem *regs;
- phys_addr_t miim_base;
- unsigned long miim_size;
- struct mii_dev *bus;
-};
-
static struct mscc_miim_dev miim[OCELOT_MIIM_BUS_COUNT];
static int miim_count = -1;
@@ -209,85 +189,6 @@ static void mscc_phy_reset(void)
}
}
-static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
-{
- return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS,
- GCB_MIIM_STAT_BUSY, false, 250, false);
-}
-
-static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- u32 val;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
- miim->regs + GCB_MIIM_MII_CMD);
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- val = readl(miim->regs + GCB_MIIM_DATA);
- if (val & GCB_MIIM_DATA_ERROR) {
- ret = -EIO;
- goto out;
- }
-
- ret = val & 0xFFFF;
- out:
- return ret;
-}
-
-static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
- u16 val)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret < 0)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
- GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
- out:
- return ret;
-}
-
-static struct mii_dev *ocelot_mdiobus_init(phys_addr_t miim_base,
- unsigned long miim_size)
-{
- struct mii_dev *bus;
-
- bus = mdio_alloc();
-
- if (!bus)
- return NULL;
-
- ++miim_count;
- sprintf(bus->name, "miim-bus%d", miim_count);
-
- miim[miim_count].regs = ioremap(miim_base, miim_size);
- miim[miim_count].miim_base = miim_base;
- miim[miim_count].miim_size = miim_size;
- bus->priv = &miim[miim_count];
- bus->read = mscc_miim_read;
- bus->write = mscc_miim_write;
-
- if (mdio_register(bus))
- return NULL;
-
- miim[miim_count].bus = bus;
- return bus;
-}
-
__weak void mscc_switch_reset(void)
{
}
@@ -682,7 +583,8 @@ static int ocelot_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
- ocelot_mdiobus_init(addr_base, addr_size);
+ mscc_mdiobus_init(miim, &miim_count, addr_base,
+ addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
diff --git a/drivers/net/mscc_eswitch/serval_switch.c b/drivers/net/mscc_eswitch/serval_switch.c
index 2559f5d0cd..1a21360a96 100644
--- a/drivers/net/mscc_eswitch/serval_switch.c
+++ b/drivers/net/mscc_eswitch/serval_switch.c
@@ -17,18 +17,7 @@
#include "mscc_xfer.h"
#include "mscc_mac_table.h"
-
-#define GCB_MIIM_MII_STATUS 0x0
-#define GCB_MIIM_STAT_BUSY BIT(3)
-#define GCB_MIIM_MII_CMD 0x8
-#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
-#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
-#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
-#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
-#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
-#define GCB_MIIM_MII_CMD_VLD BIT(31)
-#define GCB_MIIM_DATA 0xC
-#define GCB_MIIM_DATA_ERROR (0x2 << 16)
+#include "mscc_miim.h"
#define ANA_PORT_VLAN_CFG(x) (0xc000 + 0x100 * (x))
#define ANA_PORT_VLAN_CFG_AWARE_ENA BIT(20)
@@ -156,13 +145,6 @@ struct serval_private {
struct serval_phy_port_t ports[MAX_PORT];
};
-struct mscc_miim_dev {
- void __iomem *regs;
- phys_addr_t miim_base;
- unsigned long miim_size;
- struct mii_dev *bus;
-};
-
static const unsigned long serval_regs_qs[] = {
[MSCC_QS_XTR_RD] = 0x8,
[MSCC_QS_XTR_FLUSH] = 0x18,
@@ -180,84 +162,6 @@ static const unsigned long serval_regs_ana_table[] = {
static struct mscc_miim_dev miim[SERVAL_MIIM_BUS_COUNT];
static int miim_count = -1;
-static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
-{
- return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS,
- GCB_MIIM_STAT_BUSY, false, 250, false);
-}
-
-static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- u32 val;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
- miim->regs + GCB_MIIM_MII_CMD);
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- val = readl(miim->regs + GCB_MIIM_DATA);
- if (val & GCB_MIIM_DATA_ERROR) {
- ret = -EIO;
- goto out;
- }
-
- ret = val & 0xFFFF;
- out:
- return ret;
-}
-
-static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
- u16 val)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret < 0)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
- GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
- out:
- return ret;
-}
-
-static struct mii_dev *serval_mdiobus_init(phys_addr_t miim_base,
- unsigned long miim_size)
-{
- struct mii_dev *bus;
-
- bus = mdio_alloc();
- if (!bus)
- return NULL;
-
- ++miim_count;
- sprintf(bus->name, "miim-bus%d", miim_count);
-
- miim[miim_count].regs = ioremap(miim_base, miim_size);
- miim[miim_count].miim_base = miim_base;
- miim[miim_count].miim_size = miim_size;
- bus->priv = &miim[miim_count];
- bus->read = mscc_miim_read;
- bus->write = mscc_miim_write;
-
- if (mdio_register(bus))
- return NULL;
-
- miim[miim_count].bus = bus;
- return bus;
-}
-
static void serval_cpu_capture_setup(struct serval_private *priv)
{
int i;
@@ -356,8 +260,6 @@ static void serdes_write(void __iomem *base, u32 addr)
do {
data = readl(base + HSIO_MCB_SERDES1G_CFG);
} while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT);
-
- mdelay(100);
}
static void serdes1g_setup(void __iomem *base, uint32_t addr,
@@ -636,7 +538,8 @@ static int serval_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
- serval_mdiobus_init(addr_base, addr_size);
+ mscc_mdiobus_init(miim, &miim_count, addr_base,
+ addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
diff --git a/drivers/net/mscc_eswitch/servalt_switch.c b/drivers/net/mscc_eswitch/servalt_switch.c
index 995c62309d..d20ec49d56 100644
--- a/drivers/net/mscc_eswitch/servalt_switch.c
+++ b/drivers/net/mscc_eswitch/servalt_switch.c
@@ -16,18 +16,7 @@
#include <wait_bit.h>
#include "mscc_xfer.h"
-
-#define GCB_MIIM_MII_STATUS 0x0
-#define GCB_MIIM_STAT_BUSY BIT(3)
-#define GCB_MIIM_MII_CMD 0x8
-#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
-#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
-#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
-#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
-#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
-#define GCB_MIIM_MII_CMD_VLD BIT(31)
-#define GCB_MIIM_DATA 0xC
-#define GCB_MIIM_DATA_ERROR (0x3 << 16)
+#include "mscc_miim.h"
#define PHY_CFG 0x0
#define PHY_CFG_ENA 0x3
@@ -134,13 +123,6 @@ struct servalt_private {
struct servalt_phy_port_t ports[MAX_PORT];
};
-struct mscc_miim_dev {
- void __iomem *regs;
- phys_addr_t miim_base;
- unsigned long miim_size;
- struct mii_dev *bus;
-};
-
static const unsigned long servalt_regs_qs[] = {
[MSCC_QS_XTR_RD] = 0x8,
[MSCC_QS_XTR_FLUSH] = 0x18,
@@ -152,85 +134,6 @@ static const unsigned long servalt_regs_qs[] = {
static struct mscc_miim_dev miim[SERVALT_MIIM_BUS_COUNT];
static int miim_count = -1;
-static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
-{
- return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS,
- GCB_MIIM_STAT_BUSY, false, 250, false);
-}
-
-static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- u32 val;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
- miim->regs + GCB_MIIM_MII_CMD);
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- val = readl(miim->regs + GCB_MIIM_DATA);
- if (val & GCB_MIIM_DATA_ERROR) {
- ret = -EIO;
- goto out;
- }
-
- ret = val & 0xFFFF;
-out:
- return ret;
-}
-
-static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
- u16 val)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret < 0)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
- GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
-
-out:
- return ret;
-}
-
-static struct mii_dev *servalt_mdiobus_init(phys_addr_t miim_base,
- unsigned long miim_size)
-{
- struct mii_dev *bus;
-
- bus = mdio_alloc();
- if (!bus)
- return NULL;
-
- ++miim_count;
- sprintf(bus->name, "miim-bus%d", miim_count);
-
- miim[miim_count].regs = ioremap(miim_base, miim_size);
- miim[miim_count].miim_base = miim_base;
- miim[miim_count].miim_size = miim_size;
- bus->priv = &miim[miim_count];
- bus->read = mscc_miim_read;
- bus->write = mscc_miim_write;
-
- if (mdio_register(bus))
- return NULL;
-
- miim[miim_count].bus = bus;
- return bus;
-}
-
static void mscc_phy_reset(void)
{
writel(0, BASE_DEVCPU_GCB + GCB_PHY_CFG + PHY_CFG);
@@ -564,7 +467,8 @@ static int servalt_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
- servalt_mdiobus_init(addr_base, addr_size);
+ mscc_mdiobus_init(miim, &miim_count, addr_base,
+ addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c
index a04a118f90..ec81dab3f6 100644
--- a/drivers/net/phy/cortina.c
+++ b/drivers/net/phy/cortina.c
@@ -176,8 +176,13 @@ void cs4340_upload_firmware(struct phy_device *phydev)
printf("MMC read: dev # %u, block # %u, count %u ...\n",
dev, blk, cnt);
mmc_init(mmc);
+#ifdef CONFIG_BLK
+ (void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt,
+ addr);
+#else
(void)mmc->block_dev.block_read(&mmc->block_dev, blk, cnt,
addr);
+#endif
}
#endif
diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c
index 25f1332ca9..7509936465 100644
--- a/drivers/net/phy/ti.c
+++ b/drivers/net/phy/ti.c
@@ -103,7 +103,7 @@ struct dp83867_private {
int io_impedance;
bool rxctrl_strap_quirk;
int port_mirroring;
- int clk_output_sel;
+ unsigned int clk_output_sel;
};
static int dp83867_config_port_mirroring(struct phy_device *phydev)
@@ -136,17 +136,11 @@ static int dp83867_of_init(struct phy_device *phydev)
ofnode node;
u16 val;
- /* Optional configuration */
-
node = phy_get_ofnode(phydev);
if (!ofnode_valid(node))
return -EINVAL;
- /*
- * Keep the default value if ti,clk-output-sel is not set
- * or to high
- */
-
+ /* Keep the default value if ti,clk-output-sel is not set */
dp83867->clk_output_sel =
ofnode_read_u32_default(node, "ti,clk-output-sel",
DP83867_CLK_O_SEL_REF_CLK);
@@ -162,14 +156,14 @@ static int dp83867_of_init(struct phy_device *phydev)
dp83867->rxctrl_strap_quirk = true;
dp83867->rx_id_delay = ofnode_read_u32_default(node,
"ti,rx-internal-delay",
- -1);
+ DEFAULT_RX_ID_DELAY);
dp83867->tx_id_delay = ofnode_read_u32_default(node,
"ti,tx-internal-delay",
- -1);
+ DEFAULT_TX_ID_DELAY);
dp83867->fifo_depth = ofnode_read_u32_default(node, "ti,fifo-depth",
- -1);
+ DEFAULT_FIFO_DEPTH);
if (ofnode_read_bool(node, "enet-phy-lane-swap"))
dp83867->port_mirroring = DP83867_PORT_MIRRORING_EN;
diff --git a/drivers/net/ti/Kconfig b/drivers/net/ti/Kconfig
index 82bc9f5d03..ecf642de10 100644
--- a/drivers/net/ti/Kconfig
+++ b/drivers/net/ti/Kconfig
@@ -18,3 +18,11 @@ config DRIVER_TI_KEYSTONE_NET
bool "TI Keystone 2 Ethernet"
help
This driver supports the TI Keystone 2 Ethernet subsystem
+
+config TI_AM65_CPSW_NUSS
+ bool "TI K3 AM65x MCU CPSW Nuss Ethernet controller driver"
+ depends on ARCH_K3
+ select PHYLIB
+ help
+ This driver supports TI K3 MCU CPSW Nuss Ethernet controller
+ in Texas Instruments K3 AM65x SoCs.
diff --git a/drivers/net/ti/Makefile b/drivers/net/ti/Makefile
index ee3e4eb5d6..8d3808bb4b 100644
--- a/drivers/net/ti/Makefile
+++ b/drivers/net/ti/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o cpsw-common.o cpsw_mdio.o
obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o cpsw_mdio.o
+obj-$(CONFIG_TI_AM65_CPSW_NUSS) += am65-cpsw-nuss.o cpsw_mdio.o
diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c
new file mode 100644
index 0000000000..e11fbdeed3
--- /dev/null
+++ b/drivers/net/ti/am65-cpsw-nuss.c
@@ -0,0 +1,792 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Texas Instruments K3 AM65 Ethernet Switch SubSystem Driver
+ *
+ * Copyright (C) 2019, Texas Instruments, Incorporated
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <dma-uclass.h>
+#include <dm/of_access.h>
+#include <miiphy.h>
+#include <net.h>
+#include <phy.h>
+#include <power-domain.h>
+#include <linux/soc/ti/ti-udma.h>
+
+#include "cpsw_mdio.h"
+
+#define AM65_CPSW_CPSWNU_MAX_PORTS 2
+
+#define AM65_CPSW_SS_BASE 0x0
+#define AM65_CPSW_SGMII_BASE 0x100
+#define AM65_CPSW_MDIO_BASE 0xf00
+#define AM65_CPSW_XGMII_BASE 0x2100
+#define AM65_CPSW_CPSW_NU_BASE 0x20000
+#define AM65_CPSW_CPSW_NU_ALE_BASE 0x1e000
+
+#define AM65_CPSW_CPSW_NU_PORTS_OFFSET 0x1000
+#define AM65_CPSW_CPSW_NU_PORT_MACSL_OFFSET 0x330
+
+#define AM65_CPSW_MDIO_BUS_FREQ_DEF 1000000
+
+#define AM65_CPSW_CTL_REG 0x4
+#define AM65_CPSW_STAT_PORT_EN_REG 0x14
+#define AM65_CPSW_PTYPE_REG 0x18
+
+#define AM65_CPSW_CTL_REG_P0_ENABLE BIT(2)
+#define AM65_CPSW_CTL_REG_P0_TX_CRC_REMOVE BIT(13)
+#define AM65_CPSW_CTL_REG_P0_RX_PAD BIT(14)
+
+#define AM65_CPSW_P0_FLOW_ID_REG 0x8
+#define AM65_CPSW_PN_RX_MAXLEN_REG 0x24
+#define AM65_CPSW_PN_REG_SA_L 0x308
+#define AM65_CPSW_PN_REG_SA_H 0x30c
+
+#define AM65_CPSW_ALE_CTL_REG 0x8
+#define AM65_CPSW_ALE_CTL_REG_ENABLE BIT(31)
+#define AM65_CPSW_ALE_CTL_REG_RESET_TBL BIT(30)
+#define AM65_CPSW_ALE_CTL_REG_BYPASS BIT(4)
+#define AM65_CPSW_ALE_PN_CTL_REG(x) (0x40 + (x) * 4)
+#define AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD 0x3
+#define AM65_CPSW_ALE_PN_CTL_REG_MAC_ONLY BIT(11)
+
+#define AM65_CPSW_MACSL_CTL_REG 0x0
+#define AM65_CPSW_MACSL_CTL_REG_IFCTL_A BIT(15)
+#define AM65_CPSW_MACSL_CTL_REG_GIG BIT(7)
+#define AM65_CPSW_MACSL_CTL_REG_GMII_EN BIT(5)
+#define AM65_CPSW_MACSL_CTL_REG_LOOPBACK BIT(1)
+#define AM65_CPSW_MACSL_CTL_REG_FULL_DUPLEX BIT(0)
+#define AM65_CPSW_MACSL_RESET_REG 0x8
+#define AM65_CPSW_MACSL_RESET_REG_RESET BIT(0)
+#define AM65_CPSW_MACSL_STATUS_REG 0x4
+#define AM65_CPSW_MACSL_RESET_REG_PN_IDLE BIT(31)
+#define AM65_CPSW_MACSL_RESET_REG_PN_E_IDLE BIT(30)
+#define AM65_CPSW_MACSL_RESET_REG_PN_P_IDLE BIT(29)
+#define AM65_CPSW_MACSL_RESET_REG_PN_TX_IDLE BIT(28)
+#define AM65_CPSW_MACSL_RESET_REG_IDLE_MASK \
+ (AM65_CPSW_MACSL_RESET_REG_PN_IDLE | \
+ AM65_CPSW_MACSL_RESET_REG_PN_E_IDLE | \
+ AM65_CPSW_MACSL_RESET_REG_PN_P_IDLE | \
+ AM65_CPSW_MACSL_RESET_REG_PN_TX_IDLE)
+
+#define AM65_CPSW_CPPI_PKT_TYPE 0x7
+
+struct am65_cpsw_port {
+ fdt_addr_t port_base;
+ fdt_addr_t macsl_base;
+ bool disabled;
+ u32 mac_control;
+};
+
+struct am65_cpsw_common {
+ struct udevice *dev;
+ fdt_addr_t ss_base;
+ fdt_addr_t cpsw_base;
+ fdt_addr_t mdio_base;
+ fdt_addr_t ale_base;
+ fdt_addr_t gmii_sel;
+ fdt_addr_t mac_efuse;
+
+ struct clk fclk;
+ struct power_domain pwrdmn;
+
+ u32 port_num;
+ struct am65_cpsw_port ports[AM65_CPSW_CPSWNU_MAX_PORTS];
+ u32 rflow_id_base;
+
+ struct mii_dev *bus;
+ u32 bus_freq;
+
+ struct dma dma_tx;
+ struct dma dma_rx;
+ u32 rx_next;
+ u32 rx_pend;
+ bool started;
+};
+
+struct am65_cpsw_priv {
+ struct udevice *dev;
+ struct am65_cpsw_common *cpsw_common;
+ u32 port_id;
+
+ struct phy_device *phydev;
+ bool has_phy;
+ ofnode phy_node;
+ u32 phy_addr;
+};
+
+#ifdef PKTSIZE_ALIGN
+#define UDMA_RX_BUF_SIZE PKTSIZE_ALIGN
+#else
+#define UDMA_RX_BUF_SIZE ALIGN(1522, ARCH_DMA_MINALIGN)
+#endif
+
+#ifdef PKTBUFSRX
+#define UDMA_RX_DESC_NUM PKTBUFSRX
+#else
+#define UDMA_RX_DESC_NUM 4
+#endif
+
+#define mac_hi(mac) (((mac)[0] << 0) | ((mac)[1] << 8) | \
+ ((mac)[2] << 16) | ((mac)[3] << 24))
+#define mac_lo(mac) (((mac)[4] << 0) | ((mac)[5] << 8))
+
+static void am65_cpsw_set_sl_mac(struct am65_cpsw_port *slave,
+ unsigned char *addr)
+{
+ writel(mac_hi(addr),
+ slave->port_base + AM65_CPSW_PN_REG_SA_H);
+ writel(mac_lo(addr),
+ slave->port_base + AM65_CPSW_PN_REG_SA_L);
+}
+
+int am65_cpsw_macsl_reset(struct am65_cpsw_port *slave)
+{
+ u32 i = 100;
+
+ /* Set the soft reset bit */
+ writel(AM65_CPSW_MACSL_RESET_REG_RESET,
+ slave->macsl_base + AM65_CPSW_MACSL_RESET_REG);
+
+ while ((readl(slave->macsl_base + AM65_CPSW_MACSL_RESET_REG) &
+ AM65_CPSW_MACSL_RESET_REG_RESET) && i--)
+ cpu_relax();
+
+ /* Timeout on the reset */
+ return i;
+}
+
+static int am65_cpsw_macsl_wait_for_idle(struct am65_cpsw_port *slave)
+{
+ u32 i = 100;
+
+ while ((readl(slave->macsl_base + AM65_CPSW_MACSL_STATUS_REG) &
+ AM65_CPSW_MACSL_RESET_REG_IDLE_MASK) && i--)
+ cpu_relax();
+
+ return i;
+}
+
+static int am65_cpsw_update_link(struct am65_cpsw_priv *priv)
+{
+ struct am65_cpsw_common *common = priv->cpsw_common;
+ struct am65_cpsw_port *port = &common->ports[priv->port_id];
+ struct phy_device *phy = priv->phydev;
+ u32 mac_control = 0;
+
+ if (phy->link) { /* link up */
+ mac_control = /*AM65_CPSW_MACSL_CTL_REG_LOOPBACK |*/
+ AM65_CPSW_MACSL_CTL_REG_GMII_EN;
+ if (phy->speed == 1000)
+ mac_control |= AM65_CPSW_MACSL_CTL_REG_GIG;
+ if (phy->duplex == DUPLEX_FULL)
+ mac_control |= AM65_CPSW_MACSL_CTL_REG_FULL_DUPLEX;
+ if (phy->speed == 100)
+ mac_control |= AM65_CPSW_MACSL_CTL_REG_IFCTL_A;
+ }
+
+ if (mac_control == port->mac_control)
+ goto out;
+
+ if (mac_control) {
+ printf("link up on port %d, speed %d, %s duplex\n",
+ priv->port_id, phy->speed,
+ (phy->duplex == DUPLEX_FULL) ? "full" : "half");
+ } else {
+ printf("link down on port %d\n", priv->port_id);
+ }
+
+ writel(mac_control, port->macsl_base + AM65_CPSW_MACSL_CTL_REG);
+ port->mac_control = mac_control;
+
+out:
+ return phy->link;
+}
+
+#define AM65_GMII_SEL_MODE_MII 0
+#define AM65_GMII_SEL_MODE_RMII 1
+#define AM65_GMII_SEL_MODE_RGMII 2
+
+#define AM65_GMII_SEL_RGMII_IDMODE BIT(4)
+
+static void am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv,
+ phy_interface_t phy_mode, int slave)
+{
+ struct am65_cpsw_common *common = priv->cpsw_common;
+ u32 reg;
+ u32 mode = 0;
+ bool rgmii_id = false;
+
+ reg = readl(common->gmii_sel);
+
+ dev_dbg(common->dev, "old gmii_sel: %08x\n", reg);
+
+ switch (phy_mode) {
+ case PHY_INTERFACE_MODE_RMII:
+ mode = AM65_GMII_SEL_MODE_RMII;
+ break;
+
+ case PHY_INTERFACE_MODE_RGMII:
+ mode = AM65_GMII_SEL_MODE_RGMII;
+ break;
+
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ mode = AM65_GMII_SEL_MODE_RGMII;
+ rgmii_id = true;
+ break;
+
+ default:
+ dev_warn(common->dev,
+ "Unsupported PHY mode: %u. Defaulting to MII.\n",
+ phy_mode);
+ /* fallthrough */
+ case PHY_INTERFACE_MODE_MII:
+ mode = AM65_GMII_SEL_MODE_MII;
+ break;
+ };
+
+ if (rgmii_id)
+ mode |= AM65_GMII_SEL_RGMII_IDMODE;
+
+ reg = mode;
+ dev_dbg(common->dev, "gmii_sel PHY mode: %u, new gmii_sel: %08x\n",
+ phy_mode, reg);
+ writel(reg, common->gmii_sel);
+
+ reg = readl(common->gmii_sel);
+ if (reg != mode)
+ dev_err(common->dev,
+ "gmii_sel PHY mode NOT SET!: requested: %08x, gmii_sel: %08x\n",
+ mode, reg);
+}
+
+static int am65_cpsw_start(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *common = priv->cpsw_common;
+ struct am65_cpsw_port *port = &common->ports[priv->port_id];
+ struct am65_cpsw_port *port0 = &common->ports[0];
+ int ret, i;
+
+ ret = power_domain_on(&common->pwrdmn);
+ if (ret) {
+ dev_err(dev, "power_domain_on() failed %d\n", ret);
+ goto out;
+ }
+
+ ret = clk_enable(&common->fclk);
+ if (ret) {
+ dev_err(dev, "clk enabled failed %d\n", ret);
+ goto err_off_pwrdm;
+ }
+
+ common->rx_next = 0;
+ common->rx_pend = 0;
+ ret = dma_get_by_name(common->dev, "tx0", &common->dma_tx);
+ if (ret) {
+ dev_err(dev, "TX dma get failed %d\n", ret);
+ goto err_off_clk;
+ }
+ ret = dma_get_by_name(common->dev, "rx", &common->dma_rx);
+ if (ret) {
+ dev_err(dev, "RX dma get failed %d\n", ret);
+ goto err_free_tx;
+ }
+
+ for (i = 0; i < UDMA_RX_DESC_NUM; i++) {
+ ret = dma_prepare_rcv_buf(&common->dma_rx,
+ net_rx_packets[i],
+ UDMA_RX_BUF_SIZE);
+ if (ret) {
+ dev_err(dev, "RX dma add buf failed %d\n", ret);
+ goto err_free_tx;
+ }
+ }
+
+ ret = dma_enable(&common->dma_tx);
+ if (ret) {
+ dev_err(dev, "TX dma_enable failed %d\n", ret);
+ goto err_free_rx;
+ }
+ ret = dma_enable(&common->dma_rx);
+ if (ret) {
+ dev_err(dev, "RX dma_enable failed %d\n", ret);
+ goto err_dis_tx;
+ }
+
+ /* Control register */
+ writel(AM65_CPSW_CTL_REG_P0_ENABLE |
+ AM65_CPSW_CTL_REG_P0_TX_CRC_REMOVE |
+ AM65_CPSW_CTL_REG_P0_RX_PAD,
+ common->cpsw_base + AM65_CPSW_CTL_REG);
+
+ /* disable priority elevation */
+ writel(0, common->cpsw_base + AM65_CPSW_PTYPE_REG);
+
+ /* enable statistics */
+ writel(BIT(0) | BIT(priv->port_id),
+ common->cpsw_base + AM65_CPSW_STAT_PORT_EN_REG);
+
+ /* Port 0 length register */
+ writel(PKTSIZE_ALIGN, port0->port_base + AM65_CPSW_PN_RX_MAXLEN_REG);
+
+ /* set base flow_id */
+ writel(common->rflow_id_base,
+ port0->port_base + AM65_CPSW_P0_FLOW_ID_REG);
+
+ /* Reset and enable the ALE */
+ writel(AM65_CPSW_ALE_CTL_REG_ENABLE | AM65_CPSW_ALE_CTL_REG_RESET_TBL |
+ AM65_CPSW_ALE_CTL_REG_BYPASS,
+ common->ale_base + AM65_CPSW_ALE_CTL_REG);
+
+ /* port 0 put into forward mode */
+ writel(AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD,
+ common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(0));
+
+ /* PORT x configuration */
+
+ /* Port x Max length register */
+ writel(PKTSIZE_ALIGN, port->port_base + AM65_CPSW_PN_RX_MAXLEN_REG);
+
+ /* Port x set mac */
+ am65_cpsw_set_sl_mac(port, pdata->enetaddr);
+
+ /* Port x ALE: mac_only, Forwarding */
+ writel(AM65_CPSW_ALE_PN_CTL_REG_MAC_ONLY |
+ AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD,
+ common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(priv->port_id));
+
+ port->mac_control = 0;
+ if (!am65_cpsw_macsl_reset(port)) {
+ dev_err(dev, "mac_sl reset failed\n");
+ ret = -EFAULT;
+ goto err_dis_rx;
+ }
+
+ ret = phy_startup(priv->phydev);
+ if (ret) {
+ dev_err(dev, "phy_startup failed\n");
+ goto err_dis_rx;
+ }
+
+ ret = am65_cpsw_update_link(priv);
+ if (!ret) {
+ ret = -ENODEV;
+ goto err_phy_shutdown;
+ }
+
+ common->started = true;
+
+ return 0;
+
+err_phy_shutdown:
+ phy_shutdown(priv->phydev);
+err_dis_rx:
+ /* disable ports */
+ writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(priv->port_id));
+ writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(0));
+ if (!am65_cpsw_macsl_wait_for_idle(port))
+ dev_err(dev, "mac_sl idle timeout\n");
+ writel(0, port->macsl_base + AM65_CPSW_MACSL_CTL_REG);
+ writel(0, common->ale_base + AM65_CPSW_ALE_CTL_REG);
+ writel(0, common->cpsw_base + AM65_CPSW_CTL_REG);
+
+ dma_disable(&common->dma_rx);
+err_dis_tx:
+ dma_disable(&common->dma_tx);
+err_free_rx:
+ dma_free(&common->dma_rx);
+err_free_tx:
+ dma_free(&common->dma_tx);
+err_off_clk:
+ clk_disable(&common->fclk);
+err_off_pwrdm:
+ power_domain_off(&common->pwrdmn);
+out:
+ dev_err(dev, "%s end error\n", __func__);
+
+ return ret;
+}
+
+static int am65_cpsw_send(struct udevice *dev, void *packet, int length)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *common = priv->cpsw_common;
+ struct ti_udma_drv_packet_data packet_data;
+ int ret;
+
+ packet_data.pkt_type = AM65_CPSW_CPPI_PKT_TYPE;
+ packet_data.dest_tag = priv->port_id;
+ ret = dma_send(&common->dma_tx, packet, length, &packet_data);
+ if (ret) {
+ dev_err(dev, "TX dma_send failed %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int am65_cpsw_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *common = priv->cpsw_common;
+
+ /* try to receive a new packet */
+ return dma_receive(&common->dma_rx, (void **)packetp, NULL);
+}
+
+static int am65_cpsw_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *common = priv->cpsw_common;
+ int ret;
+
+ if (length > 0) {
+ u32 pkt = common->rx_next % UDMA_RX_DESC_NUM;
+
+ ret = dma_prepare_rcv_buf(&common->dma_rx,
+ net_rx_packets[pkt],
+ UDMA_RX_BUF_SIZE);
+ if (ret)
+ dev_err(dev, "RX dma free_pkt failed %d\n", ret);
+ common->rx_next++;
+ }
+
+ return 0;
+}
+
+static void am65_cpsw_stop(struct udevice *dev)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *common = priv->cpsw_common;
+ struct am65_cpsw_port *port = &common->ports[priv->port_id];
+
+ if (!common->started)
+ return;
+
+ phy_shutdown(priv->phydev);
+
+ writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(priv->port_id));
+ writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(0));
+ if (!am65_cpsw_macsl_wait_for_idle(port))
+ dev_err(dev, "mac_sl idle timeout\n");
+ writel(0, port->macsl_base + AM65_CPSW_MACSL_CTL_REG);
+ writel(0, common->ale_base + AM65_CPSW_ALE_CTL_REG);
+ writel(0, common->cpsw_base + AM65_CPSW_CTL_REG);
+
+ dma_disable(&common->dma_tx);
+ dma_free(&common->dma_tx);
+
+ dma_disable(&common->dma_rx);
+ dma_free(&common->dma_rx);
+
+ common->started = false;
+}
+
+static int am65_cpsw_read_rom_hwaddr(struct udevice *dev)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *common = priv->cpsw_common;
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ u32 mac_hi, mac_lo;
+
+ if (common->mac_efuse == FDT_ADDR_T_NONE)
+ return -1;
+
+ mac_lo = readl(common->mac_efuse);
+ mac_hi = readl(common->mac_efuse + 4);
+ pdata->enetaddr[0] = (mac_hi >> 8) & 0xff;
+ pdata->enetaddr[1] = mac_hi & 0xff;
+ pdata->enetaddr[2] = (mac_lo >> 24) & 0xff;
+ pdata->enetaddr[3] = (mac_lo >> 16) & 0xff;
+ pdata->enetaddr[4] = (mac_lo >> 8) & 0xff;
+ pdata->enetaddr[5] = mac_lo & 0xff;
+
+ return 0;
+}
+
+static const struct eth_ops am65_cpsw_ops = {
+ .start = am65_cpsw_start,
+ .send = am65_cpsw_send,
+ .recv = am65_cpsw_recv,
+ .free_pkt = am65_cpsw_free_pkt,
+ .stop = am65_cpsw_stop,
+ .read_rom_hwaddr = am65_cpsw_read_rom_hwaddr,
+};
+
+static int am65_cpsw_mdio_init(struct udevice *dev)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *cpsw_common = priv->cpsw_common;
+
+ if (!priv->has_phy || cpsw_common->bus)
+ return 0;
+
+ cpsw_common->bus = cpsw_mdio_init(dev->name,
+ cpsw_common->mdio_base,
+ cpsw_common->bus_freq,
+ clk_get_rate(&cpsw_common->fclk));
+ if (!cpsw_common->bus)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int am65_cpsw_phy_init(struct udevice *dev)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *cpsw_common = priv->cpsw_common;
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct phy_device *phydev;
+ u32 supported = PHY_GBIT_FEATURES;
+ int ret;
+
+ phydev = phy_connect(cpsw_common->bus,
+ priv->phy_addr,
+ priv->dev,
+ pdata->phy_interface);
+
+ if (!phydev) {
+ dev_err(dev, "phy_connect() failed\n");
+ return -ENODEV;
+ }
+
+ phydev->supported &= supported;
+ if (pdata->max_speed) {
+ ret = phy_set_supported(phydev, pdata->max_speed);
+ if (ret)
+ return ret;
+ }
+ phydev->advertising = phydev->supported;
+
+ if (ofnode_valid(priv->phy_node))
+ phydev->node = priv->phy_node;
+
+ priv->phydev = phydev;
+ ret = phy_config(phydev);
+ if (ret < 0)
+ pr_err("phy_config() failed: %d", ret);
+
+ return ret;
+}
+
+static int am65_cpsw_ofdata_parse_phy(struct udevice *dev, ofnode port_np)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct ofnode_phandle_args out_args;
+ const char *phy_mode;
+ int ret = 0;
+
+ phy_mode = ofnode_read_string(port_np, "phy-mode");
+ if (phy_mode) {
+ pdata->phy_interface =
+ phy_get_interface_by_name(phy_mode);
+ if (pdata->phy_interface == -1) {
+ dev_err(dev, "Invalid PHY mode '%s', port %u\n",
+ phy_mode, priv->port_id);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ ofnode_read_u32(port_np, "max-speed", (u32 *)&pdata->max_speed);
+ if (pdata->max_speed)
+ dev_err(dev, "Port %u speed froced to %uMbit\n",
+ priv->port_id, pdata->max_speed);
+
+ priv->has_phy = true;
+ ret = ofnode_parse_phandle_with_args(port_np, "phy-handle",
+ NULL, 0, 0, &out_args);
+ if (ret) {
+ dev_err(dev, "can't parse phy-handle port %u (%d)\n",
+ priv->port_id, ret);
+ priv->has_phy = false;
+ ret = 0;
+ }
+
+ priv->phy_node = out_args.node;
+ if (priv->has_phy) {
+ ret = ofnode_read_u32(priv->phy_node, "reg", &priv->phy_addr);
+ if (ret) {
+ dev_err(dev, "failed to get phy_addr port %u (%d)\n",
+ priv->port_id, ret);
+ goto out;
+ }
+ }
+
+out:
+ return ret;
+}
+
+static int am65_cpsw_probe_cpsw(struct udevice *dev)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct am65_cpsw_common *cpsw_common;
+ ofnode ports_np, node;
+ int ret, i;
+
+ priv->dev = dev;
+
+ cpsw_common = calloc(1, sizeof(*priv->cpsw_common));
+ if (!cpsw_common)
+ return -ENOMEM;
+ priv->cpsw_common = cpsw_common;
+
+ cpsw_common->dev = dev;
+ cpsw_common->ss_base = dev_read_addr(dev);
+ if (cpsw_common->ss_base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+ cpsw_common->mac_efuse = devfdt_get_addr_name(dev, "mac_efuse");
+ /* no err check - optional */
+
+ ret = power_domain_get_by_index(dev, &cpsw_common->pwrdmn, 0);
+ if (ret) {
+ dev_err(dev, "failed to get pwrdmn: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_get_by_name(dev, "fck", &cpsw_common->fclk);
+ if (ret) {
+ power_domain_free(&cpsw_common->pwrdmn);
+ dev_err(dev, "failed to get clock %d\n", ret);
+ return ret;
+ }
+
+ cpsw_common->cpsw_base = cpsw_common->ss_base + AM65_CPSW_CPSW_NU_BASE;
+ cpsw_common->ale_base = cpsw_common->cpsw_base +
+ AM65_CPSW_CPSW_NU_ALE_BASE;
+ cpsw_common->mdio_base = cpsw_common->ss_base + AM65_CPSW_MDIO_BASE;
+
+ cpsw_common->rflow_id_base = 0;
+ cpsw_common->rflow_id_base =
+ dev_read_u32_default(dev, "ti,rx-flow-id-base",
+ cpsw_common->rflow_id_base);
+
+ ports_np = dev_read_subnode(dev, "ports");
+ if (!ofnode_valid(ports_np)) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ ofnode_for_each_subnode(node, ports_np) {
+ const char *node_name;
+ u32 port_id;
+ bool disabled;
+
+ node_name = ofnode_get_name(node);
+
+ disabled = !ofnode_is_available(node);
+
+ ret = ofnode_read_u32(node, "reg", &port_id);
+ if (ret) {
+ dev_err(dev, "%s: failed to get port_id (%d)\n",
+ node_name, ret);
+ goto out;
+ }
+
+ if (port_id >= AM65_CPSW_CPSWNU_MAX_PORTS) {
+ dev_err(dev, "%s: invalid port_id (%d)\n",
+ node_name, port_id);
+ ret = -EINVAL;
+ goto out;
+ }
+ cpsw_common->port_num++;
+
+ if (!port_id)
+ continue;
+
+ priv->port_id = port_id;
+ cpsw_common->ports[port_id].disabled = disabled;
+ if (disabled)
+ continue;
+
+ ret = am65_cpsw_ofdata_parse_phy(dev, node);
+ if (ret)
+ goto out;
+ }
+
+ for (i = 0; i < AM65_CPSW_CPSWNU_MAX_PORTS; i++) {
+ struct am65_cpsw_port *port = &cpsw_common->ports[i];
+
+ port->port_base = cpsw_common->cpsw_base +
+ AM65_CPSW_CPSW_NU_PORTS_OFFSET +
+ (i * AM65_CPSW_CPSW_NU_PORTS_OFFSET);
+ port->macsl_base = port->port_base +
+ AM65_CPSW_CPSW_NU_PORT_MACSL_OFFSET;
+ }
+
+ node = dev_read_subnode(dev, "cpsw-phy-sel");
+ if (!ofnode_valid(node)) {
+ dev_err(dev, "can't find cpsw-phy-sel\n");
+ ret = -ENOENT;
+ goto out;
+ }
+
+ cpsw_common->gmii_sel = ofnode_get_addr(node);
+ if (cpsw_common->gmii_sel == FDT_ADDR_T_NONE) {
+ dev_err(dev, "failed to get gmii_sel base\n");
+ goto out;
+ }
+
+ node = dev_read_subnode(dev, "mdio");
+ if (!ofnode_valid(node)) {
+ dev_err(dev, "can't find mdio\n");
+ ret = -ENOENT;
+ goto out;
+ }
+
+ cpsw_common->bus_freq =
+ dev_read_u32_default(dev, "bus_freq",
+ AM65_CPSW_MDIO_BUS_FREQ_DEF);
+
+ am65_cpsw_gmii_sel_k3(priv, pdata->phy_interface, priv->port_id);
+
+ ret = am65_cpsw_mdio_init(dev);
+ if (ret)
+ goto out;
+
+ ret = am65_cpsw_phy_init(dev);
+ if (ret)
+ goto out;
+
+ dev_info(dev, "K3 CPSW: nuss_ver: 0x%08X cpsw_ver: 0x%08X ale_ver: 0x%08X Ports:%u rflow_id_base:%u mdio_freq:%u\n",
+ readl(cpsw_common->ss_base),
+ readl(cpsw_common->cpsw_base),
+ readl(cpsw_common->ale_base),
+ cpsw_common->port_num,
+ cpsw_common->rflow_id_base,
+ cpsw_common->bus_freq);
+
+out:
+ clk_free(&cpsw_common->fclk);
+ power_domain_free(&cpsw_common->pwrdmn);
+ return ret;
+}
+
+static const struct udevice_id am65_cpsw_nuss_ids[] = {
+ { .compatible = "ti,am654-cpsw-nuss" },
+ { }
+};
+
+U_BOOT_DRIVER(am65_cpsw_nuss_slave) = {
+ .name = "am65_cpsw_nuss_slave",
+ .id = UCLASS_ETH,
+ .of_match = am65_cpsw_nuss_ids,
+ .probe = am65_cpsw_probe_cpsw,
+ .ops = &am65_cpsw_ops,
+ .priv_auto_alloc_size = sizeof(struct am65_cpsw_priv),
+ .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
diff --git a/drivers/net/ti/cpsw_mdio.c b/drivers/net/ti/cpsw_mdio.c
index 70f547e6d7..6e8f652011 100644
--- a/drivers/net/ti/cpsw_mdio.c
+++ b/drivers/net/ti/cpsw_mdio.c
@@ -125,7 +125,7 @@ u32 cpsw_mdio_get_alive(struct mii_dev *bus)
return val & GENMASK(15, 0);
}
-struct mii_dev *cpsw_mdio_init(const char *name, u32 mdio_base,
+struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
u32 bus_freq, int fck_freq)
{
struct cpsw_mdio *cpsw_mdio;
@@ -144,7 +144,7 @@ struct mii_dev *cpsw_mdio_init(const char *name, u32 mdio_base,
return NULL;
}
- cpsw_mdio->regs = (struct cpsw_mdio_regs *)mdio_base;
+ cpsw_mdio->regs = (struct cpsw_mdio_regs *)(uintptr_t)mdio_base;
if (!bus_freq || !fck_freq)
cpsw_mdio->div = CPSW_MDIO_DIV_DEF;
diff --git a/drivers/net/ti/cpsw_mdio.h b/drivers/net/ti/cpsw_mdio.h
index 4a76d4e5c5..dbf4a2dcac 100644
--- a/drivers/net/ti/cpsw_mdio.h
+++ b/drivers/net/ti/cpsw_mdio.h
@@ -10,7 +10,7 @@
struct cpsw_mdio;
-struct mii_dev *cpsw_mdio_init(const char *name, u32 mdio_base,
+struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
u32 bus_freq, int fck_freq);
void cpsw_mdio_free(struct mii_dev *bus);
u32 cpsw_mdio_get_alive(struct mii_dev *bus);