diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2009-08-25 06:10:58 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-26 18:48:05 -0400 |
commit | d7a2ed9248a3c3ec6afe3be0c351bd1ca9e981f3 (patch) | |
tree | ed0ffe22e8a4651862710f421b61deba96b040c8 /drivers/net/phy/broadcom.c | |
parent | 4f4598fd0a87f39955e71bcb7447f403dafc20ba (diff) |
broadcom: Add AC131 phy support
This patch adds support for the AC131 fast ethernet transceiver.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy/broadcom.c')
-rw-r--r-- | drivers/net/phy/broadcom.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index dec4dec23b66..3262a2474b07 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c | |||
@@ -142,6 +142,35 @@ | |||
142 | #define PHY_BCM_FLAGS_MODE_1000BX 0x00000002 | 142 | #define PHY_BCM_FLAGS_MODE_1000BX 0x00000002 |
143 | #define PHY_BCM_FLAGS_MODE_COPPER 0x00000001 | 143 | #define PHY_BCM_FLAGS_MODE_COPPER 0x00000001 |
144 | 144 | ||
145 | |||
146 | /*****************************************************************************/ | ||
147 | /* Fast Ethernet Transceiver definitions. */ | ||
148 | /*****************************************************************************/ | ||
149 | |||
150 | #define MII_BRCM_FET_INTREG 0x1a /* Interrupt register */ | ||
151 | #define MII_BRCM_FET_IR_MASK 0x0100 /* Mask all interrupts */ | ||
152 | #define MII_BRCM_FET_IR_LINK_EN 0x0200 /* Link status change enable */ | ||
153 | #define MII_BRCM_FET_IR_SPEED_EN 0x0400 /* Link speed change enable */ | ||
154 | #define MII_BRCM_FET_IR_DUPLEX_EN 0x0800 /* Duplex mode change enable */ | ||
155 | #define MII_BRCM_FET_IR_ENABLE 0x4000 /* Interrupt enable */ | ||
156 | |||
157 | #define MII_BRCM_FET_BRCMTEST 0x1f /* Brcm test register */ | ||
158 | #define MII_BRCM_FET_BT_SRE 0x0080 /* Shadow register enable */ | ||
159 | |||
160 | |||
161 | /*** Shadow register definitions ***/ | ||
162 | |||
163 | #define MII_BRCM_FET_SHDW_MISCCTRL 0x10 /* Shadow misc ctrl */ | ||
164 | #define MII_BRCM_FET_SHDW_MC_FAME 0x4000 /* Force Auto MDIX enable */ | ||
165 | |||
166 | #define MII_BRCM_FET_SHDW_AUXMODE4 0x1a /* Auxiliary mode 4 */ | ||
167 | #define MII_BRCM_FET_SHDW_AM4_LED_MASK 0x0003 | ||
168 | #define MII_BRCM_FET_SHDW_AM4_LED_MODE1 0x0001 | ||
169 | |||
170 | #define MII_BRCM_FET_SHDW_AUXSTAT2 0x1b /* Auxiliary status 2 */ | ||
171 | #define MII_BRCM_FET_SHDW_AS2_APDE 0x0020 /* Auto power down enable */ | ||
172 | |||
173 | |||
145 | MODULE_DESCRIPTION("Broadcom PHY driver"); | 174 | MODULE_DESCRIPTION("Broadcom PHY driver"); |
146 | MODULE_AUTHOR("Maciej W. Rozycki"); | 175 | MODULE_AUTHOR("Maciej W. Rozycki"); |
147 | MODULE_LICENSE("GPL"); | 176 | MODULE_LICENSE("GPL"); |
@@ -436,6 +465,114 @@ static int bcm5481_config_aneg(struct phy_device *phydev) | |||
436 | return ret; | 465 | return ret; |
437 | } | 466 | } |
438 | 467 | ||
468 | static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set) | ||
469 | { | ||
470 | int val; | ||
471 | |||
472 | val = phy_read(phydev, reg); | ||
473 | if (val < 0) | ||
474 | return val; | ||
475 | |||
476 | return phy_write(phydev, reg, val | set); | ||
477 | } | ||
478 | |||
479 | static int brcm_fet_config_init(struct phy_device *phydev) | ||
480 | { | ||
481 | int reg, err, err2, brcmtest; | ||
482 | |||
483 | /* Reset the PHY to bring it to a known state. */ | ||
484 | err = phy_write(phydev, MII_BMCR, BMCR_RESET); | ||
485 | if (err < 0) | ||
486 | return err; | ||
487 | |||
488 | reg = phy_read(phydev, MII_BRCM_FET_INTREG); | ||
489 | if (reg < 0) | ||
490 | return reg; | ||
491 | |||
492 | /* Unmask events we are interested in and mask interrupts globally. */ | ||
493 | reg = MII_BRCM_FET_IR_DUPLEX_EN | | ||
494 | MII_BRCM_FET_IR_SPEED_EN | | ||
495 | MII_BRCM_FET_IR_LINK_EN | | ||
496 | MII_BRCM_FET_IR_ENABLE | | ||
497 | MII_BRCM_FET_IR_MASK; | ||
498 | |||
499 | err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); | ||
500 | if (err < 0) | ||
501 | return err; | ||
502 | |||
503 | /* Enable shadow register access */ | ||
504 | brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST); | ||
505 | if (brcmtest < 0) | ||
506 | return brcmtest; | ||
507 | |||
508 | reg = brcmtest | MII_BRCM_FET_BT_SRE; | ||
509 | |||
510 | err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg); | ||
511 | if (err < 0) | ||
512 | return err; | ||
513 | |||
514 | /* Set the LED mode */ | ||
515 | reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4); | ||
516 | if (reg < 0) { | ||
517 | err = reg; | ||
518 | goto done; | ||
519 | } | ||
520 | |||
521 | reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK; | ||
522 | reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1; | ||
523 | |||
524 | err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg); | ||
525 | if (err < 0) | ||
526 | goto done; | ||
527 | |||
528 | /* Enable auto MDIX */ | ||
529 | err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL, | ||
530 | MII_BRCM_FET_SHDW_MC_FAME); | ||
531 | if (err < 0) | ||
532 | goto done; | ||
533 | |||
534 | /* Enable auto power down */ | ||
535 | err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2, | ||
536 | MII_BRCM_FET_SHDW_AS2_APDE); | ||
537 | |||
538 | done: | ||
539 | /* Disable shadow register access */ | ||
540 | err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest); | ||
541 | if (!err) | ||
542 | err = err2; | ||
543 | |||
544 | return err; | ||
545 | } | ||
546 | |||
547 | static int brcm_fet_ack_interrupt(struct phy_device *phydev) | ||
548 | { | ||
549 | int reg; | ||
550 | |||
551 | /* Clear pending interrupts. */ | ||
552 | reg = phy_read(phydev, MII_BRCM_FET_INTREG); | ||
553 | if (reg < 0) | ||
554 | return reg; | ||
555 | |||
556 | return 0; | ||
557 | } | ||
558 | |||
559 | static int brcm_fet_config_intr(struct phy_device *phydev) | ||
560 | { | ||
561 | int reg, err; | ||
562 | |||
563 | reg = phy_read(phydev, MII_BRCM_FET_INTREG); | ||
564 | if (reg < 0) | ||
565 | return reg; | ||
566 | |||
567 | if (phydev->interrupts == PHY_INTERRUPT_ENABLED) | ||
568 | reg &= ~MII_BRCM_FET_IR_MASK; | ||
569 | else | ||
570 | reg |= MII_BRCM_FET_IR_MASK; | ||
571 | |||
572 | err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); | ||
573 | return err; | ||
574 | } | ||
575 | |||
439 | static struct phy_driver bcm5411_driver = { | 576 | static struct phy_driver bcm5411_driver = { |
440 | .phy_id = 0x00206070, | 577 | .phy_id = 0x00206070, |
441 | .phy_id_mask = 0xfffffff0, | 578 | .phy_id_mask = 0xfffffff0, |
@@ -571,6 +708,21 @@ static struct phy_driver bcm57780_driver = { | |||
571 | .driver = { .owner = THIS_MODULE }, | 708 | .driver = { .owner = THIS_MODULE }, |
572 | }; | 709 | }; |
573 | 710 | ||
711 | static struct phy_driver bcmac131_driver = { | ||
712 | .phy_id = 0x0143bc70, | ||
713 | .phy_id_mask = 0xfffffff0, | ||
714 | .name = "Broadcom BCMAC131", | ||
715 | .features = PHY_BASIC_FEATURES | | ||
716 | SUPPORTED_Pause | SUPPORTED_Asym_Pause, | ||
717 | .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, | ||
718 | .config_init = brcm_fet_config_init, | ||
719 | .config_aneg = genphy_config_aneg, | ||
720 | .read_status = genphy_read_status, | ||
721 | .ack_interrupt = brcm_fet_ack_interrupt, | ||
722 | .config_intr = brcm_fet_config_intr, | ||
723 | .driver = { .owner = THIS_MODULE }, | ||
724 | }; | ||
725 | |||
574 | static int __init broadcom_init(void) | 726 | static int __init broadcom_init(void) |
575 | { | 727 | { |
576 | int ret; | 728 | int ret; |
@@ -602,8 +754,13 @@ static int __init broadcom_init(void) | |||
602 | ret = phy_driver_register(&bcm57780_driver); | 754 | ret = phy_driver_register(&bcm57780_driver); |
603 | if (ret) | 755 | if (ret) |
604 | goto out_57780; | 756 | goto out_57780; |
757 | ret = phy_driver_register(&bcmac131_driver); | ||
758 | if (ret) | ||
759 | goto out_ac131; | ||
605 | return ret; | 760 | return ret; |
606 | 761 | ||
762 | out_ac131: | ||
763 | phy_driver_unregister(&bcm57780_driver); | ||
607 | out_57780: | 764 | out_57780: |
608 | phy_driver_unregister(&bcm50610m_driver); | 765 | phy_driver_unregister(&bcm50610m_driver); |
609 | out_50610m: | 766 | out_50610m: |
@@ -626,6 +783,7 @@ out_5411: | |||
626 | 783 | ||
627 | static void __exit broadcom_exit(void) | 784 | static void __exit broadcom_exit(void) |
628 | { | 785 | { |
786 | phy_driver_unregister(&bcmac131_driver); | ||
629 | phy_driver_unregister(&bcm57780_driver); | 787 | phy_driver_unregister(&bcm57780_driver); |
630 | phy_driver_unregister(&bcm50610m_driver); | 788 | phy_driver_unregister(&bcm50610m_driver); |
631 | phy_driver_unregister(&bcm50610_driver); | 789 | phy_driver_unregister(&bcm50610_driver); |