88d3c1ef430ecfe0f7cddf22589f3803a4800189
[openwrt/staging/aparcar.git] /
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
5 mdio
6
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.
12
13 Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
14 Signed-off-by: David S. Miller <davem@davemloft.net>
15 ---
16 drivers/net/dsa/qca8k.c | 112 +++++++++++++++++++++++++++++-----------
17 drivers/net/dsa/qca8k.h | 1 +
18 2 files changed, 83 insertions(+), 30 deletions(-)
19
20 --- a/drivers/net/dsa/qca8k.c
21 +++ b/drivers/net/dsa/qca8k.c
22 @@ -11,6 +11,7 @@
23 #include <linux/netdevice.h>
24 #include <net/dsa.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)
31 }
32
33 static int
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)
36 {
37 u16 r1, r2, page;
38 u32 val;
39 @@ -639,7 +640,7 @@ qca8k_mdio_busy_wait(struct qca8k_priv *
40
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);
45
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 *
49 }
50
51 static int
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)
54 {
55 + struct qca8k_priv *priv = salve_bus->priv;
56 u16 r1, r2, page;
57 - u32 phy, val;
58 + u32 val;
59 int ret;
60
61 if (regnum >= QCA8K_MDIO_MASTER_MAX_REG)
62 return -EINVAL;
63
64 - /* callee is responsible for not passing bad ports,
65 - * but we still would like to make spills impossible.
66 - */
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
72
73 qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
74
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);
78
79 exit:
80 - mutex_unlock(&priv->bus->mdio_lock);
81 -
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);
86 +
87 + mutex_unlock(&priv->bus->mdio_lock);
88
89 return ret;
90 }
91
92 static int
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)
95 {
96 + struct qca8k_priv *priv = salve_bus->priv;
97 u16 r1, r2, page;
98 - u32 phy, val;
99 + u32 val;
100 int ret;
101
102 if (regnum >= QCA8K_MDIO_MASTER_MAX_REG)
103 return -EINVAL;
104
105 - /* callee is responsible for not passing bad ports,
106 - * but we still would like to make spills impossible.
107 - */
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,
113
114 qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
115
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);
119 if (ret)
120 goto exit;
121
122 val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1);
123 - val &= QCA8K_MDIO_MASTER_DATA_MASK;
124
125 exit:
126 + /* even if the busy_wait timeouts try to clear the MASTER_EN */
127 + qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0);
128 +
129 mutex_unlock(&priv->bus->mdio_lock);
130
131 if (val >= 0)
132 val &= QCA8K_MDIO_MASTER_DATA_MASK;
133
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);
137 -
138 return val;
139 }
140
141 @@ -746,7 +738,14 @@ qca8k_phy_write(struct dsa_switch *ds, i
142 {
143 struct qca8k_priv *priv = ds->priv;
144
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
148 + * devicetree
149 + */
150 + if (priv->legacy_phy_port_mapping)
151 + port = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
152 +
153 + return qca8k_mdio_write(priv->bus, port, regnum, data);
154 }
155
156 static int
157 @@ -755,7 +754,14 @@ qca8k_phy_read(struct dsa_switch *ds, in
158 struct qca8k_priv *priv = ds->priv;
159 int ret;
160
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
164 + * devicetree
165 + */
166 + if (priv->legacy_phy_port_mapping)
167 + port = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
168 +
169 + ret = qca8k_mdio_read(priv->bus, port, regnum);
170
171 if (ret < 0)
172 return 0xffff;
173 @@ -764,10 +770,37 @@ qca8k_phy_read(struct dsa_switch *ds, in
174 }
175
176 static int
177 +qca8k_mdio_register(struct qca8k_priv *priv, struct device_node *mdio)
178 +{
179 + struct dsa_switch *ds = priv->ds;
180 + struct mii_bus *bus;
181 +
182 + bus = devm_mdiobus_alloc(ds->dev);
183 +
184 + if (!bus)
185 + return -ENOMEM;
186 +
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",
192 + ds->index);
193 +
194 + bus->parent = ds->dev;
195 + bus->phy_mask = ~ds->phys_mii_mask;
196 +
197 + ds->slave_mii_bus = bus;
198 +
199 + return devm_of_mdiobus_register(priv->dev, bus, mdio);
200 +}
201 +
202 +static int
203 qca8k_setup_mdio_bus(struct qca8k_priv *priv)
204 {
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;
209 int err;
210
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))
214 continue;
215
216 - if (of_property_read_bool(port, "phy-handle"))
217 + of_get_phy_mode(port, &mode);
218 +
219 + if (of_property_read_bool(port, "phy-handle") &&
220 + mode != PHY_INTERFACE_MODE_INTERNAL)
221 external_mdio_mask |= BIT(reg);
222 else
223 internal_mdio_mask |= BIT(reg);
224 @@ -825,8 +861,23 @@ qca8k_setup_mdio_bus(struct qca8k_priv *
225 QCA8K_MDIO_MASTER_EN);
226 }
227
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);
232 + if (err)
233 + of_node_put(mdio);
234 +
235 + return err;
236 + }
237 +
238 + /* If a mapping can't be found the legacy mapping is used,
239 + * using the qca8k_port_to_phy function
240 + */
241 + priv->legacy_phy_port_mapping = true;
242 priv->ops.phy_read = qca8k_phy_read;
243 priv->ops.phy_write = qca8k_phy_write;
244 +
245 return 0;
246 }
247
248 @@ -1212,7 +1263,8 @@ qca8k_phylink_validate(struct dsa_switch
249 case 5:
250 /* Internal PHY */
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)
255 goto unsupported;
256 break;
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 {
261 u8 switch_revision;
262 u8 rgmii_tx_delay;
263 u8 rgmii_rx_delay;
264 + bool legacy_phy_port_mapping;
265 struct regmap *regmap;
266 struct mii_bus *bus;
267 struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];