1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
18#include <linux/kernel.h>
19#include <linux/string.h>
20#include <linux/errno.h>
21#include <linux/unistd.h>
22#include <linux/interrupt.h>
23#include <linux/init.h>
24#include <linux/delay.h>
25#include <linux/netdevice.h>
26#include <linux/etherdevice.h>
27#include <linux/skbuff.h>
28#include <linux/mm.h>
29#include <linux/module.h>
30#include <linux/mii.h>
31#include <linux/ethtool.h>
32#include <linux/phy.h>
33#include <linux/timer.h>
34#include <linux/workqueue.h>
35#include <linux/mdio.h>
36#include <linux/io.h>
37#include <linux/uaccess.h>
38#include <linux/atomic.h>
39
40#include <asm/irq.h>
41
42
43
44
45
46void phy_print_status(struct phy_device *phydev)
47{
48 if (phydev->link) {
49 pr_info("%s - Link is Up - %d/%s\n",
50 dev_name(&phydev->dev),
51 phydev->speed,
52 DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
53 } else {
54 pr_info("%s - Link is Down\n", dev_name(&phydev->dev));
55 }
56}
57EXPORT_SYMBOL(phy_print_status);
58
59
60
61
62
63
64
65
66
67
68static int phy_clear_interrupt(struct phy_device *phydev)
69{
70 if (phydev->drv->ack_interrupt)
71 return phydev->drv->ack_interrupt(phydev);
72
73 return 0;
74}
75
76
77
78
79
80
81
82
83static int phy_config_interrupt(struct phy_device *phydev, u32 interrupts)
84{
85 phydev->interrupts = interrupts;
86 if (phydev->drv->config_intr)
87 return phydev->drv->config_intr(phydev);
88
89 return 0;
90}
91
92
93
94
95
96
97
98
99
100
101int phy_aneg_done(struct phy_device *phydev)
102{
103 if (phydev->drv->aneg_done)
104 return phydev->drv->aneg_done(phydev);
105
106 return genphy_aneg_done(phydev);
107}
108EXPORT_SYMBOL(phy_aneg_done);
109
110
111
112
113struct phy_setting {
114 int speed;
115 int duplex;
116 u32 setting;
117};
118
119
120static const struct phy_setting settings[] = {
121 {
122 .speed = 10000,
123 .duplex = DUPLEX_FULL,
124 .setting = SUPPORTED_10000baseT_Full,
125 },
126 {
127 .speed = SPEED_1000,
128 .duplex = DUPLEX_FULL,
129 .setting = SUPPORTED_1000baseT_Full,
130 },
131 {
132 .speed = SPEED_1000,
133 .duplex = DUPLEX_HALF,
134 .setting = SUPPORTED_1000baseT_Half,
135 },
136 {
137 .speed = SPEED_100,
138 .duplex = DUPLEX_FULL,
139 .setting = SUPPORTED_100baseT_Full,
140 },
141 {
142 .speed = SPEED_100,
143 .duplex = DUPLEX_HALF,
144 .setting = SUPPORTED_100baseT_Half,
145 },
146 {
147 .speed = SPEED_10,
148 .duplex = DUPLEX_FULL,
149 .setting = SUPPORTED_10baseT_Full,
150 },
151 {
152 .speed = SPEED_10,
153 .duplex = DUPLEX_HALF,
154 .setting = SUPPORTED_10baseT_Half,
155 },
156};
157
158#define MAX_NUM_SETTINGS ARRAY_SIZE(settings)
159
160
161
162
163
164
165
166
167
168
169
170static inline int phy_find_setting(int speed, int duplex)
171{
172 int idx = 0;
173
174 while (idx < ARRAY_SIZE(settings) &&
175 (settings[idx].speed != speed || settings[idx].duplex != duplex))
176 idx++;
177
178 return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
179}
180
181
182
183
184
185
186
187
188
189
190
191static inline int phy_find_valid(int idx, u32 features)
192{
193 while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features))
194 idx++;
195
196 return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
197}
198
199
200
201
202
203
204
205
206
207static void phy_sanitize_settings(struct phy_device *phydev)
208{
209 u32 features = phydev->supported;
210 int idx;
211
212
213 if ((features & SUPPORTED_Autoneg) == 0)
214 phydev->autoneg = AUTONEG_DISABLE;
215
216 idx = phy_find_valid(phy_find_setting(phydev->speed, phydev->duplex),
217 features);
218
219 phydev->speed = settings[idx].speed;
220 phydev->duplex = settings[idx].duplex;
221}
222
223
224
225
226
227
228
229
230
231
232
233
234
235int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
236{
237 u32 speed = ethtool_cmd_speed(cmd);
238
239 if (cmd->phy_address != phydev->addr)
240 return -EINVAL;
241
242
243 cmd->advertising &= phydev->supported;
244
245
246 if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
247 return -EINVAL;
248
249 if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
250 return -EINVAL;
251
252 if (cmd->autoneg == AUTONEG_DISABLE &&
253 ((speed != SPEED_1000 &&
254 speed != SPEED_100 &&
255 speed != SPEED_10) ||
256 (cmd->duplex != DUPLEX_HALF &&
257 cmd->duplex != DUPLEX_FULL)))
258 return -EINVAL;
259
260 phydev->autoneg = cmd->autoneg;
261
262 phydev->speed = speed;
263
264 phydev->advertising = cmd->advertising;
265
266 if (AUTONEG_ENABLE == cmd->autoneg)
267 phydev->advertising |= ADVERTISED_Autoneg;
268 else
269 phydev->advertising &= ~ADVERTISED_Autoneg;
270
271 phydev->duplex = cmd->duplex;
272
273
274 phy_start_aneg(phydev);
275
276 return 0;
277}
278EXPORT_SYMBOL(phy_ethtool_sset);
279
280int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
281{
282 cmd->supported = phydev->supported;
283
284 cmd->advertising = phydev->advertising;
285
286 ethtool_cmd_speed_set(cmd, phydev->speed);
287 cmd->duplex = phydev->duplex;
288 cmd->port = PORT_MII;
289 cmd->phy_address = phydev->addr;
290 cmd->transceiver = phy_is_internal(phydev) ?
291 XCVR_INTERNAL : XCVR_EXTERNAL;
292 cmd->autoneg = phydev->autoneg;
293
294 return 0;
295}
296EXPORT_SYMBOL(phy_ethtool_gset);
297
298
299
300
301
302
303
304
305
306
307
308int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd)
309{
310 struct mii_ioctl_data *mii_data = if_mii(ifr);
311 u16 val = mii_data->val_in;
312
313 switch (cmd) {
314 case SIOCGMIIPHY:
315 mii_data->phy_id = phydev->addr;
316
317
318 case SIOCGMIIREG:
319 mii_data->val_out = mdiobus_read(phydev->bus, mii_data->phy_id,
320 mii_data->reg_num);
321 return 0;
322
323 case SIOCSMIIREG:
324 if (mii_data->phy_id == phydev->addr) {
325 switch (mii_data->reg_num) {
326 case MII_BMCR:
327 if ((val & (BMCR_RESET | BMCR_ANENABLE)) == 0)
328 phydev->autoneg = AUTONEG_DISABLE;
329 else
330 phydev->autoneg = AUTONEG_ENABLE;
331 if (!phydev->autoneg && (val & BMCR_FULLDPLX))
332 phydev->duplex = DUPLEX_FULL;
333 else
334 phydev->duplex = DUPLEX_HALF;
335 if (!phydev->autoneg && (val & BMCR_SPEED1000))
336 phydev->speed = SPEED_1000;
337 else if (!phydev->autoneg &&
338 (val & BMCR_SPEED100))
339 phydev->speed = SPEED_100;
340 break;
341 case MII_ADVERTISE:
342 phydev->advertising = val;
343 break;
344 default:
345
346 break;
347 }
348 }
349
350 mdiobus_write(phydev->bus, mii_data->phy_id,
351 mii_data->reg_num, val);
352
353 if (mii_data->reg_num == MII_BMCR &&
354 val & BMCR_RESET)
355 return phy_init_hw(phydev);
356 return 0;
357
358 case SIOCSHWTSTAMP:
359 if (phydev->drv->hwtstamp)
360 return phydev->drv->hwtstamp(phydev, ifr);
361
362
363 default:
364 return -EOPNOTSUPP;
365 }
366}
367EXPORT_SYMBOL(phy_mii_ioctl);
368
369
370
371
372
373
374
375
376
377
378int phy_start_aneg(struct phy_device *phydev)
379{
380 int err;
381
382 mutex_lock(&phydev->lock);
383
384 if (AUTONEG_DISABLE == phydev->autoneg)
385 phy_sanitize_settings(phydev);
386
387 err = phydev->drv->config_aneg(phydev);
388 if (err < 0)
389 goto out_unlock;
390
391 if (phydev->state != PHY_HALTED) {
392 if (AUTONEG_ENABLE == phydev->autoneg) {
393 phydev->state = PHY_AN;
394 phydev->link_timeout = PHY_AN_TIMEOUT;
395 } else {
396 phydev->state = PHY_FORCING;
397 phydev->link_timeout = PHY_FORCE_TIMEOUT;
398 }
399 }
400
401out_unlock:
402 mutex_unlock(&phydev->lock);
403 return err;
404}
405EXPORT_SYMBOL(phy_start_aneg);
406
407
408
409
410
411
412
413
414
415
416
417void phy_start_machine(struct phy_device *phydev)
418{
419 queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, HZ);
420}
421
422
423
424
425
426
427
428
429
430void phy_stop_machine(struct phy_device *phydev)
431{
432 cancel_delayed_work_sync(&phydev->state_queue);
433
434 mutex_lock(&phydev->lock);
435 if (phydev->state > PHY_UP)
436 phydev->state = PHY_UP;
437 mutex_unlock(&phydev->lock);
438}
439
440
441
442
443
444
445
446
447
448
449static void phy_error(struct phy_device *phydev)
450{
451 mutex_lock(&phydev->lock);
452 phydev->state = PHY_HALTED;
453 mutex_unlock(&phydev->lock);
454}
455
456
457
458
459
460
461
462
463
464static irqreturn_t phy_interrupt(int irq, void *phy_dat)
465{
466 struct phy_device *phydev = phy_dat;
467
468 if (PHY_HALTED == phydev->state)
469 return IRQ_NONE;
470
471
472
473
474
475
476 disable_irq_nosync(irq);
477 atomic_inc(&phydev->irq_disable);
478
479 queue_work(system_power_efficient_wq, &phydev->phy_queue);
480
481 return IRQ_HANDLED;
482}
483
484
485
486
487
488static int phy_enable_interrupts(struct phy_device *phydev)
489{
490 int err = phy_clear_interrupt(phydev);
491
492 if (err < 0)
493 return err;
494
495 return phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
496}
497
498
499
500
501
502static int phy_disable_interrupts(struct phy_device *phydev)
503{
504 int err;
505
506
507 err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
508 if (err)
509 goto phy_err;
510
511
512 err = phy_clear_interrupt(phydev);
513 if (err)
514 goto phy_err;
515
516 return 0;
517
518phy_err:
519 phy_error(phydev);
520
521 return err;
522}
523
524
525
526
527
528
529
530
531
532
533
534int phy_start_interrupts(struct phy_device *phydev)
535{
536 atomic_set(&phydev->irq_disable, 0);
537 if (request_irq(phydev->irq, phy_interrupt,
538 IRQF_SHARED,
539 "phy_interrupt",
540 phydev) < 0) {
541 pr_warn("%s: Can't get IRQ %d (PHY)\n",
542 phydev->bus->name, phydev->irq);
543 phydev->irq = PHY_POLL;
544 return 0;
545 }
546
547 return phy_enable_interrupts(phydev);
548}
549EXPORT_SYMBOL(phy_start_interrupts);
550
551
552
553
554
555int phy_stop_interrupts(struct phy_device *phydev)
556{
557 int err = phy_disable_interrupts(phydev);
558
559 if (err)
560 phy_error(phydev);
561
562 free_irq(phydev->irq, phydev);
563
564
565
566
567
568
569 cancel_work_sync(&phydev->phy_queue);
570
571
572
573
574 while (atomic_dec_return(&phydev->irq_disable) >= 0)
575 enable_irq(phydev->irq);
576
577 return err;
578}
579EXPORT_SYMBOL(phy_stop_interrupts);
580
581
582
583
584
585void phy_change(struct work_struct *work)
586{
587 struct phy_device *phydev =
588 container_of(work, struct phy_device, phy_queue);
589
590 if (phy_interrupt_is_valid(phydev)) {
591 if (phydev->drv->did_interrupt &&
592 !phydev->drv->did_interrupt(phydev))
593 goto ignore;
594
595 if (phy_disable_interrupts(phydev))
596 goto phy_err;
597 }
598
599 mutex_lock(&phydev->lock);
600 if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
601 phydev->state = PHY_CHANGELINK;
602 mutex_unlock(&phydev->lock);
603
604 if (phy_interrupt_is_valid(phydev)) {
605 atomic_dec(&phydev->irq_disable);
606 enable_irq(phydev->irq);
607
608
609 if (PHY_HALTED != phydev->state &&
610 phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED))
611 goto irq_enable_err;
612 }
613
614
615 cancel_delayed_work_sync(&phydev->state_queue);
616 queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, 0);
617 return;
618
619ignore:
620 atomic_dec(&phydev->irq_disable);
621 enable_irq(phydev->irq);
622 return;
623
624irq_enable_err:
625 disable_irq(phydev->irq);
626 atomic_inc(&phydev->irq_disable);
627phy_err:
628 phy_error(phydev);
629}
630
631
632
633
634
635void phy_stop(struct phy_device *phydev)
636{
637 mutex_lock(&phydev->lock);
638
639 if (PHY_HALTED == phydev->state)
640 goto out_unlock;
641
642 if (phy_interrupt_is_valid(phydev)) {
643
644 phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
645
646
647 phy_clear_interrupt(phydev);
648 }
649
650 phydev->state = PHY_HALTED;
651
652out_unlock:
653 mutex_unlock(&phydev->lock);
654
655
656
657
658
659}
660EXPORT_SYMBOL(phy_stop);
661
662
663
664
665
666
667
668
669
670
671
672void phy_start(struct phy_device *phydev)
673{
674 mutex_lock(&phydev->lock);
675
676 switch (phydev->state) {
677 case PHY_STARTING:
678 phydev->state = PHY_PENDING;
679 break;
680 case PHY_READY:
681 phydev->state = PHY_UP;
682 break;
683 case PHY_HALTED:
684 phydev->state = PHY_RESUMING;
685 default:
686 break;
687 }
688 mutex_unlock(&phydev->lock);
689}
690EXPORT_SYMBOL(phy_start);
691
692
693
694
695
696void phy_state_machine(struct work_struct *work)
697{
698 struct delayed_work *dwork = to_delayed_work(work);
699 struct phy_device *phydev =
700 container_of(dwork, struct phy_device, state_queue);
701 bool needs_aneg = false, do_suspend = false, do_resume = false;
702 int err = 0;
703 int old_link;
704
705 mutex_lock(&phydev->lock);
706
707 switch (phydev->state) {
708 case PHY_DOWN:
709 case PHY_STARTING:
710 case PHY_READY:
711 case PHY_PENDING:
712 break;
713 case PHY_UP:
714 needs_aneg = true;
715
716 phydev->link_timeout = PHY_AN_TIMEOUT;
717
718 break;
719 case PHY_AN:
720 err = phy_read_status(phydev);
721 if (err < 0)
722 break;
723
724
725 if (!phydev->link) {
726 phydev->state = PHY_NOLINK;
727 netif_carrier_off(phydev->attached_dev);
728 phydev->adjust_link(phydev->attached_dev);
729 break;
730 }
731
732
733 err = phy_aneg_done(phydev);
734 if (err < 0)
735 break;
736
737
738 if (err > 0) {
739 phydev->state = PHY_RUNNING;
740 netif_carrier_on(phydev->attached_dev);
741 phydev->adjust_link(phydev->attached_dev);
742
743 } else if (0 == phydev->link_timeout--)
744 needs_aneg = true;
745 break;
746 case PHY_NOLINK:
747 err = phy_read_status(phydev);
748 if (err)
749 break;
750
751 if (phydev->link) {
752 if (AUTONEG_ENABLE == phydev->autoneg) {
753 err = phy_aneg_done(phydev);
754 if (err < 0)
755 break;
756
757 if (!err) {
758 phydev->state = PHY_AN;
759 phydev->link_timeout = PHY_AN_TIMEOUT;
760 break;
761 }
762 }
763 phydev->state = PHY_RUNNING;
764 netif_carrier_on(phydev->attached_dev);
765 phydev->adjust_link(phydev->attached_dev);
766 }
767 break;
768 case PHY_FORCING:
769 err = genphy_update_link(phydev);
770 if (err)
771 break;
772
773 if (phydev->link) {
774 phydev->state = PHY_RUNNING;
775 netif_carrier_on(phydev->attached_dev);
776 } else {
777 if (0 == phydev->link_timeout--)
778 needs_aneg = true;
779 }
780
781 phydev->adjust_link(phydev->attached_dev);
782 break;
783 case PHY_RUNNING:
784
785
786
787 if (phydev->irq == PHY_POLL) {
788 old_link = phydev->link;
789 err = phy_read_status(phydev);
790 if (err)
791 break;
792
793 if (old_link != phydev->link)
794 phydev->state = PHY_CHANGELINK;
795 }
796 break;
797 case PHY_CHANGELINK:
798 err = phy_read_status(phydev);
799 if (err)
800 break;
801
802 if (phydev->link) {
803 phydev->state = PHY_RUNNING;
804 netif_carrier_on(phydev->attached_dev);
805 } else {
806 phydev->state = PHY_NOLINK;
807 netif_carrier_off(phydev->attached_dev);
808 }
809
810 phydev->adjust_link(phydev->attached_dev);
811
812 if (phy_interrupt_is_valid(phydev))
813 err = phy_config_interrupt(phydev,
814 PHY_INTERRUPT_ENABLED);
815 break;
816 case PHY_HALTED:
817 if (phydev->link) {
818 phydev->link = 0;
819 netif_carrier_off(phydev->attached_dev);
820 phydev->adjust_link(phydev->attached_dev);
821 do_suspend = true;
822 }
823 break;
824 case PHY_RESUMING:
825 err = phy_clear_interrupt(phydev);
826 if (err)
827 break;
828
829 err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
830 if (err)
831 break;
832
833 if (AUTONEG_ENABLE == phydev->autoneg) {
834 err = phy_aneg_done(phydev);
835 if (err < 0)
836 break;
837
838
839
840
841 if (err > 0) {
842 err = phy_read_status(phydev);
843 if (err)
844 break;
845
846 if (phydev->link) {
847 phydev->state = PHY_RUNNING;
848 netif_carrier_on(phydev->attached_dev);
849 } else {
850 phydev->state = PHY_NOLINK;
851 }
852 phydev->adjust_link(phydev->attached_dev);
853 } else {
854 phydev->state = PHY_AN;
855 phydev->link_timeout = PHY_AN_TIMEOUT;
856 }
857 } else {
858 err = phy_read_status(phydev);
859 if (err)
860 break;
861
862 if (phydev->link) {
863 phydev->state = PHY_RUNNING;
864 netif_carrier_on(phydev->attached_dev);
865 } else {
866 phydev->state = PHY_NOLINK;
867 }
868 phydev->adjust_link(phydev->attached_dev);
869 }
870 do_resume = true;
871 break;
872 }
873
874 mutex_unlock(&phydev->lock);
875
876 if (needs_aneg)
877 err = phy_start_aneg(phydev);
878 else if (do_suspend)
879 phy_suspend(phydev);
880 else if (do_resume)
881 phy_resume(phydev);
882
883 if (err < 0)
884 phy_error(phydev);
885
886
887
888
889
890 if (phydev->irq == PHY_POLL)
891 queue_delayed_work(system_power_efficient_wq, &phydev->state_queue,
892 PHY_STATE_TIME * HZ);
893}
894
895void phy_mac_interrupt(struct phy_device *phydev, int new_link)
896{
897 phydev->link = new_link;
898
899
900 queue_work(system_power_efficient_wq, &phydev->phy_queue);
901}
902EXPORT_SYMBOL(phy_mac_interrupt);
903
904static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
905 int addr)
906{
907
908 bus->write(bus, addr, MII_MMD_CTRL, devad);
909
910
911 bus->write(bus, addr, MII_MMD_DATA, prtad);
912
913
914 bus->write(bus, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR));
915}
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932static int phy_read_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
933 int addr)
934{
935 mmd_phy_indirect(bus, prtad, devad, addr);
936
937
938 return bus->read(bus, addr, MII_MMD_DATA);
939}
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957static void phy_write_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
958 int addr, u32 data)
959{
960 mmd_phy_indirect(bus, prtad, devad, addr);
961
962
963 bus->write(bus, addr, MII_MMD_DATA, data);
964}
965
966
967
968
969
970
971
972
973
974
975
976int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
977{
978
979
980
981
982 if ((phydev->duplex == DUPLEX_FULL) &&
983 ((phydev->interface == PHY_INTERFACE_MODE_MII) ||
984 (phydev->interface == PHY_INTERFACE_MODE_GMII) ||
985 (phydev->interface == PHY_INTERFACE_MODE_RGMII))) {
986 int eee_lp, eee_cap, eee_adv;
987 u32 lp, cap, adv;
988 int idx, status;
989
990
991 status = phy_read_status(phydev);
992 if (status)
993 return status;
994
995
996 eee_cap = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
997 MDIO_MMD_PCS, phydev->addr);
998 if (eee_cap < 0)
999 return eee_cap;
1000
1001 cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap);
1002 if (!cap)
1003 return -EPROTONOSUPPORT;
1004
1005
1006
1007
1008 eee_lp = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
1009 MDIO_MMD_AN, phydev->addr);
1010 if (eee_lp < 0)
1011 return eee_lp;
1012
1013 eee_adv = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
1014 MDIO_MMD_AN, phydev->addr);
1015 if (eee_adv < 0)
1016 return eee_adv;
1017
1018 adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv);
1019 lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp);
1020 idx = phy_find_setting(phydev->speed, phydev->duplex);
1021 if (!(lp & adv & settings[idx].setting))
1022 return -EPROTONOSUPPORT;
1023
1024 if (clk_stop_enable) {
1025
1026
1027
1028 int val = phy_read_mmd_indirect(phydev->bus, MDIO_CTRL1,
1029 MDIO_MMD_PCS,
1030 phydev->addr);
1031 if (val < 0)
1032 return val;
1033
1034 val |= MDIO_PCS_CTRL1_CLKSTOP_EN;
1035 phy_write_mmd_indirect(phydev->bus, MDIO_CTRL1,
1036 MDIO_MMD_PCS, phydev->addr, val);
1037 }
1038
1039 return 0;
1040 }
1041
1042 return -EPROTONOSUPPORT;
1043}
1044EXPORT_SYMBOL(phy_init_eee);
1045
1046
1047
1048
1049
1050
1051
1052
1053int phy_get_eee_err(struct phy_device *phydev)
1054{
1055 return phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_WK_ERR,
1056 MDIO_MMD_PCS, phydev->addr);
1057}
1058EXPORT_SYMBOL(phy_get_eee_err);
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
1069{
1070 int val;
1071
1072
1073 val = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
1074 MDIO_MMD_PCS, phydev->addr);
1075 if (val < 0)
1076 return val;
1077 data->supported = mmd_eee_cap_to_ethtool_sup_t(val);
1078
1079
1080 val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
1081 MDIO_MMD_AN, phydev->addr);
1082 if (val < 0)
1083 return val;
1084 data->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
1085
1086
1087 val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
1088 MDIO_MMD_AN, phydev->addr);
1089 if (val < 0)
1090 return val;
1091 data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val);
1092
1093 return 0;
1094}
1095EXPORT_SYMBOL(phy_ethtool_get_eee);
1096
1097
1098
1099
1100
1101
1102
1103
1104int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
1105{
1106 int val = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
1107
1108 phy_write_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV, MDIO_MMD_AN,
1109 phydev->addr, val);
1110
1111 return 0;
1112}
1113EXPORT_SYMBOL(phy_ethtool_set_eee);
1114
1115int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
1116{
1117 if (phydev->drv->set_wol)
1118 return phydev->drv->set_wol(phydev, wol);
1119
1120 return -EOPNOTSUPP;
1121}
1122EXPORT_SYMBOL(phy_ethtool_set_wol);
1123
1124void phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
1125{
1126 if (phydev->drv->get_wol)
1127 phydev->drv->get_wol(phydev, wol);
1128}
1129EXPORT_SYMBOL(phy_ethtool_get_wol);
1130