summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/e1000.c15
-rw-r--r--drivers/net/e1000.h2
-rw-r--r--drivers/net/fec_mxc.c2
-rw-r--r--drivers/net/gmac_rockchip.c1
-rw-r--r--drivers/net/hifemac.c229
-rw-r--r--drivers/net/hifemac_mdio.c11
-rw-r--r--drivers/net/macb.c186
-rw-r--r--drivers/net/mtk_eth.c57
-rw-r--r--drivers/net/mtk_eth.h9
-rw-r--r--drivers/net/phy/broadcom.c17
-rw-r--r--drivers/net/phy/ethernet_id.c37
-rw-r--r--drivers/net/phy/ncsi.c17
-rw-r--r--drivers/net/phy/phy.c62
-rw-r--r--drivers/net/ti/Kconfig8
-rw-r--r--drivers/net/ti/Makefile3
-rw-r--r--drivers/net/ti/am65-cpsw-nuss.c190
-rw-r--r--drivers/net/ti/cpsw_mdio.c198
-rw-r--r--drivers/net/ti/cpsw_mdio.h2
18 files changed, 672 insertions, 374 deletions
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c
index 84a2a7cf904..4e7ba666770 100644
--- a/drivers/net/e1000.c
+++ b/drivers/net/e1000.c
@@ -116,6 +116,8 @@ static struct pci_device_id e1000_supported[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_SERDES) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_SERDES_FLASHLESS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_1000BASEKX) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I225_UNPROGRAMMED) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I225_IT) },
{}
};
@@ -1575,6 +1577,8 @@ e1000_set_mac_type(struct e1000_hw *hw)
case PCI_DEVICE_ID_INTEL_I210_SERDES:
case PCI_DEVICE_ID_INTEL_I210_SERDES_FLASHLESS:
case PCI_DEVICE_ID_INTEL_I210_1000BASEKX:
+ case PCI_DEVICE_ID_INTEL_I225_UNPROGRAMMED:
+ case PCI_DEVICE_ID_INTEL_I225_IT:
hw->mac_type = e1000_igb;
break;
default:
@@ -3258,7 +3262,8 @@ e1000_setup_copper_link(struct e1000_hw *hw)
if (ret_val)
return ret_val;
} else if (hw->phy_type == e1000_phy_m88 ||
- hw->phy_type == e1000_phy_igb) {
+ hw->phy_type == e1000_phy_igb ||
+ hw->phy_type == e1000_phy_igc) {
ret_val = e1000_copper_link_mgp_setup(hw);
if (ret_val)
return ret_val;
@@ -4531,6 +4536,8 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
case e1000_igb:
while (timeout) {
if (hw->mac_type == e1000_igb) {
+ if (hw->phy_type == e1000_phy_igc)
+ break;
if (E1000_READ_REG(hw, I210_EEMNGCTL) & cfg_mask)
break;
} else {
@@ -4769,6 +4776,7 @@ e1000_phy_reset(struct e1000_hw *hw)
case e1000_phy_igp_3:
case e1000_phy_ife:
case e1000_phy_igb:
+ case e1000_phy_igc:
ret_val = e1000_phy_hw_reset(hw);
if (ret_val)
return ret_val;
@@ -4834,6 +4842,9 @@ static int e1000_set_phy_type (struct e1000_hw *hw)
case I210_I_PHY_ID:
hw->phy_type = e1000_phy_igb;
break;
+ case I225_I_PHY_ID:
+ hw->phy_type = e1000_phy_igc;
+ break;
/* Fall Through */
default:
/* Should never have loaded on this device */
@@ -4941,6 +4952,8 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
case e1000_igb:
if (hw->phy_id == I210_I_PHY_ID)
match = true;
+ if (hw->phy_id == I225_I_PHY_ID)
+ match = true;
break;
default:
DEBUGOUT("Invalid MAC type %d\n", hw->mac_type);
diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h
index f788394da87..e1311126a3f 100644
--- a/drivers/net/e1000.h
+++ b/drivers/net/e1000.h
@@ -212,6 +212,7 @@ typedef enum {
e1000_phy_igp_3,
e1000_phy_ife,
e1000_phy_igb,
+ e1000_phy_igc,
e1000_phy_bm,
e1000_phy_undefined = 0xFF
} e1000_phy_type;
@@ -2420,6 +2421,7 @@ struct e1000_hw {
#define BME1000_E_PHY_ID 0x01410CB0
#define I210_I_PHY_ID 0x01410C00
+#define I225_I_PHY_ID 0x67C9DCC0
/* Miscellaneous PHY bit definitions. */
#define PHY_PREAMBLE 0xFFFFFFFF
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index ac937676f9c..90af18f80a8 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -1310,7 +1310,7 @@ static int fecmxc_probe(struct udevice *dev)
#ifdef CONFIG_DM_REGULATOR
if (priv->phy_supply) {
- ret = regulator_set_enable(priv->phy_supply, true);
+ ret = regulator_set_enable_if_allowed(priv->phy_supply, true);
if (ret) {
printf("%s: Error enabling phy supply\n", dev->name);
return ret;
diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c
index 04008d2b198..c1bae3f68bd 100644
--- a/drivers/net/gmac_rockchip.c
+++ b/drivers/net/gmac_rockchip.c
@@ -13,7 +13,6 @@
#include <phy.h>
#include <syscon.h>
#include <asm/global_data.h>
-#include <asm/io.h>
#include <asm/arch-rockchip/periph.h>
#include <asm/arch-rockchip/clock.h>
#include <asm/arch-rockchip/hardware.h>
diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c
index b61a29e6360..90cc247b3b6 100644
--- a/drivers/net/hifemac.c
+++ b/drivers/net/hifemac.c
@@ -15,6 +15,9 @@
#include <wait_bit.h>
#include <asm/io.h>
#include <dm/device_compat.h>
+#include <dm/lists.h>
+#include <linux/bitfield.h>
+#include <linux/ethtool.h>
#include <linux/delay.h>
#include <linux/kernel.h>
@@ -124,6 +127,57 @@ struct hisi_femac_priv {
u32 link_status;
};
+struct hisi_femac_stat_entry {
+ const char *name;
+ u32 offset;
+ u32 mask;
+};
+
+/* please refer to the datasheet for the description of these entries */
+static const struct hisi_femac_stat_entry hisi_femac_stats_table[] = {
+ { "rxsof_cnt", 0x584, GENMASK(31, 28) },
+ { "rxeof_cnt", 0x584, GENMASK(27, 24) },
+ { "rxcrcok_cnt", 0x584, GENMASK(23, 20) },
+ { "rxcrcbad_cnt", 0x584, GENMASK(19, 16) },
+ { "txsof_cnt", 0x584, GENMASK(15, 12) },
+ { "txeof_cnt", 0x584, GENMASK(11, 8) },
+ { "txcrcok_cnt", 0x584, GENMASK(7, 4) },
+ { "txcrcbad_cnt", 0x584, GENMASK(3, 0) },
+ { "pkts_cpu", 0x5a0, GENMASK(15, 0) },
+ { "addr_cpu", 0x5a4, GENMASK(15, 0) },
+ { "pkts_port", 0x5a8, GENMASK(15, 0) },
+ { "pkts_cpu2tx", 0x5ac, GENMASK(15, 0) },
+ { "rxdvrise", 0x600, GENMASK(31, 0) },
+ { "ifinoctets", 0x604, GENMASK(31, 0) },
+ { "octets_rx", 0x608, GENMASK(31, 0) },
+ { "local_mac_match", 0x60c, GENMASK(31, 0) },
+ { "pkts", 0x610, GENMASK(31, 0) },
+ { "broadcastpkts", 0x614, GENMASK(31, 0) },
+ { "multicastpkts", 0x618, GENMASK(31, 0) },
+ { "ifinucastpkts", 0x61c, GENMASK(31, 0) },
+ { "ifinerrors", 0x620, GENMASK(31, 0) },
+ { "crcerr", 0x624, GENMASK(31, 0) },
+ { "abnormalsizepkts", 0x628, GENMASK(31, 0) },
+ { "dot3alignmenterr", 0x62c, GENMASK(31, 0) },
+ { "dot3pause", 0x630, GENMASK(31, 0) },
+ { "dropevents", 0x634, GENMASK(31, 0) },
+ { "flux_frame_cnt", 0x638, GENMASK(31, 0) },
+ { "flux_drop_cnt", 0x63c, GENMASK(31, 0) },
+ { "mac_not2cpu_pkts", 0x64c, GENMASK(31, 0) },
+ { "pkts_tx", 0x780, GENMASK(31, 0) },
+ { "broadcastpkts_tx", 0x784, GENMASK(31, 0) },
+ { "multicastpkts_tx", 0x788, GENMASK(31, 0) },
+ { "ifoutucastpkts_tx", 0x78c, GENMASK(31, 0) },
+ { "octets_tx", 0x790, GENMASK(31, 0) },
+ { "dot3pause", 0x794, GENMASK(31, 0) },
+ { "retry_times_tx", 0x798, GENMASK(31, 0) },
+ { "collisions", 0x79c, GENMASK(31, 0) },
+ { "dot3latecol", 0x7a0, GENMASK(31, 0) },
+ { "dot3colok", 0x7a4, GENMASK(31, 0) },
+ { "dot3excessivecol", 0x7a8, GENMASK(31, 0) },
+ { "dot3colcnt", 0x7ac, GENMASK(31, 0) },
+};
+
static void hisi_femac_irq_enable(struct hisi_femac_priv *priv, int irqs)
{
u32 val;
@@ -245,8 +299,10 @@ static int hisi_femac_start(struct udevice *dev)
hisi_femac_rx_refill(priv);
ret = phy_startup(priv->phy);
- if (ret)
- return log_msg_ret("Failed to startup phy", ret);
+ if (ret) {
+ dev_err(dev, "Failed to startup phy: %d\n", ret);
+ return log_msg_ret("phy", ret);
+ }
if (!priv->phy->link) {
debug("%s: link down\n", __func__);
@@ -281,8 +337,10 @@ static int hisi_femac_send(struct udevice *dev, void *packet, int length)
// wait until FIFO is empty
ret = wait_for_bit_le32(priv->glb_base + GLB_IRQ_RAW, IRQ_INT_TX_PER_PACKET, true, 50, false);
- if (ret == -ETIMEDOUT)
- return log_msg_ret("FIFO timeout", ret);
+ if (ret == -ETIMEDOUT) {
+ dev_err(dev, "FIFO timeout\n");
+ return log_msg_ret("net", ret);
+ }
return 0;
}
@@ -329,10 +387,43 @@ static void hisi_femac_stop(struct udevice *dev)
writel(SOFT_RESET_ALL, priv->glb_base + GLB_SOFT_RESET);
}
-int hisi_femac_of_to_plat(struct udevice *dev)
+static int hisi_femac_get_sset_count(struct udevice *dev)
+{
+ return ARRAY_SIZE(hisi_femac_stats_table);
+}
+
+static void hisi_femac_get_strings(struct udevice *dev, u8 *data)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hisi_femac_stats_table); i++)
+ strcpy(data + i * ETH_GSTRING_LEN, hisi_femac_stats_table[i].name);
+}
+
+/* Non-constant mask variant of FIELD_GET/FIELD_PREP */
+#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
+
+static void hisi_femac_get_stats(struct udevice *dev, u64 *data)
+{
+ int i;
+ u32 mask, reg;
+ struct hisi_femac_priv *priv = dev_get_priv(dev);
+ void __iomem *port_base = priv->port_base;
+
+ for (i = 0; i < ARRAY_SIZE(hisi_femac_stats_table); i++) {
+ mask = hisi_femac_stats_table[i].mask;
+ reg = readl(port_base + hisi_femac_stats_table[i].offset);
+
+ data[i] = field_get(mask, reg);
+ }
+}
+
+static int hisi_femac_of_to_plat(struct udevice *dev)
{
int ret, i;
struct hisi_femac_priv *priv = dev_get_priv(dev);
+ ofnode mdio_node;
+ bool mdio_registered = false;
static const char * const clk_strs[] = {
[CLK_MAC] = "mac",
[CLK_BUS] = "bus",
@@ -340,40 +431,75 @@ int hisi_femac_of_to_plat(struct udevice *dev)
};
priv->port_base = dev_remap_addr_name(dev, "port");
- if (IS_ERR(priv->port_base))
- return log_msg_ret("Failed to remap port address space", PTR_ERR(priv->port_base));
+ if (!priv->port_base) {
+ dev_err(dev, "Failed to remap port address space\n");
+ return log_msg_ret("net", -EINVAL);
+ }
priv->glb_base = dev_remap_addr_name(dev, "glb");
- if (IS_ERR(priv->glb_base))
- return log_msg_ret("Failed to remap global address space", PTR_ERR(priv->glb_base));
+ if (IS_ERR(priv->glb_base)) {
+ dev_err(dev, "Failed to remap global address space\n");
+ return log_msg_ret("net", -EINVAL);
+ }
for (i = 0; i < ARRAY_SIZE(clk_strs); i++) {
priv->clks[i] = devm_clk_get(dev, clk_strs[i]);
if (IS_ERR(priv->clks[i])) {
dev_err(dev, "Error getting clock %s\n", clk_strs[i]);
- return log_msg_ret("Failed to get clocks", PTR_ERR(priv->clks[i]));
+ return log_msg_ret("clk", PTR_ERR(priv->clks[i]));
}
}
priv->mac_rst = devm_reset_control_get(dev, "mac");
- if (IS_ERR(priv->mac_rst))
- return log_msg_ret("Failed to get MAC reset", PTR_ERR(priv->mac_rst));
+ if (IS_ERR(priv->mac_rst)) {
+ dev_err(dev, "Failed to get MAC reset %ld\n", PTR_ERR(priv->mac_rst));
+ return log_msg_ret("rst", PTR_ERR(priv->mac_rst));
+ }
priv->phy_rst = devm_reset_control_get(dev, "phy");
- if (IS_ERR(priv->phy_rst))
- return log_msg_ret("Failed to get PHY reset", PTR_ERR(priv->phy_rst));
+ if (IS_ERR(priv->phy_rst)) {
+ dev_err(dev, "Failed to get PHY reset %ld\n", PTR_ERR(priv->phy_rst));
+ return log_msg_ret("rst", PTR_ERR(priv->phy_rst));
+ }
ret = dev_read_u32_array(dev,
PHY_RESET_DELAYS_PROPERTY,
priv->phy_reset_delays,
DELAYS_NUM);
- if (ret < 0)
- return log_msg_ret("Failed to get PHY reset delays", ret);
+ if (ret < 0) {
+ dev_err(dev, "Failed to get PHY reset delays %d\n", ret);
+ return log_msg_ret("rst", ret);
+ }
priv->mac_reset_delay = dev_read_u32_default(dev,
MAC_RESET_DELAY_PROPERTY,
MAC_RESET_ASSERT_PERIOD);
+ /* Create MDIO bus */
+ ofnode_for_each_subnode(mdio_node, dev_ofnode(dev)) {
+ const char *subnode_name = ofnode_get_name(mdio_node);
+ struct udevice *mdiodev;
+
+ // Skip subnodes not starting with "mdio"
+ if (strncmp(subnode_name, "mdio", 4))
+ continue;
+
+ ret = device_bind_driver_to_node(dev, "hisi-femac-mdio",
+ subnode_name, mdio_node, &mdiodev);
+ if (ret) {
+ dev_err(dev, "Failed to register MDIO bus device %d\n", ret);
+ return log_msg_ret("net", ret);
+ }
+
+ mdio_registered = true;
+ break;
+ }
+
+ if (!mdio_registered) {
+ dev_err(dev, "No MDIO subnode is found!\n");
+ return log_msg_ret("mdio", -ENODATA);
+ }
+
return 0;
}
@@ -385,37 +511,49 @@ static int hisi_femac_phy_reset(struct hisi_femac_priv *priv)
// Disable MAC clk before phy reset
ret = clk_disable(priv->clks[CLK_MAC]);
- if (ret < 0)
- return log_msg_ret("Failed to disable MAC clock", ret);
+ if (ret < 0) {
+ pr_err("%s: Failed to disable MAC clock %d\n", __func__, ret);
+ return log_msg_ret("clk", ret);
+ }
ret = clk_disable(priv->clks[CLK_BUS]);
- if (ret < 0)
- return log_msg_ret("Failed to disable bus clock", ret);
+ if (ret < 0) {
+ pr_err("%s: Failed to disable bus clock %d\n", __func__, ret);
+ return log_msg_ret("clk", ret);
+ }
udelay(delays[PRE_DELAY]);
ret = reset_assert(rst);
- if (ret < 0)
- return log_msg_ret("Failed to assert reset", ret);
+ if (ret < 0) {
+ pr_err("%s: Failed to assert reset %d\n", __func__, ret);
+ return log_msg_ret("rst", ret);
+ }
udelay(delays[PULSE]);
ret = reset_deassert(rst);
- if (ret < 0)
- return log_msg_ret("Failed to deassert reset", ret);
+ if (ret < 0) {
+ pr_err("%s: Failed to deassert reset %d\n", __func__, ret);
+ return log_msg_ret("rst", ret);
+ }
udelay(delays[POST_DELAY]);
ret = clk_enable(priv->clks[CLK_MAC]);
- if (ret < 0)
- return log_msg_ret("Failed to enable MAC clock", ret);
+ if (ret < 0) {
+ pr_err("%s: Failed to enable MAC clock %d\n", __func__, ret);
+ return log_msg_ret("clk", ret);
+ }
ret = clk_enable(priv->clks[CLK_BUS]);
- if (ret < 0)
- return log_msg_ret("Failed to enable MAC bus clock", ret);
+ if (ret < 0) {
+ pr_err("%s: Failed to enable MAC bus clock %d\n", __func__, ret);
+ return log_msg_ret("clk", ret);
+ }
return 0;
}
-int hisi_femac_probe(struct udevice *dev)
+static int hisi_femac_probe(struct udevice *dev)
{
struct hisi_femac_priv *priv = dev_get_priv(dev);
int ret, i;
@@ -423,30 +561,40 @@ int hisi_femac_probe(struct udevice *dev)
// Enable clocks
for (i = 0; i < CLK_NUM; i++) {
ret = clk_prepare_enable(priv->clks[i]);
- if (ret < 0)
- return log_msg_ret("Failed to enable clks", ret);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable clk %d: %d\n", i, ret);
+ return log_msg_ret("clk", ret);
+ }
}
// Reset MAC
ret = reset_assert(priv->mac_rst);
- if (ret < 0)
- return log_msg_ret("Failed to assert MAC reset", ret);
+ if (ret < 0) {
+ dev_err(dev, "Failed to assert MAC reset: %d\n", ret);
+ return log_msg_ret("net", ret);
+ }
udelay(priv->mac_reset_delay);
ret = reset_deassert(priv->mac_rst);
- if (ret < 0)
- return log_msg_ret("Failed to deassert MAC reset", ret);
+ if (ret < 0) {
+ dev_err(dev, "Failed to deassert MAC reset: %d\n", ret);
+ return log_msg_ret("net", ret);
+ }
// Reset PHY
ret = hisi_femac_phy_reset(priv);
- if (ret < 0)
- return log_msg_ret("Failed to reset phy", ret);
+ if (ret < 0) {
+ dev_err(dev, "Failed to reset PHY: %d\n", ret);
+ return log_msg_ret("net", ret);
+ }
// Connect to PHY
priv->phy = dm_eth_phy_connect(dev);
- if (!priv->phy)
- return log_msg_ret("Failed to connect to phy", -EINVAL);
+ if (!priv->phy) {
+ dev_err(dev, "Failed to connect to phy\n");
+ return log_msg_ret("phy", -EINVAL);
+ }
hisi_femac_port_init(priv);
return 0;
@@ -459,6 +607,9 @@ static const struct eth_ops hisi_femac_ops = {
.free_pkt = hisi_femac_free_pkt,
.stop = hisi_femac_stop,
.write_hwaddr = hisi_femac_set_hw_mac_addr,
+ .get_sset_count = hisi_femac_get_sset_count,
+ .get_strings = hisi_femac_get_strings,
+ .get_stats = hisi_femac_get_stats,
};
static const struct udevice_id hisi_femac_ids[] = {
diff --git a/drivers/net/hifemac_mdio.c b/drivers/net/hifemac_mdio.c
index 343c5f3a38a..0b59d060917 100644
--- a/drivers/net/hifemac_mdio.c
+++ b/drivers/net/hifemac_mdio.c
@@ -8,6 +8,7 @@
#include <dm.h>
#include <clk.h>
#include <miiphy.h>
+#include <dm/device_compat.h>
#include <linux/io.h>
#include <linux/iopoll.h>
@@ -74,7 +75,8 @@ static int hisi_femac_mdio_of_to_plat(struct udevice *dev)
data->membase = dev_remap_addr(dev);
if (IS_ERR(data->membase)) {
ret = PTR_ERR(data->membase);
- return log_msg_ret("Failed to remap base addr", ret);
+ dev_err(dev, "Failed to remap base addr %d\n", ret);
+ return log_msg_ret("mdio", ret);
}
// clk is optional
@@ -89,8 +91,10 @@ static int hisi_femac_mdio_probe(struct udevice *dev)
int ret;
ret = clk_prepare_enable(data->clk);
- if (ret)
- return log_msg_ret("Failed to enable clk", ret);
+ if (ret) {
+ dev_err(dev, "Failed to enable clock: %d\n", ret);
+ return log_msg_ret("clk", ret);
+ }
return 0;
}
@@ -112,5 +116,6 @@ U_BOOT_DRIVER(hisi_femac_mdio_driver) = {
.of_to_plat = hisi_femac_mdio_of_to_plat,
.probe = hisi_femac_mdio_probe,
.ops = &hisi_femac_mdio_ops,
+ .plat_auto = sizeof(struct mdio_perdev_priv),
.priv_auto = sizeof(struct hisi_femac_mdio_data),
};
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index bfc48dac079..bca014c3cbb 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -128,6 +128,8 @@ struct macb_device {
unsigned long dummy_desc_dma;
const struct device *dev;
+ unsigned int duplex;
+ unsigned int speed;
unsigned short phy_addr;
struct mii_dev *bus;
#ifdef CONFIG_PHYLIB
@@ -178,6 +180,12 @@ static int gem_is_gigabit_capable(struct macb_device *macb)
return macb_is_gem(macb) && !cpu_is_sama5d2() && !cpu_is_sama5d4();
}
+/* Is the port a fixed link */
+static int macb_port_is_fixed_link(struct macb_device *macb)
+{
+ return macb->phy_addr > PHY_MAX_ADDR;
+}
+
static void macb_mdio_write(struct macb_device *macb, u8 phy_adr, u8 reg,
u16 value)
{
@@ -666,97 +674,109 @@ static int macb_phy_init(struct udevice *dev, const char *name)
int i;
arch_get_mdio_control(name);
- /* Auto-detect phy_addr */
- ret = macb_phy_find(macb, name);
- if (ret)
- return ret;
+ /* If port is not fixed -> setup PHY */
+ if (!macb_port_is_fixed_link(macb)) {
+ /* Auto-detect phy_addr */
+ ret = macb_phy_find(macb, name);
+ if (ret)
+ return ret;
- /* Check if the PHY is up to snuff... */
- phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
- if (phy_id == 0xffff) {
- printf("%s: No PHY present\n", name);
- return -ENODEV;
- }
+ /* Check if the PHY is up to snuff... */
+ phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
+ if (phy_id == 0xffff) {
+ printf("%s: No PHY present\n", name);
+ return -ENODEV;
+ }
#ifdef CONFIG_PHYLIB
- macb->phydev = phy_connect(macb->bus, macb->phy_addr, dev,
- macb->phy_interface);
- if (!macb->phydev) {
- printf("phy_connect failed\n");
- return -ENODEV;
- }
+ macb->phydev = phy_connect(macb->bus, macb->phy_addr, dev,
+ macb->phy_interface);
+ if (!macb->phydev) {
+ printf("phy_connect failed\n");
+ return -ENODEV;
+ }
- phy_config(macb->phydev);
+ phy_config(macb->phydev);
#endif
- status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
- if (!(status & BMSR_LSTATUS)) {
- /* Try to re-negotiate if we don't have link already. */
- macb_phy_reset(macb, name);
-
- for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
- status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
- if (status & BMSR_LSTATUS) {
- /*
- * Delay a bit after the link is established,
- * so that the next xfer does not fail
- */
- mdelay(10);
- break;
+ status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
+ if (!(status & BMSR_LSTATUS)) {
+ /* Try to re-negotiate if we don't have link already. */
+ macb_phy_reset(macb, name);
+
+ for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
+ status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
+ if (status & BMSR_LSTATUS) {
+ /*
+ * Delay a bit after the link is established,
+ * so that the next xfer does not fail
+ */
+ mdelay(10);
+ break;
+ }
+ udelay(100);
}
- udelay(100);
}
- }
- if (!(status & BMSR_LSTATUS)) {
- printf("%s: link down (status: 0x%04x)\n",
- name, status);
- return -ENETDOWN;
- }
+ if (!(status & BMSR_LSTATUS)) {
+ printf("%s: link down (status: 0x%04x)\n",
+ name, status);
+ return -ENETDOWN;
+ }
- /* First check for GMAC and that it is GiB capable */
- if (gem_is_gigabit_capable(macb)) {
- lpa = macb_mdio_read(macb, macb->phy_addr, MII_STAT1000);
+ /* First check for GMAC and that it is GiB capable */
+ if (gem_is_gigabit_capable(macb)) {
+ lpa = macb_mdio_read(macb, macb->phy_addr, MII_STAT1000);
- if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL |
- LPA_1000XHALF)) {
- duplex = ((lpa & (LPA_1000FULL | LPA_1000XFULL)) ?
- 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,
- duplex ? "full" : "half",
- lpa);
+ printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n",
+ name,
+ duplex ? "full" : "half",
+ lpa);
- ncfgr = macb_readl(macb, NCFGR);
- ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
- ncfgr |= GEM_BIT(GBE);
+ ncfgr = macb_readl(macb, NCFGR);
+ ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
+ ncfgr |= GEM_BIT(GBE);
- if (duplex)
- ncfgr |= MACB_BIT(FD);
+ if (duplex)
+ ncfgr |= MACB_BIT(FD);
- macb_writel(macb, NCFGR, ncfgr);
+ macb_writel(macb, NCFGR, ncfgr);
- ret = macb_linkspd_cb(dev, _1000BASET);
- if (ret)
- return ret;
+ ret = macb_linkspd_cb(dev, _1000BASET);
+ if (ret)
+ return ret;
- return 0;
+ return 0;
+ }
}
- }
- /* fall back for EMAC checking */
- adv = macb_mdio_read(macb, macb->phy_addr, MII_ADVERTISE);
- lpa = macb_mdio_read(macb, macb->phy_addr, MII_LPA);
- media = mii_nway_result(lpa & adv);
- speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
- ? 1 : 0);
- duplex = (media & ADVERTISE_FULL) ? 1 : 0;
- printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
- name,
- speed ? "100" : "10",
- duplex ? "full" : "half",
- lpa);
+ /* fall back for EMAC checking */
+ adv = macb_mdio_read(macb, macb->phy_addr, MII_ADVERTISE);
+ lpa = macb_mdio_read(macb, macb->phy_addr, MII_LPA);
+ media = mii_nway_result(lpa & adv);
+ speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
+ ? 1 : 0);
+ duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+ printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
+ name,
+ speed ? "100" : "10",
+ duplex ? "full" : "half",
+ lpa);
+ } else {
+ /* if macb port is a fixed link */
+ /* TODO : manage gigabit capable processors */
+ speed = macb->speed;
+ duplex = macb->duplex;
+ printf("%s: link up, %sMbps %s-duplex\n",
+ name,
+ speed ? "100" : "10",
+ duplex ? "full" : "half");
+ }
ncfgr = macb_readl(macb, NCFGR);
ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE));
@@ -1276,6 +1296,28 @@ int __weak macb_late_eth_of_to_plat(struct udevice *dev)
static int macb_eth_of_to_plat(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_plat(dev);
+ struct macb_device *macb = dev_get_priv(dev);
+ void *blob = (void *)gd->fdt_blob;
+ int node = dev_of_offset(dev);
+ int fl_node, speed_fdt;
+
+ /* fetch 'fixed-link' property */
+ fl_node = fdt_subnode_offset(blob, node, "fixed-link");
+ if (fl_node >= 0) {
+ /* set phy_addr to invalid value for fixed link */
+ macb->phy_addr = PHY_MAX_ADDR + 1;
+ macb->duplex = fdtdec_get_bool(blob, fl_node, "full-duplex");
+ speed_fdt = fdtdec_get_int(blob, fl_node, "speed", 0);
+ if (speed_fdt == 100) {
+ macb->speed = 1;
+ } else if (speed_fdt == 10) {
+ macb->speed = 0;
+ } else {
+ printf("%s: The given speed %d of ethernet in the DT is not supported\n",
+ __func__, speed_fdt);
+ return -EINVAL;
+ }
+ }
pdata->iobase = (uintptr_t)dev_remap_addr(dev);
if (!pdata->iobase)
diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c
index 3cfce058451..75e7bcf83b7 100644
--- a/drivers/net/mtk_eth.c
+++ b/drivers/net/mtk_eth.c
@@ -137,6 +137,7 @@ struct mtk_eth_priv {
int force_mode;
int speed;
int duplex;
+ int mdc;
bool pn_swap;
struct phy_device *phydev;
@@ -1245,7 +1246,8 @@ static int mtk_phy_start(struct mtk_eth_priv *priv)
}
if (!priv->force_mode) {
- if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII)
+ if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII ||
+ priv->phy_interface == PHY_INTERFACE_MODE_XGMII)
mtk_xphy_link_adjust(priv);
else
mtk_phy_link_adjust(priv);
@@ -1515,7 +1517,7 @@ static void mtk_mac_init(struct mtk_eth_priv *priv)
static void mtk_xmac_init(struct mtk_eth_priv *priv)
{
- u32 sts;
+ u32 force_link = 0;
switch (priv->phy_interface) {
case PHY_INTERFACE_MODE_USXGMII:
@@ -1530,15 +1532,19 @@ static void mtk_xmac_init(struct mtk_eth_priv *priv)
SYSCFG0_GE_MODE_M << SYSCFG0_GE_MODE_S(priv->gmac_id),
0);
- if (priv->gmac_id == 1) {
+ if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII &&
+ priv->gmac_id == 1) {
mtk_infra_rmw(priv, TOPMISC_NETSYS_PCS_MUX,
NETSYS_PCS_MUX_MASK, MUX_G2_USXGMII_SEL);
- } else if (priv->gmac_id == 2) {
- sts = mtk_gmac_read(priv, XGMAC_STS(priv->gmac_id));
- sts |= XGMAC_FORCE_LINK;
- mtk_gmac_write(priv, XGMAC_STS(priv->gmac_id), sts);
}
+ if (priv->phy_interface == PHY_INTERFACE_MODE_XGMII ||
+ priv->gmac_id == 2)
+ force_link = XGMAC_FORCE_LINK(priv->gmac_id);
+
+ mtk_gmac_rmw(priv, XGMAC_STS(priv->gmac_id),
+ XGMAC_FORCE_LINK(priv->gmac_id), force_link);
+
/* Force GMAC link down */
mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), FORCE_MODE);
}
@@ -1607,6 +1613,26 @@ static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
mtk_pdma_write(priv, PDMA_RST_IDX_REG, RST_DTX_IDX0 | RST_DRX_IDX0);
}
+static void mtk_eth_mdc_init(struct mtk_eth_priv *priv)
+{
+ u32 divider;
+
+ if (priv->mdc == 0)
+ return;
+
+ divider = min_t(u32, DIV_ROUND_UP(MDC_MAX_FREQ, priv->mdc), MDC_MAX_DIVIDER);
+
+ /* Configure MDC turbo mode */
+ if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3))
+ mtk_gmac_rmw(priv, GMAC_MAC_MISC_REG, 0, MISC_MDC_TURBO);
+ else
+ mtk_gmac_rmw(priv, GMAC_PPSC_REG, 0, MISC_MDC_TURBO);
+
+ /* Configure MDC divider */
+ mtk_gmac_rmw(priv, GMAC_PPSC_REG, PHY_MDC_CFG,
+ FIELD_PREP(PHY_MDC_CFG, divider));
+}
+
static int mtk_eth_start(struct udevice *dev)
{
struct mtk_eth_priv *priv = dev_get_priv(dev);
@@ -1803,8 +1829,12 @@ static int mtk_eth_probe(struct udevice *dev)
noncached_alloc(priv->soc->rxd_size * NUM_RX_DESC,
ARCH_DMA_MINALIGN);
+ /* Set MDC divider */
+ mtk_eth_mdc_init(priv);
+
/* Set MAC mode */
- if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII)
+ if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII ||
+ priv->phy_interface == PHY_INTERFACE_MODE_XGMII)
mtk_xmac_init(priv);
else
mtk_mac_init(priv);
@@ -1881,6 +1911,17 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
priv->gmac_id = dev_read_u32_default(dev, "mediatek,gmac-id", 0);
+ priv->mdc = 0;
+ subnode = ofnode_find_subnode(dev_ofnode(dev), "mdio");
+ if (ofnode_valid(subnode)) {
+ priv->mdc = ofnode_read_u32_default(subnode, "clock-frequency", 2500000);
+ if (priv->mdc > MDC_MAX_FREQ ||
+ priv->mdc < MDC_MAX_FREQ / MDC_MAX_DIVIDER) {
+ printf("error: MDIO clock frequency out of range\n");
+ return -EINVAL;
+ }
+ }
+
/* Interface mode is required */
pdata->phy_interface = dev_read_phy_mode(dev);
priv->phy_interface = pdata->phy_interface;
diff --git a/drivers/net/mtk_eth.h b/drivers/net/mtk_eth.h
index 491cac56a81..fd31c782c7f 100644
--- a/drivers/net/mtk_eth.h
+++ b/drivers/net/mtk_eth.h
@@ -180,6 +180,12 @@ enum mkt_eth_capabilities {
/* GMAC Registers */
+#define GMAC_PPSC_REG 0x0000
+#define PHY_MDC_CFG GENMASK(29, 24)
+#define MDC_TURBO BIT(20)
+#define MDC_MAX_FREQ 25000000
+#define MDC_MAX_DIVIDER 63
+
#define GMAC_PIAC_REG 0x0004
#define PHY_ACS_ST BIT(31)
#define MDIO_REG_ADDR_S 25
@@ -197,6 +203,7 @@ enum mkt_eth_capabilities {
#define P1_XGMAC_FORCE_LINK BIT(15)
#define GMAC_MAC_MISC_REG 0x0010
+#define MISC_MDC_TURBO BIT(4)
#define GMAC_GSW_CFG_REG 0x0080
#define GSWTX_IPG_M 0xF0000
@@ -261,7 +268,7 @@ enum mkt_eth_capabilities {
/* XGMAC Status Registers */
#define XGMAC_STS(x) (((x) == 2) ? 0x001C : 0x000C)
-#define XGMAC_FORCE_LINK BIT(15)
+#define XGMAC_FORCE_LINK(x) (((x) == 1) ? BIT(31) : BIT(15))
/* XGMAC Registers */
#define XGMAC_PORT_MCR(x) (0x2000 + (((x) - 1) * 0x1000))
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 82e3bbef7dd..ecccb7c3b54 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -42,6 +42,12 @@
#define BCM54810_SHD_CLK_CTL 0x3
#define BCM54810_SHD_CLK_CTL_GTXCLK_EN BIT(9)
+#define BCM54XX_SHD_LEDS1 0x0d
+#define BCM_LED_SRC_LINKSPD2 0x1
+#define BCM_LED_SRC_ACTIVITYLED 0x3
+#define BCM54XX_SHD_LEDS1_LED3(src) (((src) & 0xf) << 4)
+#define BCM54XX_SHD_LEDS1_LED1(src) (((src) & 0xf) << 0)
+
static int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum)
{
/* The register must be written to both the Shadow Register Select and
@@ -148,7 +154,16 @@ static int bcm54210e_config(struct phy_device *phydev)
if (ret < 0)
return ret;
- return bcm5461_config(phydev);
+ ret = bcm5461_config(phydev);
+ if (ret < 0)
+ return ret;
+
+ /* Configure LEDs to blink. */
+ bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDS1,
+ BCM54XX_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
+ BCM54XX_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
+
+ return 0;
}
static int bcm54xx_parse_status(struct phy_device *phydev)
diff --git a/drivers/net/phy/ethernet_id.c b/drivers/net/phy/ethernet_id.c
index 6cb1fd4453e..4dfdee60dcc 100644
--- a/drivers/net/phy/ethernet_id.c
+++ b/drivers/net/phy/ethernet_id.c
@@ -18,12 +18,11 @@ struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev,
{
struct phy_device *phydev;
struct ofnode_phandle_args phandle_args;
- struct gpio_desc gpio;
const char *node_name;
struct udevice *pdev;
- ofnode node;
- u32 id, assert, deassert;
u16 vendor, device;
+ ofnode node;
+ u32 id;
int ret;
if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
@@ -41,35 +40,9 @@ struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev,
return NULL;
}
- if (!IS_ENABLED(CONFIG_DM_ETH_PHY)) {
- ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio,
- GPIOD_IS_OUT | GPIOD_ACTIVE_LOW);
- if (!ret) {
- assert = ofnode_read_u32_default(node,
- "reset-assert-us", 0);
- deassert = ofnode_read_u32_default(node,
- "reset-deassert-us",
- 0);
- ret = dm_gpio_set_value(&gpio, 1);
- if (ret) {
- dev_err(dev,
- "Failed assert gpio, err: %d\n", ret);
- return NULL;
- }
-
- udelay(assert);
-
- ret = dm_gpio_set_value(&gpio, 0);
- if (ret) {
- dev_err(dev,
- "Failed deassert gpio, err: %d\n",
- ret);
- return NULL;
- }
-
- udelay(deassert);
- }
- }
+ ret = phy_gpio_reset(dev);
+ if (ret)
+ return NULL;
if (phyaddr == -1)
phyaddr = ofnode_read_u32_default(phandle_args.node, "reg", -1);
diff --git a/drivers/net/phy/ncsi.c b/drivers/net/phy/ncsi.c
index eb3fd65bb47..2bca116a9d8 100644
--- a/drivers/net/phy/ncsi.c
+++ b/drivers/net/phy/ncsi.c
@@ -286,11 +286,11 @@ static void ncsi_rsp_gc(struct ncsi_rsp_pkt *pkt)
}
c = &ncsi_priv->packages[np].channels[nc];
- c->cap_generic = ntohl(gc->cap) & NCSI_CAP_GENERIC_MASK;
- c->cap_bc = ntohl(gc->bc_cap) & NCSI_CAP_BC_MASK;
- c->cap_mc = ntohl(gc->mc_cap) & NCSI_CAP_MC_MASK;
- c->cap_aen = ntohl(gc->aen_cap) & NCSI_CAP_AEN_MASK;
- c->cap_vlan = ntohl(gc->vlan_mode) & NCSI_CAP_VLAN_MASK;
+ c->cap_generic = get_unaligned_be32(&gc->cap) & NCSI_CAP_GENERIC_MASK;
+ c->cap_bc = get_unaligned_be32(&gc->bc_cap) & NCSI_CAP_BC_MASK;
+ c->cap_mc = get_unaligned_be32(&gc->mc_cap) & NCSI_CAP_MC_MASK;
+ c->cap_aen = get_unaligned_be32(&gc->aen_cap) & NCSI_CAP_AEN_MASK;
+ c->cap_vlan = gc->vlan_mode & NCSI_CAP_VLAN_MASK;
/* End of probe for this channel */
}
@@ -551,7 +551,7 @@ static int ncsi_send_command(unsigned int np, unsigned int nc, unsigned int cmd,
checksum = ncsi_calculate_checksum((unsigned char *)hdr,
sizeof(*hdr) + len);
pchecksum = (__be32 *)((void *)(hdr + 1) + len);
- put_unaligned_be32(htonl(checksum), pchecksum);
+ put_unaligned_be32(checksum, pchecksum);
if (wait) {
net_set_timeout_handler(1000UL, ncsi_timeout_handler);
@@ -619,9 +619,12 @@ static void ncsi_handle_aen(struct ip_udp_hdr *ip, unsigned int len)
/* Link or configuration lost - just redo the discovery process */
ncsi_priv->state = NCSI_PROBE_PACKAGE_SP;
- for (i = 0; i < ncsi_priv->n_packages; i++)
+ for (i = 0; i < ncsi_priv->n_packages; i++) {
free(ncsi_priv->packages[i].channels);
+ ncsi_priv->packages[i].channels = NULL;
+ }
free(ncsi_priv->packages);
+ ncsi_priv->packages = NULL;
ncsi_priv->n_packages = 0;
ncsi_priv->current_package = NCSI_PACKAGE_MAX;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 63b3e46f101..270176cfe62 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -18,6 +18,8 @@
#include <phy.h>
#include <errno.h>
#include <asm/global_data.h>
+#include <asm-generic/gpio.h>
+#include <dm/device_compat.h>
#include <dm/of_extra.h>
#include <linux/bitops.h>
#include <linux/delay.h>
@@ -566,7 +568,8 @@ struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
return NULL;
}
- if (addr >= 0 && addr < PHY_MAX_ADDR && phy_id != PHY_FIXED_ID)
+ if (addr >= 0 && addr < PHY_MAX_ADDR && phy_id != PHY_FIXED_ID &&
+ phy_id != PHY_NCSI_ID)
bus->phymap[addr] = dev;
return dev;
@@ -642,12 +645,12 @@ static struct phy_device *search_for_existing_phy(struct mii_dev *bus,
{
/* If we have one, return the existing device, with new interface */
while (phy_mask) {
- int addr = ffs(phy_mask) - 1;
+ unsigned int addr = ffs(phy_mask) - 1;
if (bus->phymap[addr])
return bus->phymap[addr];
- phy_mask &= ~(1 << addr);
+ phy_mask &= ~(1U << addr);
}
return NULL;
}
@@ -768,6 +771,59 @@ int miiphy_reset(const char *devname, unsigned char addr)
return phy_reset(phydev);
}
+#if CONFIG_IS_ENABLED(DM_GPIO) && CONFIG_IS_ENABLED(OF_REAL) && \
+ !IS_ENABLED(CONFIG_DM_ETH_PHY)
+int phy_gpio_reset(struct udevice *dev)
+{
+ struct ofnode_phandle_args phandle_args;
+ struct gpio_desc gpio;
+ u32 assert, deassert;
+ ofnode node;
+ int ret;
+
+ ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
+ &phandle_args);
+ /* No PHY handle is OK */
+ if (ret)
+ return 0;
+
+ node = phandle_args.node;
+ if (!ofnode_valid(node))
+ return -EINVAL;
+
+ ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio,
+ GPIOD_IS_OUT | GPIOD_ACTIVE_LOW);
+ /* No PHY reset GPIO is OK */
+ if (ret)
+ return 0;
+
+ assert = ofnode_read_u32_default(node, "reset-assert-us", 20000);
+ deassert = ofnode_read_u32_default(node, "reset-deassert-us", 1000);
+ ret = dm_gpio_set_value(&gpio, 1);
+ if (ret) {
+ dev_err(dev, "Failed assert gpio, err: %d\n", ret);
+ return ret;
+ }
+
+ udelay(assert);
+
+ ret = dm_gpio_set_value(&gpio, 0);
+ if (ret) {
+ dev_err(dev, "Failed deassert gpio, err: %d\n", ret);
+ return ret;
+ }
+
+ udelay(deassert);
+
+ return 0;
+}
+#else
+int phy_gpio_reset(struct udevice *dev)
+{
+ return 0;
+}
+#endif
+
struct phy_device *phy_find_by_mask(struct mii_dev *bus, uint phy_mask)
{
/* Reset the bus */
diff --git a/drivers/net/ti/Kconfig b/drivers/net/ti/Kconfig
index c75f4186285..72eccc99e5f 100644
--- a/drivers/net/ti/Kconfig
+++ b/drivers/net/ti/Kconfig
@@ -45,7 +45,15 @@ config TI_AM65_CPSW_NUSS
imply MISC_INIT_R
imply MISC
imply SYSCON
+ imply MDIO_TI_CPSW
select PHYLIB
help
This driver supports TI K3 MCU CPSW Nuss Ethernet controller
in Texas Instruments K3 AM65x SoCs.
+
+config MDIO_TI_CPSW
+ bool "TI CPSW MDIO interface support"
+ depends on DM_MDIO
+ help
+ This driver supports the TI CPSW MDIO interface found in various
+ TI SoCs.
diff --git a/drivers/net/ti/Makefile b/drivers/net/ti/Makefile
index 0ce0cf2828a..30c4c4b6d5a 100644
--- a/drivers/net/ti/Makefile
+++ b/drivers/net/ti/Makefile
@@ -5,4 +5,5 @@
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
+obj-$(CONFIG_TI_AM65_CPSW_NUSS) += am65-cpsw-nuss.o
+obj-$(CONFIG_MDIO_TI_CPSW) += cpsw_mdio.o
diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c
index 6da018c0f9d..d68ed671836 100644
--- a/drivers/net/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ti/am65-cpsw-nuss.c
@@ -31,8 +31,6 @@
#include <linux/printk.h>
#include <linux/soc/ti/ti-udma.h>
-#include "cpsw_mdio.h"
-
#define AM65_CPSW_CPSWNU_MAX_PORTS 9
#define AM65_CPSW_SS_BASE 0x0
@@ -113,7 +111,6 @@ 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;
struct clk fclk;
@@ -122,13 +119,8 @@ struct am65_cpsw_common {
u32 port_num;
struct am65_cpsw_port ports[AM65_CPSW_CPSWNU_MAX_PORTS];
- struct mii_dev *bus;
u32 bus_freq;
- struct gpio_desc mdio_gpio_reset;
- u32 reset_delay_us;
- u32 reset_post_delay_us;
-
struct dma dma_tx;
struct dma dma_rx;
u32 rx_next;
@@ -140,13 +132,7 @@ 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;
-
- bool mdio_manual_mode;
};
#ifdef PKTSIZE_ALIGN
@@ -622,111 +608,15 @@ static const struct eth_ops am65_cpsw_ops = {
.read_rom_hwaddr = am65_cpsw_read_rom_hwaddr,
};
-static const struct soc_attr k3_mdio_soc_data[] = {
- { .family = "AM62X", .revision = "SR1.0" },
- { .family = "AM64X", .revision = "SR1.0" },
- { .family = "AM64X", .revision = "SR2.0" },
- { .family = "AM65X", .revision = "SR1.0" },
- { .family = "AM65X", .revision = "SR2.0" },
- { .family = "J7200", .revision = "SR1.0" },
- { .family = "J7200", .revision = "SR2.0" },
- { .family = "J721E", .revision = "SR1.0" },
- { .family = "J721E", .revision = "SR1.1" },
- { .family = "J721S2", .revision = "SR1.0" },
- { /* sentinel */ },
-};
-
-static ofnode am65_cpsw_find_mdio(ofnode parent)
-{
- ofnode node;
-
- ofnode_for_each_subnode(node, parent)
- if (ofnode_device_is_compatible(node, "ti,cpsw-mdio"))
- return node;
-
- return ofnode_null();
-}
-
-static int am65_cpsw_mdio_setup(struct udevice *dev)
-{
- struct am65_cpsw_priv *priv = dev_get_priv(dev);
- struct am65_cpsw_common *cpsw_common = priv->cpsw_common;
- struct udevice *mdio_dev;
- ofnode mdio;
- int ret;
-
- mdio = am65_cpsw_find_mdio(dev_ofnode(cpsw_common->dev));
- if (!ofnode_valid(mdio))
- return 0;
-
- /*
- * The MDIO controller is represented in the DT binding by a
- * subnode of the MAC controller.
- *
- * We don't have a DM driver for the MDIO device yet, and thus any
- * pinctrl setting on its node will be ignored.
- *
- * However, we do need to make sure the pins states tied to the
- * MDIO node are configured properly. Fortunately, the core DM
- * does that for use when we get a device, so we can work around
- * that whole issue by just requesting a dummy MDIO driver to
- * probe, and our pins will get muxed.
- */
- ret = uclass_get_device_by_ofnode(UCLASS_MDIO, mdio, &mdio_dev);
- if (ret)
- return ret;
-
- return 0;
-}
-
-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;
- int ret;
-
- if (!priv->has_phy || cpsw_common->bus)
- return 0;
-
- if (IS_ENABLED(CONFIG_DM_GPIO)) {
- if (dm_gpio_is_valid(&cpsw_common->mdio_gpio_reset)) {
- dm_gpio_set_value(&cpsw_common->mdio_gpio_reset, 1);
- udelay(cpsw_common->reset_delay_us);
- dm_gpio_set_value(&cpsw_common->mdio_gpio_reset, 0);
- if (cpsw_common->reset_post_delay_us > 0)
- udelay(cpsw_common->reset_post_delay_us);
- }
- }
-
- ret = am65_cpsw_mdio_setup(dev);
- if (ret)
- return ret;
-
- cpsw_common->bus = cpsw_mdio_init(dev->name,
- cpsw_common->mdio_base,
- cpsw_common->bus_freq,
- clk_get_rate(&cpsw_common->fclk),
- priv->mdio_manual_mode);
- 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_plat(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);
-
+ phydev = dm_eth_phy_connect(dev);
if (!phydev) {
dev_err(dev, "phy_connect() failed\n");
return -ENODEV;
@@ -740,13 +630,10 @@ static int am65_cpsw_phy_init(struct udevice *dev)
}
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);
+ dev_err(dev, "phy_config() failed: %d", ret);
return ret;
}
@@ -755,8 +642,6 @@ static int am65_cpsw_ofdata_parse_phy(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_plat(dev);
struct am65_cpsw_priv *priv = dev_get_priv(dev);
- struct ofnode_phandle_args out_args;
- int ret = 0;
dev_read_u32(dev, "reg", &priv->port_id);
@@ -771,28 +656,7 @@ static int am65_cpsw_ofdata_parse_phy(struct udevice *dev)
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(dev_ofnode(dev), "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;
+ return 0;
}
static int am65_cpsw_port_probe(struct udevice *dev)
@@ -811,10 +675,6 @@ static int am65_cpsw_port_probe(struct udevice *dev)
sprintf(portname, "%s%s", dev->parent->name, dev->name);
device_set_name(dev, portname);
- priv->mdio_manual_mode = false;
- if (soc_device_match(k3_mdio_soc_data))
- priv->mdio_manual_mode = true;
-
ret = am65_cpsw_ofdata_parse_phy(dev);
if (ret)
goto out;
@@ -823,13 +683,8 @@ static int am65_cpsw_port_probe(struct udevice *dev)
if (ret)
goto out;
- ret = am65_cpsw_mdio_init(dev);
- if (ret)
- goto out;
-
ret = am65_cpsw_phy_init(dev);
- if (ret)
- goto out;
+
out:
return ret;
}
@@ -837,7 +692,7 @@ out:
static int am65_cpsw_probe_nuss(struct udevice *dev)
{
struct am65_cpsw_common *cpsw_common = dev_get_priv(dev);
- ofnode ports_np, node, mdio_np;
+ ofnode ports_np, node;
int ret, i;
struct udevice *port_dev;
@@ -862,25 +717,6 @@ static int am65_cpsw_probe_nuss(struct udevice *dev)
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;
-
- if (IS_ENABLED(CONFIG_DM_GPIO)) {
- /* get bus level PHY reset GPIO details */
- mdio_np = dev_read_subnode(dev, "mdio");
- if (!ofnode_valid(mdio_np)) {
- ret = -ENOENT;
- goto out;
- }
-
- cpsw_common->reset_delay_us = ofnode_read_u32_default(mdio_np, "reset-delay-us",
- DEFAULT_GPIO_RESET_DELAY);
- cpsw_common->reset_post_delay_us = ofnode_read_u32_default(mdio_np,
- "reset-post-delay-us",
- 0);
- ret = gpio_request_by_name_nodev(mdio_np, "reset-gpios", 0,
- &cpsw_common->mdio_gpio_reset,
- GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
- }
ports_np = dev_read_subnode(dev, "ethernet-ports");
if (!ofnode_valid(ports_np)) {
@@ -940,12 +776,11 @@ static int am65_cpsw_probe_nuss(struct udevice *dev)
dev_read_u32_default(dev, "bus_freq",
AM65_CPSW_MDIO_BUS_FREQ_DEF);
- dev_info(dev, "K3 CPSW: nuss_ver: 0x%08X cpsw_ver: 0x%08X ale_ver: 0x%08X Ports:%u mdio_freq:%u\n",
+ dev_info(dev, "K3 CPSW: nuss_ver: 0x%08X cpsw_ver: 0x%08X ale_ver: 0x%08X Ports:%u\n",
readl(cpsw_common->ss_base),
readl(cpsw_common->cpsw_base),
readl(cpsw_common->ale_base),
- cpsw_common->port_num,
- cpsw_common->bus_freq);
+ cpsw_common->port_num);
out:
power_domain_free(&cpsw_common->pwrdmn);
@@ -976,14 +811,3 @@ U_BOOT_DRIVER(am65_cpsw_nuss_port) = {
.plat_auto = sizeof(struct eth_pdata),
.flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_OS_PREPARE,
};
-
-static const struct udevice_id am65_cpsw_mdio_ids[] = {
- { .compatible = "ti,cpsw-mdio" },
- { }
-};
-
-U_BOOT_DRIVER(am65_cpsw_mdio) = {
- .name = "am65_cpsw_mdio",
- .id = UCLASS_MDIO,
- .of_match = am65_cpsw_mdio_ids,
-};
diff --git a/drivers/net/ti/cpsw_mdio.c b/drivers/net/ti/cpsw_mdio.c
index 74cc956785f..f1b1eba75d0 100644
--- a/drivers/net/ti/cpsw_mdio.c
+++ b/drivers/net/ti/cpsw_mdio.c
@@ -5,11 +5,15 @@
* Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
*/
+#include <clk.h>
#include <common.h>
+#include <dm/device_compat.h>
#include <log.h>
#include <malloc.h>
+#include <phy.h>
#include <asm/io.h>
#include <miiphy.h>
+#include <soc.h>
#include <wait_bit.h>
#include <linux/bitops.h>
#include <linux/delay.h>
@@ -22,6 +26,7 @@ struct cpsw_mdio_regs {
#define CONTROL_FAULT BIT(19)
#define CONTROL_FAULT_ENABLE BIT(18)
#define CONTROL_DIV_MASK GENMASK(15, 0)
+#define CONTROL_MAX_DIV CONTROL_DIV_MASK
#define MDIO_MAN_MDCLK_O BIT(2)
#define MDIO_MAN_OE BIT(1)
@@ -72,6 +77,8 @@ struct cpsw_mdio_regs {
*/
#define CPSW_MDIO_TIMEOUT 100 /* msecs */
+#define CPSW_MDIO_DEF_BUS_FREQ 2200000 /* 2.2 MHz */
+
enum cpsw_mdio_manual {
MDIO_PIN = 0,
MDIO_OE,
@@ -82,8 +89,35 @@ struct cpsw_mdio {
struct cpsw_mdio_regs *regs;
struct mii_dev *bus;
int div;
+ bool manual_mode;
+ struct clk clk;
+ unsigned long bus_freq;
};
+static int cpsw_mdio_enable(struct cpsw_mdio *data)
+{
+ int ret;
+
+ /* set enable and clock divider */
+ writel(data->div | CONTROL_ENABLE, &data->regs->control);
+ ret = wait_for_bit_le32(&data->regs->control,
+ CONTROL_IDLE, false, CPSW_MDIO_TIMEOUT, true);
+ if (ret)
+ return ret;
+
+ /*
+ * wait for scan logic to settle:
+ * the scan time consists of (a) a large fixed component, and (b) a
+ * small component that varies with the mii bus frequency. These
+ * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
+ * silicon. Since the effect of (b) was found to be largely
+ * negligible, we keep things simple here.
+ */
+ mdelay(1);
+
+ return 0;
+}
+
static void cpsw_mdio_disable(struct cpsw_mdio *mdio)
{
u32 reg;
@@ -206,10 +240,16 @@ static void cpsw_mdio_sw_preamble(struct cpsw_mdio *mdio)
}
}
+#if defined(CONFIG_DM_MDIO)
+#define MII_TO_CPSW_MDIO(bus) (dev_get_priv((struct udevice *)(bus)->priv))
+#else
+#define MII_TO_CPSW_MDIO(bus) ((bus)->priv)
+#endif
+
static int cpsw_mdio_sw_read(struct mii_dev *bus, int phy_id,
int dev_addr, int phy_reg)
{
- struct cpsw_mdio *mdio = bus->priv;
+ struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus);
u32 reg, i;
u8 ack;
@@ -266,7 +306,7 @@ static int cpsw_mdio_sw_read(struct mii_dev *bus, int phy_id,
static int cpsw_mdio_sw_write(struct mii_dev *bus, int phy_id,
int dev_addr, int phy_reg, u16 phy_data)
{
- struct cpsw_mdio *mdio = bus->priv;
+ struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus);
if ((phy_reg & ~PHY_REG_MASK) || (phy_id & ~PHY_ID_MASK))
return -EINVAL;
@@ -316,7 +356,7 @@ static int cpsw_mdio_wait_for_user_access(struct cpsw_mdio *mdio)
static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
int dev_addr, int phy_reg)
{
- struct cpsw_mdio *mdio = bus->priv;
+ struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus);
int data, ret;
u32 reg;
@@ -342,7 +382,7 @@ static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
static int cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr,
int phy_reg, u16 data)
{
- struct cpsw_mdio *mdio = bus->priv;
+ struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus);
u32 reg;
int ret;
@@ -361,9 +401,10 @@ static int cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr,
return cpsw_mdio_wait_for_user_access(mdio);
}
+#if !defined(CONFIG_MDIO_TI_CPSW)
u32 cpsw_mdio_get_alive(struct mii_dev *bus)
{
- struct cpsw_mdio *mdio = bus->priv;
+ struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus);
u32 val;
val = readl(&mdio->regs->alive);
@@ -396,22 +437,11 @@ struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
else
cpsw_mdio->div = (fck_freq / bus_freq) - 1;
cpsw_mdio->div &= CONTROL_DIV_MASK;
-
- /* set enable and clock divider */
- writel(cpsw_mdio->div | CONTROL_ENABLE | CONTROL_FAULT |
- CONTROL_FAULT_ENABLE, &cpsw_mdio->regs->control);
- wait_for_bit_le32(&cpsw_mdio->regs->control,
- CONTROL_IDLE, false, CPSW_MDIO_TIMEOUT, true);
-
- /*
- * wait for scan logic to settle:
- * the scan time consists of (a) a large fixed component, and (b) a
- * small component that varies with the mii bus frequency. These
- * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
- * silicon. Since the effect of (b) was found to be largely
- * negligible, we keep things simple here.
- */
- mdelay(1);
+ ret = cpsw_mdio_enable(cpsw_mdio);
+ if (ret) {
+ debug("mdio_enable failed: %d\n", ret);
+ goto free_bus;
+ }
if (manual_mode) {
cpsw_mdio->bus->read = cpsw_mdio_sw_read;
@@ -452,3 +482,129 @@ void cpsw_mdio_free(struct mii_dev *bus)
mdio_free(bus);
free(mdio);
}
+
+#else
+
+static int cpsw_mdio_init_clk(struct cpsw_mdio *data)
+{
+ u32 mdio_in, div;
+
+ mdio_in = clk_get_rate(&data->clk);
+ div = (mdio_in / data->bus_freq) - 1;
+ if (div > CONTROL_MAX_DIV)
+ div = CONTROL_MAX_DIV;
+
+ data->div = div;
+ return cpsw_mdio_enable(data);
+}
+
+static int cpsw_mdio_bus_read(struct udevice *dev, int addr,
+ int devad, int reg)
+{
+ struct mdio_perdev_priv *pdata = (dev) ? dev_get_uclass_priv(dev) :
+ NULL;
+ struct cpsw_mdio *priv = dev_get_priv(dev);
+
+ if (pdata && pdata->mii_bus) {
+ if (priv->manual_mode)
+ return cpsw_mdio_sw_read(pdata->mii_bus, addr, devad, reg);
+ else
+ return cpsw_mdio_read(pdata->mii_bus, addr, devad, reg);
+ }
+
+ return -1;
+}
+
+static int cpsw_mdio_bus_write(struct udevice *dev, int addr,
+ int devad, int reg, u16 val)
+{
+ struct mdio_perdev_priv *pdata = (dev) ? dev_get_uclass_priv(dev) :
+ NULL;
+ struct cpsw_mdio *priv = dev_get_priv(dev);
+
+ if (pdata && pdata->mii_bus) {
+ if (priv->manual_mode)
+ return cpsw_mdio_sw_write(pdata->mii_bus, addr, devad, reg, val);
+ else
+ return cpsw_mdio_write(pdata->mii_bus, addr, devad, reg, val);
+ }
+
+ return -1;
+}
+
+static const struct mdio_ops cpsw_mdio_ops = {
+ .read = cpsw_mdio_bus_read,
+ .write = cpsw_mdio_bus_write,
+};
+
+static const struct soc_attr k3_mdio_soc_data[] = {
+ { .family = "AM62X", .revision = "SR1.0" },
+ { .family = "AM64X", .revision = "SR1.0" },
+ { .family = "AM64X", .revision = "SR2.0" },
+ { .family = "AM65X", .revision = "SR1.0" },
+ { .family = "AM65X", .revision = "SR2.0" },
+ { .family = "J7200", .revision = "SR1.0" },
+ { .family = "J7200", .revision = "SR2.0" },
+ { .family = "J721E", .revision = "SR1.0" },
+ { .family = "J721E", .revision = "SR1.1" },
+ { .family = "J721S2", .revision = "SR1.0" },
+ { /* sentinel */ },
+};
+
+static const struct udevice_id cpsw_mdio_ids[] = {
+ { .compatible = "ti,davinci_mdio", },
+ { .compatible = "ti,cpsw-mdio", },
+ { /* sentinel */ },
+};
+
+static int cpsw_mdio_probe(struct udevice *dev)
+{
+ struct cpsw_mdio *priv = dev_get_priv(dev);
+ int ret;
+
+ if (!priv) {
+ dev_err(dev, "dev_get_priv(dev %p) = NULL\n", dev);
+ return -ENOMEM;
+ }
+
+ priv->regs = dev_remap_addr(dev);
+
+ if (soc_device_match(k3_mdio_soc_data))
+ priv->manual_mode = true;
+
+ ret = clk_get_by_name(dev, "fck", &priv->clk);
+ if (ret) {
+ dev_err(dev, "failed to get clock %d\n", ret);
+ return ret;
+ }
+
+ priv->bus_freq = dev_read_u32_default(dev, "bus_freq",
+ CPSW_MDIO_DEF_BUS_FREQ);
+ ret = cpsw_mdio_init_clk(priv);
+ if (ret) {
+ dev_err(dev, "init clock failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int cpsw_mdio_remove(struct udevice *dev)
+{
+ struct cpsw_mdio *priv = dev_get_priv(dev);
+
+ cpsw_mdio_disable(priv);
+
+ return 0;
+}
+
+U_BOOT_DRIVER(cpsw_mdio) = {
+ .name = "cpsw_mdio",
+ .id = UCLASS_MDIO,
+ .of_match = cpsw_mdio_ids,
+ .probe = cpsw_mdio_probe,
+ .remove = cpsw_mdio_remove,
+ .ops = &cpsw_mdio_ops,
+ .priv_auto = sizeof(struct cpsw_mdio),
+};
+#endif /* CONFIG_MDIO_TI_CPSW */
diff --git a/drivers/net/ti/cpsw_mdio.h b/drivers/net/ti/cpsw_mdio.h
index ddf65a4686d..240c972d697 100644
--- a/drivers/net/ti/cpsw_mdio.h
+++ b/drivers/net/ti/cpsw_mdio.h
@@ -10,9 +10,11 @@
struct cpsw_mdio;
+#if !defined(CONFIG_MDIO_TI_CPSW)
struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
u32 bus_freq, int fck_freq, bool manual_mode);
void cpsw_mdio_free(struct mii_dev *bus);
u32 cpsw_mdio_get_alive(struct mii_dev *bus);
+#endif /* CONFIG_MDIO_TI_CPSW */
#endif /* CPSW_MDIO_H_ */