[PATCH] ocp enet

John Tyner jtyner at cs.ucr.edu
Thu Feb 28 10:32:04 EST 2002


>From andrew may <acmay at acmay.homeip.net>:

Added Am79C874 support
Improved find_phy function:
  use Min/Max Phy addr defines (not sure if MAX_NUM_PHYS is still needed)
  continue to look for phy if we find a phy we don't support instead of panic
  detect/report missing pullup problem
  removed unused phy_id_done
enet_open
  checks for undetected phy and fails if no know phy is present
enet_open/close
 checks for completion of soft reset (writing 0 to soft reset has no effect)
-------------- next part --------------
diff -ur linux-base/drivers/net/ibm_ocp_enet.c linux-ppc/drivers/net/ibm_ocp_enet.c
--- linux-base/drivers/net/ibm_ocp_enet.c	Tue Feb 26 16:56:02 2002
+++ linux-ppc/drivers/net/ibm_ocp_enet.c	Wed Feb 27 15:04:30 2002
@@ -170,7 +170,10 @@
 	emacp = (emac_t *) dev->base_addr;
 	emac_ier = 0;
 	fep->sequence_done = 0;
-
+        if( !fep->phy ){
+                printk(KERN_NOTICE "%s: Cannot open interface without phy\n", dev->name );
+                return -ENODEV;
+        }
 	/* although the probe has already reset the chip we do it again here */
 	printk(KERN_NOTICE "Reset ethernet interfaces\n");
 
@@ -182,7 +185,11 @@
 	eieio();
 
 	for (loop = 0; loop < 1000; loop++) ;
-	emacp->em0mr0 = emacp->em0mr0 & ~EMAC_M0_SRST;
+	if( emacp->em0mr0 & EMAC_M0_SRST ){
+                eieio();
+                printk(KERN_NOTICE "%s: Cannot open interface without Link\n", dev->name );
+                return -ENODEV;
+        }
 	eieio();
 
 	/* Set the MAL configuration register */
@@ -404,7 +411,10 @@
 
 	for (delay = 0; delay < 1000; delay++) ;
 
-	emacp->em0mr0 = emacp->em0mr0 & ~EMAC_M0_SRST;
+	if( emacp->em0mr0 & EMAC_M0_SRST ){
+                /*not sure what to do here hopefully it clears before another open*/
+                printk( KERN_ERR "%s: Phy SoftReset didn't clear, no link?\n", dev->name );
+        }
 	eieio();
 
 	/*
diff -ur linux-base/drivers/net/ibm_ocp_enet.h linux-ppc/drivers/net/ibm_ocp_enet.h
--- linux-base/drivers/net/ibm_ocp_enet.h	Wed Feb 27 13:14:51 2002
+++ linux-ppc/drivers/net/ibm_ocp_enet.h	Wed Feb 27 14:44:56 2002
@@ -74,6 +74,8 @@
 #define BL_MAL_TXEOB		5
 #define BL_MAL_RXEOB		6
 
+#define MIN_PHY_ADDR            0x00
+#define MAX_PHY_ADDR            0x1f
 #define MAX_NUM_PHYS		4
 
 /* Transmitter timeout. */
@@ -163,7 +165,6 @@
 	int tx_slot;
 	int ack_slot;
 	uint phy_id;
-	uint phy_id_done;
 	uint phy_status;
 	uint phy_speed;
 	uint phy_duplex;
diff -ur linux-base/drivers/net/ibm_ocp_phy.c linux-ppc/drivers/net/ibm_ocp_phy.c
--- linux-base/drivers/net/ibm_ocp_phy.c	Tue Feb 26 16:56:45 2002
+++ linux-ppc/drivers/net/ibm_ocp_phy.c	Wed Feb 27 14:59:32 2002
@@ -736,6 +736,74 @@
 };
 
 /* ------------------------------------------------------------------------- */
