Пример #1
0
static void hieth_net_isr_proc(struct hieth_netdev_local *ld, int ints)
{
	if ((ints & UD_BIT_NAME(HIETH_INT_MULTI_RXRDY)) &&
			(hieth_hw_recv_tryup(ld) > 0)) {

		tasklet_schedule(&ld->bf_recv);
	}

	if (ints & UD_BIT_NAME(HIETH_INT_TXQUE_RDY)) {

		hieth_irq_disable(ld, UD_BIT_NAME(HIETH_INT_TXQUE_RDY));
		netif_wake_queue(hieth_devs_save[ld->port]);
	}
}
Пример #2
0
int hieth_glb_preinit_dummy(struct hieth_netdev_local *ld)
{
	local_lock_init(ld);

	//FIXME: hieth_glb_preinit_dummy
	//HW MAX DEFAULT RX-PKT-LEN [42,1518]
	//HW MAC FILTER TABLE DISABLE

	/*soft reset */
	hieth_writel_bits(ld, 1, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET);
	udelay(1000);
	hieth_writel_bits(ld, 0, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET);

	hieth_set_endian_mode(ld, HIETH_LITTLE_ENDIAN);

	hieth_set_linkstat(ld, 0);

	hieth_set_negmode(ld, HIETH_NEGMODE_CPUSET);

	/* RMII mode */
	hieth_set_mii_mode(ld, UD_BIT_NAME(HIETH_MII_RMII_MODE));

	hieth_writel_bits(ld, ~0, GLB_RW_IRQ_ENA, UD_BIT_NAME(BITS_IRQS));
	hieth_writel_bits(ld, ~0, GLB_RW_IRQ_ENA, UD_BIT_NAME(BITS_IRQS_ENA));
	hieth_writel_bits(ld, ~0, GLB_RW_IRQ_ENA, BITS_IRQS_ENA_ALLPORT);
	hieth_irq_disable(ld, ~0);

	/* init */
	hieth_writel(ld, 0, GLB_FWCTRL);
	hieth_writel(ld, 0, GLB_MACTCTRL);

	/*disable vlan func */
	hieth_writel_bits(ld, 0, GLB_FWCTRL, BITS_VLAN_ENABLE);

	/*enable UpEther<->CPU */
	hieth_writel_bits(ld, 1, GLB_FWCTRL, BITS_FW2CPU_ENA_UP);
	hieth_writel_bits(ld, 0, GLB_FWCTRL, BITS_FWALL2CPU_UP);
	hieth_writel_bits(ld, 0, GLB_MACTCTRL, BITS_BROAD2CPU_UP);
	hieth_writel_bits(ld, 1, GLB_MACTCTRL, BITS_MACT_ENA_UP);

	/*enable DownEther<->CPU and UpEther<->CPU */
	hieth_writel_bits(ld, 1, GLB_FWCTRL, BITS_FW2CPU_ENA_DOWN);
	hieth_writel_bits(ld, 0, GLB_FWCTRL, BITS_FWALL2CPU_DOWN);
	hieth_writel_bits(ld, 0, GLB_MACTCTRL, BITS_BROAD2CPU_DOWN);
	hieth_writel_bits(ld, 1, GLB_MACTCTRL, BITS_MACT_ENA_DOWN);

	hieth_set_mac_leadcode_cnt_limit(ld, 0);

	return 0;
}
Пример #3
0
static int hieth_net_hard_start_xmit(
		struct sk_buff *skb,
		struct net_device *dev)
{
	int ret;
	struct hieth_netdev_local *ld = netdev_priv(dev);
	int tx_lpi_assert = 0x2;
	unsigned int data;
	data = readl(ld->iobase + 0x488);

	data &= ~tx_lpi_assert;
	writel(data, ld->iobase + 0x488);

	hieth_xmit_release_skb(ld);

	dma_map_single(ld->dev, skb->data, skb->len, DMA_TO_DEVICE);

	ret = hieth_xmit_real_send(ld, skb);
	if (ret < 0) {
		ld->stats.tx_dropped++;
		hieth_error("tx bug, drop packet");
		BUG();
		return NETDEV_TX_BUSY;
	}

	dev->trans_start = jiffies;

	ld->stats.tx_packets++;
	ld->stats.tx_bytes += skb->len;

	hieth_clear_irqstatus(ld, UD_BIT_NAME(HIETH_INT_TXQUE_RDY));
	if (!hieth_hw_xmitq_ready(ld)) {
		netif_stop_queue(dev);
		hieth_irq_enable(ld, UD_BIT_NAME(HIETH_INT_TXQUE_RDY));
	}

