[POWERPC] mpc5200: Allow for fixed speed MII configurations
Grant Likely [Thu, 1 May 2008 17:05:58 +0000 (11:05 -0600)]
Various improvements for configuring the MPC5200 MII link from the
device tree:
* Look for 'current-speed' property for fixed speed MII links
* Look for 'fsl,7-wire-mode' property for boards using the 7 wire mode
* move definition of private data structure out of the header file

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Wolfgang Grandegger <wg@grandegger.com>

Documentation/powerpc/mpc52xx-device-tree-bindings.txt
drivers/net/fec_mpc52xx.c
drivers/net/fec_mpc52xx.h

index cda7a7d..6f12f1c 100644 (file)
@@ -237,6 +237,17 @@ Each GPIO controller node should have the empty property gpio-controller and
 according to the bit numbers in the GPIO control registers. The second cell
 is for flags which is currently unsused.
 
+8) FEC nodes
+The FEC node can specify one of the following properties to configure
+the MII link:
+"fsl,7-wire-mode" - An empty property that specifies the link uses 7-wire
+                    mode instead of MII
+"current-speed"   - Specifies that the MII should be configured for a fixed
+                    speed.  This property should contain two cells.  The
+                    first cell specifies the speed in Mbps and the second
+                    should be '0' for half duplex and '1' for full duplex
+"phy-handle"      - Contains a phandle to an Ethernet PHY.
+
 IV - Extra Notes
 ================
 
index d21b7ab..5f9c42e 100644 (file)
 
 #define DRIVER_NAME "mpc52xx-fec"
 
+#define FEC5200_PHYADDR_NONE   (-1)
+#define FEC5200_PHYADDR_7WIRE  (-2)
+
+/* Private driver data structure */
+struct mpc52xx_fec_priv {
+       int duplex;
+       int speed;
+       int r_irq;
+       int t_irq;
+       struct mpc52xx_fec __iomem *fec;
+       struct bcom_task *rx_dmatsk;
+       struct bcom_task *tx_dmatsk;
+       spinlock_t lock;
+       int msg_enable;
+
+       /* MDIO link details */
+       int phy_addr;
+       unsigned int phy_speed;
+       struct phy_device *phydev;
+       enum phy_state link;
+};
+
+
 static irqreturn_t mpc52xx_fec_interrupt(int, void *);
 static irqreturn_t mpc52xx_fec_rx_interrupt(int, void *);
 static irqreturn_t mpc52xx_fec_tx_interrupt(int, void *);
@@ -223,7 +246,7 @@ static int mpc52xx_fec_phy_start(struct net_device *dev)
        struct mpc52xx_fec_priv *priv = netdev_priv(dev);
        int err;
 
-       if (!priv->has_phy)
+       if (priv->phy_addr < 0)
                return 0;
 
        err = mpc52xx_fec_init_phy(dev);
