Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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}