>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);
+        }
 }

Reply via email to