/* * Initialize and enable the PHY interrupt for link-state changes */ static void enable_phyirq(struct net_device *dev) { struct at91_private *lp = netdev_priv(dev); unsigned int dsintr, irq_number; int status; irq_number = lp->board_data.phy_irq_pin; if (!irq_number) { /* * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L), * or board does not have it connected. */ mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL); return; } status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev); if (status) { printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status); return; } spin_lock_irq(&lp->lock); enable_mdi(); if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */ read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr); dsintr = dsintr & ~0xf00; /* clear bits 8..11 */ write_phy(lp->phy_address, MII_DSINTR_REG, dsintr); } else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */ read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr); dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */ write_phy(lp->phy_address, MII_ISINTE_REG, dsintr); } else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */ dsintr = (1 << 15) | ( 1 << 14); write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr); } else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */ dsintr = (1 << 10) | ( 1 << 8); write_phy(lp->phy_address, MII_TPISTATUS, dsintr); } else if (lp->phy_type == MII_T78Q21x3_ID) { /* for Teridian PHY */ read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr); dsintr = dsintr | 0x500; /* set bits 8, 10 */ write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr); } else if (lp->phy_type == MII_DP83848_ID) { /* National Semiconductor DP83848 PHY */ read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr); dsintr = dsintr | 0x3c; /* set bits 2..5 */ write_phy(lp->phy_address, MII_DPMISR_REG, dsintr); read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr); dsintr = dsintr | 0x3; /* set bits 0,1 */ write_phy(lp->phy_address, MII_DPMICR_REG, dsintr); } disable_mdi(); spin_unlock_irq(&lp->lock); }
static void enable_phyirq(struct net_device *dev) { struct at91_private *lp = netdev_priv(dev); unsigned int dsintr, irq_number; int status; irq_number = lp->board_data.phy_irq_pin; if (!irq_number) { mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL); return; } status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev); if (status) { printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status); return; } spin_lock_irq(&lp->lock); enable_mdi(); if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr); dsintr = dsintr & ~0xf00; write_phy(lp->phy_address, MII_DSINTR_REG, dsintr); } else if (lp->phy_type == MII_LXT971A_ID) { read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr); dsintr = dsintr | 0xf2; write_phy(lp->phy_address, MII_ISINTE_REG, dsintr); } else if (lp->phy_type == MII_BCM5221_ID) { dsintr = (1 << 15) | ( 1 << 14); write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr); } else if (lp->phy_type == MII_KS8721_ID) { dsintr = (1 << 10) | ( 1 << 8); write_phy(lp->phy_address, MII_TPISTATUS, dsintr); } else if (lp->phy_type == MII_T78Q21x3_ID) { read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr); dsintr = dsintr | 0x500; write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr); } else if (lp->phy_type == MII_DP83848_ID) { read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr); dsintr = dsintr | 0x3c; write_phy(lp->phy_address, MII_DPMISR_REG, dsintr); read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr); dsintr = dsintr | 0x3; write_phy(lp->phy_address, MII_DPMICR_REG, dsintr); } disable_mdi(); spin_unlock_irq(&lp->lock); }
/* initialize the interface */ static rt_err_t rt_dm9161_init(rt_device_t dev) { unsigned int phyid1, phyid2; int detected = -1; unsigned long phy_id; unsigned short phy_address = 0; while ((detected != 0) && (phy_address < 32)) { /* Read the PHY ID registers */ enable_mdi(); read_phy(phy_address, MII_PHYSID1, &phyid1); read_phy(phy_address, MII_PHYSID2, &phyid2); disable_mdi(); phy_id = (phyid1 << 16) | (phyid2 & 0xfff0); switch (phy_id) { case MII_DM9161_ID: /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */ case MII_DM9161A_ID: /* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */ case MII_RTL8201_ID: /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */ case MII_BCM5221_ID: /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */ case MII_DP83847_ID: /* National Semiconductor DP83847: */ case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */ case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */ { enable_mdi(); #warning SHOULD SET MAC ADDR //get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */ update_mac_address(); /* Program ethernet address into MAC */ //用哈希寄存器比较当前群播地址,全双工,添加CRC校验,短数据帧进行填充 sep_emac_write(MAC_CTRL, 0xa413); #warning SHOULD DETERMIN LINK SPEED update_link_speed(phy_address); dm9161_device.phy_addr = phy_address; disable_mdi(); break; } } phy_address++; } rt_dm9161_open(dev,0); return RT_EOK; }
/* * Disable the PHY interrupt */ static void disable_phyirq(struct net_device *dev) { struct at91_private *lp = netdev_priv(dev); unsigned int dsintr; unsigned int irq_number; irq_number = lp->board_data.phy_irq_pin; if (!irq_number) { del_timer_sync(&lp->check_timer); return; } spin_lock_irq(&lp->lock); enable_mdi(); if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */ read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr); dsintr = dsintr | 0xf00; /* set bits 8..11 */ write_phy(lp->phy_address, MII_DSINTR_REG, dsintr); } else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */ read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr); dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */ write_phy(lp->phy_address, MII_ISINTE_REG, dsintr); } else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */ read_phy(lp->phy_address, MII_BCMINTR_REG, &dsintr); dsintr = ~(1 << 14); write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr); } else if ((lp->phy_type == MII_KS8721_ID) || (lp->phy_type == MII_KSZ8041_ID)) { /* for Micrel PHY */ read_phy(lp->phy_address, MII_TPISTATUS, &dsintr); dsintr = ~((1 << 10) | (1 << 8)); write_phy(lp->phy_address, MII_TPISTATUS, dsintr); } else if (lp->phy_type == MII_T78Q21x3_ID) { /* for Teridian PHY */ read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr); dsintr = dsintr & ~0x500; /* clear bits 8, 10 */ write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr); } else if (lp->phy_type == MII_DP83848_ID) { /* National Semiconductor DP83848 PHY */ read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr); dsintr = dsintr & ~0x3; /* clear bits 0, 1 */ write_phy(lp->phy_address, MII_DPMICR_REG, dsintr); read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr); dsintr = dsintr & ~0x3c; /* clear bits 2..5 */ write_phy(lp->phy_address, MII_DPMISR_REG, dsintr); } else if (lp->phy_type == MII_STE100P_ID) { /* for STE100P PHY */ read_phy(lp->phy_address, MII_STE100P_XIE_REG, &dsintr); dsintr = dsintr & ~0x7f; write_phy(lp->phy_address, MII_STE100P_XIE_REG, dsintr); } disable_mdi(); spin_unlock_irq(&lp->lock); free_irq(irq_number, dev); /* Free interrupt handler */ }
/* * Access the PHY to determine the current link speed and mode, and update the * MAC accordingly. * If no link or auto-negotiation is busy, then no changes are made. */ static void update_linkspeed(struct net_device *dev, int silent) { struct at91_private *lp = netdev_priv(dev); unsigned int bmsr, bmcr, lpa, mac_cfg; unsigned int speed, duplex; if (!mii_link_ok(&lp->mii)) { /* no link */ netif_carrier_off(dev); if (!silent) printk(KERN_INFO "%s: Link down.\n", dev->name); return; } /* Link up, or auto-negotiation still in progress */ read_phy(lp->phy_address, MII_BMSR, &bmsr); read_phy(lp->phy_address, MII_BMCR, &bmcr); if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */ if (!(bmsr & BMSR_ANEGCOMPLETE)) return; /* Do nothing - another interrupt generated when negotiation complete */ read_phy(lp->phy_address, MII_LPA, &lpa); if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100; else speed = SPEED_10; if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL; else duplex = DUPLEX_HALF; } else { speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; } /* Update the MAC */ mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD); if (speed == SPEED_100) { if (duplex == DUPLEX_FULL) /* 100 Full Duplex */ mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD; else /* 100 Half Duplex */ mac_cfg |= AT91_EMAC_SPD; } else { if (duplex == DUPLEX_FULL) /* 10 Full Duplex */ mac_cfg |= AT91_EMAC_FD; else {} /* 10 Half Duplex */ } at91_emac_write(AT91_EMAC_CFG, mac_cfg); if (!silent) printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); netif_carrier_on(dev); }
static void update_linkspeed(struct net_device *dev, int silent) { struct at91_private *lp = netdev_priv(dev); unsigned int bmsr, bmcr, lpa, mac_cfg; unsigned int speed, duplex; if (!mii_link_ok(&lp->mii)) { netif_carrier_off(dev); if (!silent) printk(KERN_INFO "%s: Link down.\n", dev->name); return; } read_phy(lp->phy_address, MII_BMSR, &bmsr); read_phy(lp->phy_address, MII_BMCR, &bmcr); if (bmcr & BMCR_ANENABLE) { if (!(bmsr & BMSR_ANEGCOMPLETE)) return; read_phy(lp->phy_address, MII_LPA, &lpa); if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100; else speed = SPEED_10; if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL; else duplex = DUPLEX_HALF; } else { speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; } mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD); if (speed == SPEED_100) { if (duplex == DUPLEX_FULL) mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD; else mac_cfg |= AT91_EMAC_SPD; } else { if (duplex == DUPLEX_FULL) mac_cfg |= AT91_EMAC_FD; else {} } at91_emac_write(AT91_EMAC_CFG, mac_cfg); if (!silent) printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); netif_carrier_on(dev); }
/* * Initialize and enable the PHY interrupt for link-state changes */ static void enable_phyirq(struct net_device *dev) { struct at91_private *lp = (struct at91_private *) dev->priv; unsigned int dsintr, irq_number; int status; if (lp->phy_type == MII_RTL8201_ID) /* RTL8201 does not have an interrupt */ return; if (lp->phy_type == MII_DP83847_ID) /* DP83847 does not have an interrupt */ return; if (lp->phy_type == MII_AC101L_ID) /* AC101L interrupt not supported yet */ return; irq_number = lp->board_data.phy_irq_pin; status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev); if (status) { printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status); return; } spin_lock_irq(&lp->lock); enable_mdi(); if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */ read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr); dsintr = dsintr & ~0xf00; /* clear bits 8..11 */ write_phy(lp->phy_address, MII_DSINTR_REG, dsintr); } else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */ read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr); dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */ write_phy(lp->phy_address, MII_ISINTE_REG, dsintr); } else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */ dsintr = (1 << 15) | ( 1 << 14); write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr); } else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */ dsintr = (1 << 10) | ( 1 << 8); write_phy(lp->phy_address, MII_TPISTATUS, dsintr); } disable_mdi(); spin_unlock_irq(&lp->lock); }
/* * Disable the PHY interrupt */ static void disable_phyirq(struct net_device *dev) { struct at91_private *lp = (struct at91_private *) dev->priv; unsigned int dsintr; unsigned int irq_number; if (lp->phy_type == MII_RTL8201_ID) /* RTL8201 does not have an interrupt */ return; if (lp->phy_type == MII_DP83847_ID) /* DP83847 does not have an interrupt */ return; if (lp->phy_type == MII_AC101L_ID) /* AC101L interrupt not supported yet */ return; spin_lock_irq(&lp->lock); enable_mdi(); if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */ read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr); dsintr = dsintr | 0xf00; /* set bits 8..11 */ write_phy(lp->phy_address, MII_DSINTR_REG, dsintr); } else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */ read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr); dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */ write_phy(lp->phy_address, MII_ISINTE_REG, dsintr); } else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */ read_phy(lp->phy_address, MII_BCMINTR_REG, &dsintr); dsintr = ~(1 << 14); write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr); } else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */ read_phy(lp->phy_address, MII_TPISTATUS, &dsintr); dsintr = ~((1 << 10) | (1 << 8)); write_phy(lp->phy_address, MII_TPISTATUS, dsintr); } disable_mdi(); spin_unlock_irq(&lp->lock); irq_number = lp->board_data.phy_irq_pin; free_irq(irq_number, dev); /* Free interrupt handler */ }
static int mii_link_ok(unsigned long phy_id) { /* first, a dummy read, needed to latch some MII phys */ unsigned int value; read_phy(phy_id, MII_BMSR,&value); if (value & BMSR_LSTATUS) return 1; return 0; }
/* * Handle interrupts from the PHY */ static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *) dev_id; struct at91_private *lp = netdev_priv(dev); unsigned int phy; /* * This hander is triggered on both edges, but the PHY chips expect * level-triggering. We therefore have to check if the PHY actually has * an IRQ pending. */ enable_mdi(); if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { read_phy(lp->phy_address, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */ if (!(phy & (1 << 0))) goto done; } else if (lp->phy_type == MII_LXT971A_ID) { read_phy(lp->phy_address, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */ if (!(phy & (1 << 2))) goto done; } else if (lp->phy_type == MII_BCM5221_ID) { read_phy(lp->phy_address, MII_BCMINTR_REG, &phy); /* ack interrupt in Broadcom PHY */ if (!(phy & (1 << 0))) goto done; } else if (lp->phy_type == MII_KS8721_ID) { read_phy(lp->phy_address, MII_TPISTATUS, &phy); /* ack interrupt in Micrel PHY */ if (!(phy & ((1 << 2) | 1))) goto done; } update_linkspeed(dev, 0); done: disable_mdi(); return IRQ_HANDLED; }
static void disable_phyirq(struct net_device *dev) { struct at91_private *lp = netdev_priv(dev); unsigned int dsintr; unsigned int irq_number; irq_number = lp->board_data.phy_irq_pin; if (!irq_number) { del_timer_sync(&lp->check_timer); return; } spin_lock_irq(&lp->lock); enable_mdi(); if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr); dsintr = dsintr | 0xf00; write_phy(lp->phy_address, MII_DSINTR_REG, dsintr); } else if (lp->phy_type == MII_LXT971A_ID) { read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr); dsintr = dsintr & ~0xf2; write_phy(lp->phy_address, MII_ISINTE_REG, dsintr); } else if (lp->phy_type == MII_BCM5221_ID) { read_phy(lp->phy_address, MII_BCMINTR_REG, &dsintr); dsintr = ~(1 << 14); write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr); } else if (lp->phy_type == MII_KS8721_ID) { read_phy(lp->phy_address, MII_TPISTATUS, &dsintr); dsintr = ~((1 << 10) | (1 << 8)); write_phy(lp->phy_address, MII_TPISTATUS, dsintr); } else if (lp->phy_type == MII_T78Q21x3_ID) { read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr); dsintr = dsintr & ~0x500; write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr); } else if (lp->phy_type == MII_DP83848_ID) { read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr); dsintr = dsintr & ~0x3; write_phy(lp->phy_address, MII_DPMICR_REG, dsintr); read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr); dsintr = dsintr & ~0x3c; write_phy(lp->phy_address, MII_DPMISR_REG, dsintr); } disable_mdi(); spin_unlock_irq(&lp->lock); free_irq(irq_number, dev); }
static void reset_phy(struct net_device *dev) { struct at91_private *lp = netdev_priv(dev); unsigned int bmcr; spin_lock_irq(&lp->lock); enable_mdi(); /* Perform PHY reset */ write_phy(lp->phy_address, MII_BMCR, BMCR_RESET); /* Wait until PHY reset is complete */ do { read_phy(lp->phy_address, MII_BMCR, &bmcr); } while (!(bmcr & BMCR_RESET)); disable_mdi(); spin_unlock_irq(&lp->lock); }
static rt_err_t rt_dm9161_open(rt_device_t dev, rt_uint16_t oflag) { unsigned int dsintr; enable_mdi(); mask_irq(28); sep_emac_write(MAC_INTMASK,0x0); //首先屏蔽中断 sepether_start(); /* Enable PHY interrupt */ *(volatile unsigned long*)GPIO_PORTA_DIR |= 0x0080 ; //1 stands for in *(volatile unsigned long*)GPIO_PORTA_SEL |= 0x0080 ; //for common use *(volatile unsigned long*)GPIO_PORTA_INCTL |= 0x0080; //中断输入方式 *(volatile unsigned long*)GPIO_PORTA_INTRCTL |= (0x3UL<<14); //中断类型为低电平解发 *(volatile unsigned long*)GPIO_PORTA_INTRCLR |= 0x0080; //清除中断 *(volatile unsigned long*)GPIO_PORTA_INTRCLR = 0x0000; //清除中断 rt_hw_interrupt_install(INTSRC_MAC, rt_dm9161_isr, RT_NULL); enable_irq(INTSRC_EXINT7); read_phy(dm9161_device.phy_addr, MII_DSINTR_REG, &dsintr); dsintr = dsintr & ~0xf00; /* clear bits 8..11 */ write_phy(dm9161_device.phy_addr, MII_DSINTR_REG, dsintr); update_link_speed(dm9161_device.phy_addr); /************************************************************************************/ /* Enable MAC interrupts */ sep_emac_write(MAC_INTMASK,0xff); //open中断 sep_emac_write(MAC_INTSRC,0xff); //clear all mac irq unmask_irq(28); disable_mdi(); rt_kprintf("SEP4020 ethernet interface open!\n\r"); return RT_EOK; }
static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *) dev_id; struct at91_private *lp = netdev_priv(dev); unsigned int phy; enable_mdi(); if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { read_phy(lp->phy_address, MII_DSINTR_REG, &phy); if (!(phy & (1 << 0))) goto done; } else if (lp->phy_type == MII_LXT971A_ID) { read_phy(lp->phy_address, MII_ISINTS_REG, &phy); if (!(phy & (1 << 2))) goto done; } else if (lp->phy_type == MII_BCM5221_ID) { read_phy(lp->phy_address, MII_BCMINTR_REG, &phy); if (!(phy & (1 << 0))) goto done; } else if (lp->phy_type == MII_KS8721_ID) { read_phy(lp->phy_address, MII_TPISTATUS, &phy); if (!(phy & ((1 << 2) | 1))) goto done; } else if (lp->phy_type == MII_T78Q21x3_ID) { read_phy(lp->phy_address, MII_T78Q21INT_REG, &phy); if (!(phy & ((1 << 2) | 1))) goto done; } else if (lp->phy_type == MII_DP83848_ID) { read_phy(lp->phy_address, MII_DPPHYSTS_REG, &phy); if (!(phy & (1 << 7))) goto done; } update_linkspeed(dev, 0); done: disable_mdi(); return IRQ_HANDLED; }
static void update_link_speed(unsigned short phy_addr) { unsigned int bmsr, bmcr, lpa, mac_cfg; unsigned int speed, duplex; if (!mii_link_ok(phy_addr)) { EOUT("Link Down\n"); //goto result; } read_phy(phy_addr,MII_BMSR,&bmsr); read_phy(phy_addr,MII_BMCR,&bmcr); if (bmcr & BMCR_ANENABLE) /* AutoNegotiation is enabled */ { if (!(bmsr & BMSR_ANEGCOMPLETE)) /* Do nothing - another interrupt generated when negotiation complete */ goto result; read_phy(phy_addr, MII_LPA, &lpa); if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100; else speed = SPEED_10; if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL; else duplex = DUPLEX_HALF; } else { speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; } /* Update the MAC */ mac_cfg = sep_emac_read(MAC_CTRL); if (speed == SPEED_100) { mac_cfg |= 0x800; /* set speed 100 M */ //bmcr &=(~0x2000); //write_phy(lp->phy_address, MII_BMCR, bmcr); //将dm9161的速度设为10M if (duplex == DUPLEX_FULL) /* 100 Full Duplex */ mac_cfg |= 0x400; else /* 100 Half Duplex */ mac_cfg &= (~0x400); } else { mac_cfg &= (~0x800); /* set speed 10 M */ if (duplex == DUPLEX_FULL) /* 10 Full Duplex */ mac_cfg |= 0x400; else /* 10 Half Duplex */ mac_cfg &= (~0x400); } sep_emac_write(MAC_CTRL, mac_cfg); rt_kprintf("Link now %i M-%s\n", speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); result: mac_cfg = sep_emac_read(MAC_CTRL); DBOUT("After mac_cfg=%d\n",mac_cfg); return; }
rt_err_t lpc24xxether_init(rt_device_t dev) { unsigned int tout, i = 0; rt_uint32_t tempreg = 0; rt_uint16_t ret = 0; rt_uint32_t clk_freq = bsp_cpu_clk_freq(); clk_freq /= 100000; nic_linkup(); /* Set NetNIC_ConnStatus to TRUE by default (for uC/TCP-IP) */ /* Power Up the EMAC controller. */ PCONP |= (1 << 30); phy_hw_init(); /* Reset all EMAC internal modules. */ MAC_MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES; MAC_COMMAND = CR_REG_RES | CR_TX_RES | CR_RX_RES; /* A short delay after reset. */ for (tout = 0; tout <5000; tout++); //Deassert all prior resets MAC_MAC1 = 0; emac_tx_disable(); emac_rx_disable(); /* Configure EMAC / PHY communication to RMII mode */ MAC_COMMAND |= CR_RMII; /* Assume and configure RMII link speed logic for 10Mbit */ MAC_SUPP = 0; for (tout = 0; tout <5000; tout++); MAC_TEST = 0; MAC_MAXF = ETH_MAX_FLEN; /* Initialize MAC control registers. */ MAC_MAC1 |= MAC1_PASS_ALL; MAC_MAC2 = MAC2_CRC_EN | MAC2_PAD_EN; MAC_RXFILTERCTRL = RFC_BCAST_EN | RFC_PERFECT_EN; /* Accept Broadcast and Perfect Address frames */ // /* Enable Reduced MII interface. */ MAC_MCFG |= MCFG_CLK_DIV20 | MCFG_RES_MII; MAC_MCMD = 0; /* Clear MII command register */ for (tout = 0; tout <5000; tout++); for (i = 0; i < 7; i++) { /* Check dividers to yield MII frequency ~2.5 MHz */ if ((clk_freq / MII_Dividers[i][0]) <= 25) { /* Index [i][0] = decimal div value, [i][1] = MCFG reg val */ MAC_MCFG = MII_Dividers[i][1]; /* Remove reset, set proper MIIM divider */ break; } } /* Enable Reduced MII interface. */ //CR_PASS_RUNT_FRM 为“1”时,将小于64字节的短帧传递到存储器中,除非该短帧的CRC有误为“0”,则将短帧被滤除。 // COMMAND |= CR_PASS_RUNT_FRM; /* Reset Reduced MII Logic. */ //PHY支持寄存器??? //下面开始PHY设置 // probe phy address for(i=0;i<32;i++) { ret = read_phy(i , PHY_REG_PHYID1 ); if(ret == 0X0181) { PHYID = i; break; } } // PHYID = 0; // 复位PHY芯片 // 等待一段指定的时间,使PHY就绪 // write_phy(PHYID, PHY_REG_BMCR, BMCR_RESET|BMCR_ANRESTART|BMCR_ANENABLE ); for ( i = 0; i < 5; i++ ) { rt_delayms(1000); } for(i=0;i<32;i++) { PHYREG[i] = read_phy_ex(EMAC_CFG_PHY_ADDR ,i ,&ret); } nic_phy_init(&ret); tempreg = read_phy(PHYID, DM9161_DSCSR ); MAC_IPGR = IPGR_DEF; MAC_CLRT = CLRT_DEF; //设置MAC地址 set_mac_id(); /* Receive Broadcast, Unicast ,Multicast and Perfect Match Packets */ // MAC_RXFILTERCTRL = RFC_UCAST_EN |RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN; for(i=0;i<32;i++) { PHYREG[i] = read_phy_ex(EMAC_CFG_PHY_ADDR ,i ,&ret); } // Initialize Tx and Rx DMA Descriptors rx_descr_init(); tx_descr_init(); /* Enable EMAC interrupts. */ // MAC_INTENABLE = INT_RX_DONE | INT_TX_DONE; /* Reset all interrupts */ MAC_INTCLEAR = (INT_RX_OVERRUN | /* Clear all EMAC interrupt sources */ INT_RX_ERR | INT_RX_FIN | INT_RX_DONE | INT_TX_UNDERRUN | INT_TX_ERR | INT_TX_FIN | INT_TX_DONE | INT_SOFT_INT | INT_WAKEUP); /* update mac address */ // update_mac_address(&lpc24xx_device); nic_int_init(); /* Enable receive and transmit mode of MAC Ethernet core */ emac_rx_enanble(); emac_tx_enable(); EMAC_RxIntEn( ); return RT_EOK; }