xref: /linux/drivers/net/dsa/sja1105/sja1105_mdio.c (revision 9dbbc3b9d09d6deba9f3b9e1d5b355032ed46a75)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2021, NXP Semiconductors
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 
10 int 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 
40 int 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 
61 int 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 
111 int 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 
154 enum 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 
161 static 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 
170 static 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 
210 static 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 
251 static 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 	rc = sja1105_xfer_u32(priv, SPI_READ, regs->mdio_100base_tx + reg,
260 			      &tmp, NULL);
261 	if (rc < 0)
262 		return rc;
263 
264 	return tmp & 0xffff;
265 }
266 
267 static int sja1105_base_tx_mdio_write(struct mii_bus *bus, int phy, int reg,
268 				      u16 val)
269 {
270 	struct sja1105_mdio_private *mdio_priv = bus->priv;
271 	struct sja1105_private *priv = mdio_priv->priv;
272 	const struct sja1105_regs *regs = priv->info->regs;
273 	u32 tmp = val;
274 
275 	return sja1105_xfer_u32(priv, SPI_WRITE, regs->mdio_100base_tx + reg,
276 				&tmp, NULL);
277 }
278 
279 static int sja1105_mdiobus_base_tx_register(struct sja1105_private *priv,
280 					    struct device_node *mdio_node)
281 {
282 	struct sja1105_mdio_private *mdio_priv;
283 	struct device_node *np;
284 	struct mii_bus *bus;
285 	int rc = 0;
286 
287 	np = of_find_compatible_node(mdio_node, NULL,
288 				     "nxp,sja1110-base-tx-mdio");
289 	if (!np)
290 		return 0;
291 
292 	if (!of_device_is_available(np))
293 		goto out_put_np;
294 
295 	bus = mdiobus_alloc_size(sizeof(*mdio_priv));
296 	if (!bus) {
297 		rc = -ENOMEM;
298 		goto out_put_np;
299 	}
300 
301 	bus->name = "SJA1110 100base-TX MDIO bus";
302 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-tx",
303 		 dev_name(priv->ds->dev));
304 	bus->read = sja1105_base_tx_mdio_read;
305 	bus->write = sja1105_base_tx_mdio_write;
306 	bus->parent = priv->ds->dev;
307 	mdio_priv = bus->priv;
308 	mdio_priv->priv = priv;
309 
310 	rc = of_mdiobus_register(bus, np);
311 	if (rc) {
312 		mdiobus_free(bus);
313 		goto out_put_np;
314 	}
315 
316 	priv->mdio_base_tx = bus;
317 
318 out_put_np:
319 	of_node_put(np);
320 
321 	return rc;
322 }
323 
324 static void sja1105_mdiobus_base_tx_unregister(struct sja1105_private *priv)
325 {
326 	if (!priv->mdio_base_tx)
327 		return;
328 
329 	mdiobus_unregister(priv->mdio_base_tx);
330 	mdiobus_free(priv->mdio_base_tx);
331 	priv->mdio_base_tx = NULL;
332 }
333 
334 static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv,
335 					    struct device_node *mdio_node)
336 {
337 	struct sja1105_mdio_private *mdio_priv;
338 	struct device_node *np;
339 	struct mii_bus *bus;
340 	int rc = 0;
341 
342 	np = of_find_compatible_node(mdio_node, NULL,
343 				     "nxp,sja1110-base-t1-mdio");
344 	if (!np)
345 		return 0;
346 
347 	if (!of_device_is_available(np))
348 		goto out_put_np;
349 
350 	bus = mdiobus_alloc_size(sizeof(*mdio_priv));
351 	if (!bus) {
352 		rc = -ENOMEM;
353 		goto out_put_np;
354 	}
355 
356 	bus->name = "SJA1110 100base-T1 MDIO bus";
357 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-t1",
358 		 dev_name(priv->ds->dev));
359 	bus->read = sja1105_base_t1_mdio_read;
360 	bus->write = sja1105_base_t1_mdio_write;
361 	bus->parent = priv->ds->dev;
362 	mdio_priv = bus->priv;
363 	mdio_priv->priv = priv;
364 
365 	rc = of_mdiobus_register(bus, np);
366 	if (rc) {
367 		mdiobus_free(bus);
368 		goto out_put_np;
369 	}
370 
371 	priv->mdio_base_t1 = bus;
372 
373 out_put_np:
374 	of_node_put(np);
375 
376 	return rc;
377 }
378 
379 static void sja1105_mdiobus_base_t1_unregister(struct sja1105_private *priv)
380 {
381 	if (!priv->mdio_base_t1)
382 		return;
383 
384 	mdiobus_unregister(priv->mdio_base_t1);
385 	mdiobus_free(priv->mdio_base_t1);
386 	priv->mdio_base_t1 = NULL;
387 }
388 
389 static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
390 {
391 	struct sja1105_mdio_private *mdio_priv;
392 	struct dsa_switch *ds = priv->ds;
393 	struct mii_bus *bus;
394 	int rc = 0;
395 	int port;
396 
397 	if (!priv->info->pcs_mdio_read || !priv->info->pcs_mdio_write)
398 		return 0;
399 
400 	bus = mdiobus_alloc_size(sizeof(*mdio_priv));
401 	if (!bus)
402 		return -ENOMEM;
403 
404 	bus->name = "SJA1105 PCS MDIO bus";
405 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-pcs",
406 		 dev_name(ds->dev));
407 	bus->read = priv->info->pcs_mdio_read;
408 	bus->write = priv->info->pcs_mdio_write;
409 	bus->parent = ds->dev;
410 	/* There is no PHY on this MDIO bus => mask out all PHY addresses
411 	 * from auto probing.
412 	 */
413 	bus->phy_mask = ~0;
414 	mdio_priv = bus->priv;
415 	mdio_priv->priv = priv;
416 
417 	rc = mdiobus_register(bus);
418 	if (rc) {
419 		mdiobus_free(bus);
420 		return rc;
421 	}
422 
423 	for (port = 0; port < ds->num_ports; port++) {
424 		struct mdio_device *mdiodev;
425 		struct dw_xpcs *xpcs;
426 
427 		if (dsa_is_unused_port(ds, port))
428 			continue;
429 
430 		if (priv->phy_mode[port] != PHY_INTERFACE_MODE_SGMII &&
431 		    priv->phy_mode[port] != PHY_INTERFACE_MODE_2500BASEX)
432 			continue;
433 
434 		mdiodev = mdio_device_create(bus, port);
435 		if (IS_ERR(mdiodev)) {
436 			rc = PTR_ERR(mdiodev);
437 			goto out_pcs_free;
438 		}
439 
440 		xpcs = xpcs_create(mdiodev, priv->phy_mode[port]);
441 		if (IS_ERR(xpcs)) {
442 			rc = PTR_ERR(xpcs);
443 			goto out_pcs_free;
444 		}
445 
446 		priv->xpcs[port] = xpcs;
447 	}
448 
449 	priv->mdio_pcs = bus;
450 
451 	return 0;
452 
453 out_pcs_free:
454 	for (port = 0; port < ds->num_ports; port++) {
455 		if (!priv->xpcs[port])
456 			continue;
457 
458 		mdio_device_free(priv->xpcs[port]->mdiodev);
459 		xpcs_destroy(priv->xpcs[port]);
460 		priv->xpcs[port] = NULL;
461 	}
462 
463 	mdiobus_unregister(bus);
464 	mdiobus_free(bus);
465 
466 	return rc;
467 }
468 
469 static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv)
470 {
471 	struct dsa_switch *ds = priv->ds;
472 	int port;
473 
474 	if (!priv->mdio_pcs)
475 		return;
476 
477 	for (port = 0; port < ds->num_ports; port++) {
478 		if (!priv->xpcs[port])
479 			continue;
480 
481 		mdio_device_free(priv->xpcs[port]->mdiodev);
482 		xpcs_destroy(priv->xpcs[port]);
483 		priv->xpcs[port] = NULL;
484 	}
485 
486 	mdiobus_unregister(priv->mdio_pcs);
487 	mdiobus_free(priv->mdio_pcs);
488 	priv->mdio_pcs = NULL;
489 }
490 
491 int sja1105_mdiobus_register(struct dsa_switch *ds)
492 {
493 	struct sja1105_private *priv = ds->priv;
494 	const struct sja1105_regs *regs = priv->info->regs;
495 	struct device_node *switch_node = ds->dev->of_node;
496 	struct device_node *mdio_node;
497 	int rc;
498 
499 	rc = sja1105_mdiobus_pcs_register(priv);
500 	if (rc)
501 		return rc;
502 
503 	mdio_node = of_get_child_by_name(switch_node, "mdios");
504 	if (!mdio_node)
505 		return 0;
506 
507 	if (!of_device_is_available(mdio_node))
508 		goto out_put_mdio_node;
509 
510 	if (regs->mdio_100base_tx != SJA1105_RSV_ADDR) {
511 		rc = sja1105_mdiobus_base_tx_register(priv, mdio_node);
512 		if (rc)
513 			goto err_put_mdio_node;
514 	}
515 
516 	if (regs->mdio_100base_t1 != SJA1105_RSV_ADDR) {
517 		rc = sja1105_mdiobus_base_t1_register(priv, mdio_node);
518 		if (rc)
519 			goto err_free_base_tx_mdiobus;
520 	}
521 
522 out_put_mdio_node:
523 	of_node_put(mdio_node);
524 
525 	return 0;
526 
527 err_free_base_tx_mdiobus:
528 	sja1105_mdiobus_base_tx_unregister(priv);
529 err_put_mdio_node:
530 	of_node_put(mdio_node);
531 	sja1105_mdiobus_pcs_unregister(priv);
532 
533 	return rc;
534 }
535 
536 void sja1105_mdiobus_unregister(struct dsa_switch *ds)
537 {
538 	struct sja1105_private *priv = ds->priv;
539 
540 	sja1105_mdiobus_base_t1_unregister(priv);
541 	sja1105_mdiobus_base_tx_unregister(priv);
542 	sja1105_mdiobus_pcs_unregister(priv);
543 }
544