aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/phy.c')
-rw-r--r--drivers/net/phy/phy.c197
1 files changed, 11 insertions, 186 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 934065dd6371..d3e43631b89b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -40,21 +40,9 @@
40#include <asm/uaccess.h> 40#include <asm/uaccess.h>
41 41
42static void phy_timer(unsigned long data); 42static void phy_timer(unsigned long data);
43 43static int phy_disable_interrupts(struct phy_device *phydev);
44/* Convenience function to print out the current phy status 44static void phy_sanitize_settings(struct phy_device *phydev);
45 */ 45static int phy_stop_interrupts(struct phy_device *phydev);
46void phy_print_status(struct phy_device *phydev)
47{
48 pr_info("%s: Link is %s", phydev->dev.bus_id,
49 phydev->link ? "Up" : "Down");
50 if (phydev->link)
51 printk(" - %d/%s", phydev->speed,
52 DUPLEX_FULL == phydev->duplex ?
53 "Full" : "Half");
54
55 printk("\n");
56}
57EXPORT_SYMBOL(phy_print_status);
58 46
59 47
60/* Convenience functions for reading/writing a given PHY 48/* Convenience functions for reading/writing a given PHY
@@ -133,7 +121,7 @@ static inline int phy_aneg_done(struct phy_device *phydev)
133 * and to PHY_FORCING if auto-negotiation is disabled. Unless 121 * and to PHY_FORCING if auto-negotiation is disabled. Unless
134 * the PHY is currently HALTED. 122 * the PHY is currently HALTED.
135 */ 123 */
136int phy_start_aneg(struct phy_device *phydev) 124static int phy_start_aneg(struct phy_device *phydev)
137{ 125{
138 int err; 126 int err;
139 127
@@ -161,8 +149,6 @@ out_unlock:
161 spin_unlock(&phydev->lock); 149 spin_unlock(&phydev->lock);
162 return err; 150 return err;
163} 151}
164EXPORT_SYMBOL(phy_start_aneg);
165
166 152
167/* A structure for mapping a particular speed and duplex 153/* A structure for mapping a particular speed and duplex
168 * combination to a particular SUPPORTED and ADVERTISED value */ 154 * combination to a particular SUPPORTED and ADVERTISED value */
@@ -255,7 +241,7 @@ static inline int phy_find_valid(int idx, u32 features)
255 * duplexes. Drop down by one in this order: 1000/FULL, 241 * duplexes. Drop down by one in this order: 1000/FULL,
256 * 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF 242 * 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF
257 */ 243 */
258void phy_sanitize_settings(struct phy_device *phydev) 244static void phy_sanitize_settings(struct phy_device *phydev)
259{ 245{
260 u32 features = phydev->supported; 246 u32 features = phydev->supported;
261 int idx; 247 int idx;
@@ -270,7 +256,6 @@ void phy_sanitize_settings(struct phy_device *phydev)
270 phydev->speed = settings[idx].speed; 256 phydev->speed = settings[idx].speed;
271 phydev->duplex = settings[idx].duplex; 257 phydev->duplex = settings[idx].duplex;
272} 258}
273EXPORT_SYMBOL(phy_sanitize_settings);
274 259
275/* phy_force_reduction 260/* phy_force_reduction
276 * 261 *
@@ -477,48 +462,22 @@ void phy_error(struct phy_device *phydev)
477 spin_unlock(&phydev->lock); 462 spin_unlock(&phydev->lock);
478} 463}
479 464
480#ifdef CONFIG_PHYCONTROL 465static int phy_stop_interrupts(struct phy_device *phydev)
481
482static void phy_change(void *data);
483
484/* phy_interrupt
485 *
486 * description: When a PHY interrupt occurs, the handler disables
487 * interrupts, and schedules a work task to clear the interrupt.
488 */
489static irqreturn_t phy_interrupt(int irq, void *phy_dat, struct pt_regs *regs)
490{
491 struct phy_device *phydev = phy_dat;
492
493 /* The MDIO bus is not allowed to be written in interrupt
494 * context, so we need to disable the irq here. A work
495 * queue will write the PHY to disable and clear the
496 * interrupt, and then reenable the irq line. */
497 disable_irq_nosync(irq);
498
499 schedule_work(&phydev->phy_queue);
500
501 return IRQ_HANDLED;
502}
503
504/* Enable the interrupts from the PHY side */
505int phy_enable_interrupts(struct phy_device *phydev)
506{ 466{
507 int err; 467 int err;
508 468
509 err = phy_clear_interrupt(phydev); 469 err = phy_disable_interrupts(phydev);
510 470
511 if (err < 0) 471 if (err)
512 return err; 472 phy_error(phydev);
513 473
514 err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED); 474 free_irq(phydev->irq, phydev);
515 475
516 return err; 476 return err;
517} 477}
518EXPORT_SYMBOL(phy_enable_interrupts);
519 478
520/* Disable the PHY interrupts from the PHY side */ 479/* Disable the PHY interrupts from the PHY side */
521int phy_disable_interrupts(struct phy_device *phydev) 480static int phy_disable_interrupts(struct phy_device *phydev)
522{ 481{
523 int err; 482 int err;
524 483
@@ -541,140 +500,6 @@ phy_err:
541 500
542 return err; 501 return err;
543} 502}
544EXPORT_SYMBOL(phy_disable_interrupts);
545
546/* phy_start_interrupts
547 *
548 * description: Request the interrupt for the given PHY. If
549 * this fails, then we set irq to PHY_POLL.
550 * Otherwise, we enable the interrupts in the PHY.
551 * Returns 0 on success.
552 * This should only be called with a valid IRQ number.
553 */
554int phy_start_interrupts(struct phy_device *phydev)
555{
556 int err = 0;
557
558 INIT_WORK(&phydev->phy_queue, phy_change, phydev);
559
560 if (request_irq(phydev->irq, phy_interrupt,
561 SA_SHIRQ,
562 "phy_interrupt",
563 phydev) < 0) {
564 printk(KERN_WARNING "%s: Can't get IRQ %d (PHY)\n",
565 phydev->bus->name,
566 phydev->irq);
567 phydev->irq = PHY_POLL;
568 return 0;
569 }
570
571 err = phy_enable_interrupts(phydev);
572
573 return err;
574}
575EXPORT_SYMBOL(phy_start_interrupts);
576
577int phy_stop_interrupts(struct phy_device *phydev)
578{
579 int err;
580
581 err = phy_disable_interrupts(phydev);
582
583 if (err)
584 phy_error(phydev);
585
586 free_irq(phydev->irq, phydev);
587
588 return err;
589}
590EXPORT_SYMBOL(phy_stop_interrupts);
591
592
593/* Scheduled by the phy_interrupt/timer to handle PHY changes */
594static void phy_change(void *data)
595{
596 int err;
597 struct phy_device *phydev = data;
598
599 err = phy_disable_interrupts(phydev);
600
601 if (err)
602 goto phy_err;
603
604 spin_lock(&phydev->lock);
605 if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
606 phydev->state = PHY_CHANGELINK;
607 spin_unlock(&phydev->lock);
608
609 enable_irq(phydev->irq);
610
611 /* Reenable interrupts */
612 err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
613
614 if (err)
615 goto irq_enable_err;
616
617 return;
618
619irq_enable_err:
620 disable_irq(phydev->irq);
621phy_err:
622 phy_error(phydev);
623}
624
625/* Bring down the PHY link, and stop checking the status. */
626void phy_stop(struct phy_device *phydev)
627{
628 spin_lock(&phydev->lock);
629
630 if (PHY_HALTED == phydev->state)
631 goto out_unlock;
632
633 if (phydev->irq != PHY_POLL) {
634 /* Clear any pending interrupts */
635 phy_clear_interrupt(phydev);
636
637 /* Disable PHY Interrupts */
638 phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
639 }
640
641 phydev->state = PHY_HALTED;
642
643out_unlock:
644 spin_unlock(&phydev->lock);
645}
646
647
648/* phy_start
649 *
650 * description: Indicates the attached device's readiness to
651 * handle PHY-related work. Used during startup to start the
652 * PHY, and after a call to phy_stop() to resume operation.
653 * Also used to indicate the MDIO bus has cleared an error
654 * condition.
655 */
656void phy_start(struct phy_device *phydev)
657{
658 spin_lock(&phydev->lock);
659
660 switch (phydev->state) {
661 case PHY_STARTING:
662 phydev->state = PHY_PENDING;
663 break;
664 case PHY_READY:
665 phydev->state = PHY_UP;
666 break;
667 case PHY_HALTED:
668 phydev->state = PHY_RESUMING;
669 default:
670 break;
671 }
672 spin_unlock(&phydev->lock);
673}
674EXPORT_SYMBOL(phy_stop);
675EXPORT_SYMBOL(phy_start);
676
677#endif /* CONFIG_PHYCONTROL */
678 503
679/* PHY timer which handles the state machine */ 504/* PHY timer which handles the state machine */
680static void phy_timer(unsigned long data) 505static void phy_timer(unsigned long data)