aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/fec_mpc52xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/fec_mpc52xx.c')
-rw-r--r--drivers/net/fec_mpc52xx.c97
1 files changed, 74 insertions, 23 deletions
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index d21b7ab64bd1..5f9c42e7a7f1 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -43,6 +43,29 @@
43 43
44#define DRIVER_NAME "mpc52xx-fec" 44#define DRIVER_NAME "mpc52xx-fec"
45 45
46#define FEC5200_PHYADDR_NONE (-1)
47#define FEC5200_PHYADDR_7WIRE (-2)
48
49/* Private driver data structure */
50struct mpc52xx_fec_priv {
51 int duplex;
52 int speed;
53 int r_irq;
54 int t_irq;
55 struct mpc52xx_fec __iomem *fec;
56 struct bcom_task *rx_dmatsk;
57 struct bcom_task *tx_dmatsk;
58 spinlock_t lock;
59 int msg_enable;
60
61 /* MDIO link details */
62 int phy_addr;
63 unsigned int phy_speed;
64 struct phy_device *phydev;
65 enum phy_state link;
66};
67
68
46static irqreturn_t mpc52xx_fec_interrupt(int, void *); 69static irqreturn_t mpc52xx_fec_interrupt(int, void *);
47static irqreturn_t mpc52xx_fec_rx_interrupt(int, void *); 70static irqreturn_t mpc52xx_fec_rx_interrupt(int, void *);
48static irqreturn_t mpc52xx_fec_tx_interrupt(int, void *); 71static irqreturn_t mpc52xx_fec_tx_interrupt(int, void *);
@@ -223,7 +246,7 @@ static int mpc52xx_fec_phy_start(struct net_device *dev)
223 struct mpc52xx_fec_priv *priv = netdev_priv(dev); 246 struct mpc52xx_fec_priv *priv = netdev_priv(dev);
224 int err; 247 int err;
225 248
226 if (!priv->has_phy) 249 if (priv->phy_addr < 0)
227 return 0; 250 return 0;
228 251
229 err = mpc52xx_fec_init_phy(dev); 252 err = mpc52xx_fec_init_phy(dev);
@@ -243,7 +266,7 @@ static void mpc52xx_fec_phy_stop(struct net_device *dev)
243{ 266{
244 struct mpc52xx_fec_priv *priv = netdev_priv(dev); 267 struct mpc52xx_fec_priv *priv = netdev_priv(dev);
245 268
246 if (!priv->has_phy) 269 if (!priv->phydev)
247 return; 270 return;
248 271
249 phy_disconnect(priv->phydev); 272 phy_disconnect(priv->phydev);
@@ -255,7 +278,7 @@ static void mpc52xx_fec_phy_stop(struct net_device *dev)
255static int mpc52xx_fec_phy_mii_ioctl(struct mpc52xx_fec_priv *priv, 278static int mpc52xx_fec_phy_mii_ioctl(struct mpc52xx_fec_priv *priv,
256 struct mii_ioctl_data *mii_data, int cmd) 279 struct mii_ioctl_data *mii_data, int cmd)
257{ 280{
258 if (!priv->has_phy) 281 if (!priv->phydev)
259 return -ENOTSUPP; 282 return -ENOTSUPP;
260 283
261 return phy_mii_ioctl(priv->phydev, mii_data, cmd); 284 return phy_mii_ioctl(priv->phydev, mii_data, cmd);
@@ -265,7 +288,7 @@ static void mpc52xx_fec_phy_hw_init(struct mpc52xx_fec_priv *priv)
265{ 288{
266 struct mpc52xx_fec __iomem *fec = priv->fec; 289 struct mpc52xx_fec __iomem *fec = priv->fec;
267 290
268 if (!priv->has_phy) 291 if (priv->phydev)
269 return; 292 return;
270 293
271 out_be32(&fec->mii_speed, priv->phy_speed); 294 out_be32(&fec->mii_speed, priv->phy_speed);
@@ -704,7 +727,7 @@ static void mpc52xx_fec_start(struct net_device *dev)
704 rcntrl = FEC_RX_BUFFER_SIZE << 16; /* max frame length */ 727 rcntrl = FEC_RX_BUFFER_SIZE << 16; /* max frame length */
705 rcntrl |= FEC_RCNTRL_FCE; 728 rcntrl |= FEC_RCNTRL_FCE;
706 729
707 if (priv->has_phy) 730 if (priv->phy_addr != FEC5200_PHYADDR_7WIRE)
708 rcntrl |= FEC_RCNTRL_MII_MODE; 731 rcntrl |= FEC_RCNTRL_MII_MODE;
709 732
710 if (priv->duplex == DUPLEX_FULL) 733 if (priv->duplex == DUPLEX_FULL)
@@ -864,7 +887,10 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
864 struct net_device *ndev; 887 struct net_device *ndev;
865 struct mpc52xx_fec_priv *priv = NULL; 888 struct mpc52xx_fec_priv *priv = NULL;
866 struct resource mem; 889 struct resource mem;
867 const phandle *ph; 890 struct device_node *phy_node;
891 const phandle *phy_handle;
892 const u32 *prop;
893 int prop_size;
868 894
869 phys_addr_t rx_fifo; 895 phys_addr_t rx_fifo;
870 phys_addr_t tx_fifo; 896 phys_addr_t tx_fifo;
@@ -948,26 +974,37 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
948 mpc52xx_fec_get_paddr(ndev, ndev->dev_addr); 974 mpc52xx_fec_get_paddr(ndev, ndev->dev_addr);
949 975
950 priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT); 976 priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT);
951 priv->duplex = DUPLEX_FULL;
952
953 /* is the phy present in device tree? */
954 ph = of_get_property(op->node, "phy-handle", NULL);
955 if (ph) {
956 const unsigned int *prop;
957 struct device_node *phy_dn;
958 priv->has_phy = 1;
959 977
960 phy_dn = of_find_node_by_phandle(*ph); 978 /*
961 prop = of_get_property(phy_dn, "reg", NULL); 979 * Link mode configuration
962 priv->phy_addr = *prop; 980 */
963 981
964 of_node_put(phy_dn); 982 /* Start with safe defaults for link connection */
983 priv->phy_addr = FEC5200_PHYADDR_NONE;
984 priv->speed = 100;
985 priv->duplex = DUPLEX_HALF;
986 priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1;
987
988 /* the 7-wire property means don't use MII mode */
989 if (of_find_property(op->node, "fsl,7-wire-mode", NULL))
990 priv->phy_addr = FEC5200_PHYADDR_7WIRE;
991
992 /* The current speed preconfigures the speed of the MII link */
993 prop = of_get_property(op->node, "current-speed", &prop_size);
994 if (prop && (prop_size >= sizeof(u32) * 2)) {
995 priv->speed = prop[0];
996 priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF;
997 }
965 998
966 /* Phy speed */ 999 /* If there is a phy handle, setup link to that phy */
967 priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1; 1000 phy_handle = of_get_property(op->node, "phy-handle", &prop_size);
968 } else { 1001 if (phy_handle && (prop_size >= sizeof(phandle))) {
969 dev_info(&ndev->dev, "can't find \"phy-handle\" in device" 1002 phy_node = of_find_node_by_phandle(*phy_handle);
970 " tree, using 7-wire mode\n"); 1003 prop = of_get_property(phy_node, "reg", &prop_size);
1004 if (prop && (prop_size >= sizeof(u32)))
1005 if ((*prop >= 0) && (*prop < PHY_MAX_ADDR))
1006 priv->phy_addr = *prop;
1007 of_node_put(phy_node);
971 } 1008 }
972 1009
973 /* Hardware init */ 1010 /* Hardware init */
@@ -982,6 +1019,20 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
982 if (rv < 0) 1019 if (rv < 0)
983 goto probe_error; 1020 goto probe_error;
984 1021
1022 /* Now report the link setup */
1023 switch (priv->phy_addr) {
1024 case FEC5200_PHYADDR_NONE:
1025 dev_info(&ndev->dev, "Fixed speed MII link: %i%cD\n",
1026 priv->speed, priv->duplex ? 'F' : 'H');
1027 break;
1028 case FEC5200_PHYADDR_7WIRE:
1029 dev_info(&ndev->dev, "using 7-wire PHY mode\n");
1030 break;
1031 default:
1032 dev_info(&ndev->dev, "Using PHY at MDIO address %i\n",
1033 priv->phy_addr);
1034 }
1035
985 /* We're done ! */ 1036 /* We're done ! */
986 dev_set_drvdata(&op->dev, ndev); 1037 dev_set_drvdata(&op->dev, ndev);
987 1038