* [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana
@ 2022-10-28 0:49 Tim Harvey
2022-10-28 0:49 ` [PATCH v8 1/8] net: mdio-uclass: scan for dm mdio children on post-bind Tim Harvey
` (8 more replies)
0 siblings, 9 replies; 18+ messages in thread
From: Tim Harvey @ 2022-10-28 0:49 UTC (permalink / raw)
To: u-boot, Joe Hershberger, Ramon Fried, Vladimir Oltean,
Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
Marek Behún
Cc: Tim Harvey
This series adds a DSA driver for the MV88E6xxx based on
drivers/net/phy/mv88e61xx and uses it in the gwventana_gw5904_defconfig.
The hope is that the other three boards that use the MV88E61xx driver
can move to this as well eventually so that we can remove the non-dm
driver and the 4 Kconfig options it requires.
The MV88E6xxx has an MDIO interface thus DM_MDIO must be used so support
for a UCLASS_MDIO driver is added to the fec_mxc ethernet driver in a
way that allows a fallback to the previous non DM_MDIO case as there are
many boards out there using this driver that define DM_MDIO but do not
have the required dt props for a DM_MDIO driver which would cause a
regression.
Additionally some other patches are here suggested by Vladimir:
- ensure MDIO children are scanned on post-bind is needed
- sanity check DSA driver required ops are present
- allow DSA drivers to not require xmit/recv functions
- remove unecessary xmit/recv functions from ksz9477 driver
v8:
- en remove energy-detect low-power mode config
- add phy-mode internal dt prop to phy ports
v7:
- rebase on master
- update commit short msg (s/MV88E61xx/MV88E6xxx)
- replace inline smi_cmd* with macros using logical operators
- replace bitfield_replace with logical operators for readibility
- removed some unused register definitions
- config switch based SERDES mode once in probe vs port_enable
- rework port_enable to clean up and:
- enable energy-detect for all non fixed PHY ports
- configure RGMII delays based on interface type
- add Vladimir's rb tag to patch 8
v6:
- update commit messages
- squash accidently change to mv88e6xxx driver into previous patch
- remove unused dt label for cpu port
- removed unnecessary semicolon
- update commit msg (s/MV88E61xx/MV88E6xxx)
- remove GbE from commit msg and Kconfig desc
- squash accidental change from patch 7 into patch 6
- added error print on failure to read switch id
- mv88e6xxx_probe:
- check for switch enabled
- remove unused variable enabled
- remove unnecessary call to dsa_set_tagging
- port_probe:
- new function to configure phy features by calling phy_config
- port_enable:
- only enable energy-detect sensing on phy ports
- add phy/cmode verification mistmatch warning
- remove mv88e6xxx_fixed_port_setup()
- always force link up for fixed ports
- always set SERDES mode regardless of cpu port
- remove unnecessary setting of CPUDEST
- port_disable:
- remove pointless error check
- removed unnecessary priv data for mdio controller
- fix indentation
- change variable name for clarity
v5:
- fix typo in defconfig update
- added support for MV88E6320
- added Fabio's rb tag
v4:
- use standard Linux internal MDIO dt structure
- use PHY_FIXED_ID define
- rename to mv88e6xxx
- sort includes alphabetically
- remove dsa term from function names
- reduce indentation level and remove unecessary code in of probe_mdio
function
- rename pdev to mdev to represent mdio device
v3:
- fix mdios node in dt
- add Vladimir's rb tag's
v2:
- added Ramon's rb tag's to first two patches
- add patches for dsa-uclass to sanity check ops and make xmit/recv
optional
- fec: fix fallback for non conforming DM_MDIO dts
- mv88e61xx:
- rebase on v2022.07-rc2 (use ofnode_get_phy_node)
- remove unused commented out fields from struct
- remove unused PORT_MASK macro
- remove phy from priv struct name
- refactor code from original drivers/net/phy/mv88e61xx with
suggestions from review to consolidate some functions
into mv88e61xx_dsa_port_enable
- remove unecessary skiping of disabling of CPU port
- remove unecessary dev_set_parent_priv
- remove unnecessary static init flag
- replace debug with a dev_warn if switch device-id unsupported
- remove unnecessary xmit/recv functions as we rely on the fact that
only a single port is active instead of mangling packets
Tested on a Gateworks GW5904 which has a Marvell 88E6176 switch hanging
off the IMX6 FEC.
Best Regards,
Tim
Tim Harvey (8):
net: mdio-uclass: scan for dm mdio children on post-bind
net: dsa: move cpu port probe to dsa_post_probe
net: dsa: ensure dsa driver has proper ops
net: dsa: allow rcv() and xmit() to be optional
net: ksz9477: remove unnecessary xmit and recv functions
net: fec: add support for DM_MDIO
net: add MV88E6xxx DSA driver
board: gw_ventana: enable MV88E61XX DSA support
arch/arm/dts/imx6qdl-gw5904.dtsi | 36 +-
board/gateworks/gw_ventana/gw_ventana.c | 50 +-
configs/gwventana_gw5904_defconfig | 7 +-
drivers/net/Kconfig | 7 +
drivers/net/Makefile | 1 +
drivers/net/fec_mxc.c | 90 ++-
drivers/net/ksz9477.c | 23 -
drivers/net/mv88e6xxx.c | 755 ++++++++++++++++++++++++
net/dsa-uclass.c | 55 +-
net/mdio-uclass.c | 4 +
10 files changed, 956 insertions(+), 72 deletions(-)
create mode 100644 drivers/net/mv88e6xxx.c
--
2.25.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v8 1/8] net: mdio-uclass: scan for dm mdio children on post-bind
2022-10-28 0:49 [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana Tim Harvey
@ 2022-10-28 0:49 ` Tim Harvey
2022-10-28 0:49 ` [PATCH v8 2/8] net: dsa: move cpu port probe to dsa_post_probe Tim Harvey
` (7 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Tim Harvey @ 2022-10-28 0:49 UTC (permalink / raw)
To: u-boot, Joe Hershberger, Ramon Fried, Vladimir Oltean,
Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
Marek Behún
Cc: Tim Harvey, Fabio Estevam
If a DM_MDIO driver is used we need to scan the subnodes as well.
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
Reviewed-by: Fabio Estevam <festevam@denx.de>
---
v8:
- no changes
v7:
- no changes
v6:
- no changes
v5:
- added Fabio's rb tag
v4:
- no changes
v3:
- no changes
v2:
- added Ramon's rb tag
---
net/mdio-uclass.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/mdio-uclass.c b/net/mdio-uclass.c
index 4401492ca015..d80037d0ac71 100644
--- a/net/mdio-uclass.c
+++ b/net/mdio-uclass.c
@@ -49,7 +49,11 @@ static int dm_mdio_post_bind(struct udevice *dev)
return -EINVAL;
}
+#if CONFIG_IS_ENABLED(OF_REAL)
+ return dm_scan_fdt_dev(dev);
+#else
return 0;
+#endif
}
int dm_mdio_read(struct udevice *mdio_dev, int addr, int devad, int reg)
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v8 2/8] net: dsa: move cpu port probe to dsa_post_probe
2022-10-28 0:49 [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana Tim Harvey
2022-10-28 0:49 ` [PATCH v8 1/8] net: mdio-uclass: scan for dm mdio children on post-bind Tim Harvey
@ 2022-10-28 0:49 ` Tim Harvey
2022-10-28 0:49 ` [PATCH v8 3/8] net: dsa: ensure dsa driver has proper ops Tim Harvey
` (6 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Tim Harvey @ 2022-10-28 0:49 UTC (permalink / raw)
To: u-boot, Joe Hershberger, Ramon Fried, Vladimir Oltean,
Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
Marek Behún
Cc: Tim Harvey, Fabio Estevam
In order to ensure that a DSA driver probe gets called before
dsa_ops->port_probe move the port_probe of the cpu_port to
a post-probe function.
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Fabio Estevam <festevam@denx.de>
---
v8:
- no changes
v7:
- no changes
v6:
- removed unnecessary semicolon
v5:
- added Fabio's rb tag
v4:
- no changes
v3:
- added Vladimir's rb tag
v2:
- added Ramon's rb tag
---
net/dsa-uclass.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c
index 5b7046432ff3..5759cedcbec3 100644
--- a/net/dsa-uclass.c
+++ b/net/dsa-uclass.c
@@ -466,7 +466,6 @@ static int dsa_pre_probe(struct udevice *dev)
{
struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
struct dsa_priv *priv = dev_get_uclass_priv(dev);
- struct dsa_ops *ops = dsa_get_ops(dev);
int err;
priv->num_ports = pdata->num_ports;
@@ -482,6 +481,15 @@ static int dsa_pre_probe(struct udevice *dev)
if (err)
return err;
+ return 0;
+}
+
+static int dsa_post_probe(struct udevice *dev)
+{
+ struct dsa_priv *priv = dev_get_uclass_priv(dev);
+ struct dsa_ops *ops = dsa_get_ops(dev);
+ int err;
+
/* Simulate a probing event for the CPU port */
if (ops->port_probe) {
err = ops->port_probe(dev, priv->cpu_port,
@@ -498,6 +506,7 @@ UCLASS_DRIVER(dsa) = {
.name = "dsa",
.post_bind = dsa_post_bind,
.pre_probe = dsa_pre_probe,
+ .post_probe = dsa_post_probe,
.per_device_auto = sizeof(struct dsa_priv),
.per_device_plat_auto = sizeof(struct dsa_pdata),
.per_child_plat_auto = sizeof(struct dsa_port_pdata),
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v8 3/8] net: dsa: ensure dsa driver has proper ops
2022-10-28 0:49 [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana Tim Harvey
2022-10-28 0:49 ` [PATCH v8 1/8] net: mdio-uclass: scan for dm mdio children on post-bind Tim Harvey
2022-10-28 0:49 ` [PATCH v8 2/8] net: dsa: move cpu port probe to dsa_post_probe Tim Harvey
@ 2022-10-28 0:49 ` Tim Harvey
2022-10-28 0:49 ` [PATCH v8 4/8] net: dsa: allow rcv() and xmit() to be optional Tim Harvey
` (5 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Tim Harvey @ 2022-10-28 0:49 UTC (permalink / raw)
To: u-boot, Joe Hershberger, Ramon Fried, Vladimir Oltean,
Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
Marek Behún
Cc: Tim Harvey, Fabio Estevam
Add a function to sanity check a dsa driver having proper ops.
Suggested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Fabio Estevam <festevam@denx.de>
---
v8:
- no changes
v7:
- no changes
v6:
- no changes
v5:
- added Fabio's rb tag
v4:
- no changes
v3:
- added Vladimir's rb tag
v2: new patch
---
net/dsa-uclass.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c
index 5759cedcbec3..211a991cdd0d 100644
--- a/net/dsa-uclass.c
+++ b/net/dsa-uclass.c
@@ -342,6 +342,19 @@ U_BOOT_DRIVER(dsa_port) = {
.plat_auto = sizeof(struct eth_pdata),
};
+static int dsa_sanitize_ops(struct udevice *dev)
+{
+ struct dsa_ops *ops = dsa_get_ops(dev);
+
+ if ((!ops->xmit || !ops->rcv) &&
+ (!ops->port_enable && !ops->port_disable)) {
+ dev_err(dev, "Packets cannot be steered to ports\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/*
* This function mostly deals with pulling information out of the device tree
* into the pdata structure.
@@ -358,6 +371,10 @@ static int dsa_post_bind(struct udevice *dev)
if (!ofnode_valid(node))
return -ENODEV;
+ err = dsa_sanitize_ops(dev);
+ if (err)
+ return err;
+
pdata->master_node = ofnode_null();
node = ofnode_find_subnode(node, "ports");
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v8 4/8] net: dsa: allow rcv() and xmit() to be optional
2022-10-28 0:49 [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana Tim Harvey
` (2 preceding siblings ...)
2022-10-28 0:49 ` [PATCH v8 3/8] net: dsa: ensure dsa driver has proper ops Tim Harvey
@ 2022-10-28 0:49 ` Tim Harvey
2022-11-28 15:58 ` Tom Rini
2022-10-28 0:49 ` [PATCH v8 5/8] net: ksz9477: remove unnecessary xmit and recv functions Tim Harvey
` (4 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Tim Harvey @ 2022-10-28 0:49 UTC (permalink / raw)
To: u-boot, Joe Hershberger, Ramon Fried, Vladimir Oltean,
Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
Marek Behún
Cc: Tim Harvey, Fabio Estevam
Allow rcv() and xmit() dsa driver ops to be optional in case a driver
does not care to mangle a packet as in U-Boot only one network port is
enabled at a time and thus no packet mangling is necessary.
Suggested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Fabio Estevam <festevam@denx.de>
---
v8:
- no changes
v7:
- no changes
v6:
- no changes
v5:
- added Fabio's rb tag
v4:
- no changes
v3:
- added Vladimir's rb tag
v2: new patch
---
net/dsa-uclass.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c
index 211a991cdd0d..eba8347ae21a 100644
--- a/net/dsa-uclass.c
+++ b/net/dsa-uclass.c
@@ -131,16 +131,14 @@ static void dsa_port_stop(struct udevice *pdev)
* We copy the frame to a stack buffer where we have reserved headroom and
* tailroom space. Headroom and tailroom are set to 0.
*/
-static int dsa_port_send(struct udevice *pdev, void *packet, int length)
+static int dsa_port_mangle_packet(struct udevice *pdev, void *packet, int length)
{
+ struct dsa_port_pdata *port_pdata = dev_get_parent_plat(pdev);
struct udevice *dev = dev_get_parent(pdev);
struct dsa_priv *priv = dev_get_uclass_priv(dev);
int head = priv->headroom, tail = priv->tailroom;
- struct udevice *master = dsa_get_master(dev);
struct dsa_ops *ops = dsa_get_ops(dev);
uchar dsa_packet_tmp[PKTSIZE_ALIGN];
- struct dsa_port_pdata *port_pdata;
- int err;
if (length + head + tail > PKTSIZE_ALIGN)
return -EINVAL;
@@ -152,10 +150,21 @@ static int dsa_port_send(struct udevice *pdev, void *packet, int length)
/* copy back to preserve original buffer alignment */
memcpy(packet, dsa_packet_tmp, length);
- port_pdata = dev_get_parent_plat(pdev);
- err = ops->xmit(dev, port_pdata->index, packet, length);
- if (err)
- return err;
+ return ops->xmit(dev, port_pdata->index, packet, length);
+}
+
+static int dsa_port_send(struct udevice *pdev, void *packet, int length)
+{
+ struct udevice *dev = dev_get_parent(pdev);
+ struct udevice *master = dsa_get_master(dev);
+ struct dsa_ops *ops = dsa_get_ops(dev);
+ int err;
+
+ if (ops->xmit) {
+ err = dsa_port_mangle_packet(pdev, packet, length);
+ if (err)
+ return err;
+ }
return eth_get_ops(master)->send(master, packet, length);
}
@@ -172,7 +181,7 @@ static int dsa_port_recv(struct udevice *pdev, int flags, uchar **packetp)
int length, port_index, err;
length = eth_get_ops(master)->recv(master, flags, packetp);
- if (length <= 0)
+ if (length <= 0 || !ops->rcv)
return length;
/*
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v8 5/8] net: ksz9477: remove unnecessary xmit and recv functions
2022-10-28 0:49 [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana Tim Harvey
` (3 preceding siblings ...)
2022-10-28 0:49 ` [PATCH v8 4/8] net: dsa: allow rcv() and xmit() to be optional Tim Harvey
@ 2022-10-28 0:49 ` Tim Harvey
2022-10-28 0:49 ` [PATCH v8 6/8] net: fec: add support for DM_MDIO Tim Harvey
` (3 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Tim Harvey @ 2022-10-28 0:49 UTC (permalink / raw)
To: u-boot, Joe Hershberger, Ramon Fried, Vladimir Oltean,
Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
Marek Behún
Cc: Tim Harvey, Fabio Estevam
Remove the unnecessary xmit and recv functions.
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Fabio Estevam <festevam@denx.de>
---
v8:
- no changes
v7:
- no changes
v6:
- no changes
v5:
- added Fabio's rb tag
v4:
- no changes
v3:
- added Vladimir's rb tag
v2: new patch
---
drivers/net/ksz9477.c | 23 -----------------------
1 file changed, 23 deletions(-)
diff --git a/drivers/net/ksz9477.c b/drivers/net/ksz9477.c
index ed8f1895cb12..fb5c76c600be 100644
--- a/drivers/net/ksz9477.c
+++ b/drivers/net/ksz9477.c
@@ -62,7 +62,6 @@
struct ksz_dsa_priv {
struct udevice *dev;
- int active_port;
};
static inline int ksz_read8(struct udevice *dev, u32 reg, u8 *val)
@@ -382,9 +381,6 @@ static int ksz_port_enable(struct udevice *dev, int port, struct phy_device *phy
data8 |= SW_START;
ksz_write8(priv->dev, REG_SW_OPERATION, data8);
- /* keep track of current enabled non-cpu port */
- priv->active_port = port;
-
return 0;
}
@@ -413,28 +409,9 @@ static void ksz_port_disable(struct udevice *dev, int port, struct phy_device *p
*/
}
-static int ksz_xmit(struct udevice *dev, int port, void *packet, int length)
-{
- dev_dbg(dev, "%s P%d %d\n", __func__, port + 1, length);
-
- return 0;
-}
-
-static int ksz_recv(struct udevice *dev, int *port, void *packet, int length)
-{
- struct ksz_dsa_priv *priv = dev_get_priv(dev);
-
- dev_dbg(dev, "%s P%d %d\n", __func__, priv->active_port + 1, length);
- *port = priv->active_port;
-
- return 0;
-};
-
static const struct dsa_ops ksz_dsa_ops = {
.port_enable = ksz_port_enable,
.port_disable = ksz_port_disable,
- .xmit = ksz_xmit,
- .rcv = ksz_recv,
};
static int ksz_probe_mdio(struct udevice *dev)
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v8 6/8] net: fec: add support for DM_MDIO
2022-10-28 0:49 [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana Tim Harvey
` (4 preceding siblings ...)
2022-10-28 0:49 ` [PATCH v8 5/8] net: ksz9477: remove unnecessary xmit and recv functions Tim Harvey
@ 2022-10-28 0:49 ` Tim Harvey
2022-10-28 0:49 ` [PATCH v8 7/8] net: add MV88E6xxx DSA driver Tim Harvey
` (2 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Tim Harvey @ 2022-10-28 0:49 UTC (permalink / raw)
To: u-boot, Joe Hershberger, Ramon Fried, Vladimir Oltean,
Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
Marek Behún
Cc: Tim Harvey, Fabio Estevam
Add support for DM_MDIO by registering a UCLASS_MDIO driver and
attempting to use it. This is necessary if wanting to use a DSA
driver for example hanging off of the FEC MAC.
Care is taken to fallback to non DM_MDIO mii bus as several boards define
DM_MDIO without having the proper device-tree configuration necessary
such as an mdio subnode, a phy-mode prop, and either a valid phy-handle
prop or fixed-phy subnode which will cause dm_eth_phy_connect() to fail.
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Reviewed-by: Fabio Estevam <festevam@denx.de>
---
v8:
- no changes
v7:
- no changes
v6:
- no changes
v5:
- added Fabio's rb tag
v4:
- no changes
v3:
- no changes
v2:
- fix fallback mechanism for legacy dt's that do not have phy-handle
and mdio subnode
---
drivers/net/fec_mxc.c | 90 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 88 insertions(+), 2 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index bbc4434ddb9e..7057472710fa 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -30,6 +30,8 @@
#include <asm/arch/imx-regs.h>
#include <asm/mach-imx/sys_proto.h>
#include <asm-generic/gpio.h>
+#include <dm/device_compat.h>
+#include <dm/lists.h>
#include "fec_mxc.h"
#include <eth_phy.h>
@@ -1026,6 +1028,81 @@ struct mii_dev *fec_get_miibus(ulong base_addr, int dev_id)
return bus;
}
+#ifdef CONFIG_DM_MDIO
+struct dm_fec_mdio_priv {
+ struct ethernet_regs *regs;
+};
+
+static int dm_fec_mdio_read(struct udevice *dev, int addr, int devad, int reg)
+{
+ struct dm_fec_mdio_priv *priv = dev_get_priv(dev);
+
+ return fec_mdio_read(priv->regs, addr, reg);
+}
+
+static int dm_fec_mdio_write(struct udevice *dev, int addr, int devad, int reg, u16 data)
+{
+ struct dm_fec_mdio_priv *priv = dev_get_priv(dev);
+
+ return fec_mdio_write(priv->regs, addr, reg, data);
+}
+
+static const struct mdio_ops dm_fec_mdio_ops = {
+ .read = dm_fec_mdio_read,
+ .write = dm_fec_mdio_write,
+};
+
+static int dm_fec_mdio_probe(struct udevice *dev)
+{
+ struct dm_fec_mdio_priv *priv = dev_get_priv(dev);
+
+ priv->regs = (struct ethernet_regs *)ofnode_get_addr(dev_ofnode(dev->parent));
+
+ return 0;
+}
+
+U_BOOT_DRIVER(fec_mdio) = {
+ .name = "fec_mdio",
+ .id = UCLASS_MDIO,
+ .probe = dm_fec_mdio_probe,
+ .ops = &dm_fec_mdio_ops,
+ .priv_auto = sizeof(struct dm_fec_mdio_priv),
+};
+
+static int dm_fec_bind_mdio(struct udevice *dev)
+{
+ struct udevice *mdiodev;
+ const char *name;
+ ofnode mdio;
+ int ret = -ENODEV;
+
+ /* for a UCLASS_MDIO driver we need to bind and probe manually
+ * for an internal MDIO bus that has no dt compatible of its own
+ */
+ ofnode_for_each_subnode(mdio, dev_ofnode(dev)) {
+ name = ofnode_get_name(mdio);
+
+ if (strcmp(name, "mdio"))
+ continue;
+
+ ret = device_bind_driver_to_node(dev, "fec_mdio",
+ name, mdio, &mdiodev);
+ if (ret) {
+ printf("%s bind %s failed: %d\n", __func__, name, ret);
+ break;
+ }
+
+ /* need to probe it as there is no compatible to do so */
+ ret = uclass_get_device_by_ofnode(UCLASS_MDIO, mdio, &mdiodev);
+ if (!ret)
+ return 0;
+ printf("%s probe %s failed: %d\n", __func__, name, ret);
+ }
+
+ return ret;
+}
+#endif
+
static int fecmxc_read_rom_hwaddr(struct udevice *dev)
{
struct fec_priv *priv = dev_get_priv(dev);
@@ -1089,7 +1166,7 @@ static int device_get_phy_addr(struct fec_priv *priv, struct udevice *dev)
static int fec_phy_init(struct fec_priv *priv, struct udevice *dev)
{
- struct phy_device *phydev;
+ struct phy_device *phydev = NULL;
int addr;
addr = device_get_phy_addr(priv, dev);
@@ -1097,7 +1174,10 @@ static int fec_phy_init(struct fec_priv *priv, struct udevice *dev)
addr = CONFIG_FEC_MXC_PHYADDR;
#endif
- phydev = phy_connect(priv->bus, addr, dev, priv->interface);
+ if (IS_ENABLED(CONFIG_DM_MDIO))
+ phydev = dm_eth_phy_connect(dev);
+ if (!phydev)
+ phydev = phy_connect(priv->bus, addr, dev, priv->interface);
if (!phydev)
return -ENODEV;
@@ -1228,6 +1308,12 @@ static int fecmxc_probe(struct udevice *dev)
priv->dev_id = dev_seq(dev);
+ if (IS_ENABLED(CONFIG_DM_MDIO)) {
+ ret = dm_fec_bind_mdio(dev);
+ if (ret && ret != -ENODEV)
+ return ret;
+ }
+
#ifdef CONFIG_DM_ETH_PHY
bus = eth_phy_get_mdio_bus(dev);
#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v8 7/8] net: add MV88E6xxx DSA driver
2022-10-28 0:49 [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana Tim Harvey
` (5 preceding siblings ...)
2022-10-28 0:49 ` [PATCH v8 6/8] net: fec: add support for DM_MDIO Tim Harvey
@ 2022-10-28 0:49 ` Tim Harvey
2022-10-28 0:49 ` [PATCH v8 8/8] board: gw_ventana: enable MV88E61XX DSA support Tim Harvey
2022-10-28 8:45 ` [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana Vladimir Oltean
8 siblings, 0 replies; 18+ messages in thread
From: Tim Harvey @ 2022-10-28 0:49 UTC (permalink / raw)
To: u-boot, Joe Hershberger, Ramon Fried, Vladimir Oltean,
Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
Marek Behún
Cc: Tim Harvey, Fabio Estevam
Add a DSA driver for the MV88E6xxx compatible Ethernet switches.
Cc: Marek Behún <marek.behun@nic.cz>
Cc: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Fabio Estevam <festevam@denx.de>
---
v8:
- remove energy-detect low-power mode config
v7:
- rebase on master
- update commit short msg (s/MV88E61xx/MV88E6xxx)
- replace inline smi_cmd* with macros using logical operators
- replace bitfield_replace with logical operators for readibility
- removed some unused register definitions
- config switch based SERDES mode once in probe vs port_enable
- rework port_enable to clean up and:
- enable energy-detect for all non fixed PHY ports
- configure RGMII delays based on interface type
v6:
- update commit msg (s/MV88E61xx/MV88E6xxx)
- remove GbE from commit msg and Kconfig desc
- squash accidental change from patch 7 into patch 6
- added error print on failure to read switch id
- mv88e6xxx_probe:
- check for switch enabled
- remove unused variable enabled
- remove unnecessary call to dsa_set_tagging
- port_probe:
- new function to configure phy features by calling phy_config
- port_enable:
- only enable energy-detect sensing on phy ports
- add phy/cmode verification mistmatch warning
- remove mv88e6xxx_fixed_port_setup()
- always force link up for fixed ports
- always set SERDES mode regardless of cpu port
- remove unnecessary setting of CPUDEST
- port_disable:
- remove pointless error check
- removed unnecessary priv data for mdio controller
- fix indentation
- change variable name for clarity
v5:
- added support for MV88E6320
- added Fabio's rb tag
v4:
- rename to mv88e6xxx
- sort includes alphabetically
- remove dsa term from function names
- reduce indentation level and remove unecessary code in of probe_mdio function
- rename pdev to mdev to represent mdio device
v3:
- Added Vladimir's rb tag
v2:
- rebase on v2022.07-rc1 (use ofnode_get_phy_node)
- remove unused commented out fields from struct
- remove unused PORT_MASK macro
- remove phy from priv struct name
- refactor code from original drivers/net/phy/mv88e61xx with
suggestions from review to consolidate some functions
into mv88e61xx_dsa_port_enable
- remove unecessary skiping of disabling of CPU port
- remove unecessary dev_set_parent_priv
- remove unnecessary static init flag
- replace debug with a dev_warn if switch device-id unsupported
- remove unnecessary xmit/recv functions as we rely on the fact that
only a single port is active instead of mangling packets
---
drivers/net/Kconfig | 7 +
drivers/net/Makefile | 1 +
drivers/net/mv88e6xxx.c | 755 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 763 insertions(+)
create mode 100644 drivers/net/mv88e6xxx.c
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6bbbadc5eef3..67f23917f42c 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -438,6 +438,13 @@ config KSZ9477
This driver implements a DSA switch driver for the KSZ9477 family
of GbE switches using the I2C interface.
+config MV88E6XXX
+ bool "Marvell MV88E6xxx Ethernet switch DSA driver"
+ depends on DM_DSA && DM_MDIO
+ help
+ This driver implements a DSA switch driver for the MV88E6xxx family
+ of Ethernet switches using the MDIO interface
+
config MVGBE
bool "Marvell Orion5x/Kirkwood network interface support"
depends on ARCH_KIRKWOOD || ARCH_ORION5X
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 96b7678e9882..f05fd58e3fa7 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_MEDIATEK_ETH) += mtk_eth.o
obj-$(CONFIG_MPC8XX_FEC) += mpc8xx_fec.o
obj-$(CONFIG_MT7620_ETH) += mt7620-eth.o
obj-$(CONFIG_MT7628_ETH) += mt7628-eth.o
+obj-$(CONFIG_MV88E6XXX) += mv88e6xxx.o
obj-$(CONFIG_MVGBE) += mvgbe.o
obj-$(CONFIG_MVMDIO) += mvmdio.o
obj-$(CONFIG_MVNETA) += mvneta.o
diff --git a/drivers/net/mv88e6xxx.c b/drivers/net/mv88e6xxx.c
new file mode 100644
index 000000000000..64e860e324dc
--- /dev/null
+++ b/drivers/net/mv88e6xxx.c
@@ -0,0 +1,755 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022
+ * Gateworks Corporation <www.gateworks.com>
+ * Tim Harvey <tharvey@gateworks.com>
+ *
+ * (C) Copyright 2015
+ * Elecsys Corporation <www.elecsyscorp.com>
+ * Kevin Smith <kevin.smith@elecsyscorp.com>
+ *
+ * Original driver:
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Prafulla Wadaskar <prafulla@marvell.com>
+ */
+
+/*
+ * DSA driver for mv88e6xxx ethernet switches.
+ *
+ * This driver configures the mv88e6xxx for basic use as a DSA switch.
+ *
+ * This driver was adapted from drivers/net/phy/mv88e61xx and tested
+ * on the mv88e6176 via an SGMII interface.
+ */
+
+#include <common.h>
+#include <dm/device.h>
+#include <dm/device_compat.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/of_extra.h>
+#include <linux/delay.h>
+#include <miiphy.h>
+#include <net/dsa.h>
+
+/* Device addresses */
+#define DEVADDR_PHY(p) (p)
+#define DEVADDR_SERDES 0x0F
+
+/* SMI indirection registers for multichip addressing mode */
+#define SMI_CMD_REG 0x00
+#define SMI_DATA_REG 0x01
+
+/* Global registers */
+#define GLOBAL1_STATUS 0x00
+#define GLOBAL1_CTRL 0x04
+
+/* Global 2 registers */
+#define GLOBAL2_REG_PHY_CMD 0x18
+#define GLOBAL2_REG_PHY_DATA 0x19
+#define GLOBAL2_REG_SCRATCH 0x1A
+
+/* Port registers */
+#define PORT_REG_STATUS 0x00
+#define PORT_REG_PHYS_CTRL 0x01
+#define PORT_REG_SWITCH_ID 0x03
+#define PORT_REG_CTRL 0x04
+
+/* Phy registers */
+#define PHY_REG_PAGE 0x16
+
+/* Phy page numbers */
+#define PHY_PAGE_COPPER 0
+#define PHY_PAGE_SERDES 1
+
+/* Register fields */
+#define GLOBAL1_CTRL_SWRESET BIT(15)
+
+#define PORT_REG_STATUS_SPEED_SHIFT 8
+#define PORT_REG_STATUS_SPEED_10 0
+#define PORT_REG_STATUS_SPEED_100 1
+#define PORT_REG_STATUS_SPEED_1000 2
+
+#define PORT_REG_STATUS_CMODE_MASK 0xF
+#define PORT_REG_STATUS_CMODE_SGMII 0xa
+#define PORT_REG_STATUS_CMODE_1000BASE_X 0x9
+#define PORT_REG_STATUS_CMODE_100BASE_X 0x8
+#define PORT_REG_STATUS_CMODE_RGMII 0x7
+#define PORT_REG_STATUS_CMODE_RMII 0x5
+#define PORT_REG_STATUS_CMODE_RMII_PHY 0x4
+#define PORT_REG_STATUS_CMODE_GMII 0x3
+#define PORT_REG_STATUS_CMODE_MII 0x2
+#define PORT_REG_STATUS_CMODE_MIIPHY 0x1
+
+#define PORT_REG_PHYS_CTRL_RGMII_DELAY_RXCLK BIT(15)
+#define PORT_REG_PHYS_CTRL_RGMII_DELAY_TXCLK BIT(14)
+#define PORT_REG_PHYS_CTRL_PCS_AN_EN BIT(10)
+#define PORT_REG_PHYS_CTRL_PCS_AN_RST BIT(9)
+#define PORT_REG_PHYS_CTRL_FC_VALUE BIT(7)
+#define PORT_REG_PHYS_CTRL_FC_FORCE BIT(6)
+#define PORT_REG_PHYS_CTRL_LINK_VALUE BIT(5)
+#define PORT_REG_PHYS_CTRL_LINK_FORCE BIT(4)
+#define PORT_REG_PHYS_CTRL_DUPLEX_VALUE BIT(3)
+#define PORT_REG_PHYS_CTRL_DUPLEX_FORCE BIT(2)
+#define PORT_REG_PHYS_CTRL_SPD1000 BIT(1)
+#define PORT_REG_PHYS_CTRL_SPD100 BIT(0)
+#define PORT_REG_PHYS_CTRL_SPD_MASK (BIT(1) | BIT(0))
+
+#define PORT_REG_CTRL_PSTATE_SHIFT 0
+#define PORT_REG_CTRL_PSTATE_MASK 3
+
+/* Field values */
+#define PORT_REG_CTRL_PSTATE_DISABLED 0
+#define PORT_REG_CTRL_PSTATE_FORWARD 3
+
+/*
+ * Macros for building commands for indirect addressing modes. These are valid
+ * for both the indirect multichip addressing mode and the PHY indirection
+ * required for the writes to any PHY register.
+ */
+#define SMI_BUSY BIT(15)
+#define SMI_CMD_CLAUSE_22 BIT(12)
+#define SMI_CMD_CLAUSE_22_OP_READ (2 << 10)
+#define SMI_CMD_CLAUSE_22_OP_WRITE (1 << 10)
+#define SMI_CMD_ADDR_SHIFT 5
+#define SMI_CMD_ADDR_MASK 0x1f
+#define SMI_CMD_REG_SHIFT 0
+#define SMI_CMD_REG_MASK 0x1f
+#define SMI_CMD_READ(addr, reg) \
+ (SMI_BUSY | SMI_CMD_CLAUSE_22 | SMI_CMD_CLAUSE_22_OP_READ) | \
+ (((addr) & SMI_CMD_ADDR_MASK) << SMI_CMD_ADDR_SHIFT) | \
+ (((reg) & SMI_CMD_REG_MASK) << SMI_CMD_REG_SHIFT)
+#define SMI_CMD_WRITE(addr, reg) \
+ (SMI_BUSY | SMI_CMD_CLAUSE_22 | SMI_CMD_CLAUSE_22_OP_WRITE) | \
+ (((addr) & SMI_CMD_ADDR_MASK) << SMI_CMD_ADDR_SHIFT) | \
+ (((reg) & SMI_CMD_REG_MASK) << SMI_CMD_REG_SHIFT)
+
+/* ID register values for different switch models */
+#define PORT_SWITCH_ID_6020 0x0200
+#define PORT_SWITCH_ID_6070 0x0700
+#define PORT_SWITCH_ID_6071 0x0710
+#define PORT_SWITCH_ID_6096 0x0980
+#define PORT_SWITCH_ID_6097 0x0990
+#define PORT_SWITCH_ID_6172 0x1720
+#define PORT_SWITCH_ID_6176 0x1760
+#define PORT_SWITCH_ID_6220 0x2200
+#define PORT_SWITCH_ID_6240 0x2400
+#define PORT_SWITCH_ID_6250 0x2500
+#define PORT_SWITCH_ID_6320 0x1150
+#define PORT_SWITCH_ID_6352 0x3520
+
+struct mv88e6xxx_priv {
+ int smi_addr;
+ int id;
+ int port_count; /* Number of switch ports */
+ int port_reg_base; /* Base of the switch port registers */
+ u8 global1; /* Offset of Switch Global 1 registers */
+ u8 global2; /* Offset of Switch Global 2 registers */
+};
+
+/* Wait for the current SMI indirect command to complete */
+static int mv88e6xxx_smi_wait(struct udevice *dev, int smi_addr)
+{
+ int val;
+ u32 timeout = 100;
+
+ do {
+ val = dm_mdio_read(dev->parent, smi_addr, MDIO_DEVAD_NONE, SMI_CMD_REG);
+ if (val >= 0 && (val & SMI_BUSY) == 0)
+ return 0;
+
+ mdelay(1);
+ } while (--timeout);
+
+ dev_err(dev, "SMI busy timeout\n");
+ return -ETIMEDOUT;
+}
+
+/*
+ * The mv88e6xxx has three types of addresses: the smi bus address, the device
+ * address, and the register address. The smi bus address distinguishes it on
+ * the smi bus from other PHYs or switches. The device address determines
+ * which on-chip register set you are reading/writing (the various PHYs, their
+ * associated ports, or global configuration registers). The register address
+ * is the offset of the register you are reading/writing.
+ *
+ * When the mv88e6xxx is hardware configured to have address zero, it behaves in
+ * single-chip addressing mode, where it responds to all SMI addresses, using
+ * the smi address as its device address. This obviously only works when this
+ * is the only chip on the SMI bus. This allows the driver to access device
+ * registers without using indirection. When the chip is configured to a
+ * non-zero address, it only responds to that SMI address and requires indirect
+ * writes to access the different device addresses.
+ */
+static int mv88e6xxx_reg_read(struct udevice *dev, int addr, int reg)
+{
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
+ int smi_addr = priv->smi_addr;
+ int res;
+
+ /* In single-chip mode, the device can be addressed directly */
+ if (smi_addr == 0)
+ return dm_mdio_read(dev->parent, addr, MDIO_DEVAD_NONE, reg);
+
+ /* Wait for the bus to become free */
+ res = mv88e6xxx_smi_wait(dev, smi_addr);
+ if (res < 0)
+ return res;
+
+ /* Issue the read command */
+ res = dm_mdio_write(dev->parent, smi_addr, MDIO_DEVAD_NONE, SMI_CMD_REG,
+ SMI_CMD_READ(addr, reg));
+ if (res < 0)
+ return res;
+
+ /* Wait for the read command to complete */
+ res = mv88e6xxx_smi_wait(dev, smi_addr);
+ if (res < 0)
+ return res;
+
+ /* Read the data */
+ res = dm_mdio_read(dev->parent, smi_addr, MDIO_DEVAD_NONE, SMI_DATA_REG);
+ if (res < 0)
+ return res;
+
+ return res & 0xffff;
+}
+
+/* See the comment above mv88e6xxx_reg_read */
+static int mv88e6xxx_reg_write(struct udevice *dev, int addr, int reg, u16 val)
+{
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
+ int smi_addr = priv->smi_addr;
+ int res;
+
+ /* In single-chip mode, the device can be addressed directly */
+ if (smi_addr == 0)
+ return dm_mdio_write(dev->parent, addr, MDIO_DEVAD_NONE, reg, val);
+
+ /* Wait for the bus to become free */
+ res = mv88e6xxx_smi_wait(dev, smi_addr);
+ if (res < 0)
+ return res;
+
+ /* Set the data to write */
+ res = dm_mdio_write(dev->parent, smi_addr, MDIO_DEVAD_NONE,
+ SMI_DATA_REG, val);
+ if (res < 0)
+ return res;
+
+ /* Issue the write command */
+ res = dm_mdio_write(dev->parent, smi_addr, MDIO_DEVAD_NONE, SMI_CMD_REG,
+ SMI_CMD_WRITE(addr, reg));
+ if (res < 0)
+ return res;
+
+ /* Wait for the write command to complete */
+ res = mv88e6xxx_smi_wait(dev, smi_addr);
+ if (res < 0)
+ return res;
+
+ return 0;
+}
+
+static int mv88e6xxx_phy_wait(struct udevice *dev)
+{
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
+ int val;
+ u32 timeout = 100;
+
+ do {
+ val = mv88e6xxx_reg_read(dev, priv->global2, GLOBAL2_REG_PHY_CMD);
+ if (val >= 0 && (val & SMI_BUSY) == 0)
+ return 0;
+
+ mdelay(1);
+ } while (--timeout);
+
+ return -ETIMEDOUT;
+}
+
+static int mv88e6xxx_phy_read_indirect(struct udevice *dev, int phyad, int devad, int reg)
+{
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
+ int res;
+
+ /* Issue command to read */
+ res = mv88e6xxx_reg_write(dev, priv->global2,
+ GLOBAL2_REG_PHY_CMD,
+ SMI_CMD_READ(phyad, reg));
+
+ /* Wait for data to be read */
+ res = mv88e6xxx_phy_wait(dev);
+ if (res < 0)
+ return res;
+
+ /* Read retrieved data */
+ return mv88e6xxx_reg_read(dev, priv->global2,
+ GLOBAL2_REG_PHY_DATA);
+}
+
+static int mv88e6xxx_phy_write_indirect(struct udevice *dev, int phyad,
+ int devad, int reg, u16 data)
+{
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
+ int res;
+
+ /* Set the data to write */
+ res = mv88e6xxx_reg_write(dev, priv->global2,
+ GLOBAL2_REG_PHY_DATA, data);
+ if (res < 0)
+ return res;
+ /* Issue the write command */
+ res = mv88e6xxx_reg_write(dev, priv->global2,
+ GLOBAL2_REG_PHY_CMD,
+ SMI_CMD_WRITE(phyad, reg));
+ if (res < 0)
+ return res;
+
+ /* Wait for command to complete */
+ return mv88e6xxx_phy_wait(dev);
+}
+
+/* Wrapper function to make calls to phy_read_indirect simpler */
+static int mv88e6xxx_phy_read(struct udevice *dev, int phy, int reg)
+{
+ return mv88e6xxx_phy_read_indirect(dev, DEVADDR_PHY(phy),
+ MDIO_DEVAD_NONE, reg);
+}
+
+/* Wrapper function to make calls to phy_write_indirect simpler */
+static int mv88e6xxx_phy_write(struct udevice *dev, int phy, int reg, u16 val)
+{
+ return mv88e6xxx_phy_write_indirect(dev, DEVADDR_PHY(phy),
+ MDIO_DEVAD_NONE, reg, val);
+}
+
+static int mv88e6xxx_port_read(struct udevice *dev, u8 port, u8 reg)
+{
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
+
+ return mv88e6xxx_reg_read(dev, priv->port_reg_base + port, reg);
+}
+
+static int mv88e6xxx_port_write(struct udevice *dev, u8 port, u8 reg, u16 val)
+{
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
+
+ return mv88e6xxx_reg_write(dev, priv->port_reg_base + port, reg, val);
+}
+
+static int mv88e6xxx_set_page(struct udevice *dev, u8 phy, u8 page)
+{
+ return mv88e6xxx_phy_write(dev, phy, PHY_REG_PAGE, page);
+}
+
+static int mv88e6xxx_get_switch_id(struct udevice *dev)
+{
+ int res;
+
+ res = mv88e6xxx_port_read(dev, 0, PORT_REG_SWITCH_ID);
+ if (res < 0) {
+ dev_err(dev, "Failed to read switch ID: %d\n", res);
+ return res;
+ }
+ return res & 0xfff0;
+}
+
+static bool mv88e6xxx_6352_family(struct udevice *dev)
+{
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
+
+ switch (priv->id) {
+ case PORT_SWITCH_ID_6172:
+ case PORT_SWITCH_ID_6176:
+ case PORT_SWITCH_ID_6240:
+ case PORT_SWITCH_ID_6352:
+ return true;
+ }
+ return false;
+}
+
+static int mv88e6xxx_get_cmode(struct udevice *dev, u8 port)
+{
+ int res;
+
+ res = mv88e6xxx_port_read(dev, port, PORT_REG_STATUS);
+ if (res < 0)
+ return res;
+ return res & PORT_REG_STATUS_CMODE_MASK;
+}
+
+static int mv88e6xxx_switch_reset(struct udevice *dev)
+{
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
+ int time_ms;
+ int val;
+ u8 port;
+
+ /* Disable all ports */
+ for (port = 0; port < priv->port_count; port++) {
+ val = mv88e6xxx_port_read(dev, port, PORT_REG_CTRL);
+ if (val < 0)
+ return val;
+ val &= ~(PORT_REG_CTRL_PSTATE_MASK << PORT_REG_CTRL_PSTATE_SHIFT);
+ val |= (PORT_REG_CTRL_PSTATE_DISABLED << PORT_REG_CTRL_PSTATE_SHIFT);
+ val = mv88e6xxx_port_write(dev, port, PORT_REG_CTRL, val);
+ if (val < 0)
+ return val;
+ }
+
+ /* Wait 2 ms for queues to drain */
+ udelay(2000);
+
+ /* Reset switch */
+ val = mv88e6xxx_reg_read(dev, priv->global1, GLOBAL1_CTRL);
+ if (val < 0)
+ return val;
+ val |= GLOBAL1_CTRL_SWRESET;
+ val = mv88e6xxx_reg_write(dev, priv->global1, GLOBAL1_CTRL, val);
+ if (val < 0)
+ return val;
+
+ /* Wait up to 1 second for switch to reset complete */
+ for (time_ms = 1000; time_ms; time_ms--) {
+ val = mv88e6xxx_reg_read(dev, priv->global1, GLOBAL1_CTRL);
+ if (val >= 0 && ((val & GLOBAL1_CTRL_SWRESET) == 0))
+ break;
+ udelay(1000);
+ }
+ if (!time_ms)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int mv88e6xxx_serdes_init(struct udevice *dev)
+{
+ int val;
+
+ val = mv88e6xxx_set_page(dev, DEVADDR_SERDES, PHY_PAGE_SERDES);
+ if (val < 0)
+ return val;
+
+ /* Power up serdes module */
+ val = mv88e6xxx_phy_read(dev, DEVADDR_SERDES, MII_BMCR);
+ if (val < 0)
+ return val;
+ val &= ~(BMCR_PDOWN);
+ val = mv88e6xxx_phy_write(dev, DEVADDR_SERDES, MII_BMCR, val);
+ if (val < 0)
+ return val;
+
+ return 0;
+}
+
+/*
+ * This function is used to pre-configure the required register
+ * offsets, so that the indirect register access to the PHY registers
+ * is possible. This is necessary to be able to read the PHY ID
+ * while driver probing or in get_phy_id(). The globalN register
+ * offsets must be initialized correctly for a detected switch,
+ * otherwise detection of the PHY ID won't work!
+ */
+static int mv88e6xxx_priv_reg_offs_pre_init(struct udevice *dev)
+{
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
+
+ /*
+ * Initial 'port_reg_base' value must be an offset of existing
+ * port register, then reading the ID should succeed. First, try
+ * to read via port registers with device address 0x10 (88E6096
+ * and compatible switches).
+ */
+ priv->port_reg_base = 0x10;
+ priv->id = mv88e6xxx_get_switch_id(dev);
+ if (priv->id != 0xfff0) {
+ priv->global1 = 0x1B;
+ priv->global2 = 0x1C;
+ return 0;
+ }
+
+ /*
+ * Now try via port registers with device address 0x08
+ * (88E6020 and compatible switches).
+ */
+ priv->port_reg_base = 0x08;
+ priv->id = mv88e6xxx_get_switch_id(dev);
+ if (priv->id != 0xfff0) {
+ priv->global1 = 0x0F;
+ priv->global2 = 0x07;
+ return 0;
+ }
+
+ dev_warn(dev, "%s Unknown ID 0x%x\n", __func__, priv->id);
+
+ return -ENODEV;
+}
+
+static int mv88e6xxx_mdio_read(struct udevice *dev, int addr, int devad, int reg)
+{
+ return mv88e6xxx_phy_read_indirect(dev->parent, DEVADDR_PHY(addr),
+ MDIO_DEVAD_NONE, reg);
+}
+
+static int mv88e6xxx_mdio_write(struct udevice *dev, int addr, int devad,
+ int reg, u16 val)
+{
+ return mv88e6xxx_phy_write_indirect(dev->parent, DEVADDR_PHY(addr),
+ MDIO_DEVAD_NONE, reg, val);
+}
+
+static const struct mdio_ops mv88e6xxx_mdio_ops = {
+ .read = mv88e6xxx_mdio_read,
+ .write = mv88e6xxx_mdio_write,
+};
+
+static int mv88e6xxx_mdio_bind(struct udevice *dev)
+{
+ char name[32];
+ static int num_devices;
+
+ sprintf(name, "mv88e6xxx-mdio-%d", num_devices++);
+ device_set_name(dev, name);
+
+ return 0;
+}
+
+U_BOOT_DRIVER(mv88e6xxx_mdio) = {
+ .name = "mv88e6xxx_mdio",
+ .id = UCLASS_MDIO,
+ .ops = &mv88e6xxx_mdio_ops,
+ .bind = mv88e6xxx_mdio_bind,
+ .plat_auto = sizeof(struct mdio_perdev_priv),
+};
+
+static int mv88e6xxx_port_probe(struct udevice *dev, int port, struct phy_device *phy)
+{
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
+ int supported;
+
+ switch (priv->id) {
+ case PORT_SWITCH_ID_6020:
+ case PORT_SWITCH_ID_6070:
+ case PORT_SWITCH_ID_6071:
+ supported = PHY_BASIC_FEATURES | SUPPORTED_MII;
+ break;
+ default:
+ supported = PHY_GBIT_FEATURES;
+ break;
+ }
+
+ phy->supported &= supported;
+ phy->advertising &= supported;
+
+ return phy_config(phy);
+}
+
+static int mv88e6xxx_port_enable(struct udevice *dev, int port, struct phy_device *phy)
+{
+ int val, ret;
+
+ dev_dbg(dev, "%s P%d phy:0x%08x %s\n", __func__, port,
+ phy->phy_id, phy_string_for_interface(phy->interface));
+
+ if (phy->phy_id == PHY_FIXED_ID) {
+ /* Physical Control register: Table 62 */
+ val = mv88e6xxx_port_read(dev, port, PORT_REG_PHYS_CTRL);
+
+ /* configure RGMII delays for fixed link */
+ switch (phy->interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ dev_dbg(dev, "configure internal RGMII delays\n");
+
+ /* RGMII delays */
+ val &= ~(PORT_REG_PHYS_CTRL_RGMII_DELAY_RXCLK ||
+ PORT_REG_PHYS_CTRL_RGMII_DELAY_TXCLK);
+ if (phy->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+ phy->interface == PHY_INTERFACE_MODE_RGMII_RXID)
+ val |= PORT_REG_PHYS_CTRL_RGMII_DELAY_RXCLK;
+ if (phy->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+ phy->interface == PHY_INTERFACE_MODE_RGMII_TXID)
+ val |= PORT_REG_PHYS_CTRL_RGMII_DELAY_TXCLK;
+ break;
+ default:
+ break;
+ }
+
+ /* Force Link */
+ val |= PORT_REG_PHYS_CTRL_LINK_VALUE |
+ PORT_REG_PHYS_CTRL_LINK_FORCE;
+
+ ret = mv88e6xxx_port_write(dev, port, PORT_REG_PHYS_CTRL, val);
+ if (ret < 0)
+ return ret;
+
+ if (mv88e6xxx_6352_family(dev)) {
+ /* validate interface type */
+ dev_dbg(dev, "validate interface type\n");
+ val = mv88e6xxx_get_cmode(dev, port);
+ if (val < 0)
+ return val;
+ switch (phy->interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ if (val != PORT_REG_STATUS_CMODE_RGMII)
+ goto mismatch;
+ break;
+ case PHY_INTERFACE_MODE_1000BASEX:
+ if (val != PORT_REG_STATUS_CMODE_1000BASE_X)
+ goto mismatch;
+ break;
+mismatch:
+ default:
+ dev_err(dev, "Mismatched PHY mode %s on port %d!\n",
+ phy_string_for_interface(phy->interface), port);
+ break;
+ }
+ }
+ }
+
+ /* enable port */
+ val = mv88e6xxx_port_read(dev, port, PORT_REG_CTRL);
+ if (val < 0)
+ return val;
+ val &= ~(PORT_REG_CTRL_PSTATE_MASK << PORT_REG_CTRL_PSTATE_SHIFT);
+ val |= (PORT_REG_CTRL_PSTATE_FORWARD << PORT_REG_CTRL_PSTATE_SHIFT);
+ val = mv88e6xxx_port_write(dev, port, PORT_REG_CTRL, val);
+ if (val < 0)
+ return val;
+
+ return phy_startup(phy);
+}
+
+static void mv88e6xxx_port_disable(struct udevice *dev, int port, struct phy_device *phy)
+{
+ int val;
+
+ dev_dbg(dev, "%s P%d phy:0x%08x %s\n", __func__, port,
+ phy->phy_id, phy_string_for_interface(phy->interface));
+
+ val = mv88e6xxx_port_read(dev, port, PORT_REG_CTRL);
+ val &= ~(PORT_REG_CTRL_PSTATE_MASK << PORT_REG_CTRL_PSTATE_SHIFT);
+ val |= (PORT_REG_CTRL_PSTATE_DISABLED << PORT_REG_CTRL_PSTATE_SHIFT);
+ mv88e6xxx_port_write(dev, port, PORT_REG_CTRL, val);
+}
+
+static const struct dsa_ops mv88e6xxx_dsa_ops = {
+ .port_probe = mv88e6xxx_port_probe,
+ .port_enable = mv88e6xxx_port_enable,
+ .port_disable = mv88e6xxx_port_disable,
+};
+
+/* bind and probe the switch mdios */
+static int mv88e6xxx_probe_mdio(struct udevice *dev)
+{
+ struct udevice *mdev;
+ const char *name;
+ ofnode node;
+ int ret;
+
+ /* bind phy ports of mdio child node to mv88e6xxx_mdio device */
+ node = dev_read_subnode(dev, "mdio");
+ if (!ofnode_valid(node))
+ return 0;
+
+ name = ofnode_get_name(node);
+ ret = device_bind_driver_to_node(dev,
+ "mv88e6xxx_mdio",
+ name, node, NULL);
+ if (ret) {
+ dev_err(dev, "failed to bind %s: %d\n", name, ret);
+ } else {
+ /* need to probe it as there is no compatible to do so */
+ ret = uclass_get_device_by_ofnode(UCLASS_MDIO, node, &mdev);
+ if (ret)
+ dev_err(dev, "failed to probe %s: %d\n", name, ret);
+ }
+
+ return ret;
+}
+
+static int mv88e6xxx_probe(struct udevice *dev)
+{
+ struct dsa_pdata *dsa_pdata = dev_get_uclass_plat(dev);
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
+ int val, ret;
+
+ if (ofnode_valid(dev_ofnode(dev)) &&
+ !ofnode_is_enabled(dev_ofnode(dev))) {
+ dev_dbg(dev, "switch disabled\n");
+ return -ENODEV;
+ }
+
+ /* probe internal mdio bus */
+ ret = mv88e6xxx_probe_mdio(dev);
+ if (ret)
+ return ret;
+
+ ret = mv88e6xxx_priv_reg_offs_pre_init(dev);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "ID=0x%x PORT_BASE=0x%02x GLOBAL1=0x%02x GLOBAL2=0x%02x\n",
+ priv->id, priv->port_reg_base, priv->global1, priv->global2);
+ switch (priv->id) {
+ case PORT_SWITCH_ID_6096:
+ case PORT_SWITCH_ID_6097:
+ case PORT_SWITCH_ID_6172:
+ case PORT_SWITCH_ID_6176:
+ case PORT_SWITCH_ID_6240:
+ case PORT_SWITCH_ID_6352:
+ priv->port_count = 11;
+ break;
+ case PORT_SWITCH_ID_6020:
+ case PORT_SWITCH_ID_6070:
+ case PORT_SWITCH_ID_6071:
+ case PORT_SWITCH_ID_6220:
+ case PORT_SWITCH_ID_6250:
+ case PORT_SWITCH_ID_6320:
+ priv->port_count = 7;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ ret = mv88e6xxx_switch_reset(dev);
+ if (ret < 0)
+ return ret;
+
+ if (mv88e6xxx_6352_family(dev)) {
+ val = mv88e6xxx_get_cmode(dev, dsa_pdata->cpu_port);
+ if (val < 0)
+ return val;
+ /* initialize serdes */
+ if (val == PORT_REG_STATUS_CMODE_100BASE_X ||
+ val == PORT_REG_STATUS_CMODE_1000BASE_X ||
+ val == PORT_REG_STATUS_CMODE_SGMII) {
+ ret = mv88e6xxx_serdes_init(dev);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static const struct udevice_id mv88e6xxx_ids[] = {
+ { .compatible = "marvell,mv88e6085" },
+ { }
+};
+
+U_BOOT_DRIVER(mv88e6xxx) = {
+ .name = "mv88e6xxx",
+ .id = UCLASS_DSA,
+ .of_match = mv88e6xxx_ids,
+ .probe = mv88e6xxx_probe,
+ .ops = &mv88e6xxx_dsa_ops,
+ .priv_auto = sizeof(struct mv88e6xxx_priv),
+};
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v8 8/8] board: gw_ventana: enable MV88E61XX DSA support
2022-10-28 0:49 [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana Tim Harvey
` (6 preceding siblings ...)
2022-10-28 0:49 ` [PATCH v8 7/8] net: add MV88E6xxx DSA driver Tim Harvey
@ 2022-10-28 0:49 ` Tim Harvey
2022-10-28 8:45 ` [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana Vladimir Oltean
8 siblings, 0 replies; 18+ messages in thread
From: Tim Harvey @ 2022-10-28 0:49 UTC (permalink / raw)
To: u-boot, Joe Hershberger, Ramon Fried, Vladimir Oltean,
Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
Marek Behún
Cc: Tim Harvey, Fabio Estevam
Add MV88E61XX DSA support:
- update dt to provide internal MDIO bus and port handles.
U-Boot requires a more restrictive subset of the dt bindings
required by Linux for the sake of simplifying code
- update defconfig to remove old driver and enable new one
- replace mv88e61xx_hw_reset weak override with board_phy_config support
for register configuration that is outside the scope of the DSA driver
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Reviewed-by: Fabio Estevam <festevam@denx.de>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
v8:
- added phy-mode = "internal" to phy ports
v7:
- added Vladimir's rb tag
v6:
- update commit message
- squash accidently change to mv88e6xxx driver into previous patch
- remove unused label for cpu port
v5:
- fix typo in defconfig s/MV88E61XX/MV88E6XXX
- added Fabio's rb tag
v4:
- use standard Linux internal MDIO dt structure
- use PHY_FIXED_ID define
v3:
- move mdio's mdio@0 subnode
v2: no changes
---
arch/arm/dts/imx6qdl-gw5904.dtsi | 36 +++++++++++++++++-
board/gateworks/gw_ventana/gw_ventana.c | 50 +++++++++----------------
configs/gwventana_gw5904_defconfig | 7 ++--
3 files changed, 56 insertions(+), 37 deletions(-)
diff --git a/arch/arm/dts/imx6qdl-gw5904.dtsi b/arch/arm/dts/imx6qdl-gw5904.dtsi
index 612b6e068e28..ea54922f15f8 100644
--- a/arch/arm/dts/imx6qdl-gw5904.dtsi
+++ b/arch/arm/dts/imx6qdl-gw5904.dtsi
@@ -212,6 +212,27 @@
compatible = "marvell,mv88e6085";
reg = <0>;
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sw_phy0: ethernet-phy@0 {
+ reg = <0x0>;
+ };
+
+ sw_phy1: ethernet-phy@1 {
+ reg = <0x1>;
+ };
+
+ sw_phy2: ethernet-phy@2 {
+ reg = <0x2>;
+ };
+
+ sw_phy3: ethernet-phy@3 {
+ reg = <0x3>;
+ };
+ };
+
ports {
#address-cells = <1>;
#size-cells = <0>;
@@ -219,27 +240,40 @@
port@0 {
reg = <0>;
label = "lan4";
+ phy-handle = <&sw_phy0>;
+ phy-mode = "internal";
};
port@1 {
reg = <1>;
label = "lan3";
+ phy-handle = <&sw_phy1>;
+ phy-mode = "internal";
};
port@2 {
reg = <2>;
label = "lan2";
+ phy-handle = <&sw_phy2>;
+ phy-mode = "internal";
};
port@3 {
reg = <3>;
label = "lan1";
+ phy-handle = <&sw_phy3>;
+ phy-mode = "internal";
};
port@5 {
reg = <5>;
- label = "cpu";
ethernet = <&fec>;
+ phy-mode = "rgmii-id";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
};
};
};
diff --git a/board/gateworks/gw_ventana/gw_ventana.c b/board/gateworks/gw_ventana/gw_ventana.c
index 0ecfd98c2261..683def7e9f71 100644
--- a/board/gateworks/gw_ventana/gw_ventana.c
+++ b/board/gateworks/gw_ventana/gw_ventana.c
@@ -83,44 +83,30 @@ int board_phy_config(struct phy_device *phydev)
break;
}
+ /* Fixed PHY: for GW5904/GW5909 this is Marvell 88E6176 GbE Switch */
+ if (phydev->phy_id == PHY_FIXED_ID &&
+ (board_type == GW5904 || board_type == GW5909)) {
+ struct mii_dev *bus = miiphy_get_dev_by_name("mdio");
+
+ puts("MV88E61XX ");
+ /* GPIO[0] output CLK125 for RGMII_REFCLK */
+ bus->write(bus, 0x1c, 0, 0x1a, (1 << 15) | (0x62 << 8) | 0xfe);
+ bus->write(bus, 0x1c, 0, 0x1a, (1 << 15) | (0x68 << 8) | 7);
+
+ /* Port 0-3 LED configuration: Table 80/82 */
+ /* LED configuration: 7:4-green (8=Activity) 3:0 amber (8=Link) */
+ bus->write(bus, 0x10, 0, 0x16, 0x8088);
+ bus->write(bus, 0x11, 0, 0x16, 0x8088);
+ bus->write(bus, 0x12, 0, 0x16, 0x8088);
+ bus->write(bus, 0x13, 0, 0x16, 0x8088);
+ }
+
if (phydev->drv->config)
phydev->drv->config(phydev);
return 0;
}
-#ifdef CONFIG_MV88E61XX_SWITCH
-int mv88e61xx_hw_reset(struct phy_device *phydev)
-{
- struct mii_dev *bus = phydev->bus;
-
- /* GPIO[0] output, CLK125 */
- debug("enabling RGMII_REFCLK\n");
- bus->write(bus, 0x1c /*MV_GLOBAL2*/, 0,
- 0x1a /*MV_SCRATCH_MISC*/,
- (1 << 15) | (0x62 /*MV_GPIO_DIR*/ << 8) | 0xfe);
- bus->write(bus, 0x1c /*MV_GLOBAL2*/, 0,
- 0x1a /*MV_SCRATCH_MISC*/,
- (1 << 15) | (0x68 /*MV_GPIO01_CNTL*/ << 8) | 7);
-
- /* RGMII delay - Physical Control register bit[15:14] */
- debug("setting port%d RGMII rx/tx delay\n", CONFIG_MV88E61XX_CPU_PORT);
- /* forced 1000mbps full-duplex link */
- bus->write(bus, 0x10 + CONFIG_MV88E61XX_CPU_PORT, 0, 1, 0xc0fe);
- phydev->autoneg = AUTONEG_DISABLE;
- phydev->speed = SPEED_1000;
- phydev->duplex = DUPLEX_FULL;
-
- /* LED configuration: 7:4-green (8=Activity) 3:0 amber (8=Link) */
- bus->write(bus, 0x10, 0, 0x16, 0x8088);
- bus->write(bus, 0x11, 0, 0x16, 0x8088);
- bus->write(bus, 0x12, 0, 0x16, 0x8088);
- bus->write(bus, 0x13, 0, 0x16, 0x8088);
-
- return 0;
-}
-#endif // CONFIG_MV88E61XX_SWITCH
-
#if defined(CONFIG_VIDEO_IPUV3)
static void enable_hdmi(struct display_info_t const *dev)
{
diff --git a/configs/gwventana_gw5904_defconfig b/configs/gwventana_gw5904_defconfig
index a5b31514ff12..e2cb449b7636 100644
--- a/configs/gwventana_gw5904_defconfig
+++ b/configs/gwventana_gw5904_defconfig
@@ -108,13 +108,12 @@ CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_FSL_USDHC=y
CONFIG_MTD=y
CONFIG_PHYLIB=y
-CONFIG_MV88E61XX_SWITCH=y
-CONFIG_MV88E61XX_CPU_PORT=5
-CONFIG_MV88E61XX_PHY_PORTS=0xf
-CONFIG_MV88E61XX_FIXED_PORTS=0x0
+CONFIG_PHY_FIXED=y
CONFIG_DM_MDIO=y
+CONFIG_DM_DSA=y
CONFIG_E1000=y
CONFIG_FEC_MXC=y
+CONFIG_MV88E6XXX=y
CONFIG_MII=y
CONFIG_PCI=y
CONFIG_PCIE_IMX=y
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana
2022-10-28 0:49 [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana Tim Harvey
` (7 preceding siblings ...)
2022-10-28 0:49 ` [PATCH v8 8/8] board: gw_ventana: enable MV88E61XX DSA support Tim Harvey
@ 2022-10-28 8:45 ` Vladimir Oltean
2022-10-28 15:27 ` Tim Harvey
8 siblings, 1 reply; 18+ messages in thread
From: Vladimir Oltean @ 2022-10-28 8:45 UTC (permalink / raw)
To: tharvey
Cc: u-boot, Joe Hershberger, Ramon Fried, Stefano Babic,
Fabio Estevam, dl-uboot-imx, Marek BehĂșn
On Thu, Oct 27, 2022 at 05:49:29PM -0700, Tim Harvey wrote:
> This series adds a DSA driver for the MV88E6xxx based on
> drivers/net/phy/mv88e61xx and uses it in the gwventana_gw5904_defconfig.
Looks good, thanks. To me this is ready to go!
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana
2022-10-28 8:45 ` [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana Vladimir Oltean
@ 2022-10-28 15:27 ` Tim Harvey
0 siblings, 0 replies; 18+ messages in thread
From: Tim Harvey @ 2022-10-28 15:27 UTC (permalink / raw)
To: Vladimir Oltean
Cc: u-boot, Joe Hershberger, Ramon Fried, Stefano Babic,
Fabio Estevam, dl-uboot-imx, Marek BehĂșn
On Fri, Oct 28, 2022 at 1:45 AM Vladimir Oltean <vladimir.oltean@nxp.com> wrote:
>
> On Thu, Oct 27, 2022 at 05:49:29PM -0700, Tim Harvey wrote:
> > This series adds a DSA driver for the MV88E6xxx based on
> > drivers/net/phy/mv88e61xx and uses it in the gwventana_gw5904_defconfig.
>
> Looks good, thanks. To me this is ready to go!
Vladimir,
Great - thanks for all the help on this series!
Tim
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 4/8] net: dsa: allow rcv() and xmit() to be optional
2022-10-28 0:49 ` [PATCH v8 4/8] net: dsa: allow rcv() and xmit() to be optional Tim Harvey
@ 2022-11-28 15:58 ` Tom Rini
2022-11-29 22:53 ` Tim Harvey
0 siblings, 1 reply; 18+ messages in thread
From: Tom Rini @ 2022-11-28 15:58 UTC (permalink / raw)
To: Tim Harvey
Cc: u-boot, Joe Hershberger, Ramon Fried, Vladimir Oltean,
Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
Marek Behún, Fabio Estevam
[-- Attachment #1: Type: text/plain, Size: 682 bytes --]
On Thu, Oct 27, 2022 at 05:49:33PM -0700, Tim Harvey wrote:
> Allow rcv() and xmit() dsa driver ops to be optional in case a driver
> does not care to mangle a packet as in U-Boot only one network port is
> enabled at a time and thus no packet mangling is necessary.
>
> Suggested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> Reviewed-by: Fabio Estevam <festevam@denx.de>
This causes:
FAILED test/py/tests/test_ut.py::test_ut[ut_dm_dm_test_dsa] - AssertionError: assert False
In sandbox, and I don't know if the test or the code is wrong.
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 4/8] net: dsa: allow rcv() and xmit() to be optional
2022-11-28 15:58 ` Tom Rini
@ 2022-11-29 22:53 ` Tim Harvey
2022-11-29 23:05 ` Tom Rini
2022-11-30 0:11 ` Vladimir Oltean
0 siblings, 2 replies; 18+ messages in thread
From: Tim Harvey @ 2022-11-29 22:53 UTC (permalink / raw)
To: Tom Rini
Cc: u-boot, Joe Hershberger, Ramon Fried, Vladimir Oltean,
Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
Marek Behún, Fabio Estevam
On Mon, Nov 28, 2022 at 7:58 AM Tom Rini <trini@konsulko.com> wrote:
>
> On Thu, Oct 27, 2022 at 05:49:33PM -0700, Tim Harvey wrote:
>
> > Allow rcv() and xmit() dsa driver ops to be optional in case a driver
> > does not care to mangle a packet as in U-Boot only one network port is
> > enabled at a time and thus no packet mangling is necessary.
> >
> > Suggested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> > Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> > Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> > Reviewed-by: Fabio Estevam <festevam@denx.de>
>
> This causes:
> FAILED test/py/tests/test_ut.py::test_ut[ut_dm_dm_test_dsa] - AssertionError: assert False
>
> In sandbox, and I don't know if the test or the code is wrong.
>
Tom,
I'm not familiar at all with U-Boot's sandbox or unit test
infrastructure and am trying to learn.
I've figured out how to build sandbox and run the dm_test_dsa
(./u-boot -T -c "ut dm dsa") and see the same failure as you but I
don't understand how to debug this as it seems prints I add in
dsa_port_send and dsa_port_recv (which is what this patch modifies)
don't get print when run from the test infrastructure.
When I boot u-boot sandbox (./u-boot) I don't see any network devices
at all - perhaps I'm not booting sandbox with dm or something? I need
to understand what devices/drivers sandbox is using and how to
recreate the network environment that the dm_test_dsa function is
using which calls 'net_loop':
net_ping_ip = string_to_ip("1.2.3.5");
env_set("ethact", "eth2");
ut_assertok(net_loop(PING));
env_set("ethact", "lan0");
ut_assertok(net_loop(PING));
env_set("ethact", "lan1");
ut_assertok(net_loop(PING));
env_set("ethact", "");
Best Regards,
Tim
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 4/8] net: dsa: allow rcv() and xmit() to be optional
2022-11-29 22:53 ` Tim Harvey
@ 2022-11-29 23:05 ` Tom Rini
2022-11-30 0:11 ` Vladimir Oltean
1 sibling, 0 replies; 18+ messages in thread
From: Tom Rini @ 2022-11-29 23:05 UTC (permalink / raw)
To: Tim Harvey
Cc: u-boot, Joe Hershberger, Ramon Fried, Vladimir Oltean,
Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
Marek Behún, Fabio Estevam
[-- Attachment #1: Type: text/plain, Size: 2144 bytes --]
On Tue, Nov 29, 2022 at 02:53:15PM -0800, Tim Harvey wrote:
> On Mon, Nov 28, 2022 at 7:58 AM Tom Rini <trini@konsulko.com> wrote:
> >
> > On Thu, Oct 27, 2022 at 05:49:33PM -0700, Tim Harvey wrote:
> >
> > > Allow rcv() and xmit() dsa driver ops to be optional in case a driver
> > > does not care to mangle a packet as in U-Boot only one network port is
> > > enabled at a time and thus no packet mangling is necessary.
> > >
> > > Suggested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> > > Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> > > Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> > > Reviewed-by: Fabio Estevam <festevam@denx.de>
> >
> > This causes:
> > FAILED test/py/tests/test_ut.py::test_ut[ut_dm_dm_test_dsa] - AssertionError: assert False
> >
> > In sandbox, and I don't know if the test or the code is wrong.
> >
>
> Tom,
>
> I'm not familiar at all with U-Boot's sandbox or unit test
> infrastructure and am trying to learn.
>
> I've figured out how to build sandbox and run the dm_test_dsa
> (./u-boot -T -c "ut dm dsa") and see the same failure as you but I
> don't understand how to debug this as it seems prints I add in
> dsa_port_send and dsa_port_recv (which is what this patch modifies)
> don't get print when run from the test infrastructure.
>
> When I boot u-boot sandbox (./u-boot) I don't see any network devices
> at all - perhaps I'm not booting sandbox with dm or something? I need
> to understand what devices/drivers sandbox is using and how to
> recreate the network environment that the dm_test_dsa function is
> using which calls 'net_loop':
>
> net_ping_ip = string_to_ip("1.2.3.5");
>
> env_set("ethact", "eth2");
> ut_assertok(net_loop(PING));
>
> env_set("ethact", "lan0");
> ut_assertok(net_loop(PING));
> env_set("ethact", "lan1");
> ut_assertok(net_loop(PING));
>
> env_set("ethact", "");
This is, I think, covered by:
https://u-boot.readthedocs.io/en/latest/develop/tests_sandbox.html
and that you want ./u-boot -T (or -d path/to/test.dtb)
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 4/8] net: dsa: allow rcv() and xmit() to be optional
2022-11-29 22:53 ` Tim Harvey
2022-11-29 23:05 ` Tom Rini
@ 2022-11-30 0:11 ` Vladimir Oltean
2022-11-30 0:58 ` Tim Harvey
1 sibling, 1 reply; 18+ messages in thread
From: Vladimir Oltean @ 2022-11-30 0:11 UTC (permalink / raw)
To: Tim Harvey
Cc: Tom Rini, u-boot, Joe Hershberger, Ramon Fried, Stefano Babic,
Fabio Estevam, NXP i . MX U-Boot Team, Marek BehĂșn,
Fabio Estevam
On Tue, Nov 29, 2022 at 02:53:15PM -0800, Tim Harvey wrote:
> On Mon, Nov 28, 2022 at 7:58 AM Tom Rini <trini@konsulko.com> wrote:
> >
> > On Thu, Oct 27, 2022 at 05:49:33PM -0700, Tim Harvey wrote:
> >
> > > Allow rcv() and xmit() dsa driver ops to be optional in case a driver
> > > does not care to mangle a packet as in U-Boot only one network port is
> > > enabled at a time and thus no packet mangling is necessary.
> > >
> > > Suggested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> > > Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> > > Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> > > Reviewed-by: Fabio Estevam <festevam@denx.de>
> >
> > This causes:
> > FAILED test/py/tests/test_ut.py::test_ut[ut_dm_dm_test_dsa] - AssertionError: assert False
> >
> > In sandbox, and I don't know if the test or the code is wrong.
> >
>
> Tom,
>
> I'm not familiar at all with U-Boot's sandbox or unit test
> infrastructure and am trying to learn.
>
> I've figured out how to build sandbox and run the dm_test_dsa
> (./u-boot -T -c "ut dm dsa") and see the same failure as you but I
> don't understand how to debug this as it seems prints I add in
> dsa_port_send and dsa_port_recv (which is what this patch modifies)
> don't get print when run from the test infrastructure.
>
> When I boot u-boot sandbox (./u-boot) I don't see any network devices
> at all - perhaps I'm not booting sandbox with dm or something? I need
> to understand what devices/drivers sandbox is using and how to
> recreate the network environment that the dm_test_dsa function is
> using which calls 'net_loop':
>
> net_ping_ip = string_to_ip("1.2.3.5");
>
> env_set("ethact", "eth2");
> ut_assertok(net_loop(PING));
>
> env_set("ethact", "lan0");
> ut_assertok(net_loop(PING));
> env_set("ethact", "lan1");
> ut_assertok(net_loop(PING));
>
> env_set("ethact", "");
>
> Best Regards,
>
> Tim
I use the following steps:
export KBUILD_OUTPUT=output-sandbox
make sandbox_defconfig NO_SDL=1
make -j 8 NO_SDL=1
$KBUILD_OUTPUT/u-boot -d $KBUILD_OUTPUT/arch/sandbox/dts/test.dtb
setenv ethact lan1
ping 1.2.3.5
ut dm dsa
In this case the problem with the patch is simple, sorry for not
noticing during review.
dsa_port_mangle_packet() changes the "length" variable. But if ops->xmit
exists, eth_get_ops(master)->send() is called with a bad (old) length,
the one pre mangling.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 4/8] net: dsa: allow rcv() and xmit() to be optional
2022-11-30 0:11 ` Vladimir Oltean
@ 2022-11-30 0:58 ` Tim Harvey
2022-11-30 17:25 ` Vladimir Oltean
0 siblings, 1 reply; 18+ messages in thread
From: Tim Harvey @ 2022-11-30 0:58 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Tom Rini, u-boot, Joe Hershberger, Ramon Fried, Stefano Babic,
Fabio Estevam, NXP i . MX U-Boot Team, Marek BehĂșn,
Fabio Estevam
On Tue, Nov 29, 2022 at 4:11 PM Vladimir Oltean <vladimir.oltean@nxp.com> wrote:
>
> On Tue, Nov 29, 2022 at 02:53:15PM -0800, Tim Harvey wrote:
> > On Mon, Nov 28, 2022 at 7:58 AM Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Thu, Oct 27, 2022 at 05:49:33PM -0700, Tim Harvey wrote:
> > >
> > > > Allow rcv() and xmit() dsa driver ops to be optional in case a driver
> > > > does not care to mangle a packet as in U-Boot only one network port is
> > > > enabled at a time and thus no packet mangling is necessary.
> > > >
> > > > Suggested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> > > > Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> > > > Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> > > > Reviewed-by: Fabio Estevam <festevam@denx.de>
> > >
> > > This causes:
> > > FAILED test/py/tests/test_ut.py::test_ut[ut_dm_dm_test_dsa] - AssertionError: assert False
> > >
> > > In sandbox, and I don't know if the test or the code is wrong.
> > >
> >
> > Tom,
> >
> > I'm not familiar at all with U-Boot's sandbox or unit test
> > infrastructure and am trying to learn.
> >
> > I've figured out how to build sandbox and run the dm_test_dsa
> > (./u-boot -T -c "ut dm dsa") and see the same failure as you but I
> > don't understand how to debug this as it seems prints I add in
> > dsa_port_send and dsa_port_recv (which is what this patch modifies)
> > don't get print when run from the test infrastructure.
> >
> > When I boot u-boot sandbox (./u-boot) I don't see any network devices
> > at all - perhaps I'm not booting sandbox with dm or something? I need
> > to understand what devices/drivers sandbox is using and how to
> > recreate the network environment that the dm_test_dsa function is
> > using which calls 'net_loop':
> >
> > net_ping_ip = string_to_ip("1.2.3.5");
> >
> > env_set("ethact", "eth2");
> > ut_assertok(net_loop(PING));
> >
> > env_set("ethact", "lan0");
> > ut_assertok(net_loop(PING));
> > env_set("ethact", "lan1");
> > ut_assertok(net_loop(PING));
> >
> > env_set("ethact", "");
> >
> > Best Regards,
> >
> > Tim
>
> I use the following steps:
>
> export KBUILD_OUTPUT=output-sandbox
> make sandbox_defconfig NO_SDL=1
> make -j 8 NO_SDL=1
> $KBUILD_OUTPUT/u-boot -d $KBUILD_OUTPUT/arch/sandbox/dts/test.dtb
> setenv ethact lan1
> ping 1.2.3.5
> ut dm dsa
Thanks - now I understand how to feed sandbox a dtb!
>
> In this case the problem with the patch is simple, sorry for not
> noticing during review.
>
> dsa_port_mangle_packet() changes the "length" variable. But if ops->xmit
> exists, eth_get_ops(master)->send() is called with a bad (old) length,
> the one pre mangling.
Yes, it makes sense. How about the following patch instead:
diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c
index 211a991cdd0d..1ae9adc66eda 100644
--- a/net/dsa-uclass.c
+++ b/net/dsa-uclass.c
@@ -142,6 +142,9 @@ static int dsa_port_send(struct udevice *pdev,
void *packet, int length)
struct dsa_port_pdata *port_pdata;
int err;
+ if (!ops->xmit)
+ return eth_get_ops(master)->send(master, packet, length);
+
if (length + head + tail > PKTSIZE_ALIGN)
return -EINVAL;
@@ -172,7 +175,7 @@ static int dsa_port_recv(struct udevice *pdev, int
flags, uchar **packetp)
int length, port_index, err;
length = eth_get_ops(master)->recv(master, flags, packetp);
- if (length <= 0)
+ if (length <= 0 || !ops->rcv)
return length;
/*
Perhaps it's more elegant to wrap the bulk of dsa_port_send with an
'if (ops->xmit)' but changing the indentation makes the patch more
difficult to follow.
Best Regards,
Tim
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v8 4/8] net: dsa: allow rcv() and xmit() to be optional
2022-11-30 0:58 ` Tim Harvey
@ 2022-11-30 17:25 ` Vladimir Oltean
2022-11-30 17:27 ` Tim Harvey
0 siblings, 1 reply; 18+ messages in thread
From: Vladimir Oltean @ 2022-11-30 17:25 UTC (permalink / raw)
To: Tim Harvey
Cc: Tom Rini, u-boot, Joe Hershberger, Ramon Fried, Stefano Babic,
Fabio Estevam, NXP i . MX U-Boot Team, Marek BehĂșn,
Fabio Estevam
On Tue, Nov 29, 2022 at 04:58:33PM -0800, Tim Harvey wrote:
> Yes, it makes sense. How about the following patch instead:
>
> diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c
> index 211a991cdd0d..1ae9adc66eda 100644
> --- a/net/dsa-uclass.c
> +++ b/net/dsa-uclass.c
> @@ -142,6 +142,9 @@ static int dsa_port_send(struct udevice *pdev,
> void *packet, int length)
> struct dsa_port_pdata *port_pdata;
> int err;
>
> + if (!ops->xmit)
> + return eth_get_ops(master)->send(master, packet, length);
My 2 cents, I would avoid calling eth_get_ops(master)->send() twice.
Either keep the mangling inside the "if" block, or pass the length
argument by reference to your function, or use a goto skip_mangling.
> +
> if (length + head + tail > PKTSIZE_ALIGN)
> return -EINVAL;
>
> @@ -172,7 +175,7 @@ static int dsa_port_recv(struct udevice *pdev, int
> flags, uchar **packetp)
> int length, port_index, err;
>
> length = eth_get_ops(master)->recv(master, flags, packetp);
> - if (length <= 0)
> + if (length <= 0 || !ops->rcv)
> return length;
>
> /*
>
> Perhaps it's more elegant to wrap the bulk of dsa_port_send with an
> 'if (ops->xmit)' but changing the indentation makes the patch more
> difficult to follow.
>
> Best Regards,
>
> Tim
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 4/8] net: dsa: allow rcv() and xmit() to be optional
2022-11-30 17:25 ` Vladimir Oltean
@ 2022-11-30 17:27 ` Tim Harvey
0 siblings, 0 replies; 18+ messages in thread
From: Tim Harvey @ 2022-11-30 17:27 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Tom Rini, u-boot, Joe Hershberger, Ramon Fried, Stefano Babic,
Fabio Estevam, NXP i . MX U-Boot Team, Marek BehĂșn,
Fabio Estevam
On Wed, Nov 30, 2022 at 9:25 AM Vladimir Oltean <vladimir.oltean@nxp.com> wrote:
>
> On Tue, Nov 29, 2022 at 04:58:33PM -0800, Tim Harvey wrote:
> > Yes, it makes sense. How about the following patch instead:
> >
> > diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c
> > index 211a991cdd0d..1ae9adc66eda 100644
> > --- a/net/dsa-uclass.c
> > +++ b/net/dsa-uclass.c
> > @@ -142,6 +142,9 @@ static int dsa_port_send(struct udevice *pdev,
> > void *packet, int length)
> > struct dsa_port_pdata *port_pdata;
> > int err;
> >
> > + if (!ops->xmit)
> > + return eth_get_ops(master)->send(master, packet, length);
>
> My 2 cents, I would avoid calling eth_get_ops(master)->send() twice.
> Either keep the mangling inside the "if" block, or pass the length
> argument by reference to your function, or use a goto skip_mangling.
>
Ok, I'll submit a v9 series momentarily with an if block.
Thanks!
Tim
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2022-11-30 17:27 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-28 0:49 [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana Tim Harvey
2022-10-28 0:49 ` [PATCH v8 1/8] net: mdio-uclass: scan for dm mdio children on post-bind Tim Harvey
2022-10-28 0:49 ` [PATCH v8 2/8] net: dsa: move cpu port probe to dsa_post_probe Tim Harvey
2022-10-28 0:49 ` [PATCH v8 3/8] net: dsa: ensure dsa driver has proper ops Tim Harvey
2022-10-28 0:49 ` [PATCH v8 4/8] net: dsa: allow rcv() and xmit() to be optional Tim Harvey
2022-11-28 15:58 ` Tom Rini
2022-11-29 22:53 ` Tim Harvey
2022-11-29 23:05 ` Tom Rini
2022-11-30 0:11 ` Vladimir Oltean
2022-11-30 0:58 ` Tim Harvey
2022-11-30 17:25 ` Vladimir Oltean
2022-11-30 17:27 ` Tim Harvey
2022-10-28 0:49 ` [PATCH v8 5/8] net: ksz9477: remove unnecessary xmit and recv functions Tim Harvey
2022-10-28 0:49 ` [PATCH v8 6/8] net: fec: add support for DM_MDIO Tim Harvey
2022-10-28 0:49 ` [PATCH v8 7/8] net: add MV88E6xxx DSA driver Tim Harvey
2022-10-28 0:49 ` [PATCH v8 8/8] board: gw_ventana: enable MV88E61XX DSA support Tim Harvey
2022-10-28 8:45 ` [PATCH v8 0/8] Add MV88E6xxx DSA driver and use on gwventana Vladimir Oltean
2022-10-28 15:27 ` Tim Harvey
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.