]> Git Repo - linux.git/blob - drivers/net/dsa/sja1105/sja1105_mdio.c
x86/kaslr: Expose and use the end of the physical memory address space
[linux.git] / drivers / net / dsa / sja1105 / sja1105_mdio.c
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
10 int 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
35 int 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
52 int 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
97 int sja1110_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int mmd, int reg,
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
136 enum 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
143 static 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
152 static 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
169 static 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
193 static 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
208 static 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
230 static 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
246 static 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
258 static 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
296 out_put_np:
297         of_node_put(np);
298
299         return rc;
300 }
301
302 static 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
312 static 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
352 out_put_np:
353         of_node_put(np);
354
355         return rc;
356 }
357
358 static 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
368 static 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
425 out_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
440 static 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
461 int 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
492 out_put_mdio_node:
493         of_node_put(mdio_node);
494
495         return 0;
496
497 err_free_base_tx_mdiobus:
498         sja1105_mdiobus_base_tx_unregister(priv);
499 err_put_mdio_node:
500         of_node_put(mdio_node);
501         sja1105_mdiobus_pcs_unregister(priv);
502
503         return rc;
504 }
505
506 void 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 }
This page took 0.063879 seconds and 4 git commands to generate.