@@ -243,7 +266,7 @@ static void mpc52xx_fec_phy_stop(struct net_device *dev)
 {
        struct mpc52xx_fec_priv *priv = netdev_priv(dev);
 
-       if (!priv->has_phy)
+       if (!priv->phydev)
                return;
 
        phy_disconnect(priv->phydev);
@@ -255,7 +278,7 @@ static void mpc52xx_fec_phy_stop(struct net_device *dev)
 static int mpc52xx_fec_phy_mii_ioctl(struct mpc52xx_fec_priv *priv,
                struct mii_ioctl_data *mii_data, int cmd)
 {
-       if (!priv->has_phy)
+       if (!priv->phydev)
                return -ENOTSUPP;
 
        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)
 {
        struct mpc52xx_fec __iomem *fec = priv->fec;
 
-       if (!priv->has_phy)
+       if (priv->phydev)
                return;
 
        out_be32(&fec->mii_speed, priv->phy_speed);
@@ -704,7 +727,7 @@ static void mpc52xx_fec_start(struct net_device *dev)
        rcntrl = FEC_RX_BUFFER_SIZE << 16;      /* max frame length */
        rcntrl |= FEC_RCNTRL_FCE;
 
-       if (priv->has_phy)
+       if (priv->phy_addr != FEC5200_PHYADDR_7WIRE)
                rcntrl |= FEC_RCNTRL_MII_MODE;
 
        if (priv->duplex == DUPLEX_FULL)
@@ -864,7 +887,10 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
        struct net_device *ndev;
        struct mpc52xx_fec_priv *priv = NULL;
        struct resource mem;
-       const phandle *ph;
+       struct device_node *phy_node;
+       const phandle *phy_handle;
+       const u32 *prop;
+       int prop_size;
 
        phys_addr_t rx_fifo;
        phys_addr_t tx_fifo;
@@ -948,26 +974,37 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
                mpc52xx_fec_get_paddr(ndev, ndev->dev_addr);
 
        priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT);
-       priv->duplex = DUPLEX_FULL;
-
-       /* is the phy present in device tree? */
-       ph = of_get_property(op->node, "phy-handle", NULL);
-       if (ph) {
-               const unsigned int *prop;
-               struct device_node *phy_dn;
-               priv->has_phy = 1;
 
-               phy_dn = of_find_node_by_phandle(*ph);
-               prop = of_get_property(phy_dn, "reg", NULL);
-               priv->phy_addr = *prop;
+       /*
+        * Link mode configuration
+        */
 
-               of_node_put(phy_dn);
+       /* Start with safe defaults for link connection */
+       priv->phy_addr = FEC5200_PHYADDR_NONE;
+       priv->speed = 100;
+       priv->duplex = DUPLEX_HALF;
+       priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1;
+
+       /* the 7-wire property means don't use MII mode */
+       if (of_find_property(op->node, "fsl,7-wire-mode", NULL))
+               priv->phy_addr = FEC5200_PHYADDR_7WIRE;
+
+       /* The current speed preconfigures the speed of the MII link */
+       prop = of_get_property(op->node, "current-speed", &prop_size);
+       if (prop && (prop_size >= sizeof(u32) * 2)) {
+               priv->speed = prop[0];
+               priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF;
+       }
 
-               /* Phy speed */
-               priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1;
-       } else {
-               dev_info(&ndev->dev, "can't find \"phy-handle\" in device"
-                               " tree, using 7-wire mode\n");
+       /* If there is a phy handle, setup link to that phy */
+       phy_handle = of_get_property(op->node, "phy-handle", &prop_size);
+       if (phy_handle && (prop_size >= sizeof(phandle))) {
+               phy_node = of_find_node_by_phandle(*phy_handle);
+               prop = of_get_property(phy_node, "reg", &prop_size);
+               if (prop && (prop_size >= sizeof(u32)))
+                       if ((*prop >= 0) && (*prop < PHY_MAX_ADDR))
+                               priv->phy_addr = *prop;
+               of_node_put(phy_node);
        }
 
        /* Hardware init */
@@ -982,6 +1019,20 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
        if (rv < 0)
                goto probe_error;
 
+       /* Now report the link setup */
+       switch (priv->phy_addr) {
+        case FEC5200_PHYADDR_NONE:
+               dev_info(&ndev->dev, "Fixed speed MII link: %i%cD\n",
+                        priv->speed, priv->duplex ? 'F' : 'H');
+               break;
+        case FEC5200_PHYADDR_7WIRE:
+               dev_info(&ndev->dev, "using 7-wire PHY mode\n");
+               break;
+        default:
+               dev_info(&ndev->dev, "Using PHY at MDIO address %i\n",
+                        priv->phy_addr);
+       }
+
        /* We're done ! */
        dev_set_drvdata(&op->dev, ndev);
 
index 8b1f753..a227a52 100644 (file)
 
 #define FEC_WATCHDOG_TIMEOUT   ((400*HZ)/1000)
 
-struct mpc52xx_fec_priv {
-       int duplex;
-       int r_irq;
-       int t_irq;
-       struct mpc52xx_fec __iomem *fec;
-       struct bcom_task *rx_dmatsk;
-       struct bcom_task *tx_dmatsk;
-       spinlock_t lock;
-       int msg_enable;
-
-       int has_phy;
-       unsigned int phy_speed;
-       unsigned int phy_addr;
-       struct phy_device *phydev;
-       enum phy_state link;
-       int speed;
-};
-
-
 /* ======================================================================== */
 /* Hardware register sets & bits                                            */
 /* ======================================================================== */