diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2008-05-29 04:37:54 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-05-29 04:37:54 -0400 |
commit | 158d7abdae85e9ac43d99780c372d79c119f7626 (patch) | |
tree | 8cca893ab0ab854217249ddeea49b1280ee0361a /drivers | |
parent | dd47700310ff929b439223105364c9ee3db81511 (diff) |
tg3: Add mdio bus registration
This patch introduces code to register and unregister the tg3 mdio bus
with the system.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Benjamin Li <benli@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/tg3.c | 128 | ||||
-rw-r--r-- | drivers/net/tg3.h | 5 |
3 files changed, 127 insertions, 7 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9f6cc8a56073..78cc9495fd46 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -2228,6 +2228,7 @@ config VIA_VELOCITY | |||
2228 | config TIGON3 | 2228 | config TIGON3 |
2229 | tristate "Broadcom Tigon3 support" | 2229 | tristate "Broadcom Tigon3 support" |
2230 | depends on PCI | 2230 | depends on PCI |
2231 | select PHYLIB | ||
2231 | help | 2232 | help |
2232 | This driver supports Broadcom Tigon3 based gigabit Ethernet cards. | 2233 | This driver supports Broadcom Tigon3 based gigabit Ethernet cards. |
2233 | 2234 | ||
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 538232586ee5..ce04c64a8a6e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/skbuff.h> | 32 | #include <linux/skbuff.h> |
33 | #include <linux/ethtool.h> | 33 | #include <linux/ethtool.h> |
34 | #include <linux/mii.h> | 34 | #include <linux/mii.h> |
35 | #include <linux/phy.h> | ||
35 | #include <linux/if_vlan.h> | 36 | #include <linux/if_vlan.h> |
36 | #include <linux/ip.h> | 37 | #include <linux/ip.h> |
37 | #include <linux/tcp.h> | 38 | #include <linux/tcp.h> |
@@ -835,6 +836,115 @@ static int tg3_bmcr_reset(struct tg3 *tp) | |||
835 | return 0; | 836 | return 0; |
836 | } | 837 | } |
837 | 838 | ||
839 | static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg) | ||
840 | { | ||
841 | struct tg3 *tp = (struct tg3 *)bp->priv; | ||
842 | u32 val; | ||
843 | |||
844 | if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED) | ||
845 | return -EAGAIN; | ||
846 | |||
847 | if (tg3_readphy(tp, reg, &val)) | ||
848 | return -EIO; | ||
849 | |||
850 | return val; | ||
851 | } | ||
852 | |||
853 | static int tg3_mdio_write(struct mii_bus *bp, int mii_id, int reg, u16 val) | ||
854 | { | ||
855 | struct tg3 *tp = (struct tg3 *)bp->priv; | ||
856 | |||
857 | if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED) | ||
858 | return -EAGAIN; | ||
859 | |||
860 | if (tg3_writephy(tp, reg, val)) | ||
861 | return -EIO; | ||
862 | |||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | static int tg3_mdio_reset(struct mii_bus *bp) | ||
867 | { | ||
868 | return 0; | ||
869 | } | ||
870 | |||
871 | static void tg3_mdio_start(struct tg3 *tp) | ||
872 | { | ||
873 | if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) { | ||
874 | mutex_lock(&tp->mdio_bus.mdio_lock); | ||
875 | tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED; | ||
876 | mutex_unlock(&tp->mdio_bus.mdio_lock); | ||
877 | } | ||
878 | |||
879 | tp->mi_mode &= ~MAC_MI_MODE_AUTO_POLL; | ||
880 | tw32_f(MAC_MI_MODE, tp->mi_mode); | ||
881 | udelay(80); | ||
882 | } | ||
883 | |||
884 | static void tg3_mdio_stop(struct tg3 *tp) | ||
885 | { | ||
886 | if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) { | ||
887 | mutex_lock(&tp->mdio_bus.mdio_lock); | ||
888 | tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_PAUSED; | ||
889 | mutex_unlock(&tp->mdio_bus.mdio_lock); | ||
890 | } | ||
891 | } | ||
892 | |||
893 | static int tg3_mdio_init(struct tg3 *tp) | ||
894 | { | ||
895 | int i; | ||
896 | u32 reg; | ||
897 | struct mii_bus *mdio_bus = &tp->mdio_bus; | ||
898 | |||
899 | tg3_mdio_start(tp); | ||
900 | |||
901 | if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) || | ||
902 | (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED)) | ||
903 | return 0; | ||
904 | |||
905 | memset(mdio_bus, 0, sizeof(*mdio_bus)); | ||
906 | |||
907 | mdio_bus->name = "tg3 mdio bus"; | ||
908 | snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%x", | ||
909 | (tp->pdev->bus->number << 8) | tp->pdev->devfn); | ||
910 | mdio_bus->priv = tp; | ||
911 | mdio_bus->dev = &tp->pdev->dev; | ||
912 | mdio_bus->read = &tg3_mdio_read; | ||
913 | mdio_bus->write = &tg3_mdio_write; | ||
914 | mdio_bus->reset = &tg3_mdio_reset; | ||
915 | mdio_bus->phy_mask = ~(1 << PHY_ADDR); | ||
916 | mdio_bus->irq = &tp->mdio_irq[0]; | ||
917 | |||
918 | for (i = 0; i < PHY_MAX_ADDR; i++) | ||
919 | mdio_bus->irq[i] = PHY_POLL; | ||
920 | |||
921 | /* The bus registration will look for all the PHYs on the mdio bus. | ||
922 | * Unfortunately, it does not ensure the PHY is powered up before | ||
923 | * accessing the PHY ID registers. A chip reset is the | ||
924 | * quickest way to bring the device back to an operational state.. | ||
925 | */ | ||
926 | if (tg3_readphy(tp, MII_BMCR, ®) || (reg & BMCR_PDOWN)) | ||
927 | tg3_bmcr_reset(tp); | ||
928 | |||
929 | i = mdiobus_register(mdio_bus); | ||
930 | if (!i) | ||
931 | tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED; | ||
932 | else | ||
933 | printk(KERN_WARNING "%s: mdiobus_reg failed (0x%x)\n", | ||
934 | tp->dev->name, i); | ||
935 | |||
936 | return i; | ||
937 | } | ||
938 | |||
939 | static void tg3_mdio_fini(struct tg3 *tp) | ||
940 | { | ||
941 | if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) { | ||
942 | tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_INITED; | ||
943 | mdiobus_unregister(&tp->mdio_bus); | ||
944 | tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED; | ||
945 | } | ||
946 | } | ||
947 | |||
838 | /* tp->lock is held. */ | 948 | /* tp->lock is held. */ |
839 | static void tg3_wait_for_event_ack(struct tg3 *tp) | 949 | static void tg3_wait_for_event_ack(struct tg3 *tp) |
840 | { | 950 | { |
@@ -5386,6 +5496,8 @@ static int tg3_chip_reset(struct tg3 *tp) | |||
5386 | 5496 | ||
5387 | tg3_nvram_lock(tp); | 5497 | tg3_nvram_lock(tp); |
5388 | 5498 | ||
5499 | tg3_mdio_stop(tp); | ||
5500 | |||
5389 | /* No matching tg3_nvram_unlock() after this because | 5501 | /* No matching tg3_nvram_unlock() after this because |
5390 | * chip reset below will undo the nvram lock. | 5502 | * chip reset below will undo the nvram lock. |
5391 | */ | 5503 | */ |
@@ -5537,6 +5649,8 @@ static int tg3_chip_reset(struct tg3 *tp) | |||
5537 | tw32_f(MAC_MODE, 0); | 5649 | tw32_f(MAC_MODE, 0); |
5538 | udelay(40); | 5650 | udelay(40); |
5539 | 5651 | ||
5652 | tg3_mdio_start(tp); | ||
5653 | |||
5540 | err = tg3_poll_fw(tp); | 5654 | err = tg3_poll_fw(tp); |
5541 | if (err) | 5655 | if (err) |
5542 | return err; | 5656 | return err; |
@@ -7168,10 +7282,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) | |||
7168 | tw32_f(MAC_RX_MODE, tp->rx_mode); | 7282 | tw32_f(MAC_RX_MODE, tp->rx_mode); |
7169 | udelay(10); | 7283 | udelay(10); |
7170 | 7284 | ||
7171 | tp->mi_mode &= ~MAC_MI_MODE_AUTO_POLL; | ||
7172 | tw32_f(MAC_MI_MODE, tp->mi_mode); | ||
7173 | udelay(80); | ||
7174 | |||
7175 | tw32(MAC_LED_CTRL, tp->led_ctrl); | 7285 | tw32(MAC_LED_CTRL, tp->led_ctrl); |
7176 | 7286 | ||
7177 | tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); | 7287 | tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); |
@@ -11850,9 +11960,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
11850 | GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX) | 11960 | GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX) |
11851 | tp->coalesce_mode |= HOSTCC_MODE_32BYTE; | 11961 | tp->coalesce_mode |= HOSTCC_MODE_32BYTE; |
11852 | 11962 | ||
11853 | /* Initialize MAC MI mode, polling disabled. */ | 11963 | err = tg3_mdio_init(tp); |
11854 | tw32_f(MAC_MI_MODE, tp->mi_mode); | 11964 | if (err) |
11855 | udelay(80); | 11965 | return err; |
11856 | 11966 | ||
11857 | /* Initialize data/descriptor byte/word swapping. */ | 11967 | /* Initialize data/descriptor byte/word swapping. */ |
11858 | val = tr32(GRC_MODE); | 11968 | val = tr32(GRC_MODE); |
@@ -13052,6 +13162,10 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) | |||
13052 | struct tg3 *tp = netdev_priv(dev); | 13162 | struct tg3 *tp = netdev_priv(dev); |
13053 | 13163 | ||
13054 | flush_scheduled_work(); | 13164 | flush_scheduled_work(); |
13165 | |||
13166 | if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) | ||
13167 | tg3_mdio_fini(tp); | ||
13168 | |||
13055 | unregister_netdev(dev); | 13169 | unregister_netdev(dev); |
13056 | if (tp->aperegs) { | 13170 | if (tp->aperegs) { |
13057 | iounmap(tp->aperegs); | 13171 | iounmap(tp->aperegs); |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index a3598ed9f5fc..e0914fdaf274 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -2481,6 +2481,8 @@ struct tg3 { | |||
2481 | #define TG3_FLG3_5761_5784_AX_FIXES 0x00000004 | 2481 | #define TG3_FLG3_5761_5784_AX_FIXES 0x00000004 |
2482 | #define TG3_FLG3_5701_DMA_BUG 0x00000008 | 2482 | #define TG3_FLG3_5701_DMA_BUG 0x00000008 |
2483 | #define TG3_FLG3_USE_PHYLIB 0x00000010 | 2483 | #define TG3_FLG3_USE_PHYLIB 0x00000010 |
2484 | #define TG3_FLG3_MDIOBUS_INITED 0x00000020 | ||
2485 | #define TG3_FLG3_MDIOBUS_PAUSED 0x00000040 | ||
2484 | 2486 | ||
2485 | struct timer_list timer; | 2487 | struct timer_list timer; |
2486 | u16 timer_counter; | 2488 | u16 timer_counter; |
@@ -2521,6 +2523,9 @@ struct tg3 { | |||
2521 | int msi_cap; | 2523 | int msi_cap; |
2522 | int pcix_cap; | 2524 | int pcix_cap; |
2523 | 2525 | ||
2526 | struct mii_bus mdio_bus; | ||
2527 | int mdio_irq[PHY_MAX_ADDR]; | ||
2528 | |||
2524 | /* PHY info */ | 2529 | /* PHY info */ |
2525 | u32 phy_id; | 2530 | u32 phy_id; |
2526 | #define PHY_ID_MASK 0xfffffff0 | 2531 | #define PHY_ID_MASK 0xfffffff0 |