[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