net: dsa: sja1105: migrate to xpcs for SGMII
[linux-2.6-microblaze.git] / drivers / net / dsa / sja1105 / sja1105_mdio.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2021, NXP Semiconductors
3  */
4 #include <linux/pcs/pcs-xpcs.h>
5 #include <linux/of_mdio.h>
6 #include "sja1105.h"
7
8 int sja1105_pcs_mdio_read(struct mii_bus *bus, int phy, int reg)
9 {
10         struct sja1105_mdio_private *mdio_priv = bus->priv;
11         struct sja1105_private *priv = mdio_priv->priv;
12         u64 addr;
13         u32 tmp;
14         u16 mmd;
15         int rc;
16
17         if (!(reg & MII_ADDR_C45))
18                 return -EINVAL;
19
20         mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
21         addr = (mmd << 16) | (reg & GENMASK(15, 0));
22
23         if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
24                 return 0xffff;
25
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);
30
31         rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
32         if (rc < 0)
33                 return rc;
34
35         return tmp & 0xffff;
36 }
37
38 int sja1105_pcs_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
39 {
40         struct sja1105_mdio_private *mdio_priv = bus->priv;
41         struct sja1105_private *priv = mdio_priv->priv;
42         u64 addr;
43         u32 tmp;
44         u16 mmd;
45
46         if (!(reg & MII_ADDR_C45))
47                 return -EINVAL;
48
49         mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
50         addr = (mmd << 16) | (reg & GENMASK(15, 0));
51         tmp = val;
52
53         if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
54                 return -EINVAL;
55
56         return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
57 }
58
59 enum sja1105_mdio_opcode {
60         SJA1105_C45_ADDR = 0,
61         SJA1105_C22 = 1,
62         SJA1105_C45_DATA = 2,
63         SJA1105_C45_DATA_AUTOINC = 3,
64 };
65
66 static u64 sja1105_base_t1_encode_addr(struct sja1105_private *priv,
67                                        int phy, enum sja1105_mdio_opcode op,
68                                        int xad)
69 {
70         const struct sja1105_regs *regs = priv->info->regs;
71
72         return regs->mdio_100base_t1 | (phy << 7) | (op << 5) | (xad << 0);
73 }
74
75 static int sja1105_base_t1_mdio_read(struct mii_bus *bus, int phy, int reg)
76 {
77         struct sja1105_mdio_private *mdio_priv = bus->priv;
78         struct sja1105_private *priv = mdio_priv->priv;
79         u64 addr;
80         u32 tmp;
81         int rc;
82
83         if (reg & MII_ADDR_C45) {
84                 u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
85
86                 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR,
87                                                    mmd);
88
89                 tmp = reg & MII_REGADDR_C45_MASK;
90
91                 rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
92                 if (rc < 0)
93                         return rc;
94
95                 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA,
96                                                    mmd);
97
98                 rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
99                 if (rc < 0)
100                         return rc;
101
102                 return tmp & 0xffff;
103         }
104
105         /* Clause 22 read */
106         addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
107
108         rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
109         if (rc < 0)
110                 return rc;
111
112         return tmp & 0xffff;
113 }
114
115 static int sja1105_base_t1_mdio_write(struct mii_bus *bus, int phy, int reg,
116                                       u16 val)
117 {
118         struct sja1105_mdio_private *mdio_priv = bus->priv;
119         struct sja1105_private *priv = mdio_priv->priv;
120         u64 addr;
121         u32 tmp;
122         int rc;
123
124         if (reg & MII_ADDR_C45) {
125                 u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
126
127                 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR,
128                                                    mmd);
129
130                 tmp = reg & MII_REGADDR_C45_MASK;
131
132                 rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
133                 if (rc < 0)
134                         return rc;
135
136                 addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA,
137                                                    mmd);
138
139                 tmp = val & 0xffff;
140
141                 rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
142                 if (rc < 0)
143                         return rc;
144
145                 return 0;
146         }
147
148         /* Clause 22 write */
149         addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
150
151         tmp = val & 0xffff;
152
153         return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
154 }
155
156 static int sja1105_base_tx_mdio_read(struct mii_bus *bus, int phy, int reg)
157 {
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;
161         u32 tmp;
162         int rc;
163
164         rc = sja1105_xfer_u32(priv, SPI_READ, regs->mdio_100base_tx + reg,
165                               &tmp, NULL);
166         if (rc < 0)
167                 return rc;
168
169         return tmp & 0xffff;
170 }
171
172 static int sja1105_base_tx_mdio_write(struct mii_bus *bus, int phy, int reg,
173                                       u16 val)
174 {
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;
178         u32 tmp = val;
179
180         return sja1105_xfer_u32(priv, SPI_WRITE, regs->mdio_100base_tx + reg,
181                                 &tmp, NULL);
182 }
183
184 static int sja1105_mdiobus_base_tx_register(struct sja1105_private *priv,
185                                             struct device_node *mdio_node)
186 {
187         struct sja1105_mdio_private *mdio_priv;
188         struct device_node *np;
189         struct mii_bus *bus;
190         int rc = 0;
191
192         np = of_find_compatible_node(mdio_node, NULL,
193                                      "nxp,sja1110-base-tx-mdio");
194         if (!np)
195                 return 0;
196
197         if (!of_device_is_available(np))
198                 goto out_put_np;
199
200         bus = mdiobus_alloc_size(sizeof(*mdio_priv));
201         if (!bus) {
202                 rc = -ENOMEM;
203                 goto out_put_np;
204         }
205
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;
214
215         rc = of_mdiobus_register(bus, np);
216         if (rc) {
217                 mdiobus_free(bus);
218                 goto out_put_np;
219         }
220
221         priv->mdio_base_tx = bus;
222
223 out_put_np:
224         of_node_put(np);
225
226         return rc;
227 }
228
229 static void sja1105_mdiobus_base_tx_unregister(struct sja1105_private *priv)
230 {
231         if (!priv->mdio_base_tx)
232                 return;
233
234         mdiobus_unregister(priv->mdio_base_tx);
235         mdiobus_free(priv->mdio_base_tx);
236         priv->mdio_base_tx = NULL;
237 }
238
239 static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv,
240                                             struct device_node *mdio_node)
241 {
242         struct sja1105_mdio_private *mdio_priv;
243         struct device_node *np;
244         struct mii_bus *bus;
245         int rc = 0;
246
247         np = of_find_compatible_node(mdio_node, NULL,
248                                      "nxp,sja1110-base-t1-mdio");
249         if (!np)
250                 return 0;
251
252         if (!of_device_is_available(np))
253                 goto out_put_np;
254
255         bus = mdiobus_alloc_size(sizeof(*mdio_priv));
256         if (!bus) {
257                 rc = -ENOMEM;
258                 goto out_put_np;
259         }
260
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;
269
270         rc = of_mdiobus_register(bus, np);
271         if (rc) {
272                 mdiobus_free(bus);
273                 goto out_put_np;
274         }
275
276         priv->mdio_base_t1 = bus;
277
278 out_put_np:
279         of_node_put(np);
280
281         return rc;
282 }
283
284 static void sja1105_mdiobus_base_t1_unregister(struct sja1105_private *priv)
285 {
286         if (!priv->mdio_base_t1)
287                 return;
288
289         mdiobus_unregister(priv->mdio_base_t1);
290         mdiobus_free(priv->mdio_base_t1);
291         priv->mdio_base_t1 = NULL;
292 }
293
294 static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
295 {
296         struct sja1105_mdio_private *mdio_priv;
297         struct dsa_switch *ds = priv->ds;
298         struct mii_bus *bus;
299         int rc = 0;
300         int port;
301
302         if (!priv->info->pcs_mdio_read || !priv->info->pcs_mdio_write)
303                 return 0;
304
305         bus = mdiobus_alloc_size(sizeof(*mdio_priv));
306         if (!bus)
307                 return -ENOMEM;
308
309         bus->name = "SJA1105 PCS MDIO bus";
310         snprintf(bus->id, MII_BUS_ID_SIZE, "%s-pcs",
311                  dev_name(ds->dev));
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
316          * from auto probing.
317          */
318         bus->phy_mask = ~0;
319         mdio_priv = bus->priv;
320         mdio_priv->priv = priv;
321
322         rc = mdiobus_register(bus);
323         if (rc) {
324                 mdiobus_free(bus);
325                 return rc;
326         }
327
328         for (port = 0; port < ds->num_ports; port++) {
329                 struct mdio_device *mdiodev;
330                 struct dw_xpcs *xpcs;
331
332                 if (dsa_is_unused_port(ds, port))
333                         continue;
334
335                 if (priv->phy_mode[port] != PHY_INTERFACE_MODE_SGMII)
336                         continue;
337
338                 mdiodev = mdio_device_create(bus, port);
339                 if (IS_ERR(mdiodev)) {
340                         rc = PTR_ERR(mdiodev);
341                         goto out_pcs_free;
342                 }
343
344                 xpcs = xpcs_create(mdiodev, priv->phy_mode[port]);
345                 if (IS_ERR(xpcs)) {
346                         rc = PTR_ERR(xpcs);
347                         goto out_pcs_free;
348                 }
349
350                 priv->xpcs[port] = xpcs;
351         }
352
353         priv->mdio_pcs = bus;
354
355         return 0;
356
357 out_pcs_free:
358         for (port = 0; port < ds->num_ports; port++) {
359                 if (!priv->xpcs[port])
360                         continue;
361
362                 mdio_device_free(priv->xpcs[port]->mdiodev);
363                 xpcs_destroy(priv->xpcs[port]);
364                 priv->xpcs[port] = NULL;
365         }
366
367         mdiobus_unregister(bus);
368         mdiobus_free(bus);
369
370         return rc;
371 }
372
373 static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv)
374 {
375         struct dsa_switch *ds = priv->ds;
376         int port;
377
378         if (!priv->mdio_pcs)
379                 return;
380
381         for (port = 0; port < ds->num_ports; port++) {
382                 if (!priv->xpcs[port])
383                         continue;
384
385                 mdio_device_free(priv->xpcs[port]->mdiodev);
386                 xpcs_destroy(priv->xpcs[port]);
387                 priv->xpcs[port] = NULL;
388         }
389
390         mdiobus_unregister(priv->mdio_pcs);
391         mdiobus_free(priv->mdio_pcs);
392         priv->mdio_pcs = NULL;
393 }
394
395 int sja1105_mdiobus_register(struct dsa_switch *ds)
396 {
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;
401         int rc;
402
403         rc = sja1105_mdiobus_pcs_register(priv);
404         if (rc)
405                 return rc;
406
407         mdio_node = of_get_child_by_name(switch_node, "mdios");
408         if (!mdio_node)
409                 return 0;
410
411         if (!of_device_is_available(mdio_node))
412                 goto out_put_mdio_node;
413
414         if (regs->mdio_100base_tx != SJA1105_RSV_ADDR) {
415                 rc = sja1105_mdiobus_base_tx_register(priv, mdio_node);
416                 if (rc)
417                         goto err_put_mdio_node;
418         }
419
420         if (regs->mdio_100base_t1 != SJA1105_RSV_ADDR) {
421                 rc = sja1105_mdiobus_base_t1_register(priv, mdio_node);
422                 if (rc)
423                         goto err_free_base_tx_mdiobus;
424         }
425
426 out_put_mdio_node:
427         of_node_put(mdio_node);
428
429         return 0;
430
431 err_free_base_tx_mdiobus:
432         sja1105_mdiobus_base_tx_unregister(priv);
433 err_put_mdio_node:
434         of_node_put(mdio_node);
435         sja1105_mdiobus_pcs_unregister(priv);
436
437         return rc;
438 }
439
440 void sja1105_mdiobus_unregister(struct dsa_switch *ds)
441 {
442         struct sja1105_private *priv = ds->priv;
443
444         sja1105_mdiobus_base_t1_unregister(priv);
445         sja1105_mdiobus_base_tx_unregister(priv);
446         sja1105_mdiobus_pcs_unregister(priv);
447 }