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