Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright 2021 NXP
0003  */
0004 #include <linux/pcs/pcs-xpcs.h>
0005 #include <linux/of_mdio.h>
0006 #include "sja1105.h"
0007 
0008 #define SJA1110_PCS_BANK_REG        SJA1110_SPI_ADDR(0x3fc)
0009 
0010 int sja1105_pcs_mdio_read(struct mii_bus *bus, int phy, int reg)
0011 {
0012     struct sja1105_mdio_private *mdio_priv = bus->priv;
0013     struct sja1105_private *priv = mdio_priv->priv;
0014     u64 addr;
0015     u32 tmp;
0016     u16 mmd;
0017     int rc;
0018 
0019     if (!(reg & MII_ADDR_C45))
0020         return -EINVAL;
0021 
0022     mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
0023     addr = (mmd << 16) | (reg & GENMASK(15, 0));
0024 
0025     if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
0026         return 0xffff;
0027 
0028     if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID1)
0029         return NXP_SJA1105_XPCS_ID >> 16;
0030     if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID2)
0031         return NXP_SJA1105_XPCS_ID & GENMASK(15, 0);
0032 
0033     rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
0034     if (rc < 0)
0035         return rc;
0036 
0037     return tmp & 0xffff;
0038 }
0039 
0040 int sja1105_pcs_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
0041 {
0042     struct sja1105_mdio_private *mdio_priv = bus->priv;
0043     struct sja1105_private *priv = mdio_priv->priv;
0044     u64 addr;
0045     u32 tmp;
0046     u16 mmd;
0047 
0048     if (!(reg & MII_ADDR_C45))
0049         return -EINVAL;
0050 
0051     mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
0052     addr = (mmd << 16) | (reg & GENMASK(15, 0));
0053     tmp = val;
0054 
0055     if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
0056         return -EINVAL;
0057 
0058     return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
0059 }
0060 
0061 int sja1110_pcs_mdio_read(struct mii_bus *bus, int phy, int reg)
0062 {
0063     struct sja1105_mdio_private *mdio_priv = bus->priv;
0064     struct sja1105_private *priv = mdio_priv->priv;
0065     const struct sja1105_regs *regs = priv->info->regs;
0066     int offset, bank;
0067     u64 addr;
0068     u32 tmp;
0069     u16 mmd;
0070     int rc;
0071 
0072     if (!(reg & MII_ADDR_C45))
0073         return -EINVAL;
0074 
0075     if (regs->pcs_base[phy] == SJA1105_RSV_ADDR)
0076         return -ENODEV;
0077 
0078     mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
0079     addr = (mmd << 16) | (reg & GENMASK(15, 0));
0080 
0081     if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID1)
0082         return NXP_SJA1110_XPCS_ID >> 16;
0083     if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID2)
0084         return NXP_SJA1110_XPCS_ID & GENMASK(15, 0);
0085 
0086     bank = addr >> 8;
0087     offset = addr & GENMASK(7, 0);
0088 
0089     /* This addressing scheme reserves register 0xff for the bank address
0090      * register, so that can never be addressed.
0091      */
0092     if (WARN_ON(offset == 0xff))
0093         return -ENODEV;
0094 
0095     tmp = bank;
0096 
0097     rc = sja1105_xfer_u32(priv, SPI_WRITE,
0098                   regs->pcs_base[phy] + SJA1110_PCS_BANK_REG,
0099                   &tmp, NULL);
0100     if (rc < 0)
0101         return rc;
0102 
0103     rc = sja1105_xfer_u32(priv, SPI_READ, regs->pcs_base[phy] + offset,
0104                   &tmp, NULL);
0105     if (rc < 0)
0106         return rc;
0107 
0108     return tmp & 0xffff;
0109 }
0110 
0111 int sja1110_pcs_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
0112 {
0113     struct sja1105_mdio_private *mdio_priv = bus->priv;
0114     struct sja1105_private *priv = mdio_priv->priv;
0115     const struct sja1105_regs *regs = priv->info->regs;
0116     int offset, bank;
0117     u64 addr;
0118     u32 tmp;
0119     u16 mmd;
0120     int rc;
0121 
0122     if (!(reg & MII_ADDR_C45))
0123         return -EINVAL;
0124 
0125     if (regs->pcs_base[phy] == SJA1105_RSV_ADDR)
0126         return -ENODEV;
0127 
0128     mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
0129     addr = (mmd << 16) | (reg & GENMASK(15, 0));
0130 
0131     bank = addr >> 8;
0132     offset = addr & GENMASK(7, 0);
0133 
0134     /* This addressing scheme reserves register 0xff for the bank address
0135      * register, so that can never be addressed.
0136      */
0137     if (WARN_ON(offset == 0xff))
0138         return -ENODEV;
0139 
0140     tmp = bank;
0141 
0142     rc = sja1105_xfer_u32(priv, SPI_WRITE,
0143                   regs->pcs_base[phy] + SJA1110_PCS_BANK_REG,
0144                   &tmp, NULL);
0145     if (rc < 0)
0146         return rc;
0147 
0148     tmp = val;
0149 
0150     return sja1105_xfer_u32(priv, SPI_WRITE, regs->pcs_base[phy] + offset,
0151                 &tmp, NULL);
0152 }
0153 
0154 enum sja1105_mdio_opcode {
0155     SJA1105_C45_ADDR = 0,
0156     SJA1105_C22 = 1,
0157     SJA1105_C45_DATA = 2,
0158     SJA1105_C45_DATA_AUTOINC = 3,
0159 };
0160 
0161 static u64 sja1105_base_t1_encode_addr(struct sja1105_private *priv,
0162                        int phy, enum sja1105_mdio_opcode op,
0163                        int xad)
0164 {
0165     const struct sja1105_regs *regs = priv->info->regs;
0166 
0167     return regs->mdio_100base_t1 | (phy << 7) | (op << 5) | (xad << 0);
0168 }
0169 
0170 static int sja1105_base_t1_mdio_read(struct mii_bus *bus, int phy, int reg)
0171 {
0172     struct sja1105_mdio_private *mdio_priv = bus->priv;
0173     struct sja1105_private *priv = mdio_priv->priv;
0174     u64 addr;
0175     u32 tmp;
0176     int rc;
0177 
0178     if (reg & MII_ADDR_C45) {
0179         u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
0180 
0181         addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR,
0182                            mmd);
0183 
0184         tmp = reg & MII_REGADDR_C45_MASK;
0185 
0186         rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
0187         if (rc < 0)
0188             return rc;
0189 
0190         addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA,
0191                            mmd);
0192 
0193         rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
0194         if (rc < 0)
0195             return rc;
0196 
0197         return tmp & 0xffff;
0198     }
0199 
0200     /* Clause 22 read */
0201     addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
0202 
0203     rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
0204     if (rc < 0)
0205         return rc;
0206 
0207     return tmp & 0xffff;
0208 }
0209 
0210 static int sja1105_base_t1_mdio_write(struct mii_bus *bus, int phy, int reg,
0211                       u16 val)
0212 {
0213     struct sja1105_mdio_private *mdio_priv = bus->priv;
0214     struct sja1105_private *priv = mdio_priv->priv;
0215     u64 addr;
0216     u32 tmp;
0217     int rc;
0218 
0219     if (reg & MII_ADDR_C45) {
0220         u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
0221 
0222         addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR,
0223                            mmd);
0224 
0225         tmp = reg & MII_REGADDR_C45_MASK;
0226 
0227         rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
0228         if (rc < 0)
0229             return rc;
0230 
0231         addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA,
0232                            mmd);
0233 
0234         tmp = val & 0xffff;
0235 
0236         rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
0237         if (rc < 0)
0238             return rc;
0239 
0240         return 0;
0241     }
0242 
0243     /* Clause 22 write */
0244     addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
0245 
0246     tmp = val & 0xffff;
0247 
0248     return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
0249 }
0250 
0251 static int sja1105_base_tx_mdio_read(struct mii_bus *bus, int phy, int reg)
0252 {
0253     struct sja1105_mdio_private *mdio_priv = bus->priv;
0254     struct sja1105_private *priv = mdio_priv->priv;
0255     const struct sja1105_regs *regs = priv->info->regs;
0256     u32 tmp;
0257     int rc;
0258 
0259     rc = sja1105_xfer_u32(priv, SPI_READ, regs->mdio_100base_tx + reg,
0260                   &tmp, NULL);
0261     if (rc < 0)
0262         return rc;
0263 
0264     return tmp & 0xffff;
0265 }
0266 
0267 static int sja1105_base_tx_mdio_write(struct mii_bus *bus, int phy, int reg,
0268                       u16 val)
0269 {
0270     struct sja1105_mdio_private *mdio_priv = bus->priv;
0271     struct sja1105_private *priv = mdio_priv->priv;
0272     const struct sja1105_regs *regs = priv->info->regs;
0273     u32 tmp = val;
0274 
0275     return sja1105_xfer_u32(priv, SPI_WRITE, regs->mdio_100base_tx + reg,
0276                 &tmp, NULL);
0277 }
0278 
0279 static int sja1105_mdiobus_base_tx_register(struct sja1105_private *priv,
0280                         struct device_node *mdio_node)
0281 {
0282     struct sja1105_mdio_private *mdio_priv;
0283     struct device_node *np;
0284     struct mii_bus *bus;
0285     int rc = 0;
0286 
0287     np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-tx-mdio");
0288     if (!np)
0289         return 0;
0290 
0291     if (!of_device_is_available(np))
0292         goto out_put_np;
0293 
0294     bus = mdiobus_alloc_size(sizeof(*mdio_priv));
0295     if (!bus) {
0296         rc = -ENOMEM;
0297         goto out_put_np;
0298     }
0299 
0300     bus->name = "SJA1110 100base-TX MDIO bus";
0301     snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-tx",
0302          dev_name(priv->ds->dev));
0303     bus->read = sja1105_base_tx_mdio_read;
0304     bus->write = sja1105_base_tx_mdio_write;
0305     bus->parent = priv->ds->dev;
0306     mdio_priv = bus->priv;
0307     mdio_priv->priv = priv;
0308 
0309     rc = of_mdiobus_register(bus, np);
0310     if (rc) {
0311         mdiobus_free(bus);
0312         goto out_put_np;
0313     }
0314 
0315     priv->mdio_base_tx = bus;
0316 
0317 out_put_np:
0318     of_node_put(np);
0319 
0320     return rc;
0321 }
0322 
0323 static void sja1105_mdiobus_base_tx_unregister(struct sja1105_private *priv)
0324 {
0325     if (!priv->mdio_base_tx)
0326         return;
0327 
0328     mdiobus_unregister(priv->mdio_base_tx);
0329     mdiobus_free(priv->mdio_base_tx);
0330     priv->mdio_base_tx = NULL;
0331 }
0332 
0333 static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv,
0334                         struct device_node *mdio_node)
0335 {
0336     struct sja1105_mdio_private *mdio_priv;
0337     struct device_node *np;
0338     struct mii_bus *bus;
0339     int rc = 0;
0340 
0341     np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-t1-mdio");
0342     if (!np)
0343         return 0;
0344 
0345     if (!of_device_is_available(np))
0346         goto out_put_np;
0347 
0348     bus = mdiobus_alloc_size(sizeof(*mdio_priv));
0349     if (!bus) {
0350         rc = -ENOMEM;
0351         goto out_put_np;
0352     }
0353 
0354     bus->name = "SJA1110 100base-T1 MDIO bus";
0355     snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-t1",
0356          dev_name(priv->ds->dev));
0357     bus->read = sja1105_base_t1_mdio_read;
0358     bus->write = sja1105_base_t1_mdio_write;
0359     bus->parent = priv->ds->dev;
0360     mdio_priv = bus->priv;
0361     mdio_priv->priv = priv;
0362 
0363     rc = of_mdiobus_register(bus, np);
0364     if (rc) {
0365         mdiobus_free(bus);
0366         goto out_put_np;
0367     }
0368 
0369     priv->mdio_base_t1 = bus;
0370 
0371 out_put_np:
0372     of_node_put(np);
0373 
0374     return rc;
0375 }
0376 
0377 static void sja1105_mdiobus_base_t1_unregister(struct sja1105_private *priv)
0378 {
0379     if (!priv->mdio_base_t1)
0380         return;
0381 
0382     mdiobus_unregister(priv->mdio_base_t1);
0383     mdiobus_free(priv->mdio_base_t1);
0384     priv->mdio_base_t1 = NULL;
0385 }
0386 
0387 static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
0388 {
0389     struct sja1105_mdio_private *mdio_priv;
0390     struct dsa_switch *ds = priv->ds;
0391     struct mii_bus *bus;
0392     int rc = 0;
0393     int port;
0394 
0395     if (!priv->info->pcs_mdio_read || !priv->info->pcs_mdio_write)
0396         return 0;
0397 
0398     bus = mdiobus_alloc_size(sizeof(*mdio_priv));
0399     if (!bus)
0400         return -ENOMEM;
0401 
0402     bus->name = "SJA1105 PCS MDIO bus";
0403     snprintf(bus->id, MII_BUS_ID_SIZE, "%s-pcs",
0404          dev_name(ds->dev));
0405     bus->read = priv->info->pcs_mdio_read;
0406     bus->write = priv->info->pcs_mdio_write;
0407     bus->parent = ds->dev;
0408     /* There is no PHY on this MDIO bus => mask out all PHY addresses
0409      * from auto probing.
0410      */
0411     bus->phy_mask = ~0;
0412     mdio_priv = bus->priv;
0413     mdio_priv->priv = priv;
0414 
0415     rc = mdiobus_register(bus);
0416     if (rc) {
0417         mdiobus_free(bus);
0418         return rc;
0419     }
0420 
0421     for (port = 0; port < ds->num_ports; port++) {
0422         struct mdio_device *mdiodev;
0423         struct dw_xpcs *xpcs;
0424 
0425         if (dsa_is_unused_port(ds, port))
0426             continue;
0427 
0428         if (priv->phy_mode[port] != PHY_INTERFACE_MODE_SGMII &&
0429             priv->phy_mode[port] != PHY_INTERFACE_MODE_2500BASEX)
0430             continue;
0431 
0432         mdiodev = mdio_device_create(bus, port);
0433         if (IS_ERR(mdiodev)) {
0434             rc = PTR_ERR(mdiodev);
0435             goto out_pcs_free;
0436         }
0437 
0438         xpcs = xpcs_create(mdiodev, priv->phy_mode[port]);
0439         if (IS_ERR(xpcs)) {
0440             rc = PTR_ERR(xpcs);
0441             goto out_pcs_free;
0442         }
0443 
0444         priv->xpcs[port] = xpcs;
0445     }
0446 
0447     priv->mdio_pcs = bus;
0448 
0449     return 0;
0450 
0451 out_pcs_free:
0452     for (port = 0; port < ds->num_ports; port++) {
0453         if (!priv->xpcs[port])
0454             continue;
0455 
0456         mdio_device_free(priv->xpcs[port]->mdiodev);
0457         xpcs_destroy(priv->xpcs[port]);
0458         priv->xpcs[port] = NULL;
0459     }
0460 
0461     mdiobus_unregister(bus);
0462     mdiobus_free(bus);
0463 
0464     return rc;
0465 }
0466 
0467 static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv)
0468 {
0469     struct dsa_switch *ds = priv->ds;
0470     int port;
0471 
0472     if (!priv->mdio_pcs)
0473         return;
0474 
0475     for (port = 0; port < ds->num_ports; port++) {
0476         if (!priv->xpcs[port])
0477             continue;
0478 
0479         mdio_device_free(priv->xpcs[port]->mdiodev);
0480         xpcs_destroy(priv->xpcs[port]);
0481         priv->xpcs[port] = NULL;
0482     }
0483 
0484     mdiobus_unregister(priv->mdio_pcs);
0485     mdiobus_free(priv->mdio_pcs);
0486     priv->mdio_pcs = NULL;
0487 }
0488 
0489 int sja1105_mdiobus_register(struct dsa_switch *ds)
0490 {
0491     struct sja1105_private *priv = ds->priv;
0492     const struct sja1105_regs *regs = priv->info->regs;
0493     struct device_node *switch_node = ds->dev->of_node;
0494     struct device_node *mdio_node;
0495     int rc;
0496 
0497     rc = sja1105_mdiobus_pcs_register(priv);
0498     if (rc)
0499         return rc;
0500 
0501     mdio_node = of_get_child_by_name(switch_node, "mdios");
0502     if (!mdio_node)
0503         return 0;
0504 
0505     if (!of_device_is_available(mdio_node))
0506         goto out_put_mdio_node;
0507 
0508     if (regs->mdio_100base_tx != SJA1105_RSV_ADDR) {
0509         rc = sja1105_mdiobus_base_tx_register(priv, mdio_node);
0510         if (rc)
0511             goto err_put_mdio_node;
0512     }
0513 
0514     if (regs->mdio_100base_t1 != SJA1105_RSV_ADDR) {
0515         rc = sja1105_mdiobus_base_t1_register(priv, mdio_node);
0516         if (rc)
0517             goto err_free_base_tx_mdiobus;
0518     }
0519 
0520 out_put_mdio_node:
0521     of_node_put(mdio_node);
0522 
0523     return 0;
0524 
0525 err_free_base_tx_mdiobus:
0526     sja1105_mdiobus_base_tx_unregister(priv);
0527 err_put_mdio_node:
0528     of_node_put(mdio_node);
0529     sja1105_mdiobus_pcs_unregister(priv);
0530 
0531     return rc;
0532 }
0533 
0534 void sja1105_mdiobus_unregister(struct dsa_switch *ds)
0535 {
0536     struct sja1105_private *priv = ds->priv;
0537 
0538     sja1105_mdiobus_base_t1_unregister(priv);
0539     sja1105_mdiobus_base_tx_unregister(priv);
0540     sja1105_mdiobus_pcs_unregister(priv);
0541 }