	return NETDEV_TX_OK;
}
Пример #4
0
static void hieth_adjust_link(struct net_device *dev)
{
	int stat = 0;
	struct hieth_netdev_local *ld = netdev_priv(dev);

	stat |= (ld->phy->link) ? HIETH_LINKED : 0;
	stat |= (ld->phy->duplex == DUPLEX_FULL) ? HIETH_DUP_FULL : 0;
	stat |= (ld->phy->speed == SPEED_100) ? HIETH_SPD_100M : 0;

	if (stat != ld->link_stat) {
		if (ld->phy->link == 0) {
			printk(KERN_INFO "***link down status changed***.\n");
			writel(0x0, ld->iobase + 0x490);
			writel(0x0, ld->iobase + 0x484);
		} else {
			writel(0x1, ld->iobase + 0x490);
#ifdef CONFIG_EEE_SUPPORT
			if (eee_available > NO_EEE) {
				int data = ld->driver->eee_enable();
				if (DEBUG)
					printk(KERN_INFO "adjust_link "
						"data:(=2?): %d\n", data);
				if (eee_available == MAC_EEE) {
					writel(0x10, ld->iobase + 0x484);
					/* enable intr */
					writel(0x1f, ld->iobase + 0x480);
				} else
					writel(0x0, ld->iobase + 0x484);

			}
#endif
		}

		hieth_set_linkstat(ld, stat);
		phy_print_status(ld->phy);
		ld->link_stat = stat;
		hieth_set_mii_mode(ld, UD_BIT_NAME(CONFIG_HIETH_MII_RMII_MODE));
	}
}
Пример #5
0
static int hieth_net_close(struct net_device *dev)
{
	struct hieth_netdev_local *ld = netdev_priv(dev);

	hieth_irq_disable(ld, UD_BIT_NAME(HIETH_INT_MULTI_RXRDY));

	phy_stop(ld->phy);

	del_timer_sync(&ld->monitor);

	/* reset and init port */
	hieth_port_reset(ld, ld->port);
	hieth_port_init(ld, ld->port);

	skb_queue_purge(&ld->rx_head);
	skb_queue_purge(&ld->rx_hw);
	skb_queue_purge(&ld->tx_hw);
	ld->tx_hw_cnt = 0;

	module_put(THIS_MODULE);

	return 0;
}
Пример #6
0
static int hieth_platdev_probe_port(struct platform_device *pdev, int port)
{
	int ret = -1;
	struct net_device *netdev = NULL;
	struct hieth_netdev_local *ld;

	if ((UP_PORT != port) && (DOWN_PORT != port)) {
		hieth_error("port error!");
		ret = -ENODEV;
		goto _error_exit;
	}

	netdev = alloc_etherdev(sizeof(*ld));
	if (netdev == NULL) {
		hieth_error("alloc_etherdev fail!");
		ret = -ENOMEM;
		goto _error_alloc_etherdev;
	}
	SET_NETDEV_DEV(netdev, &pdev->dev);
	netdev->irq = CONFIG_HIETH_IRQNUM;
	netdev->watchdog_timeo	= 3*HZ;
	netdev->netdev_ops	= &hieth_netdev_ops;
	netdev->ethtool_ops	= &hieth_ethtools_ops;

	/* init hieth_global somethings... */
	hieth_devs_save[port] = netdev;

	/* init hieth_local_driver */
	ld = netdev_priv(netdev);
	memset(ld, 0, sizeof(*ld));

	local_lock_init(ld);

	ld->iobase = (unsigned long)ioremap_nocache(CONFIG_HIETH_IOBASE, \
					CONFIG_HIETH_IOSIZE);
	if (!ld->iobase) {
		hieth_error("ioremap_nocache err, base=0x%.8x, size=0x%.8x\n",
				CONFIG_HIETH_IOBASE, CONFIG_HIETH_IOSIZE);
		ret = -EFAULT;
		goto _error_ioremap_nocache;
	}
	ld->iobase_phys = CONFIG_HIETH_IOBASE;

	ld->port = port;

	ld->dev = &(pdev->dev);

	/* reset and init port */
	hieth_port_reset(ld, ld->port);
	hieth_port_init(ld, ld->port);

	ld->depth.hw_xmitq = CONFIG_HIETH_HWQ_XMIT_DEPTH;

	memset(ld->phy_name, 0, sizeof(ld->phy_name));
	snprintf(ld->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, \
		HIETH_MIIBUS_NAME, UD_PHY_NAME(CONFIG_HIETH_PHYID));

	ld->phy = phy_connect(netdev, ld->phy_name, hieth_adjust_link, 0, \
			UD_BIT_NAME(CONFIG_HIETH_MII_RMII_MODE) ? \
			PHY_INTERFACE_MODE_MII : PHY_INTERFACE_MODE_MII);
	if (IS_ERR(ld->phy)) {
		hieth_error("connect to phy_device %s failed!", ld->phy_name);
		ld->phy = NULL;
		goto _error_phy_connect;
	}

	skb_queue_head_init(&ld->rx_head);
	skb_queue_head_init(&ld->rx_hw);
	skb_queue_head_init(&ld->tx_hw);
	ld->tx_hw_cnt = 0;

	ret = hieth_init_skb_buffers(ld);
	if (ret) {
		hieth_error("hieth_init_skb_buffers failed!");
		goto _error_init_skb_buffers;
	}

	ret = register_netdev(netdev);
	if (ret) {
		hieth_error("register_netdev %s failed!", netdev->name);
		goto _error_register_netdev;
	}

	return ret;

_error_register_netdev:
	hieth_destroy_skb_buffers(ld);

_error_init_skb_buffers:
	phy_disconnect(ld->phy);
	ld->phy = NULL;

_error_phy_connect:
	iounmap((void *)ld->iobase);

_error_ioremap_nocache:
	local_lock_exit();
	hieth_devs_save[port] = NULL;
	free_netdev(netdev);

_error_alloc_etherdev:

_error_exit:
	return ret;
}
Пример #7
0
static int hieth_net_open(struct net_device *dev)
{
	struct hieth_netdev_local *ld = netdev_priv(dev);
	unsigned int data;
	unsigned long phy_id;

	try_module_get(THIS_MODULE);

	/* init tasklet */
	ld->bf_recv.next = NULL;
	ld->bf_recv.state = 0;
	ld->bf_recv.func = hieth_bfproc_recv;
	ld->bf_recv.data = (unsigned long)dev;
	atomic_set(&ld->bf_recv.count, 0);

	/* setup hardware */
	hieth_set_hwq_depth(ld);

	hieth_clear_irqstatus(ld, UD_BIT_NAME(BITS_IRQS_MASK));

	netif_carrier_off(dev);

	hieth_feed_hw(ld);

	netif_start_queue(dev);

	ld->link_stat = 0;
	phy_start(ld->phy);

	hieth_irq_enable(ld, UD_BIT_NAME(HIETH_INT_MULTI_RXRDY));
	hieth_writel_bits(ld, 1, GLB_RW_IRQ_ENA, UD_BIT_NAME(BITS_IRQS_ENA));
	hieth_writel_bits(ld, 1, GLB_RW_IRQ_ENA, BITS_IRQS_ENA_ALLPORT);

	init_timer(&ld->monitor);
	ld->monitor.function = hieth_monitor_func;
	ld->monitor.data = (unsigned long)dev;
	ld->monitor.expires = jiffies
		+ msecs_to_jiffies(CONFIG_HIETH_MONITOR_TIMER);
	add_timer(&ld->monitor);

	data = readl(ld->iobase + 0x210);
	data |= 0x40000000;	/* do CRC check in mac*/
	writel(data, ld->iobase + 0x210);


	phy_id = phy_id_read();

#ifdef CONFIG_EEE_SUPPORT
	hiphyinfo = phy_search_ids(phy_id);

	if (hiphyinfo) {
		eee_available = hiphyinfo->with_eee;
		if (DEBUG)
			printk(KERN_INFO "fit_phy_id : %x, phy_name: %s,"
				"eee :%x\n", (unsigned int)hiphyinfo->phy_id,
				hiphyinfo->name, (unsigned int)eee_available);
		ld->driver = hiphyinfo->driver;

		if (eee_available > NO_EEE) {
			data = 0x0;
			data_tmp = ld->driver->eee_enable();

			if (eee_available == MAC_EEE) {
				/* init EEE timer */
				/* 0x35 only for FPGA(54M)*/
				writel(0x35, ld->iobase + 0x494);
				writel(0x1e03e8, ld->iobase + 0x48c);
				writel(0xf42400, ld->iobase + 0x488);
				data = readl(ld->iobase + 0x490);
				data |= 0x2;
				writel(data, ld->iobase + 0x490);

				/* enable EEE */
				writel(0x10, ld->iobase + 0x484);
				if (DEBUG)
					printk(KERN_INFO "mac eee mode start "
							"to enable, eee :%x\n",
							eee_available);
				data = readl(ld->iobase + 0x488);
				data |= 0x1;    /* mac-eee_enable */
				writel(data, ld->iobase + 0x488);
			}

		}

	} else {
		printk(KERN_INFO "non-EEE mode\n");
		eee_available = NO_EEE;
	}
#endif
	return 0;
}