summaryrefslogtreecommitdiffstats
path: root/drivers/net/fec_mpc52xx.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2008-05-06 17:55:32 +0000
committerSteve French <sfrench@us.ibm.com>2008-05-06 17:55:32 +0000
commita815752ac0ffdb910e92958d41d28f4fb28e5296 (patch)
treea3aa16a282354da0debe8e3a3a7ed8aac6e54001 /drivers/net/fec_mpc52xx.c
parent5ade9deaaa3e1f7291467d97b238648e43eae15e (diff)
parenta15306365a16380f3bafee9e181ba01231d4acd7 (diff)
downloadlinux-a815752ac0ffdb910e92958d41d28f4fb28e5296.tar.bz2
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/net/fec_mpc52xx.c')
-rw-r--r--drivers/net/fec_mpc52xx.c120
1 files changed, 87 insertions, 33 deletions
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index e5e6352556fa..5f9c42e7a7f1 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -43,6 +43,29 @@
#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);
@@ -491,20 +514,23 @@ static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id)
out_be32(&fec->ievent, ievent); /* clear pending events */
- if (ievent & ~(FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) {
- if (ievent & ~FEC_IEVENT_TFINT)
- dev_dbg(&dev->dev, "ievent: %08x\n", ievent);
+ /* on fifo error, soft-reset fec */
+ if (ievent & (FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) {
+
+ if (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR))
+ dev_warn(&dev->dev, "FEC_IEVENT_RFIFO_ERROR\n");
+ if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR))
+ dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n");
+
+ mpc52xx_fec_reset(dev);
+
+ netif_wake_queue(dev);
return IRQ_HANDLED;
}
- if (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR))
- dev_warn(&dev->dev, "FEC_IEVENT_RFIFO_ERROR\n");
- if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR))
- dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n");
-
- mpc52xx_fec_reset(dev);
+ if (ievent & ~FEC_IEVENT_TFINT)
+ dev_dbg(&dev->dev, "ievent: %08x\n", ievent);
- netif_wake_queue(dev);
return IRQ_HANDLED;
}
@@ -701,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)
@@ -861,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;
@@ -945,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 */
@@ -979,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);