Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

Apr 14-17, 2025
Register
Loading...
v6.8
  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, &reg, 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, &reg, 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}
v6.2
  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}