aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2009-08-25 06:10:58 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-26 18:48:05 -0400
commitd7a2ed9248a3c3ec6afe3be0c351bd1ca9e981f3 (patch)
treeed0ffe22e8a4651862710f421b61deba96b040c8 /drivers
parent4f4598fd0a87f39955e71bcb7447f403dafc20ba (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')
-rw-r--r--drivers/net/phy/broadcom.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index dec4dec23b6..3262a2474b0 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
145MODULE_DESCRIPTION("Broadcom PHY driver"); 174MODULE_DESCRIPTION("Broadcom PHY driver");
146MODULE_AUTHOR("Maciej W. Rozycki"); 175MODULE_AUTHOR("Maciej W. Rozycki");
147MODULE_LICENSE("GPL"); 176MODULE_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
468static 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
479static 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
538done:
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
547static 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
559static 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
439static struct phy_driver bcm5411_driver = { 576static 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
711static 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
574static int __init broadcom_init(void) 726static 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
762out_ac131:
763 phy_driver_unregister(&bcm57780_driver);
607out_57780: 764out_57780:
608 phy_driver_unregister(&bcm50610m_driver); 765 phy_driver_unregister(&bcm50610m_driver);
609out_50610m: 766out_50610m:
@@ -626,6 +783,7 @@ out_5411:
626 783
627static void __exit broadcom_exit(void) 784static 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);