diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2009-04-25 08:53:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-04-27 05:53:48 -0400 |
commit | fe192a49118f5b1272317d60c7930ece4e13ae49 (patch) | |
tree | 9bafb44af6a43861ec7b906c897ac9f4570124a0 | |
parent | 324931ba21858c34787dee7d222388ef3fb41ee0 (diff) |
net: Rework gianfar driver to use of_mdio infrastructure.
This patch simplifies the driver by making use of more common code.
Tested on Freescale MPC8349emitxgp eval board
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/gianfar.c | 109 | ||||
-rw-r--r-- | drivers/net/gianfar.h | 4 |
2 files changed, 39 insertions, 74 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index b2c49679bba7..dae14373296a 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -75,6 +75,7 @@ | |||
75 | #include <linux/if_vlan.h> | 75 | #include <linux/if_vlan.h> |
76 | #include <linux/spinlock.h> | 76 | #include <linux/spinlock.h> |
77 | #include <linux/mm.h> | 77 | #include <linux/mm.h> |
78 | #include <linux/of_mdio.h> | ||
78 | #include <linux/of_platform.h> | 79 | #include <linux/of_platform.h> |
79 | #include <linux/ip.h> | 80 | #include <linux/ip.h> |
80 | #include <linux/tcp.h> | 81 | #include <linux/tcp.h> |
@@ -168,17 +169,13 @@ static inline int gfar_uses_fcb(struct gfar_private *priv) | |||
168 | 169 | ||
169 | static int gfar_of_init(struct net_device *dev) | 170 | static int gfar_of_init(struct net_device *dev) |
170 | { | 171 | { |
171 | struct device_node *phy, *mdio; | ||
172 | const unsigned int *id; | ||
173 | const char *model; | 172 | const char *model; |
174 | const char *ctype; | 173 | const char *ctype; |
175 | const void *mac_addr; | 174 | const void *mac_addr; |
176 | const phandle *ph; | ||
177 | u64 addr, size; | 175 | u64 addr, size; |
178 | int err = 0; | 176 | int err = 0; |
179 | struct gfar_private *priv = netdev_priv(dev); | 177 | struct gfar_private *priv = netdev_priv(dev); |
180 | struct device_node *np = priv->node; | 178 | struct device_node *np = priv->node; |
181 | char bus_name[MII_BUS_ID_SIZE]; | ||
182 | const u32 *stash; | 179 | const u32 *stash; |
183 | const u32 *stash_len; | 180 | const u32 *stash_len; |
184 | const u32 *stash_idx; | 181 | const u32 *stash_idx; |
@@ -264,8 +261,8 @@ static int gfar_of_init(struct net_device *dev) | |||
264 | if (of_get_property(np, "fsl,magic-packet", NULL)) | 261 | if (of_get_property(np, "fsl,magic-packet", NULL)) |
265 | priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET; | 262 | priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET; |
266 | 263 | ||
267 | ph = of_get_property(np, "phy-handle", NULL); | 264 | priv->phy_node = of_parse_phandle(np, "phy-handle", 0); |
268 | if (ph == NULL) { | 265 | if (!priv->phy_node) { |
269 | u32 *fixed_link; | 266 | u32 *fixed_link; |
270 | 267 | ||
271 | fixed_link = (u32 *)of_get_property(np, "fixed-link", NULL); | 268 | fixed_link = (u32 *)of_get_property(np, "fixed-link", NULL); |
@@ -273,57 +270,10 @@ static int gfar_of_init(struct net_device *dev) | |||
273 | err = -ENODEV; | 270 | err = -ENODEV; |
274 | goto err_out; | 271 | goto err_out; |
275 | } | 272 | } |
276 | |||
277 | snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), | ||
278 | PHY_ID_FMT, "0", fixed_link[0]); | ||
279 | } else { | ||
280 | phy = of_find_node_by_phandle(*ph); | ||
281 | |||
282 | if (phy == NULL) { | ||
283 | err = -ENODEV; | ||
284 | goto err_out; | ||
285 | } | ||
286 | |||
287 | mdio = of_get_parent(phy); | ||
288 | |||
289 | id = of_get_property(phy, "reg", NULL); | ||
290 | |||
291 | of_node_put(phy); | ||
292 | |||
293 | fsl_pq_mdio_bus_name(bus_name, mdio); | ||
294 | of_node_put(mdio); | ||
295 | snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), "%s:%02x", | ||
296 | bus_name, *id); | ||
297 | } | 273 | } |
298 | 274 | ||
299 | /* Find the TBI PHY. If it's not there, we don't support SGMII */ | 275 | /* Find the TBI PHY. If it's not there, we don't support SGMII */ |
300 | ph = of_get_property(np, "tbi-handle", NULL); | 276 | priv->tbi_node = of_parse_phandle(np, "tbi-handle", 0); |
301 | if (ph) { | ||
302 | struct device_node *tbi = of_find_node_by_phandle(*ph); | ||
303 | struct of_device *ofdev; | ||
304 | struct mii_bus *bus; | ||
305 | |||
306 | if (!tbi) | ||
307 | return 0; | ||
308 | |||
309 | mdio = of_get_parent(tbi); | ||
310 | if (!mdio) | ||
311 | return 0; | ||
312 | |||
313 | ofdev = of_find_device_by_node(mdio); | ||
314 | |||
315 | of_node_put(mdio); | ||
316 | |||
317 | id = of_get_property(tbi, "reg", NULL); | ||
318 | if (!id) | ||
319 | return 0; | ||
320 | |||
321 | of_node_put(tbi); | ||
322 | |||
323 | bus = dev_get_drvdata(&ofdev->dev); | ||
324 | |||
325 | priv->tbiphy = bus->phy_map[*id]; | ||
326 | } | ||
327 | 277 | ||
328 | return 0; | 278 | return 0; |
329 | 279 | ||
@@ -529,6 +479,10 @@ static int gfar_probe(struct of_device *ofdev, | |||
529 | register_fail: | 479 | register_fail: |
530 | iounmap(priv->regs); | 480 | iounmap(priv->regs); |
531 | regs_fail: | 481 | regs_fail: |
482 | if (priv->phy_node) | ||
483 | of_node_put(priv->phy_node); | ||
484 | if (priv->tbi_node) | ||
485 | of_node_put(priv->tbi_node); | ||
532 | free_netdev(dev); | 486 | free_netdev(dev); |
533 | return err; | 487 | return err; |
534 | } | 488 | } |
@@ -537,6 +491,11 @@ static int gfar_remove(struct of_device *ofdev) | |||
537 | { | 491 | { |
538 | struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); | 492 | struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); |
539 | 493 | ||
494 | if (priv->phy_node) | ||
495 | of_node_put(priv->phy_node); | ||
496 | if (priv->tbi_node) | ||
497 | of_node_put(priv->tbi_node); | ||
498 | |||
540 | dev_set_drvdata(&ofdev->dev, NULL); | 499 | dev_set_drvdata(&ofdev->dev, NULL); |
541 | 500 | ||
542 | iounmap(priv->regs); | 501 | iounmap(priv->regs); |
@@ -690,7 +649,6 @@ static int init_phy(struct net_device *dev) | |||
690 | uint gigabit_support = | 649 | uint gigabit_support = |
691 | priv->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? | 650 | priv->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? |
692 | SUPPORTED_1000baseT_Full : 0; | 651 | SUPPORTED_1000baseT_Full : 0; |
693 | struct phy_device *phydev; | ||
694 | phy_interface_t interface; | 652 | phy_interface_t interface; |
695 | 653 | ||
696 | priv->oldlink = 0; | 654 | priv->oldlink = 0; |
@@ -699,21 +657,21 @@ static int init_phy(struct net_device *dev) | |||
699 | 657 | ||
700 | interface = gfar_get_interface(dev); | 658 | interface = gfar_get_interface(dev); |
701 | 659 | ||
702 | phydev = phy_connect(dev, priv->phy_bus_id, &adjust_link, 0, interface); | 660 | if (priv->phy_node) { |
661 | priv->phydev = of_phy_connect(dev, priv->phy_node, &adjust_link, | ||
662 | 0, interface); | ||
663 | if (!priv->phydev) { | ||
664 | dev_err(&dev->dev, "error: Could not attach to PHY\n"); | ||
665 | return -ENODEV; | ||
666 | } | ||
667 | } | ||
703 | 668 | ||
704 | if (interface == PHY_INTERFACE_MODE_SGMII) | 669 | if (interface == PHY_INTERFACE_MODE_SGMII) |
705 | gfar_configure_serdes(dev); | 670 | gfar_configure_serdes(dev); |
706 | 671 | ||
707 | if (IS_ERR(phydev)) { | ||
708 | printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); | ||
709 | return PTR_ERR(phydev); | ||
710 | } | ||
711 | |||
712 | /* Remove any features not supported by the controller */ | 672 | /* Remove any features not supported by the controller */ |
713 | phydev->supported &= (GFAR_SUPPORTED | gigabit_support); | 673 | priv->phydev->supported &= (GFAR_SUPPORTED | gigabit_support); |
714 | phydev->advertising = phydev->supported; | 674 | priv->phydev->advertising = priv->phydev->supported; |
715 | |||
716 | priv->phydev = phydev; | ||
717 | 675 | ||
718 | return 0; | 676 | return 0; |
719 | } | 677 | } |
@@ -730,10 +688,17 @@ static int init_phy(struct net_device *dev) | |||
730 | static void gfar_configure_serdes(struct net_device *dev) | 688 | static void gfar_configure_serdes(struct net_device *dev) |
731 | { | 689 | { |
732 | struct gfar_private *priv = netdev_priv(dev); | 690 | struct gfar_private *priv = netdev_priv(dev); |
691 | struct phy_device *tbiphy; | ||
692 | |||
693 | if (!priv->tbi_node) { | ||
694 | dev_warn(&dev->dev, "error: SGMII mode requires that the " | ||
695 | "device tree specify a tbi-handle\n"); | ||
696 | return; | ||
697 | } | ||
733 | 698 | ||
734 | if (!priv->tbiphy) { | 699 | tbiphy = of_phy_find_device(priv->tbi_node); |
735 | printk(KERN_WARNING "SGMII mode requires that the device " | 700 | if (!tbiphy) { |
736 | "tree specify a tbi-handle\n"); | 701 | dev_err(&dev->dev, "error: Could not get TBI device\n"); |
737 | return; | 702 | return; |
738 | } | 703 | } |
739 | 704 | ||
@@ -743,17 +708,17 @@ static void gfar_configure_serdes(struct net_device *dev) | |||
743 | * everything for us? Resetting it takes the link down and requires | 708 | * everything for us? Resetting it takes the link down and requires |
744 | * several seconds for it to come back. | 709 | * several seconds for it to come back. |
745 | */ | 710 | */ |
746 | if (phy_read(priv->tbiphy, MII_BMSR) & BMSR_LSTATUS) | 711 | if (phy_read(tbiphy, MII_BMSR) & BMSR_LSTATUS) |
747 | return; | 712 | return; |
748 | 713 | ||
749 | /* Single clk mode, mii mode off(for serdes communication) */ | 714 | /* Single clk mode, mii mode off(for serdes communication) */ |
750 | phy_write(priv->tbiphy, MII_TBICON, TBICON_CLK_SELECT); | 715 | phy_write(tbiphy, MII_TBICON, TBICON_CLK_SELECT); |
751 | 716 | ||
752 | phy_write(priv->tbiphy, MII_ADVERTISE, | 717 | phy_write(tbiphy, MII_ADVERTISE, |
753 | ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE | | 718 | ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE | |
754 | ADVERTISE_1000XPSE_ASYM); | 719 | ADVERTISE_1000XPSE_ASYM); |
755 | 720 | ||
756 | phy_write(priv->tbiphy, MII_BMCR, BMCR_ANENABLE | | 721 | phy_write(tbiphy, MII_BMCR, BMCR_ANENABLE | |
757 | BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000); | 722 | BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000); |
758 | } | 723 | } |
759 | 724 | ||
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 0642d52aef5c..91317bc11154 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -779,7 +779,8 @@ struct gfar_private { | |||
779 | spinlock_t bflock; | 779 | spinlock_t bflock; |
780 | 780 | ||
781 | phy_interface_t interface; | 781 | phy_interface_t interface; |
782 | char phy_bus_id[BUS_ID_SIZE]; | 782 | struct device_node *phy_node; |
783 | struct device_node *tbi_node; | ||
783 | u32 device_flags; | 784 | u32 device_flags; |
784 | unsigned char rx_csum_enable:1, | 785 | unsigned char rx_csum_enable:1, |
785 | extended_hash:1, | 786 | extended_hash:1, |
@@ -793,7 +794,6 @@ struct gfar_private { | |||
793 | 794 | ||
794 | /* PHY stuff */ | 795 | /* PHY stuff */ |
795 | struct phy_device *phydev; | 796 | struct phy_device *phydev; |
796 | struct phy_device *tbiphy; | ||
797 | struct mii_bus *mii_bus; | 797 | struct mii_bus *mii_bus; |
798 | int oldspeed; | 798 | int oldspeed; |
799 | int oldduplex; | 799 | int oldduplex; |