Example #1
0
static int phy_autoneg(struct net_device *dev)
{
	struct tangox_enet_priv *priv;
	int loop;
	unsigned int val = 0;

	priv = netdev_priv(dev);

	/* reset phy */
	val = enet_mdio_read(dev, priv->mii.phy_id, MII_BMCR);
	enet_mdio_write(dev, priv->mii.phy_id, MII_BMCR, val | BMCR_ANENABLE|BMCR_ANRESTART);
	udelay(100);
	loop = 10000;
	while (loop) {
	if (enet_mdio_read(dev, priv->mii.phy_id, MII_BMSR) &  BMSR_ANEGCOMPLETE)
			break;

		mdelay(1);
		loop--;
	}

	if (!loop) {
		printk(KERN_ERR "%s: PHY autonegotiation does not complete...\n", priv->name);
		return -EBUSY;
	}
	return 0;
}
Example #2
0
static int phy_reset(struct net_device *dev)
{
	struct tangox_enet_priv *priv;
	int loop;
	unsigned int val = 0;

	priv = netdev_priv(dev);

	/* reset phy */
	val = enet_mdio_read(dev, priv->mii.phy_id, MII_BMCR);
	enet_mdio_write(dev, priv->mii.phy_id, MII_BMCR, val | BMCR_RESET);

	/* wait for the reset bit to clear */
	udelay(100);
	loop = 100;
	while (loop) {
		if (!(enet_mdio_read(dev, priv->mii.phy_id,
				     MII_BMCR) & BMCR_RESET))
			break;
		mdelay(1);
		loop--;
	}

	if (!loop) {
		printk(KERN_ERR "%s: PHY reset does not complete...\n", priv->name);
		return -EBUSY;
	}
	return 0;
}
Example #3
0
static int enet_get_speed(struct net_device *dev)
{
	struct tangox_enet_priv *priv;
	unsigned int physr;
	int speed = 100;

	priv = netdev_priv(dev);
	if(priv->rgmii == 0){
		/*Realtek*/
		physr = enet_mdio_read(dev, priv->mii.phy_id, MII_PHYADDR);
		switch(physr & 0x3){
		case 1:
			speed = 100;
			break;
		case 2:
			speed = 10;
			break;
		default:			
			speed = 0;
			break;
		}
		return speed;
	}
	/* Vitesse */
	physr = enet_mdio_read(dev, priv->mii.phy_id, MII_NCONFIG);
	physr >>= 3;

	switch(physr & 0x3){
		case 0:	
			speed = 10;
			break;
		case 1:
			speed = 100;
			break;
		case 2:
			speed = 1000;
			break;
		case 3:
			speed = 0;
			break;
	}
	return speed;
}
Example #4
0
static void enet_mac_config(struct net_device *dev)
{
	struct tangox_enet_priv *priv;
	unsigned char val;
	int speed;

	priv = netdev_priv(dev);

	if(priv->rgmii == 0) {
		/* 100 baseT, realtek*/
		val = enet_readb(ENET_MAC_MODE(priv->enet_mac_base));
		if(val & (GMAC_MODE | RGMII_MODE)){
			val &= ~(GMAC_MODE | RGMII_MODE);    /*disable Gigabit mode for now*/
			//val |= /*LB_EN |*/ BST_EN;	     /*loopback off, burst on*/
			enet_writeb(ENET_MAC_MODE(priv->enet_mac_base), val);
		}
		return;
	}

	/*set RGMII skew timing compensation enable */
	/* This added 2ns delay to RX_CLK and TX_CLK*/
	val = enet_mdio_read(dev, priv->mii.phy_id, MII_RESV1);
	enet_mdio_write(dev, priv->mii.phy_id, MII_RESV1 , val | (1<<8));
	
	val = enet_readl(ENET_MAC_MODE(priv->enet_mac_base));
	speed = enet_get_speed(dev);
	if(speed == 1000 ){
		if((val & RGMII_MODE) && (val & GMAC_MODE))
			return; /* configured for gigabit */

		val |= RGMII_MODE;	
		val |= GMAC_MODE;
		enet_writeb(ENET_MAC_MODE(priv->enet_mac_base), val);
		//printk("set 1000mbps  val=0x%x\n",  val);
	}else if(speed == 100){
		if((val & RGMII_MODE) && !(val & GMAC_MODE))
			return; /* configured for 100mbps*/
		val |= RGMII_MODE;	
		val &= ~GMAC_MODE;
		enet_writeb(ENET_MAC_MODE(priv->enet_mac_base), val);
    	//printk("set 100mbps  val=0x%x\n",  val);
	}else /*TODO*/
	;	//printk("set 10 mbps or other val=0x%x\n",  val);

	/*set threshold for internal clock 0x1*/
	enet_writeb(ENET_IC_THRESHOLD(priv->enet_mac_base), (speed==1000 ? 3:1));

	/*set slot time  0x7f for 10/100Mbps*/
	enet_writeb(ENET_SLOT_TIME(priv->enet_mac_base), (speed==1000 ? 0xff : 0x7f));

	//phy_autoneg(dev);
}
Example #5
0
int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr)
{
	return enet_mdio_read((struct enet*)bus->priv, phyAddr, regAddr);
}
Example #6
0
static int enet_probe(int idx)
{
	struct tangox_enet_priv *priv;
	struct net_device *dev;
	int ret;
	struct sockaddr sock;
	char pad_mode;
	short clk_div;
	unsigned long enet_mac_base;
	const char *name;

	enet_mac_base = eth_mac_cores[idx].enet_mac_base;
	name = eth_mac_cores[idx].name;

#if 1 /* this part may be moved to boot loader */
	/* set pad_mode*/
	pad_mode = enet_readb(enet_mac_base + 0x400);
	enet_writeb(enet_mac_base + 0x400, pad_mode & 0xf0);
	pad_mode = enet_readb(enet_mac_base + 0x400);

	/* set MDIO clock divider */
	clk_div = enet_readw(enet_mac_base + 0x420);
	//DBG("default clk_div =%d\n", clk_div);
	//enet_writew(enet_mac_base + 0x420, 50);
	enet_writew(enet_mac_base + 0x420, tangox_get_sysclock() / (2500000 * 2));
	clk_div = enet_readw(enet_mac_base + 0x420);
	//DBG("clk_div =%d: set MDIO clock=200/%d=%dMHz\n", clk_div, clk_div, 200/(clk_div*2));
#endif

	/* allocate  netdevice structure  with enough  length  for our
	 * context data */
	dev = alloc_etherdev(sizeof (*priv));
	if (!dev)
		return -ENOMEM;

	/* initialize private data */
	priv = netdev_priv(dev);
	memset(priv, 0, sizeof (*priv));
	priv->enet_mac_base = enet_mac_base;
	priv->name = name;
	priv->pending_tx = -1;
	priv->pending_tx_cnt = 0;
	priv->reclaim_limit = -1;
	spin_lock_init(&priv->tx_lock);
	spin_lock_init(&priv->ier_lock);
	spin_lock_init(&priv->maccr_lock);

	/* init tx done tasklet */
	tasklet_init(&priv->tx_reclaim_tasklet, enet_tx_reclaim,
		     (unsigned long)dev);
#if 0
	/* init tx reclaim timer */
	init_timer(&priv->tx_reclaim_timer);
	priv->tx_reclaim_timer.data = (unsigned long )dev;
	priv->tx_reclaim_timer.function = enet_tx_reclaim_timer;
#endif
	/* init link check timer and mii lock */
	init_timer(&priv->link_check_timer);
	priv->link_check_timer.data = (unsigned long)dev;
	priv->link_check_timer.function = enet_link_check;
	spin_lock_init(&priv->mii_lock);

	/* fill mii info */
	priv->mii.dev = dev;
	priv->mii.phy_id_mask  = 0x1f;
	priv->mii.reg_num_mask = 0x1f;
	priv->mii.mdio_read = enet_mdio_read;
	priv->mii.mdio_write = enet_mdio_write;
	
	if (eth_mac_cores[idx].phy_id != -1) {
		/* phy id forced, just check for sanity */
		if (eth_mac_cores[idx].phy_id < 0 || eth_mac_cores[idx].phy_id > 31) {
			ret = -EINVAL;
			goto err_free;
		}
		priv->mii.phy_id = eth_mac_cores[idx].phy_id;

	} else {
		int i;

		/* try to probe phy if not given */
		for (i = 0; i <32; i++) {
			uint32_t id;
			int val;

			val = enet_mdio_read(dev, i, MII_PHYSID1);
			id = (val << 16);
			val = enet_mdio_read(dev, i, MII_PHYSID2);
			id |= val;
			if (id != 0xffffffff && id != 0x00000000) {
				/* check vsc8061 */
				if(id == 0x00070421)
					priv->rgmii = 1;
				break;
			}
		}
		if (i == 32) {
			printk(KERN_ERR "%s: unable to autodetect phy\n", priv->name);
			ret = -EIO;
			goto err_free;
		}
		printk(KERN_ERR "%s: detected phy %s at address 0x%02x\n", name,(priv->rgmii? "vsc8601":""), i);
		priv->mii.phy_id = i;
	}

	printk(KERN_INFO "%s: Ethernet driver for SMP864x/SMP865x internal MAC core %d: %s Base at 0x%lx\n",
				 name, idx, priv->rgmii?"1000Mbps":"100Mbps",  enet_mac_base);

	/* initialize hardware */
	if ((ret = enet_hw_init(dev)))
		goto err_free;

	/* initialize dma descriptors */
	if ((ret = enet_dma_init(priv)))
		goto err_free;

	ret = request_irq(eth_mac_cores[idx].irq, enet_isr, IRQF_DISABLED,
			  eth_mac_cores[idx].name, dev);
	dev->irq = eth_mac_cores[idx].irq;

	if (ret)
		goto err_free;

	/* install driver callbacks and register netdevice */
	dev->open = enet_open;
	dev->stop = enet_stop;
	dev->hard_start_xmit = enet_xmit;
	dev->get_stats = enet_get_stats;
	dev->set_mac_address = enet_set_mac_address;
	dev->set_multicast_list = enet_set_multicast_list;
	dev->poll = enet_poll;
	dev->ethtool_ops = &enet_ethtool_ops;
	dev->do_ioctl = enet_ioctl;
	dev->weight = RX_DESC_COUNT;
	dev->tx_queue_len = TX_DESC_COUNT;
#ifdef ENABLE_MULTICAST
	dev->flags |= IFF_MULTICAST;
#else	
	dev->flags &= ~IFF_MULTICAST;
#endif

	/* set default mac address */
	tangox_ethernet_getmac(idx, dev->dev_addr);
	memcpy(&(sock.sa_data), dev->dev_addr, ETH_ALEN);

	enet_set_mac_address(dev, &sock);

	if ((ret = register_netdev(dev))) {
		printk(KERN_ERR "%s: unable to register netdevice\n", priv->name);
		goto err_free;
	}

	printk(KERN_INFO "%s: mac address %02x:%02x:%02x:%02x:%02x:%02x\n", priv->name,
	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
	       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);

	eth_mac_cores[idx].gdev = dev;
	return 0;

err_free:
	if (dev->irq)
		free_irq(dev->irq, dev);
	enet_dma_free(priv);
	free_netdev(dev);
	return ret;
}