1
2
3
4
5#include <linux/export.h>
6#include <linux/phy.h>
7#include <linux/of.h>
8
9
10
11
12
13
14const char *phy_speed_to_str(int speed)
15{
16 BUILD_BUG_ON_MSG(__ETHTOOL_LINK_MODE_MASK_NBITS != 92,
17 "Enum ethtool_link_mode_bit_indices and phylib are out of sync. "
18 "If a speed or mode has been added please update phy_speed_to_str "
19 "and the PHY settings array.\n");
20
21 switch (speed) {
22 case SPEED_10:
23 return "10Mbps";
24 case SPEED_100:
25 return "100Mbps";
26 case SPEED_1000:
27 return "1Gbps";
28 case SPEED_2500:
29 return "2.5Gbps";
30 case SPEED_5000:
31 return "5Gbps";
32 case SPEED_10000:
33 return "10Gbps";
34 case SPEED_14000:
35 return "14Gbps";
36 case SPEED_20000:
37 return "20Gbps";
38 case SPEED_25000:
39 return "25Gbps";
40 case SPEED_40000:
41 return "40Gbps";
42 case SPEED_50000:
43 return "50Gbps";
44 case SPEED_56000:
45 return "56Gbps";
46 case SPEED_100000:
47 return "100Gbps";
48 case SPEED_200000:
49 return "200Gbps";
50 case SPEED_400000:
51 return "400Gbps";
52 case SPEED_UNKNOWN:
53 return "Unknown";
54 default:
55 return "Unsupported (update phy-core.c)";
56 }
57}
58EXPORT_SYMBOL_GPL(phy_speed_to_str);
59
60
61
62
63
64
65const char *phy_duplex_to_str(unsigned int duplex)
66{
67 if (duplex == DUPLEX_HALF)
68 return "Half";
69 if (duplex == DUPLEX_FULL)
70 return "Full";
71 if (duplex == DUPLEX_UNKNOWN)
72 return "Unknown";
73 return "Unsupported (update phy-core.c)";
74}
75EXPORT_SYMBOL_GPL(phy_duplex_to_str);
76
77
78
79
80
81
82#define PHY_SETTING(s, d, b) { .speed = SPEED_ ## s, .duplex = DUPLEX_ ## d, \
83 .bit = ETHTOOL_LINK_MODE_ ## b ## _BIT}
84
85static const struct phy_setting settings[] = {
86
87 PHY_SETTING( 400000, FULL, 400000baseCR8_Full ),
88 PHY_SETTING( 400000, FULL, 400000baseKR8_Full ),
89 PHY_SETTING( 400000, FULL, 400000baseLR8_ER8_FR8_Full ),
90 PHY_SETTING( 400000, FULL, 400000baseDR8_Full ),
91 PHY_SETTING( 400000, FULL, 400000baseSR8_Full ),
92 PHY_SETTING( 400000, FULL, 400000baseCR4_Full ),
93 PHY_SETTING( 400000, FULL, 400000baseKR4_Full ),
94 PHY_SETTING( 400000, FULL, 400000baseLR4_ER4_FR4_Full ),
95 PHY_SETTING( 400000, FULL, 400000baseDR4_Full ),
96 PHY_SETTING( 400000, FULL, 400000baseSR4_Full ),
97
98 PHY_SETTING( 200000, FULL, 200000baseCR4_Full ),
99 PHY_SETTING( 200000, FULL, 200000baseKR4_Full ),
100 PHY_SETTING( 200000, FULL, 200000baseLR4_ER4_FR4_Full ),
101 PHY_SETTING( 200000, FULL, 200000baseDR4_Full ),
102 PHY_SETTING( 200000, FULL, 200000baseSR4_Full ),
103 PHY_SETTING( 200000, FULL, 200000baseCR2_Full ),
104 PHY_SETTING( 200000, FULL, 200000baseKR2_Full ),
105 PHY_SETTING( 200000, FULL, 200000baseLR2_ER2_FR2_Full ),
106 PHY_SETTING( 200000, FULL, 200000baseDR2_Full ),
107 PHY_SETTING( 200000, FULL, 200000baseSR2_Full ),
108
109 PHY_SETTING( 100000, FULL, 100000baseCR4_Full ),
110 PHY_SETTING( 100000, FULL, 100000baseKR4_Full ),
111 PHY_SETTING( 100000, FULL, 100000baseLR4_ER4_Full ),
112 PHY_SETTING( 100000, FULL, 100000baseSR4_Full ),
113 PHY_SETTING( 100000, FULL, 100000baseCR2_Full ),
114 PHY_SETTING( 100000, FULL, 100000baseKR2_Full ),
115 PHY_SETTING( 100000, FULL, 100000baseLR2_ER2_FR2_Full ),
116 PHY_SETTING( 100000, FULL, 100000baseDR2_Full ),
117 PHY_SETTING( 100000, FULL, 100000baseSR2_Full ),
118 PHY_SETTING( 100000, FULL, 100000baseCR_Full ),
119 PHY_SETTING( 100000, FULL, 100000baseKR_Full ),
120 PHY_SETTING( 100000, FULL, 100000baseLR_ER_FR_Full ),
121 PHY_SETTING( 100000, FULL, 100000baseDR_Full ),
122 PHY_SETTING( 100000, FULL, 100000baseSR_Full ),
123
124 PHY_SETTING( 56000, FULL, 56000baseCR4_Full ),
125 PHY_SETTING( 56000, FULL, 56000baseKR4_Full ),
126 PHY_SETTING( 56000, FULL, 56000baseLR4_Full ),
127 PHY_SETTING( 56000, FULL, 56000baseSR4_Full ),
128
129 PHY_SETTING( 50000, FULL, 50000baseCR2_Full ),
130 PHY_SETTING( 50000, FULL, 50000baseKR2_Full ),
131 PHY_SETTING( 50000, FULL, 50000baseSR2_Full ),
132 PHY_SETTING( 50000, FULL, 50000baseCR_Full ),
133 PHY_SETTING( 50000, FULL, 50000baseKR_Full ),
134 PHY_SETTING( 50000, FULL, 50000baseLR_ER_FR_Full ),
135 PHY_SETTING( 50000, FULL, 50000baseDR_Full ),
136 PHY_SETTING( 50000, FULL, 50000baseSR_Full ),
137
138 PHY_SETTING( 40000, FULL, 40000baseCR4_Full ),
139 PHY_SETTING( 40000, FULL, 40000baseKR4_Full ),
140 PHY_SETTING( 40000, FULL, 40000baseLR4_Full ),
141 PHY_SETTING( 40000, FULL, 40000baseSR4_Full ),
142
143 PHY_SETTING( 25000, FULL, 25000baseCR_Full ),
144 PHY_SETTING( 25000, FULL, 25000baseKR_Full ),
145 PHY_SETTING( 25000, FULL, 25000baseSR_Full ),
146
147 PHY_SETTING( 20000, FULL, 20000baseKR2_Full ),
148 PHY_SETTING( 20000, FULL, 20000baseMLD2_Full ),
149
150 PHY_SETTING( 10000, FULL, 10000baseCR_Full ),
151 PHY_SETTING( 10000, FULL, 10000baseER_Full ),
152 PHY_SETTING( 10000, FULL, 10000baseKR_Full ),
153 PHY_SETTING( 10000, FULL, 10000baseKX4_Full ),
154 PHY_SETTING( 10000, FULL, 10000baseLR_Full ),
155 PHY_SETTING( 10000, FULL, 10000baseLRM_Full ),
156 PHY_SETTING( 10000, FULL, 10000baseR_FEC ),
157 PHY_SETTING( 10000, FULL, 10000baseSR_Full ),
158 PHY_SETTING( 10000, FULL, 10000baseT_Full ),
159
160 PHY_SETTING( 5000, FULL, 5000baseT_Full ),
161
162 PHY_SETTING( 2500, FULL, 2500baseT_Full ),
163 PHY_SETTING( 2500, FULL, 2500baseX_Full ),
164
165 PHY_SETTING( 1000, FULL, 1000baseKX_Full ),
166 PHY_SETTING( 1000, FULL, 1000baseT_Full ),
167 PHY_SETTING( 1000, HALF, 1000baseT_Half ),
168 PHY_SETTING( 1000, FULL, 1000baseT1_Full ),
169 PHY_SETTING( 1000, FULL, 1000baseX_Full ),
170
171 PHY_SETTING( 100, FULL, 100baseT_Full ),
172 PHY_SETTING( 100, FULL, 100baseT1_Full ),
173 PHY_SETTING( 100, HALF, 100baseT_Half ),
174 PHY_SETTING( 100, HALF, 100baseFX_Half ),
175 PHY_SETTING( 100, FULL, 100baseFX_Full ),
176
177 PHY_SETTING( 10, FULL, 10baseT_Full ),
178 PHY_SETTING( 10, HALF, 10baseT_Half ),
179};
180#undef PHY_SETTING
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199const struct phy_setting *
200phy_lookup_setting(int speed, int duplex, const unsigned long *mask, bool exact)
201{
202 const struct phy_setting *p, *match = NULL, *last = NULL;
203 int i;
204
205 for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
206 if (p->bit < __ETHTOOL_LINK_MODE_MASK_NBITS &&
207 test_bit(p->bit, mask)) {
208 last = p;
209 if (p->speed == speed && p->duplex == duplex) {
210
211 match = p;
212 break;
213 } else if (!exact) {
214 if (!match && p->speed <= speed)
215
216 match = p;
217
218 if (p->speed < speed)
219 break;
220 }
221 }
222 }
223
224 if (!match && !exact)
225 match = last;
226
227 return match;
228}
229EXPORT_SYMBOL_GPL(phy_lookup_setting);
230
231size_t phy_speeds(unsigned int *speeds, size_t size,
232 unsigned long *mask)
233{
234 size_t count;
235 int i;
236
237 for (i = 0, count = 0; i < ARRAY_SIZE(settings) && count < size; i++)
238 if (settings[i].bit < __ETHTOOL_LINK_MODE_MASK_NBITS &&
239 test_bit(settings[i].bit, mask) &&
240 (count == 0 || speeds[count - 1] != settings[i].speed))
241 speeds[count++] = settings[i].speed;
242
243 return count;
244}
245
246static int __set_linkmode_max_speed(u32 max_speed, unsigned long *addr)
247{
248 const struct phy_setting *p;
249 int i;
250
251 for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
252 if (p->speed > max_speed)
253 linkmode_clear_bit(p->bit, addr);
254 else
255 break;
256 }
257
258 return 0;
259}
260
261static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
262{
263 return __set_linkmode_max_speed(max_speed, phydev->supported);
264}
265
266
267
268
269
270
271
272
273
274
275
276int phy_set_max_speed(struct phy_device *phydev, u32 max_speed)
277{
278 int err;
279
280 err = __set_phy_supported(phydev, max_speed);
281 if (err)
282 return err;
283
284 phy_advertise_supported(phydev);
285
286 return 0;
287}
288EXPORT_SYMBOL(phy_set_max_speed);
289
290void of_set_phy_supported(struct phy_device *phydev)
291{
292 struct device_node *node = phydev->mdio.dev.of_node;
293 u32 max_speed;
294
295 if (!IS_ENABLED(CONFIG_OF_MDIO))
296 return;
297
298 if (!node)
299 return;
300
301 if (!of_property_read_u32(node, "max-speed", &max_speed))
302 __set_phy_supported(phydev, max_speed);
303}
304
305void of_set_phy_eee_broken(struct phy_device *phydev)
306{
307 struct device_node *node = phydev->mdio.dev.of_node;
308 u32 broken = 0;
309
310 if (!IS_ENABLED(CONFIG_OF_MDIO))
311 return;
312
313 if (!node)
314 return;
315
316 if (of_property_read_bool(node, "eee-broken-100tx"))
317 broken |= MDIO_EEE_100TX;
318 if (of_property_read_bool(node, "eee-broken-1000t"))
319 broken |= MDIO_EEE_1000T;
320 if (of_property_read_bool(node, "eee-broken-10gt"))
321 broken |= MDIO_EEE_10GT;
322 if (of_property_read_bool(node, "eee-broken-1000kx"))
323 broken |= MDIO_EEE_1000KX;
324 if (of_property_read_bool(node, "eee-broken-10gkx4"))
325 broken |= MDIO_EEE_10GKX4;
326 if (of_property_read_bool(node, "eee-broken-10gkr"))
327 broken |= MDIO_EEE_10GKR;
328
329 phydev->eee_broken_modes = broken;
330}
331
332
333
334
335
336
337
338
339
340
341
342void phy_resolve_aneg_pause(struct phy_device *phydev)
343{
344 if (phydev->duplex == DUPLEX_FULL) {
345 phydev->pause = linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
346 phydev->lp_advertising);
347 phydev->asym_pause = linkmode_test_bit(
348 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
349 phydev->lp_advertising);
350 }
351}
352EXPORT_SYMBOL_GPL(phy_resolve_aneg_pause);
353
354
355
356
357
358
359
360
361
362void phy_resolve_aneg_linkmode(struct phy_device *phydev)
363{
364 __ETHTOOL_DECLARE_LINK_MODE_MASK(common);
365 int i;
366
367 linkmode_and(common, phydev->lp_advertising, phydev->advertising);
368
369 for (i = 0; i < ARRAY_SIZE(settings); i++)
370 if (test_bit(settings[i].bit, common)) {
371 phydev->speed = settings[i].speed;
372 phydev->duplex = settings[i].duplex;
373 break;
374 }
375
376 phy_resolve_aneg_pause(phydev);
377}
378EXPORT_SYMBOL_GPL(phy_resolve_aneg_linkmode);
379
380
381
382
383
384
385
386
387
388
389void phy_check_downshift(struct phy_device *phydev)
390{
391 __ETHTOOL_DECLARE_LINK_MODE_MASK(common);
392 int i, speed = SPEED_UNKNOWN;
393
394 phydev->downshifted_rate = 0;
395
396 if (phydev->autoneg == AUTONEG_DISABLE ||
397 phydev->speed == SPEED_UNKNOWN)
398 return;
399
400 linkmode_and(common, phydev->lp_advertising, phydev->advertising);
401
402 for (i = 0; i < ARRAY_SIZE(settings); i++)
403 if (test_bit(settings[i].bit, common)) {
404 speed = settings[i].speed;
405 break;
406 }
407
408 if (speed == SPEED_UNKNOWN || phydev->speed >= speed)
409 return;
410
411 phydev_warn(phydev, "Downshift occurred from negotiated speed %s to actual speed %s, check cabling!\n",
412 phy_speed_to_str(speed), phy_speed_to_str(phydev->speed));
413
414 phydev->downshifted_rate = 1;
415}
416EXPORT_SYMBOL_GPL(phy_check_downshift);
417
418static int phy_resolve_min_speed(struct phy_device *phydev, bool fdx_only)
419{
420 __ETHTOOL_DECLARE_LINK_MODE_MASK(common);
421 int i = ARRAY_SIZE(settings);
422
423 linkmode_and(common, phydev->lp_advertising, phydev->advertising);
424
425 while (--i >= 0) {
426 if (test_bit(settings[i].bit, common)) {
427 if (fdx_only && settings[i].duplex != DUPLEX_FULL)
428 continue;
429 return settings[i].speed;
430 }
431 }
432
433 return SPEED_UNKNOWN;
434}
435
436int phy_speed_down_core(struct phy_device *phydev)
437{
438 int min_common_speed = phy_resolve_min_speed(phydev, true);
439
440 if (min_common_speed == SPEED_UNKNOWN)
441 return -EINVAL;
442
443 return __set_linkmode_max_speed(min_common_speed, phydev->advertising);
444}
445
446static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad,
447 u16 regnum)
448{
449
450 __mdiobus_write(bus, phy_addr, MII_MMD_CTRL, devad);
451
452
453 __mdiobus_write(bus, phy_addr, MII_MMD_DATA, regnum);
454
455
456 __mdiobus_write(bus, phy_addr, MII_MMD_CTRL,
457 devad | MII_MMD_CTRL_NOINCR);
458}
459
460
461
462
463
464
465
466
467
468
469int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
470{
471 int val;
472
473 if (regnum > (u16)~0 || devad > 32)
474 return -EINVAL;
475
476 if (phydev->drv && phydev->drv->read_mmd) {
477 val = phydev->drv->read_mmd(phydev, devad, regnum);
478 } else if (phydev->is_c45) {
479 val = __mdiobus_c45_read(phydev->mdio.bus, phydev->mdio.addr,
480 devad, regnum);
481 } else {
482 struct mii_bus *bus = phydev->mdio.bus;
483 int phy_addr = phydev->mdio.addr;
484
485 mmd_phy_indirect(bus, phy_addr, devad, regnum);
486
487
488 val = __mdiobus_read(bus, phy_addr, MII_MMD_DATA);
489 }
490 return val;
491}
492EXPORT_SYMBOL(__phy_read_mmd);
493
494
495
496
497
498
499
500
501
502
503int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
504{
505 int ret;
506
507 phy_lock_mdio_bus(phydev);
508 ret = __phy_read_mmd(phydev, devad, regnum);
509 phy_unlock_mdio_bus(phydev);
510
511 return ret;
512}
513EXPORT_SYMBOL(phy_read_mmd);
514
515
516
517
518
519
520
521
522
523
524
525int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
526{
527 int ret;
528
529 if (regnum > (u16)~0 || devad > 32)
530 return -EINVAL;
531
532 if (phydev->drv && phydev->drv->write_mmd) {
533 ret = phydev->drv->write_mmd(phydev, devad, regnum, val);
534 } else if (phydev->is_c45) {
535 ret = __mdiobus_c45_write(phydev->mdio.bus, phydev->mdio.addr,
536 devad, regnum, val);
537 } else {
538 struct mii_bus *bus = phydev->mdio.bus;
539 int phy_addr = phydev->mdio.addr;
540
541 mmd_phy_indirect(bus, phy_addr, devad, regnum);
542
543
544 __mdiobus_write(bus, phy_addr, MII_MMD_DATA, val);
545
546 ret = 0;
547 }
548 return ret;
549}
550EXPORT_SYMBOL(__phy_write_mmd);
551
552
553
554
555
556
557
558
559
560
561
562int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
563{
564 int ret;
565
566 phy_lock_mdio_bus(phydev);
567 ret = __phy_write_mmd(phydev, devad, regnum, val);
568 phy_unlock_mdio_bus(phydev);
569
570 return ret;
571}
572EXPORT_SYMBOL(phy_write_mmd);
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
588{
589 int ret;
590
591 phy_lock_mdio_bus(phydev);
592 ret = __phy_modify_changed(phydev, regnum, mask, set);
593 phy_unlock_mdio_bus(phydev);
594
595 return ret;
596}
597EXPORT_SYMBOL_GPL(phy_modify_changed);
598
599
600
601
602
603
604
605
606
607
608
609
610int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
611{
612 int ret;
613
614 ret = __phy_modify_changed(phydev, regnum, mask, set);
615
616 return ret < 0 ? ret : 0;
617}
618EXPORT_SYMBOL_GPL(__phy_modify);
619
620
621
622
623
624
625
626
627
628
629
630
631int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
632{
633 int ret;
634
635 phy_lock_mdio_bus(phydev);
636 ret = __phy_modify(phydev, regnum, mask, set);
637 phy_unlock_mdio_bus(phydev);
638
639 return ret;
640}
641EXPORT_SYMBOL_GPL(phy_modify);
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
657 u16 mask, u16 set)
658{
659 int new, ret;
660
661 ret = __phy_read_mmd(phydev, devad, regnum);
662 if (ret < 0)
663 return ret;
664
665 new = (ret & ~mask) | set;
666 if (new == ret)
667 return 0;
668
669 ret = __phy_write_mmd(phydev, devad, regnum, new);
670
671 return ret < 0 ? ret : 1;
672}
673EXPORT_SYMBOL_GPL(__phy_modify_mmd_changed);
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
690 u16 mask, u16 set)
691{
692 int ret;
693
694 phy_lock_mdio_bus(phydev);
695 ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
696 phy_unlock_mdio_bus(phydev);
697
698 return ret;
699}
700EXPORT_SYMBOL_GPL(phy_modify_mmd_changed);
701
702
703
704
705
706
707
708
709
710
711
712
713
714int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
715 u16 mask, u16 set)
716{
717 int ret;
718
719 ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
720
721 return ret < 0 ? ret : 0;
722}
723EXPORT_SYMBOL_GPL(__phy_modify_mmd);
724
725
726
727
728
729
730
731
732
733
734
735
736
737int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
738 u16 mask, u16 set)
739{
740 int ret;
741
742 phy_lock_mdio_bus(phydev);
743 ret = __phy_modify_mmd(phydev, devad, regnum, mask, set);
744 phy_unlock_mdio_bus(phydev);
745
746 return ret;
747}
748EXPORT_SYMBOL_GPL(phy_modify_mmd);
749
750static int __phy_read_page(struct phy_device *phydev)
751{
752 if (WARN_ONCE(!phydev->drv->read_page, "read_page callback not available, PHY driver not loaded?\n"))
753 return -EOPNOTSUPP;
754
755 return phydev->drv->read_page(phydev);
756}
757
758static int __phy_write_page(struct phy_device *phydev, int page)
759{
760 if (WARN_ONCE(!phydev->drv->write_page, "write_page callback not available, PHY driver not loaded?\n"))
761 return -EOPNOTSUPP;
762
763 return phydev->drv->write_page(phydev, page);
764}
765
766
767
768
769
770
771
772
773
774int phy_save_page(struct phy_device *phydev)
775{
776 phy_lock_mdio_bus(phydev);
777 return __phy_read_page(phydev);
778}
779EXPORT_SYMBOL_GPL(phy_save_page);
780
781
782
783
784
785
786
787
788
789
790
791
792int phy_select_page(struct phy_device *phydev, int page)
793{
794 int ret, oldpage;
795
796 oldpage = ret = phy_save_page(phydev);
797 if (ret < 0)
798 return ret;
799
800 if (oldpage != page) {
801 ret = __phy_write_page(phydev, page);
802 if (ret < 0)
803 return ret;
804 }
805
806 return oldpage;
807}
808EXPORT_SYMBOL_GPL(phy_select_page);
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826int phy_restore_page(struct phy_device *phydev, int oldpage, int ret)
827{
828 int r;
829
830 if (oldpage >= 0) {
831 r = __phy_write_page(phydev, oldpage);
832
833
834
835
836 if (ret >= 0 && r < 0)
837 ret = r;
838 } else {
839
840 ret = oldpage;
841 }
842
843 phy_unlock_mdio_bus(phydev);
844
845 return ret;
846}
847EXPORT_SYMBOL_GPL(phy_restore_page);
848
849
850
851
852
853
854
855
856
857int phy_read_paged(struct phy_device *phydev, int page, u32 regnum)
858{
859 int ret = 0, oldpage;
860
861 oldpage = phy_select_page(phydev, page);
862 if (oldpage >= 0)
863 ret = __phy_read(phydev, regnum);
864
865 return phy_restore_page(phydev, oldpage, ret);
866}
867EXPORT_SYMBOL(phy_read_paged);
868
869
870
871
872
873
874
875
876
877
878int phy_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val)
879{
880 int ret = 0, oldpage;
881
882 oldpage = phy_select_page(phydev, page);
883 if (oldpage >= 0)
884 ret = __phy_write(phydev, regnum, val);
885
886 return phy_restore_page(phydev, oldpage, ret);
887}
888EXPORT_SYMBOL(phy_write_paged);
889
890
891
892
893
894
895
896
897
898
899
900int phy_modify_paged_changed(struct phy_device *phydev, int page, u32 regnum,
901 u16 mask, u16 set)
902{
903 int ret = 0, oldpage;
904
905 oldpage = phy_select_page(phydev, page);
906 if (oldpage >= 0)
907 ret = __phy_modify_changed(phydev, regnum, mask, set);
908
909 return phy_restore_page(phydev, oldpage, ret);
910}
911EXPORT_SYMBOL(phy_modify_paged_changed);
912
913
914
915
916
917
918
919
920
921
922
923int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum,
924 u16 mask, u16 set)
925{
926 int ret = phy_modify_paged_changed(phydev, page, regnum, mask, set);
927
928 return ret < 0 ? ret : 0;
929}
930EXPORT_SYMBOL(phy_modify_paged);
931