1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright 2021, NXP Semiconductors 3 */ 4 #include <linux/of_mdio.h> 5 #include "sja1105.h" 6 7 enum sja1105_mdio_opcode { 8 SJA1105_C45_ADDR = 0, 9 SJA1105_C22 = 1, 10 SJA1105_C45_DATA = 2, 11 SJA1105_C45_DATA_AUTOINC = 3, 12 }; 13 14 static u64 sja1105_base_t1_encode_addr(struct sja1105_private *priv, 15 int phy, enum sja1105_mdio_opcode op, 16 int xad) 17 { 18 const struct sja1105_regs *regs = priv->info->regs; 19 20 return regs->mdio_100base_t1 | (phy << 7) | (op << 5) | (xad << 0); 21 } 22 23 static int sja1105_base_t1_mdio_read(struct mii_bus *bus, int phy, int reg) 24 { 25 struct sja1105_mdio_private *mdio_priv = bus->priv; 26 struct sja1105_private *priv = mdio_priv->priv; 27 u64 addr; 28 u32 tmp; 29 int rc; 30 31 if (reg & MII_ADDR_C45) { 32 u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f; 33 34 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR, 35 mmd); 36 37 tmp = reg & MII_REGADDR_C45_MASK; 38 39 rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL); 40 if (rc < 0) 41 return rc; 42 43 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA, 44 mmd); 45 46 rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL); 47 if (rc < 0) 48 return rc; 49 50 return tmp & 0xffff; 51 } 52 53 /* Clause 22 read */ 54 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f); 55 56 rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL); 57 if (rc < 0) 58 return rc; 59 60 return tmp & 0xffff; 61 } 62 63 static int sja1105_base_t1_mdio_write(struct mii_bus *bus, int phy, int reg, 64 u16 val) 65 { 66 struct sja1105_mdio_private *mdio_priv = bus->priv; 67 struct sja1105_private *priv = mdio_priv->priv; 68 u64 addr; 69 u32 tmp; 70 int rc; 71 72 if (reg & MII_ADDR_C45) { 73 u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f; 74 75 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR, 76 mmd); 77 78 tmp = reg & MII_REGADDR_C45_MASK; 79 80 rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL); 81 if (rc < 0) 82 return rc; 83 84 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA, 85 mmd); 86 87 tmp = val & 0xffff; 88 89 rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL); 90 if (rc < 0) 91 return rc; 92 93 return 0; 94 } 95 96 /* Clause 22 write */ 97 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f); 98 99 tmp = val & 0xffff; 100 101 return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL); 102 } 103 104 static int sja1105_base_tx_mdio_read(struct mii_bus *bus, int phy, int reg) 105 { 106 struct sja1105_mdio_private *mdio_priv = bus->priv; 107 struct sja1105_private *priv = mdio_priv->priv; 108 const struct sja1105_regs *regs = priv->info->regs; 109 u32 tmp; 110 int rc; 111 112 rc = sja1105_xfer_u32(priv, SPI_READ, regs->mdio_100base_tx + reg, 113 &tmp, NULL); 114 if (rc < 0) 115 return rc; 116 117 return tmp & 0xffff; 118 } 119 120 static int sja1105_base_tx_mdio_write(struct mii_bus *bus, int phy, int reg, 121 u16 val) 122 { 123 struct sja1105_mdio_private *mdio_priv = bus->priv; 124 struct sja1105_private *priv = mdio_priv->priv; 125 const struct sja1105_regs *regs = priv->info->regs; 126 u32 tmp = val; 127 128 return sja1105_xfer_u32(priv, SPI_WRITE, regs->mdio_100base_tx + reg, 129 &tmp, NULL); 130 } 131 132 static int sja1105_mdiobus_base_tx_register(struct sja1105_private *priv, 133 struct device_node *mdio_node) 134 { 135 struct sja1105_mdio_private *mdio_priv; 136 struct device_node *np; 137 struct mii_bus *bus; 138 int rc = 0; 139 140 np = of_find_compatible_node(mdio_node, NULL, 141 "nxp,sja1110-base-tx-mdio"); 142 if (!np) 143 return 0; 144 145 if (!of_device_is_available(np)) 146 goto out_put_np; 147 148 bus = mdiobus_alloc_size(sizeof(*mdio_priv)); 149 if (!bus) { 150 rc = -ENOMEM; 151 goto out_put_np; 152 } 153 154 bus->name = "SJA1110 100base-TX MDIO bus"; 155 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-tx", 156 dev_name(priv->ds->dev)); 157 bus->read = sja1105_base_tx_mdio_read; 158 bus->write = sja1105_base_tx_mdio_write; 159 bus->parent = priv->ds->dev; 160 mdio_priv = bus->priv; 161 mdio_priv->priv = priv; 162 163 rc = of_mdiobus_register(bus, np); 164 if (rc) { 165 mdiobus_free(bus); 166 goto out_put_np; 167 } 168 169 priv->mdio_base_tx = bus; 170 171 out_put_np: 172 of_node_put(np); 173 174 return 0; 175 } 176 177 static void sja1105_mdiobus_base_tx_unregister(struct sja1105_private *priv) 178 { 179 if (!priv->mdio_base_tx) 180 return; 181 182 mdiobus_unregister(priv->mdio_base_tx); 183 mdiobus_free(priv->mdio_base_tx); 184 priv->mdio_base_tx = NULL; 185 } 186 187 static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv, 188 struct device_node *mdio_node) 189 { 190 struct sja1105_mdio_private *mdio_priv; 191 struct device_node *np; 192 struct mii_bus *bus; 193 int rc = 0; 194 195 np = of_find_compatible_node(mdio_node, NULL, 196 "nxp,sja1110-base-t1-mdio"); 197 if (!np) 198 return 0; 199 200 if (!of_device_is_available(np)) 201 goto out_put_np; 202 203 bus = mdiobus_alloc_size(sizeof(*mdio_priv)); 204 if (!bus) { 205 rc = -ENOMEM; 206 goto out_put_np; 207 } 208 209 bus->name = "SJA1110 100base-T1 MDIO bus"; 210 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-t1", 211 dev_name(priv->ds->dev)); 212 bus->read = sja1105_base_t1_mdio_read; 213 bus->write = sja1105_base_t1_mdio_write; 214 bus->parent = priv->ds->dev; 215 mdio_priv = bus->priv; 216 mdio_priv->priv = priv; 217 218 rc = of_mdiobus_register(bus, np); 219 if (rc) { 220 mdiobus_free(bus); 221 goto out_put_np; 222 } 223 224 priv->mdio_base_t1 = bus; 225 226 out_put_np: 227 of_node_put(np); 228 229 return rc; 230 } 231 232 static void sja1105_mdiobus_base_t1_unregister(struct sja1105_private *priv) 233 { 234 if (!priv->mdio_base_t1) 235 return; 236 237 mdiobus_unregister(priv->mdio_base_t1); 238 mdiobus_free(priv->mdio_base_t1); 239 priv->mdio_base_t1 = NULL; 240 } 241 242 int sja1105_mdiobus_register(struct dsa_switch *ds) 243 { 244 struct sja1105_private *priv = ds->priv; 245 const struct sja1105_regs *regs = priv->info->regs; 246 struct device_node *switch_node = ds->dev->of_node; 247 struct device_node *mdio_node; 248 int rc; 249 250 mdio_node = of_get_child_by_name(switch_node, "mdios"); 251 if (!mdio_node) 252 return 0; 253 254 if (!of_device_is_available(mdio_node)) 255 goto out_put_mdio_node; 256 257 if (regs->mdio_100base_tx != SJA1105_RSV_ADDR) { 258 rc = sja1105_mdiobus_base_tx_register(priv, mdio_node); 259 if (rc) 260 goto err_put_mdio_node; 261 } 262 263 if (regs->mdio_100base_t1 != SJA1105_RSV_ADDR) { 264 rc = sja1105_mdiobus_base_t1_register(priv, mdio_node); 265 if (rc) 266 goto err_free_base_tx_mdiobus; 267 } 268 269 out_put_mdio_node: 270 of_node_put(mdio_node); 271 272 return 0; 273 274 err_free_base_tx_mdiobus: 275 sja1105_mdiobus_base_tx_unregister(priv); 276 err_put_mdio_node: 277 of_node_put(mdio_node); 278 279 return rc; 280 } 281 282 void sja1105_mdiobus_unregister(struct dsa_switch *ds) 283 { 284 struct sja1105_private *priv = ds->priv; 285 286 sja1105_mdiobus_base_t1_unregister(priv); 287 sja1105_mdiobus_base_tx_unregister(priv); 288 } 289