Loading...
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright 2021 NXP
3 */
4#include <linux/pcs/pcs-xpcs.h>
5#include <linux/of_mdio.h>
6#include "sja1105.h"
7
8#define SJA1110_PCS_BANK_REG SJA1110_SPI_ADDR(0x3fc)
9
10int sja1105_pcs_mdio_read_c45(struct mii_bus *bus, int phy, int mmd, int reg)
11{
12 struct sja1105_mdio_private *mdio_priv = bus->priv;
13 struct sja1105_private *priv = mdio_priv->priv;
14 u64 addr;
15 u32 tmp;
16 int rc;
17
18 addr = (mmd << 16) | reg;
19
20 if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
21 return 0xffff;
22
23 if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID1)
24 return NXP_SJA1105_XPCS_ID >> 16;
25 if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID2)
26 return NXP_SJA1105_XPCS_ID & GENMASK(15, 0);
27
28 rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
29 if (rc < 0)
30 return rc;
31
32 return tmp & 0xffff;
33}
34
35int sja1105_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int mmd,
36 int reg, u16 val)
37{
38 struct sja1105_mdio_private *mdio_priv = bus->priv;
39 struct sja1105_private *priv = mdio_priv->priv;
40 u64 addr;
41 u32 tmp;
42
43 addr = (mmd << 16) | reg;
44 tmp = val;
45
46 if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
47 return -EINVAL;
48
49 return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
50}
51
52int sja1110_pcs_mdio_read_c45(struct mii_bus *bus, int phy, int mmd, int reg)
53{
54 struct sja1105_mdio_private *mdio_priv = bus->priv;
55 struct sja1105_private *priv = mdio_priv->priv;
56 const struct sja1105_regs *regs = priv->info->regs;
57 int offset, bank;
58 u64 addr;
59 u32 tmp;
60 int rc;
61
62 if (regs->pcs_base[phy] == SJA1105_RSV_ADDR)
63 return -ENODEV;
64
65 addr = (mmd << 16) | reg;
66
67 if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID1)
68 return NXP_SJA1110_XPCS_ID >> 16;
69 if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID2)
70 return NXP_SJA1110_XPCS_ID & GENMASK(15, 0);
71
72 bank = addr >> 8;
73 offset = addr & GENMASK(7, 0);
74
75 /* This addressing scheme reserves register 0xff for the bank address
76 * register, so that can never be addressed.
77 */
78 if (WARN_ON(offset == 0xff))
79 return -ENODEV;
80
81 tmp = bank;
82
83 rc = sja1105_xfer_u32(priv, SPI_WRITE,
84 regs->pcs_base[phy] + SJA1110_PCS_BANK_REG,
85 &tmp, NULL);
86 if (rc < 0)
87 return rc;
88
89 rc = sja1105_xfer_u32(priv, SPI_READ, regs->pcs_base[phy] + offset,
90 &tmp, NULL);
91 if (rc < 0)
92 return rc;
93
94 return tmp & 0xffff;
95}
96
97int sja1110_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int reg, int mmd,
98 u16 val)
99{
100 struct sja1105_mdio_private *mdio_priv = bus->priv;
101 struct sja1105_private *priv = mdio_priv->priv;
102 const struct sja1105_regs *regs = priv->info->regs;
103 int offset, bank;
104 u64 addr;
105 u32 tmp;
106 int rc;
107
108 if (regs->pcs_base[phy] == SJA1105_RSV_ADDR)
109 return -ENODEV;
110
111 addr = (mmd << 16) | reg;
112
113 bank = addr >> 8;
114 offset = addr & GENMASK(7, 0);
115
116 /* This addressing scheme reserves register 0xff for the bank address
117 * register, so that can never be addressed.
118 */
119 if (WARN_ON(offset == 0xff))
120 return -ENODEV;
121
122 tmp = bank;
123
124 rc = sja1105_xfer_u32(priv, SPI_WRITE,
125 regs->pcs_base[phy] + SJA1110_PCS_BANK_REG,
126 &tmp, NULL);
127 if (rc < 0)
128 return rc;
129
130 tmp = val;
131
132 return sja1105_xfer_u32(priv, SPI_WRITE, regs->pcs_base[phy] + offset,
133 &tmp, NULL);
134}
135
136enum sja1105_mdio_opcode {
137 SJA1105_C45_ADDR = 0,
138 SJA1105_C22 = 1,
139 SJA1105_C45_DATA = 2,
140 SJA1105_C45_DATA_AUTOINC = 3,
141};
142
143static u64 sja1105_base_t1_encode_addr(struct sja1105_private *priv,
144 int phy, enum sja1105_mdio_opcode op,
145 int xad)
146{
147 const struct sja1105_regs *regs = priv->info->regs;
148
149 return regs->mdio_100base_t1 | (phy << 7) | (op << 5) | (xad << 0);
150}
151
152static int sja1105_base_t1_mdio_read_c22(struct mii_bus *bus, int phy, int reg)
153{
154 struct sja1105_mdio_private *mdio_priv = bus->priv;
155 struct sja1105_private *priv = mdio_priv->priv;
156 u64 addr;
157 u32 tmp;
158 int rc;
159
160 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
161
162 rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
163 if (rc < 0)
164 return rc;
165
166 return tmp & 0xffff;
167}
168
169static int sja1105_base_t1_mdio_read_c45(struct mii_bus *bus, int phy,
170 int mmd, int reg)
171{
172 struct sja1105_mdio_private *mdio_priv = bus->priv;
173 struct sja1105_private *priv = mdio_priv->priv;
174 u64 addr;
175 u32 tmp;
176 int rc;
177
178 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR, mmd);
179
180 rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, ®, NULL);
181 if (rc < 0)
182 return rc;
183
184 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA, mmd);
185
186 rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
187 if (rc < 0)
188 return rc;
189
190 return tmp & 0xffff;
191}
192
193static int sja1105_base_t1_mdio_write_c22(struct mii_bus *bus, int phy, int reg,
194 u16 val)
195{
196 struct sja1105_mdio_private *mdio_priv = bus->priv;
197 struct sja1105_private *priv = mdio_priv->priv;
198 u64 addr;
199 u32 tmp;
200
201 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
202
203 tmp = val & 0xffff;
204
205 return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
206}
207
208static int sja1105_base_t1_mdio_write_c45(struct mii_bus *bus, int phy,
209 int mmd, int reg, u16 val)
210{
211 struct sja1105_mdio_private *mdio_priv = bus->priv;
212 struct sja1105_private *priv = mdio_priv->priv;
213 u64 addr;
214 u32 tmp;
215 int rc;
216
217 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR, mmd);
218
219 rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, ®, NULL);
220 if (rc < 0)
221 return rc;
222
223 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA, mmd);
224
225 tmp = val & 0xffff;
226
227 return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
228}
229
230static int sja1105_base_tx_mdio_read(struct mii_bus *bus, int phy, int reg)
231{
232 struct sja1105_mdio_private *mdio_priv = bus->priv;
233 struct sja1105_private *priv = mdio_priv->priv;
234 const struct sja1105_regs *regs = priv->info->regs;
235 u32 tmp;
236 int rc;
237
238 rc = sja1105_xfer_u32(priv, SPI_READ, regs->mdio_100base_tx + reg,
239 &tmp, NULL);
240 if (rc < 0)
241 return rc;
242
243 return tmp & 0xffff;
244}
245
246static int sja1105_base_tx_mdio_write(struct mii_bus *bus, int phy, int reg,
247 u16 val)
248{
249 struct sja1105_mdio_private *mdio_priv = bus->priv;
250 struct sja1105_private *priv = mdio_priv->priv;
251 const struct sja1105_regs *regs = priv->info->regs;
252 u32 tmp = val;
253
254 return sja1105_xfer_u32(priv, SPI_WRITE, regs->mdio_100base_tx + reg,
255 &tmp, NULL);
256}
257
258static int sja1105_mdiobus_base_tx_register(struct sja1105_private *priv,
259 struct device_node *mdio_node)
260{
261 struct sja1105_mdio_private *mdio_priv;
262 struct device_node *np;
263 struct mii_bus *bus;
264 int rc = 0;
265
266 np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-tx-mdio");
267 if (!np)
268 return 0;
269
270 if (!of_device_is_available(np))
271 goto out_put_np;
272
273 bus = mdiobus_alloc_size(sizeof(*mdio_priv));
274 if (!bus) {
275 rc = -ENOMEM;
276 goto out_put_np;
277 }
278
279 bus->name = "SJA1110 100base-TX MDIO bus";
280 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-tx",
281 dev_name(priv->ds->dev));
282 bus->read = sja1105_base_tx_mdio_read;
283 bus->write = sja1105_base_tx_mdio_write;
284 bus->parent = priv->ds->dev;
285 mdio_priv = bus->priv;
286 mdio_priv->priv = priv;
287
288 rc = of_mdiobus_register(bus, np);
289 if (rc) {
290 mdiobus_free(bus);
291 goto out_put_np;
292 }
293
294 priv->mdio_base_tx = bus;
295
296out_put_np:
297 of_node_put(np);
298
299 return rc;
300}
301
302static void sja1105_mdiobus_base_tx_unregister(struct sja1105_private *priv)
303{
304 if (!priv->mdio_base_tx)
305 return;
306
307 mdiobus_unregister(priv->mdio_base_tx);
308 mdiobus_free(priv->mdio_base_tx);
309 priv->mdio_base_tx = NULL;
310}
311
312static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv,
313 struct device_node *mdio_node)
314{
315 struct sja1105_mdio_private *mdio_priv;
316 struct device_node *np;
317 struct mii_bus *bus;
318 int rc = 0;
319
320 np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-t1-mdio");
321 if (!np)
322 return 0;
323
324 if (!of_device_is_available(np))
325 goto out_put_np;
326
327 bus = mdiobus_alloc_size(sizeof(*mdio_priv));
328 if (!bus) {
329 rc = -ENOMEM;
330 goto out_put_np;
331 }
332
333 bus->name = "SJA1110 100base-T1 MDIO bus";
334 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-t1",
335 dev_name(priv->ds->dev));
336 bus->read = sja1105_base_t1_mdio_read_c22;
337 bus->write = sja1105_base_t1_mdio_write_c22;
338 bus->read_c45 = sja1105_base_t1_mdio_read_c45;
339 bus->write_c45 = sja1105_base_t1_mdio_write_c45;
340 bus->parent = priv->ds->dev;
341 mdio_priv = bus->priv;
342 mdio_priv->priv = priv;
343
344 rc = of_mdiobus_register(bus, np);
345 if (rc) {
346 mdiobus_free(bus);
347 goto out_put_np;
348 }
349
350 priv->mdio_base_t1 = bus;
351
352out_put_np:
353 of_node_put(np);
354
355 return rc;
356}
357
358static void sja1105_mdiobus_base_t1_unregister(struct sja1105_private *priv)
359{
360 if (!priv->mdio_base_t1)
361 return;
362
363 mdiobus_unregister(priv->mdio_base_t1);
364 mdiobus_free(priv->mdio_base_t1);
365 priv->mdio_base_t1 = NULL;
366}
367
368static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
369{
370 struct sja1105_mdio_private *mdio_priv;
371 struct dsa_switch *ds = priv->ds;
372 struct mii_bus *bus;
373 int rc = 0;
374 int port;
375
376 if (!priv->info->pcs_mdio_read_c45 || !priv->info->pcs_mdio_write_c45)
377 return 0;
378
379 bus = mdiobus_alloc_size(sizeof(*mdio_priv));
380 if (!bus)
381 return -ENOMEM;
382
383 bus->name = "SJA1105 PCS MDIO bus";
384 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-pcs",
385 dev_name(ds->dev));
386 bus->read_c45 = priv->info->pcs_mdio_read_c45;
387 bus->write_c45 = priv->info->pcs_mdio_write_c45;
388 bus->parent = ds->dev;
389 /* There is no PHY on this MDIO bus => mask out all PHY addresses
390 * from auto probing.
391 */
392 bus->phy_mask = ~0;
393 mdio_priv = bus->priv;
394 mdio_priv->priv = priv;
395
396 rc = mdiobus_register(bus);
397 if (rc) {
398 mdiobus_free(bus);
399 return rc;
400 }
401
402 for (port = 0; port < ds->num_ports; port++) {
403 struct dw_xpcs *xpcs;
404
405 if (dsa_is_unused_port(ds, port))
406 continue;
407
408 if (priv->phy_mode[port] != PHY_INTERFACE_MODE_SGMII &&
409 priv->phy_mode[port] != PHY_INTERFACE_MODE_2500BASEX)
410 continue;
411
412 xpcs = xpcs_create_mdiodev(bus, port, priv->phy_mode[port]);
413 if (IS_ERR(xpcs)) {
414 rc = PTR_ERR(xpcs);
415 goto out_pcs_free;
416 }
417
418 priv->xpcs[port] = xpcs;
419 }
420
421 priv->mdio_pcs = bus;
422
423 return 0;
424
425out_pcs_free:
426 for (port = 0; port < ds->num_ports; port++) {
427 if (!priv->xpcs[port])
428 continue;
429
430 xpcs_destroy(priv->xpcs[port]);
431 priv->xpcs[port] = NULL;
432 }
433
434 mdiobus_unregister(bus);
435 mdiobus_free(bus);
436
437 return rc;
438}
439
440static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv)
441{
442 struct dsa_switch *ds = priv->ds;
443 int port;
444
445 if (!priv->mdio_pcs)
446 return;
447
448 for (port = 0; port < ds->num_ports; port++) {
449 if (!priv->xpcs[port])
450 continue;
451
452 xpcs_destroy(priv->xpcs[port]);
453 priv->xpcs[port] = NULL;
454 }
455
456 mdiobus_unregister(priv->mdio_pcs);
457 mdiobus_free(priv->mdio_pcs);
458 priv->mdio_pcs = NULL;
459}
460
461int sja1105_mdiobus_register(struct dsa_switch *ds)
462{
463 struct sja1105_private *priv = ds->priv;
464 const struct sja1105_regs *regs = priv->info->regs;
465 struct device_node *switch_node = ds->dev->of_node;
466 struct device_node *mdio_node;
467 int rc;
468
469 rc = sja1105_mdiobus_pcs_register(priv);
470 if (rc)
471 return rc;
472
473 mdio_node = of_get_child_by_name(switch_node, "mdios");
474 if (!mdio_node)
475 return 0;
476
477 if (!of_device_is_available(mdio_node))
478 goto out_put_mdio_node;
479
480 if (regs->mdio_100base_tx != SJA1105_RSV_ADDR) {
481 rc = sja1105_mdiobus_base_tx_register(priv, mdio_node);
482 if (rc)
483 goto err_put_mdio_node;
484 }
485
486 if (regs->mdio_100base_t1 != SJA1105_RSV_ADDR) {
487 rc = sja1105_mdiobus_base_t1_register(priv, mdio_node);
488 if (rc)
489 goto err_free_base_tx_mdiobus;
490 }
491
492out_put_mdio_node:
493 of_node_put(mdio_node);
494
495 return 0;
496
497err_free_base_tx_mdiobus:
498 sja1105_mdiobus_base_tx_unregister(priv);
499err_put_mdio_node:
500 of_node_put(mdio_node);
501 sja1105_mdiobus_pcs_unregister(priv);
502
503 return rc;
504}
505
506void sja1105_mdiobus_unregister(struct dsa_switch *ds)
507{
508 struct sja1105_private *priv = ds->priv;
509
510 sja1105_mdiobus_base_t1_unregister(priv);
511 sja1105_mdiobus_base_tx_unregister(priv);
512 sja1105_mdiobus_pcs_unregister(priv);
513}
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright 2021 NXP
3 */
4#include <linux/pcs/pcs-xpcs.h>
5#include <linux/of_mdio.h>
6#include "sja1105.h"
7
8#define SJA1110_PCS_BANK_REG SJA1110_SPI_ADDR(0x3fc)
9
10int sja1105_pcs_mdio_read(struct mii_bus *bus, int phy, int reg)
11{
12 struct sja1105_mdio_private *mdio_priv = bus->priv;
13 struct sja1105_private *priv = mdio_priv->priv;
14 u64 addr;
15 u32 tmp;
16 u16 mmd;
17 int rc;
18
19 if (!(reg & MII_ADDR_C45))
20 return -EINVAL;
21
22 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
23 addr = (mmd << 16) | (reg & GENMASK(15, 0));
24
25 if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
26 return 0xffff;
27
28 if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID1)
29 return NXP_SJA1105_XPCS_ID >> 16;
30 if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID2)
31 return NXP_SJA1105_XPCS_ID & GENMASK(15, 0);
32
33 rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
34 if (rc < 0)
35 return rc;
36
37 return tmp & 0xffff;
38}
39
40int sja1105_pcs_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
41{
42 struct sja1105_mdio_private *mdio_priv = bus->priv;
43 struct sja1105_private *priv = mdio_priv->priv;
44 u64 addr;
45 u32 tmp;
46 u16 mmd;
47
48 if (!(reg & MII_ADDR_C45))
49 return -EINVAL;
50
51 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
52 addr = (mmd << 16) | (reg & GENMASK(15, 0));
53 tmp = val;
54
55 if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
56 return -EINVAL;
57
58 return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
59}
60
61int sja1110_pcs_mdio_read(struct mii_bus *bus, int phy, int reg)
62{
63 struct sja1105_mdio_private *mdio_priv = bus->priv;
64 struct sja1105_private *priv = mdio_priv->priv;
65 const struct sja1105_regs *regs = priv->info->regs;
66 int offset, bank;
67 u64 addr;
68 u32 tmp;
69 u16 mmd;
70 int rc;
71
72 if (!(reg & MII_ADDR_C45))
73 return -EINVAL;
74
75 if (regs->pcs_base[phy] == SJA1105_RSV_ADDR)
76 return -ENODEV;
77
78 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
79 addr = (mmd << 16) | (reg & GENMASK(15, 0));
80
81 if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID1)
82 return NXP_SJA1110_XPCS_ID >> 16;
83 if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID2)
84 return NXP_SJA1110_XPCS_ID & GENMASK(15, 0);
85
86 bank = addr >> 8;
87 offset = addr & GENMASK(7, 0);
88
89 /* This addressing scheme reserves register 0xff for the bank address
90 * register, so that can never be addressed.
91 */
92 if (WARN_ON(offset == 0xff))
93 return -ENODEV;
94
95 tmp = bank;
96
97 rc = sja1105_xfer_u32(priv, SPI_WRITE,
98 regs->pcs_base[phy] + SJA1110_PCS_BANK_REG,
99 &tmp, NULL);
100 if (rc < 0)
101 return rc;
102
103 rc = sja1105_xfer_u32(priv, SPI_READ, regs->pcs_base[phy] + offset,
104 &tmp, NULL);
105 if (rc < 0)
106 return rc;
107
108 return tmp & 0xffff;
109}
110
111int sja1110_pcs_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
112{
113 struct sja1105_mdio_private *mdio_priv = bus->priv;
114 struct sja1105_private *priv = mdio_priv->priv;
115 const struct sja1105_regs *regs = priv->info->regs;
116 int offset, bank;
117 u64 addr;
118 u32 tmp;
119 u16 mmd;
120 int rc;
121
122 if (!(reg & MII_ADDR_C45))
123 return -EINVAL;
124
125 if (regs->pcs_base[phy] == SJA1105_RSV_ADDR)
126 return -ENODEV;
127
128 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
129 addr = (mmd << 16) | (reg & GENMASK(15, 0));
130
131 bank = addr >> 8;
132 offset = addr & GENMASK(7, 0);
133
134 /* This addressing scheme reserves register 0xff for the bank address
135 * register, so that can never be addressed.
136 */
137 if (WARN_ON(offset == 0xff))
138 return -ENODEV;
139
140 tmp = bank;
141
142 rc = sja1105_xfer_u32(priv, SPI_WRITE,
143 regs->pcs_base[phy] + SJA1110_PCS_BANK_REG,
144 &tmp, NULL);
145 if (rc < 0)
146 return rc;
147
148 tmp = val;
149
150 return sja1105_xfer_u32(priv, SPI_WRITE, regs->pcs_base[phy] + offset,
151 &tmp, NULL);
152}
153
154enum sja1105_mdio_opcode {
155 SJA1105_C45_ADDR = 0,
156 SJA1105_C22 = 1,
157 SJA1105_C45_DATA = 2,
158 SJA1105_C45_DATA_AUTOINC = 3,
159};
160
161static u64 sja1105_base_t1_encode_addr(struct sja1105_private *priv,
162 int phy, enum sja1105_mdio_opcode op,
163 int xad)
164{
165 const struct sja1105_regs *regs = priv->info->regs;
166
167 return regs->mdio_100base_t1 | (phy << 7) | (op << 5) | (xad << 0);
168}
169
170static int sja1105_base_t1_mdio_read(struct mii_bus *bus, int phy, int reg)
171{
172 struct sja1105_mdio_private *mdio_priv = bus->priv;
173 struct sja1105_private *priv = mdio_priv->priv;
174 u64 addr;
175 u32 tmp;
176 int rc;
177
178 if (reg & MII_ADDR_C45) {
179 u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
180
181 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR,
182 mmd);
183
184 tmp = reg & MII_REGADDR_C45_MASK;
185
186 rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
187 if (rc < 0)
188 return rc;
189
190 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA,
191 mmd);
192
193 rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
194 if (rc < 0)
195 return rc;
196
197 return tmp & 0xffff;
198 }
199
200 /* Clause 22 read */
201 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
202
203 rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
204 if (rc < 0)
205 return rc;
206
207 return tmp & 0xffff;
208}
209
210static int sja1105_base_t1_mdio_write(struct mii_bus *bus, int phy, int reg,
211 u16 val)
212{
213 struct sja1105_mdio_private *mdio_priv = bus->priv;
214 struct sja1105_private *priv = mdio_priv->priv;
215 u64 addr;
216 u32 tmp;
217 int rc;
218
219 if (reg & MII_ADDR_C45) {
220 u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
221
222 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR,
223 mmd);
224
225 tmp = reg & MII_REGADDR_C45_MASK;
226
227 rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
228 if (rc < 0)
229 return rc;
230
231 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA,
232 mmd);
233
234 tmp = val & 0xffff;
235
236 rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
237 if (rc < 0)
238 return rc;
239
240 return 0;
241 }
242
243 /* Clause 22 write */
244 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
245
246 tmp = val & 0xffff;
247
248 return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
249}
250
251static int sja1105_base_tx_mdio_read(struct mii_bus *bus, int phy, int reg)
252{
253 struct sja1105_mdio_private *mdio_priv = bus->priv;
254 struct sja1105_private *priv = mdio_priv->priv;
255 const struct sja1105_regs *regs = priv->info->regs;
256 u32 tmp;
257 int rc;
258
259 if (reg & MII_ADDR_C45)
260 return -EOPNOTSUPP;
261
262 rc = sja1105_xfer_u32(priv, SPI_READ, regs->mdio_100base_tx + reg,
263 &tmp, NULL);
264 if (rc < 0)
265 return rc;
266
267 return tmp & 0xffff;
268}
269
270static int sja1105_base_tx_mdio_write(struct mii_bus *bus, int phy, int reg,
271 u16 val)
272{
273 struct sja1105_mdio_private *mdio_priv = bus->priv;
274 struct sja1105_private *priv = mdio_priv->priv;
275 const struct sja1105_regs *regs = priv->info->regs;
276 u32 tmp = val;
277
278 if (reg & MII_ADDR_C45)
279 return -EOPNOTSUPP;
280
281 return sja1105_xfer_u32(priv, SPI_WRITE, regs->mdio_100base_tx + reg,
282 &tmp, NULL);
283}
284
285static int sja1105_mdiobus_base_tx_register(struct sja1105_private *priv,
286 struct device_node *mdio_node)
287{
288 struct sja1105_mdio_private *mdio_priv;
289 struct device_node *np;
290 struct mii_bus *bus;
291 int rc = 0;
292
293 np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-tx-mdio");
294 if (!np)
295 return 0;
296
297 if (!of_device_is_available(np))
298 goto out_put_np;
299
300 bus = mdiobus_alloc_size(sizeof(*mdio_priv));
301 if (!bus) {
302 rc = -ENOMEM;
303 goto out_put_np;
304 }
305
306 bus->name = "SJA1110 100base-TX MDIO bus";
307 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-tx",
308 dev_name(priv->ds->dev));
309 bus->read = sja1105_base_tx_mdio_read;
310 bus->write = sja1105_base_tx_mdio_write;
311 bus->parent = priv->ds->dev;
312 mdio_priv = bus->priv;
313 mdio_priv->priv = priv;
314
315 rc = of_mdiobus_register(bus, np);
316 if (rc) {
317 mdiobus_free(bus);
318 goto out_put_np;
319 }
320
321 priv->mdio_base_tx = bus;
322
323out_put_np:
324 of_node_put(np);
325
326 return rc;
327}
328
329static void sja1105_mdiobus_base_tx_unregister(struct sja1105_private *priv)
330{
331 if (!priv->mdio_base_tx)
332 return;
333
334 mdiobus_unregister(priv->mdio_base_tx);
335 mdiobus_free(priv->mdio_base_tx);
336 priv->mdio_base_tx = NULL;
337}
338
339static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv,
340 struct device_node *mdio_node)
341{
342 struct sja1105_mdio_private *mdio_priv;
343 struct device_node *np;
344 struct mii_bus *bus;
345 int rc = 0;
346
347 np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-t1-mdio");
348 if (!np)
349 return 0;
350
351 if (!of_device_is_available(np))
352 goto out_put_np;
353
354 bus = mdiobus_alloc_size(sizeof(*mdio_priv));
355 if (!bus) {
356 rc = -ENOMEM;
357 goto out_put_np;
358 }
359
360 bus->name = "SJA1110 100base-T1 MDIO bus";
361 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-t1",
362 dev_name(priv->ds->dev));
363 bus->read = sja1105_base_t1_mdio_read;
364 bus->write = sja1105_base_t1_mdio_write;
365 bus->parent = priv->ds->dev;
366 mdio_priv = bus->priv;
367 mdio_priv->priv = priv;
368
369 rc = of_mdiobus_register(bus, np);
370 if (rc) {
371 mdiobus_free(bus);
372 goto out_put_np;
373 }
374
375 priv->mdio_base_t1 = bus;
376
377out_put_np:
378 of_node_put(np);
379
380 return rc;
381}
382
383static void sja1105_mdiobus_base_t1_unregister(struct sja1105_private *priv)
384{
385 if (!priv->mdio_base_t1)
386 return;
387
388 mdiobus_unregister(priv->mdio_base_t1);
389 mdiobus_free(priv->mdio_base_t1);
390 priv->mdio_base_t1 = NULL;
391}
392
393static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
394{
395 struct sja1105_mdio_private *mdio_priv;
396 struct dsa_switch *ds = priv->ds;
397 struct mii_bus *bus;
398 int rc = 0;
399 int port;
400
401 if (!priv->info->pcs_mdio_read || !priv->info->pcs_mdio_write)
402 return 0;
403
404 bus = mdiobus_alloc_size(sizeof(*mdio_priv));
405 if (!bus)
406 return -ENOMEM;
407
408 bus->name = "SJA1105 PCS MDIO bus";
409 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-pcs",
410 dev_name(ds->dev));
411 bus->read = priv->info->pcs_mdio_read;
412 bus->write = priv->info->pcs_mdio_write;
413 bus->parent = ds->dev;
414 /* There is no PHY on this MDIO bus => mask out all PHY addresses
415 * from auto probing.
416 */
417 bus->phy_mask = ~0;
418 mdio_priv = bus->priv;
419 mdio_priv->priv = priv;
420
421 rc = mdiobus_register(bus);
422 if (rc) {
423 mdiobus_free(bus);
424 return rc;
425 }
426
427 for (port = 0; port < ds->num_ports; port++) {
428 struct mdio_device *mdiodev;
429 struct dw_xpcs *xpcs;
430
431 if (dsa_is_unused_port(ds, port))
432 continue;
433
434 if (priv->phy_mode[port] != PHY_INTERFACE_MODE_SGMII &&
435 priv->phy_mode[port] != PHY_INTERFACE_MODE_2500BASEX)
436 continue;
437
438 mdiodev = mdio_device_create(bus, port);
439 if (IS_ERR(mdiodev)) {
440 rc = PTR_ERR(mdiodev);
441 goto out_pcs_free;
442 }
443
444 xpcs = xpcs_create(mdiodev, priv->phy_mode[port]);
445 if (IS_ERR(xpcs)) {
446 rc = PTR_ERR(xpcs);
447 goto out_pcs_free;
448 }
449
450 priv->xpcs[port] = xpcs;
451 }
452
453 priv->mdio_pcs = bus;
454
455 return 0;
456
457out_pcs_free:
458 for (port = 0; port < ds->num_ports; port++) {
459 if (!priv->xpcs[port])
460 continue;
461
462 mdio_device_free(priv->xpcs[port]->mdiodev);
463 xpcs_destroy(priv->xpcs[port]);
464 priv->xpcs[port] = NULL;
465 }
466
467 mdiobus_unregister(bus);
468 mdiobus_free(bus);
469
470 return rc;
471}
472
473static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv)
474{
475 struct dsa_switch *ds = priv->ds;
476 int port;
477
478 if (!priv->mdio_pcs)
479 return;
480
481 for (port = 0; port < ds->num_ports; port++) {
482 if (!priv->xpcs[port])
483 continue;
484
485 mdio_device_free(priv->xpcs[port]->mdiodev);
486 xpcs_destroy(priv->xpcs[port]);
487 priv->xpcs[port] = NULL;
488 }
489
490 mdiobus_unregister(priv->mdio_pcs);
491 mdiobus_free(priv->mdio_pcs);
492 priv->mdio_pcs = NULL;
493}
494
495int sja1105_mdiobus_register(struct dsa_switch *ds)
496{
497 struct sja1105_private *priv = ds->priv;
498 const struct sja1105_regs *regs = priv->info->regs;
499 struct device_node *switch_node = ds->dev->of_node;
500 struct device_node *mdio_node;
501 int rc;
502
503 rc = sja1105_mdiobus_pcs_register(priv);
504 if (rc)
505 return rc;
506
507 mdio_node = of_get_child_by_name(switch_node, "mdios");
508 if (!mdio_node)
509 return 0;
510
511 if (!of_device_is_available(mdio_node))
512 goto out_put_mdio_node;
513
514 if (regs->mdio_100base_tx != SJA1105_RSV_ADDR) {
515 rc = sja1105_mdiobus_base_tx_register(priv, mdio_node);
516 if (rc)
517 goto err_put_mdio_node;
518 }
519
520 if (regs->mdio_100base_t1 != SJA1105_RSV_ADDR) {
521 rc = sja1105_mdiobus_base_t1_register(priv, mdio_node);
522 if (rc)
523 goto err_free_base_tx_mdiobus;
524 }
525
526out_put_mdio_node:
527 of_node_put(mdio_node);
528
529 return 0;
530
531err_free_base_tx_mdiobus:
532 sja1105_mdiobus_base_tx_unregister(priv);
533err_put_mdio_node:
534 of_node_put(mdio_node);
535 sja1105_mdiobus_pcs_unregister(priv);
536
537 return rc;
538}
539
540void sja1105_mdiobus_unregister(struct dsa_switch *ds)
541{
542 struct sja1105_private *priv = ds->priv;
543
544 sja1105_mdiobus_base_t1_unregister(priv);
545 sja1105_mdiobus_base_tx_unregister(priv);
546 sja1105_mdiobus_pcs_unregister(priv);
547}