1 From 759bafb8a3226326ca357613bc90acf738f80c32 Mon Sep 17 00:00:00 2001
2 From: Ansuel Smith <ansuelsmth@gmail.com>
3 Date: Fri, 14 May 2021 23:00:10 +0200
4 Subject: [PATCH] net: dsa: qca8k: add support for internal phy and internal
7 Add support to setup_mdio_bus for internal phy declaration. Introduce a
8 flag to use the legacy port phy mapping by default and use the direct
9 mapping if a mdio node is detected in the switch node. Register a
10 dedicated mdio internal mdio bus to address the different mapping
11 between port and phy if the mdio node is detected.
13 Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
14 Signed-off-by: David S. Miller <davem@davemloft.net>
16 drivers/net/dsa/qca8k.c | 112 +++++++++++++++++++++++++++++-----------
17 drivers/net/dsa/qca8k.h | 1 +
18 2 files changed, 83 insertions(+), 30 deletions(-)
20 --- a/drivers/net/dsa/qca8k.c
21 +++ b/drivers/net/dsa/qca8k.c
23 #include <linux/netdevice.h>
25 #include <linux/of_net.h>
26 +#include <linux/of_mdio.h>
27 #include <linux/of_platform.h>
28 #include <linux/if_bridge.h>
29 #include <linux/mdio.h>
30 @@ -629,7 +630,7 @@ qca8k_port_to_phy(int port)
34 -qca8k_mdio_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
35 +qca8k_mdio_busy_wait(struct mii_bus *bus, u32 reg, u32 mask)
39 @@ -639,7 +640,7 @@ qca8k_mdio_busy_wait(struct qca8k_priv *
41 ret = read_poll_timeout(qca8k_mii_read32, val, !(val & mask), 0,
42 QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false,
43 - priv->bus, 0x10 | r2, r1);
44 + bus, 0x10 | r2, r1);
46 /* Check if qca8k_read has failed for a different reason
47 * before returnting -ETIMEDOUT
48 @@ -651,19 +652,16 @@ qca8k_mdio_busy_wait(struct qca8k_priv *
52 -qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data)
53 +qca8k_mdio_write(struct mii_bus *salve_bus, int phy, int regnum, u16 data)
55 + struct qca8k_priv *priv = salve_bus->priv;
61 if (regnum >= QCA8K_MDIO_MASTER_MAX_REG)
64 - /* callee is responsible for not passing bad ports,
65 - * but we still would like to make spills impossible.
67 - phy = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
68 val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN |
69 QCA8K_MDIO_MASTER_WRITE | QCA8K_MDIO_MASTER_PHY_ADDR(phy) |
70 QCA8K_MDIO_MASTER_REG_ADDR(regnum) |
71 @@ -679,33 +677,29 @@ qca8k_mdio_write(struct qca8k_priv *priv
73 qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
75 - ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
76 + ret = qca8k_mdio_busy_wait(priv->bus, QCA8K_MDIO_MASTER_CTRL,
77 QCA8K_MDIO_MASTER_BUSY);
80 - mutex_unlock(&priv->bus->mdio_lock);
82 /* even if the busy_wait timeouts try to clear the MASTER_EN */
83 - qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
84 - QCA8K_MDIO_MASTER_EN);
85 + qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0);
87 + mutex_unlock(&priv->bus->mdio_lock);
93 -qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum)
94 +qca8k_mdio_read(struct mii_bus *salve_bus, int phy, int regnum)
96 + struct qca8k_priv *priv = salve_bus->priv;
102 if (regnum >= QCA8K_MDIO_MASTER_MAX_REG)
105 - /* callee is responsible for not passing bad ports,
106 - * but we still would like to make spills impossible.
108 - phy = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
109 val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN |
110 QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) |
111 QCA8K_MDIO_MASTER_REG_ADDR(regnum);
112 @@ -720,24 +714,22 @@ qca8k_mdio_read(struct qca8k_priv *priv,
114 qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
116 - ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
117 + ret = qca8k_mdio_busy_wait(priv->bus, QCA8K_MDIO_MASTER_CTRL,
118 QCA8K_MDIO_MASTER_BUSY);
122 val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1);
123 - val &= QCA8K_MDIO_MASTER_DATA_MASK;
126 + /* even if the busy_wait timeouts try to clear the MASTER_EN */
127 + qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0);
129 mutex_unlock(&priv->bus->mdio_lock);
132 val &= QCA8K_MDIO_MASTER_DATA_MASK;
134 - /* even if the busy_wait timeouts try to clear the MASTER_EN */
135 - qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
136 - QCA8K_MDIO_MASTER_EN);
141 @@ -746,7 +738,14 @@ qca8k_phy_write(struct dsa_switch *ds, i
143 struct qca8k_priv *priv = ds->priv;
145 - return qca8k_mdio_write(priv, port, regnum, data);
146 + /* Check if the legacy mapping should be used and the
147 + * port is not correctly mapped to the right PHY in the
150 + if (priv->legacy_phy_port_mapping)
151 + port = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
153 + return qca8k_mdio_write(priv->bus, port, regnum, data);
157 @@ -755,7 +754,14 @@ qca8k_phy_read(struct dsa_switch *ds, in
158 struct qca8k_priv *priv = ds->priv;
161 - ret = qca8k_mdio_read(priv, port, regnum);
162 + /* Check if the legacy mapping should be used and the
163 + * port is not correctly mapped to the right PHY in the
166 + if (priv->legacy_phy_port_mapping)
167 + port = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
169 + ret = qca8k_mdio_read(priv->bus, port, regnum);
173 @@ -764,10 +770,37 @@ qca8k_phy_read(struct dsa_switch *ds, in
177 +qca8k_mdio_register(struct qca8k_priv *priv, struct device_node *mdio)
179 + struct dsa_switch *ds = priv->ds;
180 + struct mii_bus *bus;
182 + bus = devm_mdiobus_alloc(ds->dev);
187 + bus->priv = (void *)priv;
188 + bus->name = "qca8k slave mii";
189 + bus->read = qca8k_mdio_read;
190 + bus->write = qca8k_mdio_write;
191 + snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d",
194 + bus->parent = ds->dev;
195 + bus->phy_mask = ~ds->phys_mii_mask;
197 + ds->slave_mii_bus = bus;
199 + return devm_of_mdiobus_register(priv->dev, bus, mdio);
203 qca8k_setup_mdio_bus(struct qca8k_priv *priv)
205 u32 internal_mdio_mask = 0, external_mdio_mask = 0, reg;
206 - struct device_node *ports, *port;
207 + struct device_node *ports, *port, *mdio;
208 + phy_interface_t mode;
211 ports = of_get_child_by_name(priv->dev->of_node, "ports");
212 @@ -788,7 +821,10 @@ qca8k_setup_mdio_bus(struct qca8k_priv *
213 if (!dsa_is_user_port(priv->ds, reg))
216 - if (of_property_read_bool(port, "phy-handle"))
217 + of_get_phy_mode(port, &mode);
219 + if (of_property_read_bool(port, "phy-handle") &&
220 + mode != PHY_INTERFACE_MODE_INTERNAL)
221 external_mdio_mask |= BIT(reg);
223 internal_mdio_mask |= BIT(reg);
224 @@ -825,8 +861,23 @@ qca8k_setup_mdio_bus(struct qca8k_priv *
225 QCA8K_MDIO_MASTER_EN);
228 + /* Check if the devicetree declare the port:phy mapping */
229 + mdio = of_get_child_by_name(priv->dev->of_node, "mdio");
230 + if (of_device_is_available(mdio)) {
231 + err = qca8k_mdio_register(priv, mdio);
238 + /* If a mapping can't be found the legacy mapping is used,
239 + * using the qca8k_port_to_phy function
241 + priv->legacy_phy_port_mapping = true;
242 priv->ops.phy_read = qca8k_phy_read;
243 priv->ops.phy_write = qca8k_phy_write;
248 @@ -1212,7 +1263,8 @@ qca8k_phylink_validate(struct dsa_switch
251 if (state->interface != PHY_INTERFACE_MODE_NA &&
252 - state->interface != PHY_INTERFACE_MODE_GMII)
253 + state->interface != PHY_INTERFACE_MODE_GMII &&
254 + state->interface != PHY_INTERFACE_MODE_INTERNAL)
257 case 6: /* 2nd CPU port / external PHY */
258 --- a/drivers/net/dsa/qca8k.h
259 +++ b/drivers/net/dsa/qca8k.h
260 @@ -255,6 +255,7 @@ struct qca8k_priv {
264 + bool legacy_phy_port_mapping;
265 struct regmap *regmap;
267 struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];