Beispiel #1
0
/*
 * 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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
/* 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 */
}
Beispiel #5
0
/*
 * 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);
}
Beispiel #6
0
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);
}
Beispiel #7
0
/*
 * 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);
}
Beispiel #8
0
/*
 * 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 */
}
Beispiel #9
0
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;
}
Beispiel #11
0
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);			
}
Beispiel #12
0
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);
}
Beispiel #13
0
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;
}
Beispiel #14
0
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;
}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}