* [PATCH v4 1/4] dt-bindings: net: dsa: qca8k: fix example
@ 2019-03-22 0:05 Christian Lamparter
2019-03-22 0:05 ` [PATCH v4 2/4] dt-bindings: net: dsa: qca8k: support internal mdio-bus Christian Lamparter
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Christian Lamparter @ 2019-03-22 0:05 UTC (permalink / raw)
To: netdev, devicetree
Cc: Florian Fainelli, Vivien Didelot, Andrew Lunn, Rob Herring,
Mark Rutland, Marek Behun
In the example, the phy at phy@0 is clashing with
the switch0@0 at the same address. Usually, the switches
are accessible through pseudo PHYs which in case of the
qca8k are located at 0x10 - 0x18.
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
---
Documentation/devicetree/bindings/net/dsa/qca8k.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/dsa/qca8k.txt b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
index bbcb255c3150..5eda99e6c86e 100644
--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
@@ -55,12 +55,12 @@ Example:
reg = <4>;
};
- switch0@0 {
+ switch@10 {
compatible = "qca,qca8337";
#address-cells = <1>;
#size-cells = <0>;
- reg = <0>;
+ reg = <0x10>;
ports {
#address-cells = <1>;
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 2/4] dt-bindings: net: dsa: qca8k: support internal mdio-bus
2019-03-22 0:05 [PATCH v4 1/4] dt-bindings: net: dsa: qca8k: fix example Christian Lamparter
@ 2019-03-22 0:05 ` Christian Lamparter
2019-03-22 0:05 ` [PATCH v4 3/4] net: dsa: qca8k: remove leftover phy accessors Christian Lamparter
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Christian Lamparter @ 2019-03-22 0:05 UTC (permalink / raw)
To: netdev, devicetree
Cc: Florian Fainelli, Vivien Didelot, Andrew Lunn, Rob Herring,
Mark Rutland, Marek Behun
This patch updates the qca8k's binding to document to the
approach for using the internal mdio-bus of the supported
qca8k switches.
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
---
.../devicetree/bindings/net/dsa/qca8k.txt | 69 +++++++++++++++++--
1 file changed, 64 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/dsa/qca8k.txt b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
index 5eda99e6c86e..93a7469e70d4 100644
--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
@@ -12,10 +12,15 @@ Required properties:
Subnodes:
The integrated switch subnode should be specified according to the binding
-described in dsa/dsa.txt. As the QCA8K switches do not have a N:N mapping of
-port and PHY id, each subnode describing a port needs to have a valid phandle
-referencing the internal PHY connected to it. The CPU port of this switch is
-always port 0.
+described in dsa/dsa.txt. If the QCA8K switch is connect to a SoC's external
+mdio-bus each subnode describing a port needs to have a valid phandle
+referencing the internal PHY it is connected to. This is because there's no
+N:N mapping of port and PHY id.
+
+Don't use mixed external and internal mdio-bus configurations, as this is
+not supported by the hardware.
+
+The CPU port of this switch is always port 0.
A CPU port node has the following optional node:
@@ -31,8 +36,9 @@ For QCA8K the 'fixed-link' sub-node supports only the following properties:
- 'full-duplex' (boolean, optional), to indicate that full duplex is
used. When absent, half duplex is assumed.
-Example:
+Examples:
+for the external mdio-bus configuration:
&mdio0 {
phy_port1: phy@0 {
@@ -108,3 +114,56 @@ Example:
};
};
};
+
+for the internal master mdio-bus configuration:
+
+ &mdio0 {
+ switch@10 {
+ compatible = "qca,qca8337";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <0x10>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ label = "cpu";
+ ethernet = <&gmac1>;
+ phy-mode = "rgmii";
+ fixed-link {
+ speed = 1000;
+ full-duplex;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ label = "lan1";
+ };
+
+ port@2 {
+ reg = <2>;
+ label = "lan2";
+ };
+
+ port@3 {
+ reg = <3>;
+ label = "lan3";
+ };
+
+ port@4 {
+ reg = <4>;
+ label = "lan4";
+ };
+
+ port@5 {
+ reg = <5>;
+ label = "wan";
+ };
+ };
+ };
+ };
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 3/4] net: dsa: qca8k: remove leftover phy accessors
2019-03-22 0:05 [PATCH v4 1/4] dt-bindings: net: dsa: qca8k: fix example Christian Lamparter
2019-03-22 0:05 ` [PATCH v4 2/4] dt-bindings: net: dsa: qca8k: support internal mdio-bus Christian Lamparter
@ 2019-03-22 0:05 ` Christian Lamparter
2019-03-22 0:05 ` [PATCH v4 4/4] net: dsa: qca8k: extend slave-bus implementations Christian Lamparter
2019-03-26 17:47 ` [PATCH v4 1/4] dt-bindings: net: dsa: qca8k: fix example David Miller
3 siblings, 0 replies; 5+ messages in thread
From: Christian Lamparter @ 2019-03-22 0:05 UTC (permalink / raw)
To: netdev, devicetree
Cc: Florian Fainelli, Vivien Didelot, Andrew Lunn, Rob Herring,
Mark Rutland, Marek Behun
This belated patch implements Andrew Lunn's request of
"remove the phy_read() and phy_write() functions."
<https://lore.kernel.org/patchwork/comment/902734/>
While seemingly harmless, this causes the switch's user
port PHYs to get registered twice. This is because the
DSA subsystem will create a slave mdio-bus not knowing
that the qca8k_phy_(read|write) accessors operate on
the external mdio-bus. So the same "bus" gets effectively
duplicated.
Cc: stable@vger.kernel.org
Fixes: 6b93fb46480a ("net-next: dsa: add new driver for qca8xxx family")
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
---
This (standalone) patch should be much easier to backport than
the big one.
---
drivers/net/dsa/qca8k.c | 18 ------------------
1 file changed, 18 deletions(-)
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 576b37d12a63..14ad78225f07 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -624,22 +624,6 @@ qca8k_adjust_link(struct dsa_switch *ds, int port, struct phy_device *phy)
qca8k_port_set_status(priv, port, 1);
}
-static int
-qca8k_phy_read(struct dsa_switch *ds, int phy, int regnum)
-{
- struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
-
- return mdiobus_read(priv->bus, phy, regnum);
-}
-
-static int
-qca8k_phy_write(struct dsa_switch *ds, int phy, int regnum, u16 val)
-{
- struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
-
- return mdiobus_write(priv->bus, phy, regnum, val);
-}
-
static void
qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data)
{
@@ -879,8 +863,6 @@ static const struct dsa_switch_ops qca8k_switch_ops = {
.setup = qca8k_setup,
.adjust_link = qca8k_adjust_link,
.get_strings = qca8k_get_strings,
- .phy_read = qca8k_phy_read,
- .phy_write = qca8k_phy_write,
.get_ethtool_stats = qca8k_get_ethtool_stats,
.get_sset_count = qca8k_get_sset_count,
.get_mac_eee = qca8k_get_mac_eee,
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 4/4] net: dsa: qca8k: extend slave-bus implementations
2019-03-22 0:05 [PATCH v4 1/4] dt-bindings: net: dsa: qca8k: fix example Christian Lamparter
2019-03-22 0:05 ` [PATCH v4 2/4] dt-bindings: net: dsa: qca8k: support internal mdio-bus Christian Lamparter
2019-03-22 0:05 ` [PATCH v4 3/4] net: dsa: qca8k: remove leftover phy accessors Christian Lamparter
@ 2019-03-22 0:05 ` Christian Lamparter
2019-03-26 17:47 ` [PATCH v4 1/4] dt-bindings: net: dsa: qca8k: fix example David Miller
3 siblings, 0 replies; 5+ messages in thread
From: Christian Lamparter @ 2019-03-22 0:05 UTC (permalink / raw)
To: netdev, devicetree
Cc: Florian Fainelli, Vivien Didelot, Andrew Lunn, Rob Herring,
Mark Rutland, Marek Behun
This patch implements accessors for the QCA8337 MDIO access
through the MDIO_MASTER register, which makes it possible to
access the PHYs on slave-bus through the switch. In cases
where the switch ports are already mapped via external
"phy-phandles", the internal mdio-bus is disabled in order to
prevent a duplicated discovery and enumeration of the same
PHYs. Don't use mixed external and internal mdio-bus
configurations, as this is not supported by the hardware.
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
---
Changes from v3:
- removed unneccessary PHYAD checks
- let dsa subsystem setup the slave bus, but only if needed
- saved an indent level in qca8k_setup_mdio_bus()
- Reverse XMAS tree-ized
Changes from v2:
- Make it compatible with existing configurations
- make it clear that's sadly a either external or
internal mdio bus access.
Changes from v1:
- drop DT port <-> phy mapping
- added register definitions for the MDIO control register
- implemented new slave-mdio bus accessors
- DT-binding: fix switch's PSEUDO_PHY address. It's 0x10 not 0.
Old patch (+ discussion) for reference:
<https://patchwork.ozlabs.org/patch/1036309/>
Tested on a Compex WPQ864 (IPQ8064 + QCA8337N)
internal bus:
qca8k 37000000.mdio-mii:10 lan1 (uninitialized): PHY [dsa-0.0:01] driver [Generic PHY]
qca8k 37000000.mdio-mii:10 lan2 (uninitialized): PHY [dsa-0.0:02] driver [Generic PHY]
qca8k 37000000.mdio-mii:10 lan3 (uninitialized): PHY [dsa-0.0:03] driver [Generic PHY]
qca8k 37000000.mdio-mii:10 lan4 (uninitialized): PHY [dsa-0.0:04] driver [Generic PHY]
qca8k 37000000.mdio-mii:10 wan (uninitialized): PHY [dsa-0.0:05] driver [Generic PHY]
external bus:
qca8k 37000000.mdio-mii:10 lan1 (uninitialized): PHY [37000000.mdio-mii:00] driver [Generic PHY]
qca8k 37000000.mdio-mii:10 lan2 (uninitialized): PHY [37000000.mdio-mii:01] driver [Generic PHY]
qca8k 37000000.mdio-mii:10 lan3 (uninitialized): PHY [37000000.mdio-mii:02] driver [Generic PHY]
qca8k 37000000.mdio-mii:10 lan4 (uninitialized): PHY [37000000.mdio-mii:03] driver [Generic PHY]
qca8k 37000000.mdio-mii:10 wan (uninitialized): PHY [37000000.mdio-mii:04] driver [Generic PHY]
---
drivers/net/dsa/qca8k.c | 156 +++++++++++++++++++++++++++++++++++++++-
drivers/net/dsa/qca8k.h | 13 ++++
2 files changed, 168 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 14ad78225f07..c4fa400efdcc 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -481,6 +481,155 @@ qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable)
qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask);
}
+static u32
+qca8k_port_to_phy(int port)
+{
+ /* From Andrew Lunn:
+ * Port 0 has no internal phy.
+ * Port 1 has an internal PHY at MDIO address 0.
+ * Port 2 has an internal PHY at MDIO address 1.
+ * ...
+ * Port 5 has an internal PHY at MDIO address 4.
+ * Port 6 has no internal PHY.
+ */
+
+ return port - 1;
+}
+
+static int
+qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data)
+{
+ u32 phy, val;
+
+ if (regnum >= QCA8K_MDIO_MASTER_MAX_REG)
+ return -EINVAL;
+
+ /* callee is responsible for not passing bad ports,
+ * but we still would like to make spills impossible.
+ */
+ phy = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
+ val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN |
+ QCA8K_MDIO_MASTER_WRITE | QCA8K_MDIO_MASTER_PHY_ADDR(phy) |
+ QCA8K_MDIO_MASTER_REG_ADDR(regnum) |
+ QCA8K_MDIO_MASTER_DATA(data);
+
+ qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
+
+ return qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
+ QCA8K_MDIO_MASTER_BUSY);
+}
+
+static int
+qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum)
+{
+ u32 phy, val;
+
+ if (regnum >= QCA8K_MDIO_MASTER_MAX_REG)
+ return -EINVAL;
+
+ /* callee is responsible for not passing bad ports,
+ * but we still would like to make spills impossible.
+ */
+ phy = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
+ val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN |
+ QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) |
+ QCA8K_MDIO_MASTER_REG_ADDR(regnum);
+
+ qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
+
+ if (qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
+ QCA8K_MDIO_MASTER_BUSY))
+ return -ETIMEDOUT;
+
+ val = (qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL) &
+ QCA8K_MDIO_MASTER_DATA_MASK);
+
+ return val;
+}
+
+static int
+qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data)
+{
+ struct qca8k_priv *priv = ds->priv;
+
+ return qca8k_mdio_write(priv, port, regnum, data);
+}
+
+static int
+qca8k_phy_read(struct dsa_switch *ds, int port, int regnum)
+{
+ struct qca8k_priv *priv = ds->priv;
+ int ret;
+
+ ret = qca8k_mdio_read(priv, port, regnum);
+
+ if (ret < 0)
+ return 0xffff;
+
+ return ret;
+}
+
+static int
+qca8k_setup_mdio_bus(struct qca8k_priv *priv)
+{
+ u32 internal_mdio_mask = 0, external_mdio_mask = 0, reg;
+ struct device_node *ports, *port;
+ int err;
+
+ ports = of_get_child_by_name(priv->dev->of_node, "ports");
+ if (!ports)
+ return -EINVAL;
+
+ for_each_available_child_of_node(ports, port) {
+ err = of_property_read_u32(port, "reg", ®);
+ if (err)
+ return err;
+
+ if (!dsa_is_user_port(priv->ds, reg))
+ continue;
+
+ if (of_property_read_bool(port, "phy-handle"))
+ external_mdio_mask |= BIT(reg);
+ else
+ internal_mdio_mask |= BIT(reg);
+ }
+
+ if (!external_mdio_mask && !internal_mdio_mask) {
+ dev_err(priv->dev, "no PHYs are defined.\n");
+ return -EINVAL;
+ }
+
+ /* The QCA8K_MDIO_MASTER_EN Bit, which grants access to PHYs through
+ * the MDIO_MASTER register also _disconnects_ the external MDC
+ * passthrough to the internal PHYs. It's not possible to use both
+ * configurations at the same time!
+ *
+ * Because this came up during the review process:
+ * If the external mdio-bus driver is capable magically disabling
+ * the QCA8K_MDIO_MASTER_EN and mutex/spin-locking out the qca8k's
+ * accessors for the time being, it would be possible to pull this
+ * off.
+ */
+ if (!!external_mdio_mask && !!internal_mdio_mask) {
+ dev_err(priv->dev, "either internal or external mdio bus configuration is supported.\n");
+ return -EINVAL;
+ }
+
+ if (external_mdio_mask) {
+ /* Make sure to disable the internal mdio bus in cases
+ * a dt-overlay and driver reload changed the configuration
+ */
+
+ qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
+ QCA8K_MDIO_MASTER_EN);
+ return 0;
+ }
+
+ priv->ops.phy_read = qca8k_phy_read;
+ priv->ops.phy_write = qca8k_phy_write;
+ return 0;
+}
+
static int
qca8k_setup(struct dsa_switch *ds)
{
@@ -502,6 +651,10 @@ qca8k_setup(struct dsa_switch *ds)
if (IS_ERR(priv->regmap))
pr_warn("regmap initialization failed");
+ ret = qca8k_setup_mdio_bus(priv);
+ if (ret)
+ return ret;
+
/* Initialize CPU port pad mode (xMII type, delays...) */
phy_mode = of_get_phy_mode(ds->ports[QCA8K_CPU_PORT].dn);
if (phy_mode < 0) {
@@ -905,7 +1058,8 @@ qca8k_sw_probe(struct mdio_device *mdiodev)
return -ENOMEM;
priv->ds->priv = priv;
- priv->ds->ops = &qca8k_switch_ops;
+ priv->ops = qca8k_switch_ops;
+ priv->ds->ops = &priv->ops;
mutex_init(&priv->reg_mutex);
dev_set_drvdata(&mdiodev->dev, priv);
diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h
index d146e54c8a6c..249fd62268e5 100644
--- a/drivers/net/dsa/qca8k.h
+++ b/drivers/net/dsa/qca8k.h
@@ -49,6 +49,18 @@
#define QCA8K_MIB_FLUSH BIT(24)
#define QCA8K_MIB_CPU_KEEP BIT(20)
#define QCA8K_MIB_BUSY BIT(17)
+#define QCA8K_MDIO_MASTER_CTRL 0x3c
+#define QCA8K_MDIO_MASTER_BUSY BIT(31)
+#define QCA8K_MDIO_MASTER_EN BIT(30)
+#define QCA8K_MDIO_MASTER_READ BIT(27)
+#define QCA8K_MDIO_MASTER_WRITE 0
+#define QCA8K_MDIO_MASTER_SUP_PRE BIT(26)
+#define QCA8K_MDIO_MASTER_PHY_ADDR(x) ((x) << 21)
+#define QCA8K_MDIO_MASTER_REG_ADDR(x) ((x) << 16)
+#define QCA8K_MDIO_MASTER_DATA(x) (x)
+#define QCA8K_MDIO_MASTER_DATA_MASK GENMASK(15, 0)
+#define QCA8K_MDIO_MASTER_MAX_PORTS 5
+#define QCA8K_MDIO_MASTER_MAX_REG 32
#define QCA8K_GOL_MAC_ADDR0 0x60
#define QCA8K_GOL_MAC_ADDR1 0x64
#define QCA8K_REG_PORT_STATUS(_i) (0x07c + (_i) * 4)
@@ -169,6 +181,7 @@ struct qca8k_priv {
struct dsa_switch *ds;
struct mutex reg_mutex;
struct device *dev;
+ struct dsa_switch_ops ops;
};
struct qca8k_mib_desc {
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v4 1/4] dt-bindings: net: dsa: qca8k: fix example
2019-03-22 0:05 [PATCH v4 1/4] dt-bindings: net: dsa: qca8k: fix example Christian Lamparter
` (2 preceding siblings ...)
2019-03-22 0:05 ` [PATCH v4 4/4] net: dsa: qca8k: extend slave-bus implementations Christian Lamparter
@ 2019-03-26 17:47 ` David Miller
3 siblings, 0 replies; 5+ messages in thread
From: David Miller @ 2019-03-26 17:47 UTC (permalink / raw)
To: chunkeey
Cc: netdev, devicetree, f.fainelli, vivien.didelot, andrew, robh+dt,
mark.rutland, marek.behun
From: Christian Lamparter <chunkeey@gmail.com>
Date: Fri, 22 Mar 2019 01:05:00 +0100
> In the example, the phy at phy@0 is clashing with
> the switch0@0 at the same address. Usually, the switches
> are accessible through pseudo PHYs which in case of the
> qca8k are located at 0x10 - 0x18.
>
> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
> Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
Series applied.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2019-03-26 17:47 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-22 0:05 [PATCH v4 1/4] dt-bindings: net: dsa: qca8k: fix example Christian Lamparter
2019-03-22 0:05 ` [PATCH v4 2/4] dt-bindings: net: dsa: qca8k: support internal mdio-bus Christian Lamparter
2019-03-22 0:05 ` [PATCH v4 3/4] net: dsa: qca8k: remove leftover phy accessors Christian Lamparter
2019-03-22 0:05 ` [PATCH v4 4/4] net: dsa: qca8k: extend slave-bus implementations Christian Lamparter
2019-03-26 17:47 ` [PATCH v4 1/4] dt-bindings: net: dsa: qca8k: fix example David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).