1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2021, NXP Semiconductors
4 #include <linux/pcs/pcs-xpcs.h>
5 #include <linux/of_mdio.h>
8 int sja1105_pcs_mdio_read(struct mii_bus *bus, int phy, int reg)
10 struct sja1105_mdio_private *mdio_priv = bus->priv;
11 struct sja1105_private *priv = mdio_priv->priv;
17 if (!(reg & MII_ADDR_C45))
20 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
21 addr = (mmd << 16) | (reg & GENMASK(15, 0));
23 if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
26 if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID1)
27 return NXP_SJA1105_XPCS_ID >> 16;
28 if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID2)
29 return NXP_SJA1105_XPCS_ID & GENMASK(15, 0);
31 rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
38 int sja1105_pcs_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
40 struct sja1105_mdio_private *mdio_priv = bus->priv;
41 struct sja1105_private *priv = mdio_priv->priv;
46 if (!(reg & MII_ADDR_C45))
49 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
50 addr = (mmd << 16) | (reg & GENMASK(15, 0));
53 if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
56 return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
59 enum sja1105_mdio_opcode {
63 SJA1105_C45_DATA_AUTOINC = 3,
66 static u64 sja1105_base_t1_encode_addr(struct sja1105_private *priv,
67 int phy, enum sja1105_mdio_opcode op,
70 const struct sja1105_regs *regs = priv->info->regs;
72 return regs->mdio_100base_t1 | (phy << 7) | (op << 5) | (xad << 0);
75 static int sja1105_base_t1_mdio_read(struct mii_bus *bus, int phy, int reg)
77 struct sja1105_mdio_private *mdio_priv = bus->priv;
78 struct sja1105_private *priv = mdio_priv->priv;
83 if (reg & MII_ADDR_C45) {
84 u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
86 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR,
89 tmp = reg & MII_REGADDR_C45_MASK;
91 rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
95 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA,
98 rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
106 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
108 rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
115 static int sja1105_base_t1_mdio_write(struct mii_bus *bus, int phy, int reg,
118 struct sja1105_mdio_private *mdio_priv = bus->priv;
119 struct sja1105_private *priv = mdio_priv->priv;
124 if (reg & MII_ADDR_C45) {
125 u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
127 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR,
130 tmp = reg & MII_REGADDR_C45_MASK;
132 rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
136 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA,
141 rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
148 /* Clause 22 write */
149 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
153 return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
156 static int sja1105_base_tx_mdio_read(struct mii_bus *bus, int phy, int reg)
158 struct sja1105_mdio_private *mdio_priv = bus->priv;
159 struct sja1105_private *priv = mdio_priv->priv;
160 const struct sja1105_regs *regs = priv->info->regs;
164 rc = sja1105_xfer_u32(priv, SPI_READ, regs->mdio_100base_tx + reg,
172 static int sja1105_base_tx_mdio_write(struct mii_bus *bus, int phy, int reg,
175 struct sja1105_mdio_private *mdio_priv = bus->priv;
176 struct sja1105_private *priv = mdio_priv->priv;
177 const struct sja1105_regs *regs = priv->info->regs;
180 return sja1105_xfer_u32(priv, SPI_WRITE, regs->mdio_100base_tx + reg,
184 static int sja1105_mdiobus_base_tx_register(struct sja1105_private *priv,
185 struct device_node *mdio_node)
187 struct sja1105_mdio_private *mdio_priv;
188 struct device_node *np;
192 np = of_find_compatible_node(mdio_node, NULL,
193 "nxp,sja1110-base-tx-mdio");
197 if (!of_device_is_available(np))
200 bus = mdiobus_alloc_size(sizeof(*mdio_priv));
206 bus->name = "SJA1110 100base-TX MDIO bus";
207 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-tx",
208 dev_name(priv->ds->dev));
209 bus->read = sja1105_base_tx_mdio_read;
210 bus->write = sja1105_base_tx_mdio_write;
211 bus->parent = priv->ds->dev;
212 mdio_priv = bus->priv;
213 mdio_priv->priv = priv;
215 rc = of_mdiobus_register(bus, np);
221 priv->mdio_base_tx = bus;
229 static void sja1105_mdiobus_base_tx_unregister(struct sja1105_private *priv)
231 if (!priv->mdio_base_tx)
234 mdiobus_unregister(priv->mdio_base_tx);
235 mdiobus_free(priv->mdio_base_tx);
236 priv->mdio_base_tx = NULL;
239 static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv,
240 struct device_node *mdio_node)
242 struct sja1105_mdio_private *mdio_priv;
243 struct device_node *np;
247 np = of_find_compatible_node(mdio_node, NULL,
248 "nxp,sja1110-base-t1-mdio");
252 if (!of_device_is_available(np))
255 bus = mdiobus_alloc_size(sizeof(*mdio_priv));
261 bus->name = "SJA1110 100base-T1 MDIO bus";
262 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-t1",
263 dev_name(priv->ds->dev));
264 bus->read = sja1105_base_t1_mdio_read;
265 bus->write = sja1105_base_t1_mdio_write;
266 bus->parent = priv->ds->dev;
267 mdio_priv = bus->priv;
268 mdio_priv->priv = priv;
270 rc = of_mdiobus_register(bus, np);
276 priv->mdio_base_t1 = bus;
284 static void sja1105_mdiobus_base_t1_unregister(struct sja1105_private *priv)
286 if (!priv->mdio_base_t1)
289 mdiobus_unregister(priv->mdio_base_t1);
290 mdiobus_free(priv->mdio_base_t1);
291 priv->mdio_base_t1 = NULL;
294 static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
296 struct sja1105_mdio_private *mdio_priv;
297 struct dsa_switch *ds = priv->ds;
302 if (!priv->info->pcs_mdio_read || !priv->info->pcs_mdio_write)
305 bus = mdiobus_alloc_size(sizeof(*mdio_priv));
309 bus->name = "SJA1105 PCS MDIO bus";
310 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-pcs",
312 bus->read = priv->info->pcs_mdio_read;
313 bus->write = priv->info->pcs_mdio_write;
314 bus->parent = ds->dev;
315 /* There is no PHY on this MDIO bus => mask out all PHY addresses
319 mdio_priv = bus->priv;
320 mdio_priv->priv = priv;
322 rc = mdiobus_register(bus);
328 for (port = 0; port < ds->num_ports; port++) {
329 struct mdio_device *mdiodev;
330 struct dw_xpcs *xpcs;
332 if (dsa_is_unused_port(ds, port))
335 if (priv->phy_mode[port] != PHY_INTERFACE_MODE_SGMII)
338 mdiodev = mdio_device_create(bus, port);
339 if (IS_ERR(mdiodev)) {
340 rc = PTR_ERR(mdiodev);
344 xpcs = xpcs_create(mdiodev, priv->phy_mode[port]);
350 priv->xpcs[port] = xpcs;
353 priv->mdio_pcs = bus;
358 for (port = 0; port < ds->num_ports; port++) {
359 if (!priv->xpcs[port])
362 mdio_device_free(priv->xpcs[port]->mdiodev);
363 xpcs_destroy(priv->xpcs[port]);
364 priv->xpcs[port] = NULL;
367 mdiobus_unregister(bus);
373 static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv)
375 struct dsa_switch *ds = priv->ds;
381 for (port = 0; port < ds->num_ports; port++) {
382 if (!priv->xpcs[port])
385 mdio_device_free(priv->xpcs[port]->mdiodev);
386 xpcs_destroy(priv->xpcs[port]);
387 priv->xpcs[port] = NULL;
390 mdiobus_unregister(priv->mdio_pcs);
391 mdiobus_free(priv->mdio_pcs);
392 priv->mdio_pcs = NULL;
395 int sja1105_mdiobus_register(struct dsa_switch *ds)
397 struct sja1105_private *priv = ds->priv;
398 const struct sja1105_regs *regs = priv->info->regs;
399 struct device_node *switch_node = ds->dev->of_node;
400 struct device_node *mdio_node;
403 rc = sja1105_mdiobus_pcs_register(priv);
407 mdio_node = of_get_child_by_name(switch_node, "mdios");
411 if (!of_device_is_available(mdio_node))
412 goto out_put_mdio_node;
414 if (regs->mdio_100base_tx != SJA1105_RSV_ADDR) {
415 rc = sja1105_mdiobus_base_tx_register(priv, mdio_node);
417 goto err_put_mdio_node;
420 if (regs->mdio_100base_t1 != SJA1105_RSV_ADDR) {
421 rc = sja1105_mdiobus_base_t1_register(priv, mdio_node);
423 goto err_free_base_tx_mdiobus;
427 of_node_put(mdio_node);
431 err_free_base_tx_mdiobus:
432 sja1105_mdiobus_base_tx_unregister(priv);
434 of_node_put(mdio_node);
435 sja1105_mdiobus_pcs_unregister(priv);
440 void sja1105_mdiobus_unregister(struct dsa_switch *ds)
442 struct sja1105_private *priv = ds->priv;
444 sja1105_mdiobus_base_t1_unregister(priv);
445 sja1105_mdiobus_base_tx_unregister(priv);
446 sja1105_mdiobus_pcs_unregister(priv);