示例#1
0
文件: mcfmii.c 项目: 0s4l/u-boot-xlnx
void __mii_init(void)
{
	FEC_INFO_T *info;
	volatile FEC_T *fecp;
	struct eth_device *dev;
	int miispd = 0, i = 0;
	u16 status = 0;
	u16 linkgood = 0;

	/* retrieve from register structure */
	dev = eth_get_dev();
	info = dev->priv;

	fecp = (FEC_T *) info->miibase;

	fecpin_setclear(dev, 1);

	mii_reset(info);

	/* We use strictly polling mode only */
	fecp->eimr = 0;

	/* Clear any pending interrupt */
	fecp->eir = 0xffffffff;

	/* Set MII speed */
	miispd = (gd->bus_clk / 1000000) / 5;
	fecp->mscr = miispd << 1;

	info->phy_addr = mii_discover_phy(dev);

	while (i < MCFFEC_TOUT_LOOP) {
		status = 0;
		i++;
		/* Read PHY control register */
		miiphy_read(dev->name, info->phy_addr, MII_BMCR, &status);

		/* If phy set to autonegotiate, wait for autonegotiation done,
		 * if phy is not autonegotiating, just wait for link up.
		 */
		if ((status & BMCR_ANENABLE) == BMCR_ANENABLE) {
			linkgood = (BMSR_ANEGCOMPLETE | BMSR_LSTATUS);
		} else {
			linkgood = BMSR_LSTATUS;
		}
		/* Read PHY status register */
		miiphy_read(dev->name, info->phy_addr, MII_BMSR, &status);
		if ((status & linkgood) == linkgood)
			break;

		udelay(1);
	}
	if (i >= MCFFEC_TOUT_LOOP) {
		printf("Link UP timeout\n");
	}

	/* adapt to the duplex and speed settings of the phy */
	info->dup_spd = miiphy_duplex(dev->name, info->phy_addr) << 16;
	info->dup_spd |= miiphy_speed(dev->name, info->phy_addr);
}
示例#2
0
static void mii_write_bmcr(Mii *s, uint16_t v)
{
    if (v & 0x8000) {
        mii_reset(s);
    } else {
        s->regs[MII_BMCR] = v;
    }
}
示例#3
0
文件: skeleton.c 项目: Afterglow/ipxe
/**
 * Probe PCI device
 *
 * @v pci		PCI device
 * @ret rc		Return status code
 */
