net: phy: provide full set of accessor functions to MMD registers
[sfrench/cifs-2.6.git] / drivers / net / phy / phy-core.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Core PHY library, taken from phy.c
4  */
5 #include <linux/export.h>
6 #include <linux/phy.h>
7
8 const char *phy_speed_to_str(int speed)
9 {
10         switch (speed) {
11         case SPEED_10:
12                 return "10Mbps";
13         case SPEED_100:
14                 return "100Mbps";
15         case SPEED_1000:
16                 return "1Gbps";
17         case SPEED_2500:
18                 return "2.5Gbps";
19         case SPEED_5000:
20                 return "5Gbps";
21         case SPEED_10000:
22                 return "10Gbps";
23         case SPEED_14000:
24                 return "14Gbps";
25         case SPEED_20000:
26                 return "20Gbps";
27         case SPEED_25000:
28                 return "25Gbps";
29         case SPEED_40000:
30                 return "40Gbps";
31         case SPEED_50000:
32                 return "50Gbps";
33         case SPEED_56000:
34                 return "56Gbps";
35         case SPEED_100000:
36                 return "100Gbps";
37         case SPEED_UNKNOWN:
38                 return "Unknown";
39         default:
40                 return "Unsupported (update phy-core.c)";
41         }
42 }
43 EXPORT_SYMBOL_GPL(phy_speed_to_str);
44
45 const char *phy_duplex_to_str(unsigned int duplex)
46 {
47         if (duplex == DUPLEX_HALF)
48                 return "Half";
49         if (duplex == DUPLEX_FULL)
50                 return "Full";
51         if (duplex == DUPLEX_UNKNOWN)
52                 return "Unknown";
53         return "Unsupported (update phy-core.c)";
54 }
55 EXPORT_SYMBOL_GPL(phy_duplex_to_str);
56
57 /* A mapping of all SUPPORTED settings to speed/duplex.  This table
58  * must be grouped by speed and sorted in descending match priority
59  * - iow, descending speed. */
60 static const struct phy_setting settings[] = {
61         /* 100G */
62         {
63                 .speed = SPEED_100000,
64                 .duplex = DUPLEX_FULL,
65                 .bit = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
66         },
67         {
68                 .speed = SPEED_100000,
69                 .duplex = DUPLEX_FULL,
70                 .bit = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
71         },
72         {
73                 .speed = SPEED_100000,
74                 .duplex = DUPLEX_FULL,
75                 .bit = ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
76         },
77         {
78                 .speed = SPEED_100000,
79                 .duplex = DUPLEX_FULL,
80                 .bit = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
81         },
82         /* 56G */
83         {
84                 .speed = SPEED_56000,
85                 .duplex = DUPLEX_FULL,
86                 .bit = ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT,
87         },
88         {
89                 .speed = SPEED_56000,
90                 .duplex = DUPLEX_FULL,
91                 .bit = ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT,
92         },
93         {
94                 .speed = SPEED_56000,
95                 .duplex = DUPLEX_FULL,
96                 .bit = ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT,
97         },
98         {
99                 .speed = SPEED_56000,
100                 .duplex = DUPLEX_FULL,
101                 .bit = ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT,
102         },
103         /* 50G */
104         {
105                 .speed = SPEED_50000,
106                 .duplex = DUPLEX_FULL,
107                 .bit = ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
108         },
109         {
110                 .speed = SPEED_50000,
111                 .duplex = DUPLEX_FULL,
112                 .bit = ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
113         },
114         {
115                 .speed = SPEED_50000,
116                 .duplex = DUPLEX_FULL,
117                 .bit = ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
118         },
119         /* 40G */
120         {
121                 .speed = SPEED_40000,
122                 .duplex = DUPLEX_FULL,
123                 .bit = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
124         },
125         {
126                 .speed = SPEED_40000,
127                 .duplex = DUPLEX_FULL,
128                 .bit = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
129         },
130         {
131                 .speed = SPEED_40000,
132                 .duplex = DUPLEX_FULL,
133                 .bit = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
134         },
135         {
136                 .speed = SPEED_40000,
137                 .duplex = DUPLEX_FULL,
138                 .bit = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
139         },
140         /* 25G */
141         {
142                 .speed = SPEED_25000,
143                 .duplex = DUPLEX_FULL,
144                 .bit = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
145         },
146         {
147                 .speed = SPEED_25000,
148                 .duplex = DUPLEX_FULL,
149                 .bit = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
150         },
151         {
152                 .speed = SPEED_25000,
153                 .duplex = DUPLEX_FULL,
154                 .bit = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
155         },
156
157         /* 20G */
158         {
159                 .speed = SPEED_20000,
160                 .duplex = DUPLEX_FULL,
161                 .bit = ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
162         },
163         {
164                 .speed = SPEED_20000,
165                 .duplex = DUPLEX_FULL,
166                 .bit = ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT,
167         },
168         /* 10G */
169         {
170                 .speed = SPEED_10000,
171                 .duplex = DUPLEX_FULL,
172                 .bit = ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
173         },
174         {
175                 .speed = SPEED_10000,
176                 .duplex = DUPLEX_FULL,
177                 .bit = ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
178         },
179         {
180                 .speed = SPEED_10000,
181                 .duplex = DUPLEX_FULL,
182                 .bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
183         },
184         {
185                 .speed = SPEED_10000,
186                 .duplex = DUPLEX_FULL,
187                 .bit = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
188         },
189         {
190                 .speed = SPEED_10000,
191                 .duplex = DUPLEX_FULL,
192                 .bit = ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
193         },
194         {
195                 .speed = SPEED_10000,
196                 .duplex = DUPLEX_FULL,
197                 .bit = ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
198         },
199         {
200                 .speed = SPEED_10000,
201                 .duplex = DUPLEX_FULL,
202                 .bit = ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
203         },
204         {
205                 .speed = SPEED_10000,
206                 .duplex = DUPLEX_FULL,
207                 .bit = ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
208         },
209         {
210                 .speed = SPEED_10000,
211                 .duplex = DUPLEX_FULL,
212                 .bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
213         },
214         /* 5G */
215         {
216                 .speed = SPEED_5000,
217                 .duplex = DUPLEX_FULL,
218                 .bit = ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
219         },
220
221         /* 2.5G */
222         {
223                 .speed = SPEED_2500,
224                 .duplex = DUPLEX_FULL,
225                 .bit = ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
226         },
227         {
228                 .speed = SPEED_2500,
229                 .duplex = DUPLEX_FULL,
230                 .bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
231         },
232         /* 1G */
233         {
234                 .speed = SPEED_1000,
235                 .duplex = DUPLEX_FULL,
236                 .bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
237         },
238         {
239                 .speed = SPEED_1000,
240                 .duplex = DUPLEX_FULL,
241                 .bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
242         },
243         {
244                 .speed = SPEED_1000,
245                 .duplex = DUPLEX_HALF,
246                 .bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
247         },
248         {
249                 .speed = SPEED_1000,
250                 .duplex = DUPLEX_FULL,
251                 .bit = ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
252         },
253         /* 100M */
254         {
255                 .speed = SPEED_100,
256                 .duplex = DUPLEX_FULL,
257                 .bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
258         },
259         {
260                 .speed = SPEED_100,
261                 .duplex = DUPLEX_HALF,
262                 .bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT,
263         },
264         /* 10M */
265         {
266                 .speed = SPEED_10,
267                 .duplex = DUPLEX_FULL,
268                 .bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT,
269         },
270         {
271                 .speed = SPEED_10,
272                 .duplex = DUPLEX_HALF,
273                 .bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT,
274         },
275 };
276
277 /**
278  * phy_lookup_setting - lookup a PHY setting
279  * @speed: speed to match
280  * @duplex: duplex to match
281  * @mask: allowed link modes
282  * @exact: an exact match is required
283  *
284  * Search the settings array for a setting that matches the speed and
285  * duplex, and which is supported.
286  *
287  * If @exact is unset, either an exact match or %NULL for no match will
288  * be returned.
289  *
290  * If @exact is set, an exact match, the fastest supported setting at
291  * or below the specified speed, the slowest supported setting, or if
292  * they all fail, %NULL will be returned.
293  */
294 const struct phy_setting *
295 phy_lookup_setting(int speed, int duplex, const unsigned long *mask, bool exact)
296 {
297         const struct phy_setting *p, *match = NULL, *last = NULL;
298         int i;
299
300         for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
301                 if (p->bit < __ETHTOOL_LINK_MODE_MASK_NBITS &&
302                     test_bit(p->bit, mask)) {
303                         last = p;
304                         if (p->speed == speed && p->duplex == duplex) {
305                                 /* Exact match for speed and duplex */
306                                 match = p;
307                                 break;
308                         } else if (!exact) {
309                                 if (!match && p->speed <= speed)
310                                         /* Candidate */
311                                         match = p;
312
313                                 if (p->speed < speed)
314                                         break;
315                         }
316                 }
317         }
318
319         if (!match && !exact)
320                 match = last;
321
322         return match;
323 }
324 EXPORT_SYMBOL_GPL(phy_lookup_setting);
325
326 size_t phy_speeds(unsigned int *speeds, size_t size,
327                   unsigned long *mask)
328 {
329         size_t count;
330         int i;
331
332         for (i = 0, count = 0; i < ARRAY_SIZE(settings) && count < size; i++)
333                 if (settings[i].bit < __ETHTOOL_LINK_MODE_MASK_NBITS &&
334                     test_bit(settings[i].bit, mask) &&
335                     (count == 0 || speeds[count - 1] != settings[i].speed))
336                         speeds[count++] = settings[i].speed;
337
338         return count;
339 }
340
341 /**
342  * phy_resolve_aneg_linkmode - resolve the advertisements into phy settings
343  * @phydev: The phy_device struct
344  *
345  * Resolve our and the link partner advertisements into their corresponding
346  * speed and duplex. If full duplex was negotiated, extract the pause mode
347  * from the link partner mask.
348  */
349 void phy_resolve_aneg_linkmode(struct phy_device *phydev)
350 {
351         __ETHTOOL_DECLARE_LINK_MODE_MASK(common);
352
353         linkmode_and(common, phydev->lp_advertising, phydev->advertising);
354
355         if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, common)) {
356                 phydev->speed = SPEED_10000;
357                 phydev->duplex = DUPLEX_FULL;
358         } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
359                                      common)) {
360                 phydev->speed = SPEED_5000;
361                 phydev->duplex = DUPLEX_FULL;
362         } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
363                                      common)) {
364                 phydev->speed = SPEED_2500;
365                 phydev->duplex = DUPLEX_FULL;
366         } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
367                                      common)) {
368                 phydev->speed = SPEED_1000;
369                 phydev->duplex = DUPLEX_FULL;
370         } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
371                                      common)) {
372                 phydev->speed = SPEED_1000;
373                 phydev->duplex = DUPLEX_HALF;
374         } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
375                                      common)) {
376                 phydev->speed = SPEED_100;
377                 phydev->duplex = DUPLEX_FULL;
378         } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
379                                      common)) {
380                 phydev->speed = SPEED_100;
381                 phydev->duplex = DUPLEX_HALF;
382         } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
383                                      common)) {
384                 phydev->speed = SPEED_10;
385                 phydev->duplex = DUPLEX_FULL;
386         } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
387                                      common)) {
388                 phydev->speed = SPEED_10;
389                 phydev->duplex = DUPLEX_HALF;
390         }
391
392         if (phydev->duplex == DUPLEX_FULL) {
393                 phydev->pause = linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
394                                                   phydev->lp_advertising);
395                 phydev->asym_pause = linkmode_test_bit(
396                         ETHTOOL_LINK_MODE_Asym_Pause_BIT,
397                         phydev->lp_advertising);
398         }
399 }
400 EXPORT_SYMBOL_GPL(phy_resolve_aneg_linkmode);
401
402 static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad,
403                              u16 regnum)
404 {
405         /* Write the desired MMD Devad */
406         __mdiobus_write(bus, phy_addr, MII_MMD_CTRL, devad);
407
408         /* Write the desired MMD register address */
409         __mdiobus_write(bus, phy_addr, MII_MMD_DATA, regnum);
410
411         /* Select the Function : DATA with no post increment */
412         __mdiobus_write(bus, phy_addr, MII_MMD_CTRL,
413                         devad | MII_MMD_CTRL_NOINCR);
414 }
415
416 /**
417  * __phy_read_mmd - Convenience function for reading a register
418  * from an MMD on a given PHY.
419  * @phydev: The phy_device struct
420  * @devad: The MMD to read from (0..31)
421  * @regnum: The register on the MMD to read (0..65535)
422  *
423  * Same rules as for __phy_read();
424  */
425 int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
426 {
427         int val;
428
429         if (regnum > (u16)~0 || devad > 32)
430                 return -EINVAL;
431
432         if (phydev->drv->read_mmd) {
433                 val = phydev->drv->read_mmd(phydev, devad, regnum);
434         } else if (phydev->is_c45) {
435                 u32 addr = MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff);
436
437                 val = __mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, addr);
438         } else {
439                 struct mii_bus *bus = phydev->mdio.bus;
440                 int phy_addr = phydev->mdio.addr;
441
442                 mmd_phy_indirect(bus, phy_addr, devad, regnum);
443
444                 /* Read the content of the MMD's selected register */
445                 val = __mdiobus_read(bus, phy_addr, MII_MMD_DATA);
446         }
447         return val;
448 }
449 EXPORT_SYMBOL(__phy_read_mmd);
450
451 /**
452  * phy_read_mmd - Convenience function for reading a register
453  * from an MMD on a given PHY.
454  * @phydev: The phy_device struct
455  * @devad: The MMD to read from
456  * @regnum: The register on the MMD to read
457  *
458  * Same rules as for phy_read();
459  */
460 int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
461 {
462         int ret;
463
464         mutex_lock(&phydev->mdio.bus->mdio_lock);
465         ret = __phy_read_mmd(phydev, devad, regnum);
466         mutex_unlock(&phydev->mdio.bus->mdio_lock);
467
468         return ret;
469 }
470 EXPORT_SYMBOL(phy_read_mmd);
471
472 /**
473  * __phy_write_mmd - Convenience function for writing a register
474  * on an MMD on a given PHY.
475  * @phydev: The phy_device struct
476  * @devad: The MMD to read from
477  * @regnum: The register on the MMD to read
478  * @val: value to write to @regnum
479  *
480  * Same rules as for __phy_write();
481  */
482 int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
483 {
484         int ret;
485
486         if (regnum > (u16)~0 || devad > 32)
487                 return -EINVAL;
488
489         if (phydev->drv->write_mmd) {
490                 ret = phydev->drv->write_mmd(phydev, devad, regnum, val);
491         } else if (phydev->is_c45) {
492                 u32 addr = MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff);
493
494                 ret = __mdiobus_write(phydev->mdio.bus, phydev->mdio.addr,
495                                       addr, val);
496         } else {
497                 struct mii_bus *bus = phydev->mdio.bus;
498                 int phy_addr = phydev->mdio.addr;
499
500                 mmd_phy_indirect(bus, phy_addr, devad, regnum);
501
502                 /* Write the data into MMD's selected register */
503                 __mdiobus_write(bus, phy_addr, MII_MMD_DATA, val);
504
505                 ret = 0;
506         }
507         return ret;
508 }
509 EXPORT_SYMBOL(__phy_write_mmd);
510
511 /**
512  * phy_write_mmd - Convenience function for writing a register
513  * on an MMD on a given PHY.
514  * @phydev: The phy_device struct
515  * @devad: The MMD to read from
516  * @regnum: The register on the MMD to read
517  * @val: value to write to @regnum
518  *
519  * Same rules as for phy_write();
520  */
521 int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
522 {
523         int ret;
524
525         mutex_lock(&phydev->mdio.bus->mdio_lock);
526         ret = __phy_write_mmd(phydev, devad, regnum, val);
527         mutex_unlock(&phydev->mdio.bus->mdio_lock);
528
529         return ret;
530 }
531 EXPORT_SYMBOL(phy_write_mmd);
532
533 /**
534  * __phy_modify() - Convenience function for modifying a PHY register
535  * @phydev: a pointer to a &struct phy_device
536  * @regnum: register number
537  * @mask: bit mask of bits to clear
538  * @set: bit mask of bits to set
539  *
540  * Unlocked helper function which allows a PHY register to be modified as
541  * new register value = (old register value & ~mask) | set
542  */
543 int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
544 {
545         int ret;
546
547         ret = __phy_read(phydev, regnum);
548         if (ret < 0)
549                 return ret;
550
551         ret = __phy_write(phydev, regnum, (ret & ~mask) | set);
552
553         return ret < 0 ? ret : 0;
554 }
555 EXPORT_SYMBOL_GPL(__phy_modify);
556
557 /**
558  * phy_modify - Convenience function for modifying a given PHY register
559  * @phydev: the phy_device struct
560  * @regnum: register number to write
561  * @mask: bit mask of bits to clear
562  * @set: new value of bits set in mask to write to @regnum
563  *
564  * NOTE: MUST NOT be called from interrupt context,
565  * because the bus read/write functions may wait for an interrupt
566  * to conclude the operation.
567  */
568 int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
569 {
570         int ret;
571
572         mutex_lock(&phydev->mdio.bus->mdio_lock);
573         ret = __phy_modify(phydev, regnum, mask, set);
574         mutex_unlock(&phydev->mdio.bus->mdio_lock);
575
576         return ret;
577 }
578 EXPORT_SYMBOL_GPL(phy_modify);
579
580 /**
581  * __phy_modify_mmd - Convenience function for modifying a register on MMD
582  * @phydev: the phy_device struct
583  * @devad: the MMD containing register to modify
584  * @regnum: register number to modify
585  * @mask: bit mask of bits to clear
586  * @set: new value of bits set in mask to write to @regnum
587  *
588  * Unlocked helper function which allows a MMD register to be modified as
589  * new register value = (old register value & ~mask) | set
590  */
591 int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
592                      u16 mask, u16 set)
593 {
594         int ret;
595
596         ret = __phy_read_mmd(phydev, devad, regnum);
597         if (ret < 0)
598                 return ret;
599
600         ret = __phy_write_mmd(phydev, devad, regnum, (ret & ~mask) | set);
601
602         return ret < 0 ? ret : 0;
603 }
604 EXPORT_SYMBOL_GPL(__phy_modify_mmd);
605
606 /**
607  * phy_modify_mmd - Convenience function for modifying a register on MMD
608  * @phydev: the phy_device struct
609  * @devad: the MMD containing register to modify
610  * @regnum: register number to modify
611  * @mask: bit mask of bits to clear
612  * @set: new value of bits set in mask to write to @regnum
613  *
614  * NOTE: MUST NOT be called from interrupt context,
615  * because the bus read/write functions may wait for an interrupt
616  * to conclude the operation.
617  */
618 int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
619                    u16 mask, u16 set)
620 {
621         int ret;
622
623         mutex_lock(&phydev->mdio.bus->mdio_lock);
624         ret = __phy_modify_mmd(phydev, devad, regnum, mask, set);
625         mutex_unlock(&phydev->mdio.bus->mdio_lock);
626
627         return ret;
628 }
629 EXPORT_SYMBOL_GPL(phy_modify_mmd);
630
631 static int __phy_read_page(struct phy_device *phydev)
632 {
633         return phydev->drv->read_page(phydev);
634 }
635
636 static int __phy_write_page(struct phy_device *phydev, int page)
637 {
638         return phydev->drv->write_page(phydev, page);
639 }
640
641 /**
642  * phy_save_page() - take the bus lock and save the current page
643  * @phydev: a pointer to a &struct phy_device
644  *
645  * Take the MDIO bus lock, and return the current page number. On error,
646  * returns a negative errno. phy_restore_page() must always be called
647  * after this, irrespective of success or failure of this call.
648  */
649 int phy_save_page(struct phy_device *phydev)
650 {
651         mutex_lock(&phydev->mdio.bus->mdio_lock);
652         return __phy_read_page(phydev);
653 }
654 EXPORT_SYMBOL_GPL(phy_save_page);
655
656 /**
657  * phy_select_page() - take the bus lock, save the current page, and set a page
658  * @phydev: a pointer to a &struct phy_device
659  * @page: desired page
660  *
661  * Take the MDIO bus lock to protect against concurrent access, save the
662  * current PHY page, and set the current page.  On error, returns a
663  * negative errno, otherwise returns the previous page number.
664  * phy_restore_page() must always be called after this, irrespective
665  * of success or failure of this call.
666  */
667 int phy_select_page(struct phy_device *phydev, int page)
668 {
669         int ret, oldpage;
670
671         oldpage = ret = phy_save_page(phydev);
672         if (ret < 0)
673                 return ret;
674
675         if (oldpage != page) {
676                 ret = __phy_write_page(phydev, page);
677                 if (ret < 0)
678                         return ret;
679         }
680
681         return oldpage;
682 }
683 EXPORT_SYMBOL_GPL(phy_select_page);
684
685 /**
686  * phy_restore_page() - restore the page register and release the bus lock
687  * @phydev: a pointer to a &struct phy_device
688  * @oldpage: the old page, return value from phy_save_page() or phy_select_page()
689  * @ret: operation's return code
690  *
691  * Release the MDIO bus lock, restoring @oldpage if it is a valid page.
692  * This function propagates the earliest error code from the group of
693  * operations.
694  *
695  * Returns:
696  *   @oldpage if it was a negative value, otherwise
697  *   @ret if it was a negative errno value, otherwise
698  *   phy_write_page()'s negative value if it were in error, otherwise
699  *   @ret.
700  */
701 int phy_restore_page(struct phy_device *phydev, int oldpage, int ret)
702 {
703         int r;
704
705         if (oldpage >= 0) {
706                 r = __phy_write_page(phydev, oldpage);
707
708                 /* Propagate the operation return code if the page write
709                  * was successful.
710                  */
711                 if (ret >= 0 && r < 0)
712                         ret = r;
713         } else {
714                 /* Propagate the phy page selection error code */
715                 ret = oldpage;
716         }
717
718         mutex_unlock(&phydev->mdio.bus->mdio_lock);
719
720         return ret;
721 }
722 EXPORT_SYMBOL_GPL(phy_restore_page);
723
724 /**
725  * phy_read_paged() - Convenience function for reading a paged register
726  * @phydev: a pointer to a &struct phy_device
727  * @page: the page for the phy
728  * @regnum: register number
729  *
730  * Same rules as for phy_read().
731  */
732 int phy_read_paged(struct phy_device *phydev, int page, u32 regnum)
733 {
734         int ret = 0, oldpage;
735
736         oldpage = phy_select_page(phydev, page);
737         if (oldpage >= 0)
738                 ret = __phy_read(phydev, regnum);
739
740         return phy_restore_page(phydev, oldpage, ret);
741 }
742 EXPORT_SYMBOL(phy_read_paged);
743
744 /**
745  * phy_write_paged() - Convenience function for writing a paged register
746  * @phydev: a pointer to a &struct phy_device
747  * @page: the page for the phy
748  * @regnum: register number
749  * @val: value to write
750  *
751  * Same rules as for phy_write().
752  */
753 int phy_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val)
754 {
755         int ret = 0, oldpage;
756
757         oldpage = phy_select_page(phydev, page);
758         if (oldpage >= 0)
759                 ret = __phy_write(phydev, regnum, val);
760
761         return phy_restore_page(phydev, oldpage, ret);
762 }
763 EXPORT_SYMBOL(phy_write_paged);
764
765 /**
766  * phy_modify_paged() - Convenience function for modifying a paged register
767  * @phydev: a pointer to a &struct phy_device
768  * @page: the page for the phy
769  * @regnum: register number
770  * @mask: bit mask of bits to clear
771  * @set: bit mask of bits to set
772  *
773  * Same rules as for phy_read() and phy_write().
774  */
775 int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum,
776                      u16 mask, u16 set)
777 {
778         int ret = 0, oldpage;
779
780         oldpage = phy_select_page(phydev, page);
781         if (oldpage >= 0)
782                 ret = __phy_modify(phydev, regnum, mask, set);
783
784         return phy_restore_page(phydev, oldpage, ret);
785 }
786 EXPORT_SYMBOL(phy_modify_paged);