summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/Kconfig22
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/designware.c20
-rw-r--r--drivers/net/mdio_mux_sandbox.c97
-rw-r--r--drivers/net/mdio_sandbox.c16
-rw-r--r--drivers/net/phy/aquantia.c28
-rw-r--r--drivers/net/phy/phy.c11
7 files changed, 183 insertions, 12 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 635f8d72c2..403df5e960 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -24,6 +24,18 @@ config DM_MDIO
This is currently implemented in net/mdio-uclass.c
Look in include/miiphy.h for details.
+config DM_MDIO_MUX
+ bool "Enable Driver Model for MDIO MUX devices"
+ depends on DM_MDIO
+ help
+ Enable driver model for MDIO MUX devices
+
+ Adds UCLASS_MDIO_MUX DM class supporting MDIO MUXes. Useful for
+ systems that support DM_MDIO and integrate one or multiple muxes on
+ the MDIO bus.
+ This is currently implemented in net/mdio-mux-uclass.c
+ Look in include/miiphy.h for details.
+
config MDIO_SANDBOX
depends on DM_MDIO && SANDBOX
default y
@@ -34,6 +46,16 @@ config MDIO_SANDBOX
This driver is used in for testing in test/dm/mdio.c
+config MDIO_MUX_SANDBOX
+ depends on DM_MDIO_MUX && MDIO_SANDBOX
+ default y
+ bool "Sandbox: Mocked MDIO-MUX driver"
+ help
+ This driver implements dummy select/deselect ops mimicking a MUX on
+ the MDIO bux. It uses mdio_sandbox driver as parent MDIO.
+
+ This driver is used 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 40038427db..3c473b205d 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_LAN91C96) += lan91c96.o
obj-$(CONFIG_LPC32XX_ETH) += lpc32xx_eth.o
obj-$(CONFIG_MACB) += macb.o
obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
+obj-$(CONFIG_MDIO_MUX_SANDBOX) += mdio_mux_sandbox.o
obj-$(CONFIG_MPC8XX_FEC) += mpc8xx_fec.o
obj-$(CONFIG_MT7628_ETH) += mt7628-eth.o
obj-$(CONFIG_MVGBE) += mvgbe.o
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 2c5d9560c5..3b6cf5ddb5 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -677,10 +677,10 @@ int designware_eth_probe(struct udevice *dev)
struct dw_eth_dev *priv = dev_get_priv(dev);
u32 iobase = pdata->iobase;
ulong ioaddr;
- int ret;
+ int ret, err;
struct reset_ctl_bulk reset_bulk;
#ifdef CONFIG_CLK
- int i, err, clock_nb;
+ int i, clock_nb;
priv->clock_count = 0;
clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
@@ -753,13 +753,23 @@ int designware_eth_probe(struct udevice *dev)
priv->interface = pdata->phy_interface;
priv->max_speed = pdata->max_speed;
- dw_mdio_init(dev->name, dev);
+ ret = dw_mdio_init(dev->name, dev);
+ if (ret) {
+ err = ret;
+ goto mdio_err;
+ }
priv->bus = miiphy_get_dev_by_name(dev->name);
ret = dw_phy_init(priv, dev);
debug("%s, ret=%d\n", __func__, ret);
+ if (!ret)
+ return 0;
- return ret;
+ /* continue here for cleanup if no PHY found */
+ err = ret;
+ mdio_unregister(priv->bus);
+ mdio_free(priv->bus);
+mdio_err:
#ifdef CONFIG_CLK
clk_err:
@@ -767,8 +777,8 @@ clk_err:
if (ret)
pr_err("failed to disable all clocks\n");
- return err;
#endif
+ return err;
}
static int designware_eth_remove(struct udevice *dev)
diff --git a/drivers/net/mdio_mux_sandbox.c b/drivers/net/mdio_mux_sandbox.c
new file mode 100644
index 0000000000..3dba4d18a1
--- /dev/null
+++ b/drivers/net/mdio_mux_sandbox.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Alex Marginean, NXP
+ */
+
+#include <dm.h>
+#include <errno.h>
+#include <miiphy.h>
+
+/* macros copied over from mdio_sandbox.c */
+#define SANDBOX_PHY_ADDR 5
+#define SANDBOX_PHY_REG_CNT 2
+
+struct mdio_mux_sandbox_priv {
+ int enabled;
+ int sel;
+};
+
+static int mdio_mux_sandbox_mark_selection(struct udevice *dev, int sel)
+{
+ struct udevice *mdio;
+ struct mdio_ops *ops;
+ int err;
+
+ /*
+ * find the sandbox parent mdio and write a register on the PHY there
+ * so the mux test can verify selection.
+ */
+ err = uclass_get_device_by_name(UCLASS_MDIO, "mdio-test", &mdio);
+ if (err)
+ return err;
+ ops = mdio_get_ops(mdio);
+ return ops->write(mdio, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
+ SANDBOX_PHY_REG_CNT - 1, (u16)sel);
+}
+
+static int mdio_mux_sandbox_select(struct udevice *dev, int cur, int sel)
+{
+ struct mdio_mux_sandbox_priv *priv = dev_get_priv(dev);
+
+ if (!priv->enabled)
+ return -ENODEV;
+
+ if (cur != priv->sel)
+ return -EINVAL;
+
+ priv->sel = sel;
+ mdio_mux_sandbox_mark_selection(dev, priv->sel);
+
+ return 0;
+}
+
+static int mdio_mux_sandbox_deselect(struct udevice *dev, int sel)
+{
+ struct mdio_mux_sandbox_priv *priv = dev_get_priv(dev);
+
+ if (!priv->enabled)
+ return -ENODEV;
+
+ if (sel != priv->sel)
+ return -EINVAL;
+
+ priv->sel = -1;
+ mdio_mux_sandbox_mark_selection(dev, priv->sel);
+
+ return 0;
+}
+
+static const struct mdio_mux_ops mdio_mux_sandbox_ops = {
+ .select = mdio_mux_sandbox_select,
+ .deselect = mdio_mux_sandbox_deselect,
+};
+
+static int mdio_mux_sandbox_probe(struct udevice *dev)
+{
+ struct mdio_mux_sandbox_priv *priv = dev_get_priv(dev);
+
+ priv->enabled = 1;
+ priv->sel = -1;
+
+ return 0;
+}
+
+static const struct udevice_id mdio_mux_sandbox_ids[] = {
+ { .compatible = "sandbox,mdio-mux" },
+ { }
+};
+
+U_BOOT_DRIVER(mdio_mux_sandbox) = {
+ .name = "mdio_mux_sandbox",
+ .id = UCLASS_MDIO_MUX,
+ .of_match = mdio_mux_sandbox_ids,
+ .probe = mdio_mux_sandbox_probe,
+ .ops = &mdio_mux_sandbox_ops,
+ .priv_auto_alloc_size = sizeof(struct mdio_mux_sandbox_priv),
+};
diff --git a/drivers/net/mdio_sandbox.c b/drivers/net/mdio_sandbox.c
index 07515e078c..df053f5381 100644
--- a/drivers/net/mdio_sandbox.c
+++ b/drivers/net/mdio_sandbox.c
@@ -9,11 +9,11 @@
#include <miiphy.h>
#define SANDBOX_PHY_ADDR 5
-#define SANDBOX_PHY_REG 0
+#define SANDBOX_PHY_REG_CNT 2
struct mdio_sandbox_priv {
int enabled;
- u16 reg;
+ u16 reg[SANDBOX_PHY_REG_CNT];
};
static int mdio_sandbox_read(struct udevice *dev, int addr, int devad, int reg)
@@ -27,10 +27,10 @@ static int mdio_sandbox_read(struct udevice *dev, int addr, int devad, int reg)
return -ENODEV;
if (devad != MDIO_DEVAD_NONE)
return -ENODEV;
- if (reg != SANDBOX_PHY_REG)
+ if (reg < 0 || reg > SANDBOX_PHY_REG_CNT)
return -ENODEV;
- return priv->reg;
+ return priv->reg[reg];
}
static int mdio_sandbox_write(struct udevice *dev, int addr, int devad, int reg,
@@ -45,10 +45,10 @@ static int mdio_sandbox_write(struct udevice *dev, int addr, int devad, int reg,
return -ENODEV;
if (devad != MDIO_DEVAD_NONE)
return -ENODEV;
- if (reg != SANDBOX_PHY_REG)
+ if (reg < 0 || reg > SANDBOX_PHY_REG_CNT)
return -ENODEV;
- priv->reg = val;
+ priv->reg[reg] = val;
return 0;
}
@@ -56,8 +56,10 @@ static int mdio_sandbox_write(struct udevice *dev, int addr, int devad, int reg,
static int mdio_sandbox_reset(struct udevice *dev)
{
struct mdio_sandbox_priv *priv = dev_get_priv(dev);
+ int i;
- priv->reg = 0;
+ for (i = 0; i < SANDBOX_PHY_REG_CNT; i++)
+ priv->reg[i] = 0;
return 0;
}
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
index 5c3298d612..465ec2d342 100644
--- a/drivers/net/phy/aquantia.c
+++ b/drivers/net/phy/aquantia.c
@@ -461,6 +461,19 @@ struct phy_driver aqr107_driver = {
.shutdown = &gen10g_shutdown,
};
+struct phy_driver aqr112_driver = {
+ .name = "Aquantia AQR112",
+ .uid = 0x3a1b660,
+ .mask = 0xfffffff0,
+ .features = PHY_10G_FEATURES,
+ .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS |
+ MDIO_MMD_PHYXS | MDIO_MMD_AN |
+ MDIO_MMD_VEND1),
+ .config = &aquantia_config,
+ .startup = &aquantia_startup,
+ .shutdown = &gen10g_shutdown,
+};
+
struct phy_driver aqr405_driver = {
.name = "Aquantia AQR405",
.uid = 0x3a1b4b2,
@@ -474,6 +487,19 @@ struct phy_driver aqr405_driver = {
.shutdown = &gen10g_shutdown,
};
+struct phy_driver aqr412_driver = {
+ .name = "Aquantia AQR412",
+ .uid = 0x3a1b710,
+ .mask = 0xfffffff0,
+ .features = PHY_10G_FEATURES,
+ .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS |
+ MDIO_MMD_PHYXS | MDIO_MMD_AN |
+ MDIO_MMD_VEND1),
+ .config = &aquantia_config,
+ .startup = &aquantia_startup,
+ .shutdown = &gen10g_shutdown,
+};
+
int phy_aquantia_init(void)
{
phy_register(&aq1202_driver);
@@ -481,7 +507,9 @@ int phy_aquantia_init(void)
phy_register(&aqr105_driver);
phy_register(&aqr106_driver);
phy_register(&aqr107_driver);
+ phy_register(&aqr112_driver);
phy_register(&aqr405_driver);
+ phy_register(&aqr412_driver);
return 0;
}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index c1c1af9abd..ae37dd6c1e 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -727,12 +727,23 @@ static struct phy_device *create_phy_by_mask(struct mii_dev *bus,
while (phy_mask) {
int addr = ffs(phy_mask) - 1;
int r = get_phy_id(bus, addr, devad, &phy_id);
+
+ /*
+ * If the PHY ID is flat 0 we ignore it. There are C45 PHYs
+ * that return all 0s for C22 reads (like Aquantia AQR112) and
+ * there are C22 PHYs that return all 0s for C45 reads (like
+ * Atheros AR8035).
+ */
+ if (r == 0 && phy_id == 0)
+ goto next;
+
/* If the PHY ID is mostly f's, we didn't find anything */
if (r == 0 && (phy_id & 0x1fffffff) != 0x1fffffff) {
is_c45 = (devad == MDIO_DEVAD_NONE) ? false : true;
return phy_device_create(bus, addr, phy_id, is_c45,
interface);
}
+next:
phy_mask &= ~(1 << addr);
}
return NULL;