static int skeleton_probe ( struct pci_device *pci ) {
	struct net_device *netdev;
	struct skeleton_nic *skel;
	int rc;

	/* Allocate and initialise net device */
	netdev = alloc_etherdev ( sizeof ( *skel ) );
	if ( ! netdev ) {
		rc = -ENOMEM;
		goto err_alloc;
	}
	netdev_init ( netdev, &skeleton_operations );
	skel = netdev->priv;
	pci_set_drvdata ( pci, netdev );
	netdev->dev = &pci->dev;
	memset ( skel, 0, sizeof ( *skel ) );

	/* Fix up PCI device */
	adjust_pci_device ( pci );

	/* Map registers */
	skel->regs = ioremap ( pci->membase, SKELETON_BAR_SIZE );

	/* Reset the NIC */
	if ( ( rc = skeleton_reset ( skel ) ) != 0 )
		goto err_reset;

	/* Initialise and reset MII interface */
	mii_init ( &skel->mii, &skeleton_mii_operations );
	if ( ( rc = mii_reset ( &skel->mii ) ) != 0 ) {
		DBGC ( skel, "SKELETON %p could not reset MII: %s\n",
		       skel, strerror ( rc ) );
		goto err_mii_reset;
	}

	/* Register network device */
	if ( ( rc = register_netdev ( netdev ) ) != 0 )
		goto err_register_netdev;

	/* Set initial link state */
	skeleton_check_link ( netdev );

	return 0;

	unregister_netdev ( netdev );
 err_register_netdev:
 err_mii_reset:
	skeleton_reset ( skel );
 err_reset:
	iounmap ( skel->regs );
	netdev_nullify ( netdev );
	netdev_put ( netdev );
 err_alloc:
	return rc;
}
示例#4
0
void __mii_init(void)
{
	volatile fec_t *fecp;
	struct fec_info_s *info;
	struct eth_device *dev;
	int miispd = 0, i = 0;
	u16 autoneg = 0;

	/* retrieve from register structure */
	dev = eth_get_dev();
	info = dev->priv;

	fecp = (fec_t *) info->miibase;

	fecpin_setclear(dev, 1);

	mii_reset(info);

	/* We use strictly polling mode only */
	fecp->eimr = 0;

	/* Clear any pending interrupt */
	fecp->eir = 0xffffffff;

	/* Set MII speed */
	miispd = (gd->bus_clk / 1000000) / 5;
	fecp->mscr = miispd << 1;

	info->phy_addr = mii_discover_phy(dev);

#define AUTONEGLINK		(PHY_BMSR_AUTN_COMP | PHY_BMSR_LS)
	while (i < MCFFEC_TOUT_LOOP) {
		autoneg = 0;
		miiphy_read(dev->name, info->phy_addr, PHY_BMSR, &autoneg);
		i++;

		if ((autoneg & AUTONEGLINK) == AUTONEGLINK)
			break;

		udelay(500);
	}
	if (i >= MCFFEC_TOUT_LOOP) {
		printf("Auto Negotiation not complete\n");
	}

	/* adapt to the half/full speed settings */
	info->dup_spd = miiphy_duplex(dev->name, info->phy_addr) << 16;
	info->dup_spd |= miiphy_speed(dev->name, info->phy_addr);
}
示例#5
0
/*
 * ISR/periodic callbacks.
 */