+/* The AMD Am79C874 NetPHY-1LP same as AC101                                 */
+/* This is a hackish copy of the 75 right now. It works for now.             */
+/* It has 100FX support that I have not been able to add/test yet            */
+/*                                                                Andrew May */
+/* Using the same register definitions same as Am79c875*/
+
+static void
+mii_parse_Am79C874_pcr(uint mii_reg, struct net_device *dev)
+{
+	struct fec_enet_private *fep = dev->priv;
+	volatile uint *s = &(fep->phy_status);
+
+	*s &= ~(PHY_CONF_SPMASK);
+	printk("mii_reg 0x%x status 0x%x mask 0x%x\n", mii_reg, fep->phy_status,
+	       (mii_reg >> 5));
+
+	switch ((mii_reg >> 5)) {
+	case 0x1:
+		*s |= PHY_STAT_10HDX;
+		break;
+
+	case 0x3:
+		*s |= PHY_STAT_10FDX;
+		break;
+
+	case 0x7:
+		*s |= PHY_STAT_100HDX;
+		break;
+
+	case 0xf:
+		*s |= PHY_STAT_100FDX;
+		break;
+	}
+}
+static phy_info_t phy_info_Am79C874 = {
+	0x0022561b,
+	"Am79c874",
+	0,
+	(const phy_cmd_t[]) {	/* config */
+
+			     /* parse cr and anar to get some info */
+
+			     {mk_mii_read(MII_REG_CR), mii_parse_cr},
+			     {mk_mii_read(MII_REG_ANAR), mii_parse_anar},
+			     {mk_mii_end,}
+			     },
+	(const phy_cmd_t[]) {	/* startup - enable interrupts */
+			     {mk_mii_write(MII_REG_CR, PHY_BMCR_AUTON), NULL},	/* Auto neg. on */
+                             /*{ mk_mii_write(MII_AM79C875_MFR, 0x4000), NULL},*/ /* int 1 to signle interrupt */
+                             /*{ mk_mii_write(MII_AM79C875_ICR, 0x00ff), NULL },*/ /* enable interrupts */
+			     {mk_mii_write(MII_REG_CR, PHY_BMCR_RST_NEG), NULL},	/* autonegotiate */
+			     {mk_mii_end,}
+			     },
+	(const phy_cmd_t[]) {	/* ack_int */
+
+			     {mk_mii_read(MII_AM79C875_ICR), NULL},
+			     {mk_mii_read(MII_REG_SR), mii_parse_sr},
+			     {mk_mii_read(MII_REG_ANAR), mii_parse_anar},
+			     {mk_mii_read(MII_REG_ANAR),
+			      mii_parse_Am79C874_pcr},
+			     {mk_mii_end,}
+			     },
+	(const phy_cmd_t[]) {	/* shutdown - nothing */
+			     {mk_mii_end,}
+			     },
+};
+
+/* ------------------------------------------------------------------------- */
 /* The Broadcom BCM5221 */
 
 /* register definitions */
@@ -841,6 +909,7 @@
 	&phy_info_dp83846A,
 	&phy_info_lu3x31ft,
 	&phy_info_Am79C875,
+	&phy_info_Am79C874,
 	&phy_info_bcm5221,
 	NULL
 };
@@ -966,39 +1035,46 @@
 {
 	struct fec_enet_private *fep;
 	int i;
-	uint phy_reg, phy_reg2;
-	uint phytype;
+	uint phy_reg;
 
 	fep = (struct fec_enet_private *) dev->priv;
-	for (i = 0; i < MAX_NUM_PHYS; i++) {
+	for (i = MIN_PHY_ADDR; i <= MAX_PHY_ADDR; i++) {
 		fep->phy_addr = i;
 		if (!(fec_enet_mdio_read(dev, mk_mii_read(MII_REG_PHYIR1),
-					&phy_reg)) && 
-		    !(fec_enet_mdio_read(dev, mk_mii_read(MII_REG_PHYIR2),
-		                        &phy_reg2)))
+                                         &phy_reg)) )
 			break;
+        got_bad_phy:
 	}
 
-	fep->phy_addr = i;
-	if ((phytype = (phy_reg & 0xffff)) != 0xffff) {
-		/* Got first part of ID, now get remainder. */
-		fep->phy_id = phytype << 16;
-		fec_enet_mdio_read(dev, mk_mii_read(MII_REG_PHYIR2), &phy_reg);
-		fep->phy_id |= (phy_reg & 0xffff);
+        if( i <= MAX_PHY_ADDR ){
+		/* Got 2nd part of ID, now get remainder. */
+                fep->phy_id = (phy_reg&0xffff) << 16;
+
+                if( fec_enet_mdio_read(dev, mk_mii_read(MII_REG_PHYIR2),
+                                       &phy_reg) ){
+                        if( i == MIN_PHY_ADDR )
+                                printk( KERN_ERR "%s: Got bad Phy Read, missing MDIO pullup?\n", dev->name );
+                        goto got_bad_phy;
+                }
+
+		fep->phy_id |= (phy_reg&0xffff);
+
 		for (i = 0; phy_info[i]; i++)
 			if (phy_info[i]->id ==
 			    (fep->phy_id >> phy_info[i]->shift))
 				break;
-		if (!phy_info[i])
-			panic("%s: PHY id 0x%08x is not supported!\n",
-			      dev->name, fep->phy_id);
+		if (!phy_info[i]){
+			printk( KERN_ERR "%s: PHY id 0x%08x is not supported!\n",
+                                dev->name, fep->phy_id);
+                        i = fep->phy_addr;
+                        goto got_bad_phy;
+                }
 
 		fep->phy = phy_info[i];
-		fep->phy_id_done = 1;
 
 		printk("%s: Phy @ 0x%x, type %s (0x%08x)\n",
 		       dev->name, fep->phy_addr, fep->phy->name, fep->phy_id);
-	} else
-		printk("fec: No PHY device found.\n");
-
+	} else {
+                printk("%s: No PHY device found.\n", dev->name);
+        }
 }


More information about the Linuxppc-embedded mailing list