]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/phy/broadcom.c
Add support for SMSC LAN8187 and LAN8700 PHYs
[linux-2.6-omap-h63xx.git] / drivers / net / phy / broadcom.c
index 29666c85ed55936683e4cfc4b7dc0a1f03efb8dd..60c5cfe969186344b4e36021c6efd0fdd468313e 100644 (file)
@@ -99,6 +99,41 @@ static int bcm54xx_config_intr(struct phy_device *phydev)
        return err;
 }
 
+static int bcm5481_config_aneg(struct phy_device *phydev)
+{
+       int ret;
+
+       /* Aneg firsly. */
+       ret = genphy_config_aneg(phydev);
+
+       /* Then we can set up the delay. */
+       if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
+               u16 reg;
+
+               /*
+                * There is no BCM5481 specification available, so down
+                * here is everything we know about "register 0x18". This
+                * at least helps BCM5481 to successfuly receive packets
+                * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
+                * says: "This sets delay between the RXD and RXC signals
+                * instead of using trace lengths to achieve timing".
+                */
+
+               /* Set RDX clk delay. */
+               reg = 0x7 | (0x7 << 12);
+               phy_write(phydev, 0x18, reg);
+
+               reg = phy_read(phydev, 0x18);
+               /* Set RDX-RXC skew. */
+               reg |= (1 << 8);
+               /* Write bits 14:0. */
+               reg |= (1 << 15);
+               phy_write(phydev, 0x18, reg);
+       }
+
+       return ret;
+}
+
 static struct phy_driver bcm5411_driver = {
        .phy_id         = 0x00206070,
        .phy_id_mask    = 0xfffffff0,
@@ -141,6 +176,48 @@ static struct phy_driver bcm5461_driver = {
        .driver         = { .owner = THIS_MODULE },
 };
 
+static struct phy_driver bcm5464_driver = {
+       .phy_id         = 0x002060b0,
+       .phy_id_mask    = 0xfffffff0,
+       .name           = "Broadcom BCM5464",
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+       .config_init    = bcm54xx_config_init,
+       .config_aneg    = genphy_config_aneg,
+       .read_status    = genphy_read_status,
+       .ack_interrupt  = bcm54xx_ack_interrupt,
+       .config_intr    = bcm54xx_config_intr,
+       .driver         = { .owner = THIS_MODULE },
+};
+
+static struct phy_driver bcm5481_driver = {
+       .phy_id         = 0x0143bca0,
+       .phy_id_mask    = 0xfffffff0,
+       .name           = "Broadcom BCM5481",
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+       .config_init    = bcm54xx_config_init,
+       .config_aneg    = bcm5481_config_aneg,
+       .read_status    = genphy_read_status,
+       .ack_interrupt  = bcm54xx_ack_interrupt,
+       .config_intr    = bcm54xx_config_intr,
+       .driver         = { .owner = THIS_MODULE },
+};
+
+static struct phy_driver bcm5482_driver = {
+       .phy_id         = 0x0143bcb0,
+       .phy_id_mask    = 0xfffffff0,
+       .name           = "Broadcom BCM5482",
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+       .config_init    = bcm54xx_config_init,
+       .config_aneg    = genphy_config_aneg,
+       .read_status    = genphy_read_status,
+       .ack_interrupt  = bcm54xx_ack_interrupt,
+       .config_intr    = bcm54xx_config_intr,
+       .driver         = { .owner = THIS_MODULE },
+};
+
 static int __init broadcom_init(void)
 {
        int ret;
@@ -154,8 +231,23 @@ static int __init broadcom_init(void)
        ret = phy_driver_register(&bcm5461_driver);
        if (ret)
                goto out_5461;
+       ret = phy_driver_register(&bcm5464_driver);
+       if (ret)
+               goto out_5464;
+       ret = phy_driver_register(&bcm5481_driver);
+       if (ret)
+               goto out_5481;
+       ret = phy_driver_register(&bcm5482_driver);
+       if (ret)
+               goto out_5482;
        return ret;
 
+out_5482:
+       phy_driver_unregister(&bcm5481_driver);
+out_5481:
+       phy_driver_unregister(&bcm5464_driver);
+out_5464:
+       phy_driver_unregister(&bcm5461_driver);
 out_5461:
        phy_driver_unregister(&bcm5421_driver);
 out_5421:
@@ -166,6 +258,9 @@ out_5411:
 
 static void __exit broadcom_exit(void)
 {
+       phy_driver_unregister(&bcm5482_driver);
+       phy_driver_unregister(&bcm5481_driver);
+       phy_driver_unregister(&bcm5464_driver);
        phy_driver_unregister(&bcm5461_driver);
        phy_driver_unregister(&bcm5421_driver);
        phy_driver_unregister(&bcm5411_driver);