uint_t
efe_intr(caddr_t arg1, caddr_t arg2)
{
	efe_t *efep = (void *)arg1;
	uint32_t status;
	mblk_t *mp = NULL;

	_NOTE(ARGUNUSED(arg2));

	mutex_enter(&efep->efe_intrlock);

	if (efep->efe_flags & FLAG_SUSPENDED) {
		mutex_exit(&efep->efe_intrlock);
		return (DDI_INTR_UNCLAIMED);
	}

	status = GETCSR(efep, CSR_INTSTAT);
	if (!(status & INTSTAT_ACTV)) {
		mutex_exit(&efep->efe_intrlock);
		return (DDI_INTR_UNCLAIMED);
	}
	PUTCSR(efep, CSR_INTSTAT, status);

	if (status & INTSTAT_RCC) {
		mp = efe_recv(efep);
	}

	if (status & INTSTAT_RQE) {
		efep->efe_ierrors++;
		efep->efe_macrcv_errors++;

		/* Kick the receiver */
		PUTCSR(efep, CSR_COMMAND, COMMAND_RXQUEUED);
	}

	if (status & INTSTAT_TXC) {
		mutex_enter(&efep->efe_txlock);

		efe_send_done(efep);

		mutex_exit(&efep->efe_txlock);
	}

	if (status & INTSTAT_FATAL) {
		mutex_enter(&efep->efe_txlock);

		efe_error(efep->efe_dip, "bus error; resetting!");
		efe_restart(efep);

		mutex_exit(&efep->efe_txlock);
	}

	mutex_exit(&efep->efe_intrlock);

	if (mp != NULL) {
		mac_rx(efep->efe_mh, NULL, mp);
	}

	if (status & INTSTAT_TXC) {
		mac_tx_update(efep->efe_mh);
	}

	if (status & INTSTAT_FATAL) {
		mii_reset(efep->efe_miih);
	}

	return (DDI_INTR_CLAIMED);
}
示例#6
0
void __mii_init(void)
{
	FEC_INFO_T *info;
	volatile FEC_T *fecp;
	struct eth_device *dev;
	int miispd = 0, i = 0;
	u16 status = 0;
	u16 linkgood = 0;

	/* retrieve from register structure */
	dev = eth_get_dev();
	info = dev->priv;

	fecp = (FEC_T *) info->miibase;

	fecpin_setclear(dev, 1);

	mii_reset(info);

	/* We use strictly polling mode only */
	fecp->eimr = 0;

	/* Clear any pending interrupt */
	fecp->eir = 0xffffffff;

	/* Set MII speed */
#ifdef CONFIG_M68K
	miispd = (gd->bus_clk / 1000000) / 5;
#else
	/*
	 * The MSCR[MII_SPEED] bit field is minus 1 encoded.
	 *
	 * We round the value in MSCR[MII_SPEED] up, so that the MDC frequency
	 * never exceeds CONFIG_MCFFEC_MII_SPEED_LIMIT.
	 */
	miispd =
		(CONFIG_MCFFEC_MAC_CLK - 1) /
		(2 * CONFIG_MCFFEC_MII_SPEED_LIMIT);
#endif /* CONFIG_M68K */
	if (miispd > MCFFEC_MII_SPEED_MAX)
		miispd = MCFFEC_MII_SPEED_MAX;

	fecp->mscr = miispd << 1;

	info->phy_addr = mii_discover_phy(dev);

	while (i < MCFFEC_TOUT_LOOP) {
		status = 0;
		i++;
		/* Read PHY control register */
		miiphy_read(dev->name, info->phy_addr, PHY_BMCR, &status);

		/* If phy set to autonegotiate, wait for autonegotiation done,
		 * if phy is not autonegotiating, just wait for link up.
		 */
		if ((status & PHY_BMCR_AUTON) == PHY_BMCR_AUTON) {
			linkgood = (PHY_BMSR_AUTN_COMP | PHY_BMSR_LS);
		} else {
			linkgood = PHY_BMSR_LS;
		}
		/* Read PHY status register */
		miiphy_read(dev->name, info->phy_addr, PHY_BMSR, &status);
		if ((status & linkgood) == linkgood)
			break;

		udelay(1);
	}
	if (i >= MCFFEC_TOUT_LOOP) {
		printf("Link UP timeout\n");
	}

	/* adapt to the duplex and speed settings of the phy */
	info->dup_spd = miiphy_duplex(dev->name, info->phy_addr) << 16;
	info->dup_spd |= miiphy_speed(dev->name, info->phy_addr);
}
示例#7
0
static unsigned
pcn_intr(caddr_t arg1)
{
	pcn_t		*pcnp = (void *)arg1;
	mblk_t		*mp = NULL;
	uint32_t	status, status2;
	boolean_t	do_reset = B_FALSE;

	mutex_enter(&pcnp->pcn_intrlock);

	if (IS_SUSPENDED(pcnp)) {
		mutex_exit(&pcnp->pcn_intrlock);
		return (DDI_INTR_UNCLAIMED);
	}

	while ((status = pcn_csr_read(pcnp, PCN_CSR_CSR)) & PCN_CSR_INTR) {
		pcn_csr_write(pcnp, PCN_CSR_CSR, status);

		status2 = pcn_csr_read(pcnp, PCN_CSR_EXTCTL2);

		if (status & PCN_CSR_TINT) {
			mutex_enter(&pcnp->pcn_xmtlock);
			pcn_reclaim(pcnp);
			mutex_exit(&pcnp->pcn_xmtlock);
		}

		if (status & PCN_CSR_RINT)
			mp = pcn_receive(pcnp);

		if (status & PCN_CSR_ERR) {
			do_reset = B_TRUE;
			break;
		}

		/* timer interrupt */
		if (status2 & PCN_EXTCTL2_STINT) {
			/* ack it */
			PCN_CSR_SETBIT(pcnp, PCN_CSR_EXTCTL2,
			    PCN_EXTCTL2_STINT);

			if (pcn_watchdog(pcnp) != DDI_SUCCESS) {
				do_reset = B_TRUE;
				break;
			}
		}
	}

	if (do_reset) {
		mutex_enter(&pcnp->pcn_xmtlock);
		pcn_resetall(pcnp);
		mutex_exit(&pcnp->pcn_xmtlock);
		mutex_exit(&pcnp->pcn_intrlock);

		mii_reset(pcnp->pcn_mii);
	} else {
		mutex_exit(&pcnp->pcn_intrlock);
	}

	if (mp)
		mac_rx(pcnp->pcn_mh, NULL, mp);

	return (DDI_INTR_CLAIMED);
}
示例#8
0
文件: rhine.c 项目: 42wim/ipxe
/**
 * Probe PCI device
 *
 * @v pci		PCI device
 * @ret rc		Return status code
 */
static int rhine_probe ( struct pci_device *pci ) {
	struct net_device *netdev;
	struct rhine_nic *rhn;
	uint8_t revision;
	unsigned int i;
	int rc;

	/* Allocate and initialise net device */
	netdev = alloc_etherdev ( sizeof ( *rhn ) );
	if ( ! netdev ) {
		rc = -ENOMEM;
		goto err_alloc;
	}
	netdev_init ( netdev, &rhine_operations );
	rhn = netdev->priv;
	pci_set_drvdata ( pci, netdev );
	netdev->dev = &pci->dev;
	memset ( rhn, 0, sizeof ( *rhn ) );
	rhine_init_ring ( &rhn->tx, RHINE_TXDESC_NUM, RHINE_TXQUEUE_BASE );
	rhine_init_ring ( &rhn->rx, RHINE_RXDESC_NUM, RHINE_RXQUEUE_BASE );

	/* Fix up PCI device */
	adjust_pci_device ( pci );

	/* Map registers */
	rhn->regs = ioremap ( pci->membase, RHINE_BAR_SIZE );
	rhn->ioaddr = pci->ioaddr;
	DBGC ( rhn, "RHINE %p regs at %08lx, I/O at %04lx\n", rhn,
	       pci->membase, pci->ioaddr );

	/* Reset the NIC */
	if ( ( rc = rhine_reset ( rhn ) ) != 0 )
		goto err_reset;

	/* Reload EEPROM */
	if ( ( rc = rhine_reload_eeprom ( rhn ) ) != 0 )
		goto err_reload_eeprom;

	/* Read card revision and enable MMIO */
	pci_read_config_byte ( pci, PCI_REVISION, &revision );
	DBGC ( rhn, "RHINE %p revision %#02x detected\n", rhn, revision );
	rhine_enable_mmio ( rhn, revision );

	/* Read MAC address */
	for ( i = 0 ; i < ETH_ALEN ; i++ )
		netdev->hw_addr[i] = readb ( rhn->regs + RHINE_MAC + i );

	/* Initialise and reset MII interface */
	mii_init ( &rhn->mii, &rhine_mii_operations );
	if ( ( rc = mii_reset ( &rhn->mii ) ) != 0 ) {
		DBGC ( rhn, "RHINE %p could not reset MII: %s\n",
		       rhn, strerror ( rc ) );
		goto err_mii_reset;
	}
	DBGC ( rhn, "RHINE PHY vendor %04x device %04x\n",
	       rhine_mii_read ( &rhn->mii, 0x02 ),
	       rhine_mii_read ( &rhn->mii, 0x03 ) );

	/* Register network device */
	if ( ( rc = register_netdev ( netdev ) ) != 0 )
		goto err_register_netdev;

	/* Set initial link state */
	rhine_check_link ( netdev );

	return 0;

 err_register_netdev:
 err_mii_reset:
 err_reload_eeprom:
	rhine_reset ( rhn );
 err_reset:
	netdev_nullify ( netdev );
	netdev_put ( netdev );
 err_alloc:
	return rc;
}