18a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/*
28a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * Xilinx Axi Ethernet device driver
38a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
48a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * Copyright (c) 2008 Nissin Systems Co., Ltd.,  Yoshio Kashiwagi
58a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * Copyright (c) 2005-2008 DLA Systems,  David H. Lynch Jr. <dhlii@dlasys.net>
68a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * Copyright (c) 2008-2009 Secret Lab Technologies Ltd.
759a54f3082b9847c1240e24879750e3a03f96754Michal Simek * Copyright (c) 2010 - 2011 Michal Simek <monstr@monstr.eu>
859a54f3082b9847c1240e24879750e3a03f96754Michal Simek * Copyright (c) 2010 - 2011 PetaLogix
959a54f3082b9847c1240e24879750e3a03f96754Michal Simek * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved.
108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This is a driver for the Xilinx Axi Ethernet which is used in the Virtex6
128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * and Spartan6.
138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * TODO:
158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *  - Add Axi Fifo support.
168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *  - Factor out Axi DMA code into separate driver.
178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *  - Test and fix basic multicast filtering.
188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *  - Add support for extended multicast filtering.
198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *  - Test basic VLAN support.
208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *  - Add support for extended VLAN support.
218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#include <linux/delay.h>
248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#include <linux/etherdevice.h>
258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#include <linux/init.h>
268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#include <linux/module.h>
278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#include <linux/netdevice.h>
288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#include <linux/of_mdio.h>
298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#include <linux/of_platform.h>
308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#include <linux/of_address.h>
318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#include <linux/skbuff.h>
328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#include <linux/spinlock.h>
338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#include <linux/phy.h>
348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#include <linux/mii.h>
358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#include <linux/ethtool.h>
368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#include "xilinx_axienet.h"
388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/* Descriptors defines for Tx and Rx DMA - 2^n for the best performance */
408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#define TX_BD_NUM		64
418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#define RX_BD_NUM		128
428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/* Must be shorter than length of ethtool_drvinfo.driver field to fit */
448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#define DRIVER_NAME		"xaxienet"
458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#define DRIVER_DESCRIPTION	"Xilinx Axi Ethernet driver"
468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#define DRIVER_VERSION		"1.00a"
478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#define AXIENET_REGS_N		32
498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/* Match table for of_platform binding */
518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic struct of_device_id axienet_of_match[] __devinitdata = {
528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	{ .compatible = "xlnx,axi-ethernet-1.00.a", },
538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	{ .compatible = "xlnx,axi-ethernet-1.01.a", },
548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	{ .compatible = "xlnx,axi-ethernet-2.01.a", },
558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	{},
568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net};
578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netMODULE_DEVICE_TABLE(of, axienet_of_match);
598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/* Option table for setting up Axi Ethernet hardware options */
618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic struct axienet_option axienet_options[] = {
628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Turn on jumbo packet support for both Rx and Tx */
638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	{
648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.opt = XAE_OPTION_JUMBO,
658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.reg = XAE_TC_OFFSET,
668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.m_or = XAE_TC_JUM_MASK,
678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}, {
688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.opt = XAE_OPTION_JUMBO,
698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.reg = XAE_RCW1_OFFSET,
708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.m_or = XAE_RCW1_JUM_MASK,
718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}, { /* Turn on VLAN packet support for both Rx and Tx */
728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.opt = XAE_OPTION_VLAN,
738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.reg = XAE_TC_OFFSET,
748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.m_or = XAE_TC_VLAN_MASK,
758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}, {
768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.opt = XAE_OPTION_VLAN,
778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.reg = XAE_RCW1_OFFSET,
788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.m_or = XAE_RCW1_VLAN_MASK,
798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}, { /* Turn on FCS stripping on receive packets */
808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.opt = XAE_OPTION_FCS_STRIP,
818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.reg = XAE_RCW1_OFFSET,
828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.m_or = XAE_RCW1_FCS_MASK,
838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}, { /* Turn on FCS insertion on transmit packets */
848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.opt = XAE_OPTION_FCS_INSERT,
858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.reg = XAE_TC_OFFSET,
868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.m_or = XAE_TC_FCS_MASK,
878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}, { /* Turn off length/type field checking on receive packets */
888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.opt = XAE_OPTION_LENTYPE_ERR,
898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.reg = XAE_RCW1_OFFSET,
908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.m_or = XAE_RCW1_LT_DIS_MASK,
918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}, { /* Turn on Rx flow control */
928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.opt = XAE_OPTION_FLOW_CONTROL,
938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.reg = XAE_FCC_OFFSET,
948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.m_or = XAE_FCC_FCRX_MASK,
958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}, { /* Turn on Tx flow control */
968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.opt = XAE_OPTION_FLOW_CONTROL,
978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.reg = XAE_FCC_OFFSET,
988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.m_or = XAE_FCC_FCTX_MASK,
998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}, { /* Turn on promiscuous frame filtering */
1008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.opt = XAE_OPTION_PROMISC,
1018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.reg = XAE_FMI_OFFSET,
1028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.m_or = XAE_FMI_PM_MASK,
1038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}, { /* Enable transmitter */
1048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.opt = XAE_OPTION_TXEN,
1058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.reg = XAE_TC_OFFSET,
1068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.m_or = XAE_TC_TX_MASK,
1078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}, { /* Enable receiver */
1088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.opt = XAE_OPTION_RXEN,
1098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.reg = XAE_RCW1_OFFSET,
1108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		.m_or = XAE_RCW1_RX_MASK,
1118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	},
1128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	{}
1138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net};
1148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
1158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
1168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_dma_in32 - Memory mapped Axi DMA register read
1178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @lp:		Pointer to axienet local structure
1188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @reg:	Address offset from the base address of the Axi DMA core
1198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
1208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * returns: The contents of the Axi DMA register
1218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
1228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This function returns the contents of the corresponding Axi DMA register.
1238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
1248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic inline u32 axienet_dma_in32(struct axienet_local *lp, off_t reg)
1258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
1268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return in_be32(lp->dma_regs + reg);
1278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
1288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
1298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
1308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_dma_out32 - Memory mapped Axi DMA register write.
1318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @lp:		Pointer to axienet local structure
1328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @reg:	Address offset from the base address of the Axi DMA core
1338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @value:	Value to be written into the Axi DMA register
1348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
1358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This function writes the desired value into the corresponding Axi DMA
1368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * register.
1378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
1388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic inline void axienet_dma_out32(struct axienet_local *lp,
1398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				     off_t reg, u32 value)
1408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
1418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	out_be32((lp->dma_regs + reg), value);
1428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
1438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
1448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
1458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_dma_bd_release - Release buffer descriptor rings
1468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to the net_device structure
1478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
1488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This function is used to release the descriptors allocated in
1498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_dma_bd_init. axienet_dma_bd_release is called when Axi Ethernet
1508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * driver stop api is called.
1518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
1528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic void axienet_dma_bd_release(struct net_device *ndev)
1538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
1548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	int i;
1558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
1568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
1578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	for (i = 0; i < RX_BD_NUM; i++) {
1588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dma_unmap_single(ndev->dev.parent, lp->rx_bd_v[i].phys,
1598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				 lp->max_frm_size, DMA_FROM_DEVICE);
1608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_kfree_skb((struct sk_buff *)
1618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			      (lp->rx_bd_v[i].sw_id_offset));
1628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
1638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
1648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (lp->rx_bd_v) {
1658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dma_free_coherent(ndev->dev.parent,
1668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				  sizeof(*lp->rx_bd_v) * RX_BD_NUM,
1678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				  lp->rx_bd_v,
1688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				  lp->rx_bd_p);
1698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
1708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (lp->tx_bd_v) {
1718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dma_free_coherent(ndev->dev.parent,
1728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				  sizeof(*lp->tx_bd_v) * TX_BD_NUM,
1738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				  lp->tx_bd_v,
1748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				  lp->tx_bd_p);
1758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
1768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
1778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
1788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
1798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_dma_bd_init - Setup buffer descriptor rings for Axi DMA
1808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to the net_device structure
1818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
1828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * returns: 0, on success
1838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *	    -ENOMEM, on failure
1848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
1858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This function is called to initialize the Rx and Tx DMA descriptor
1868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * rings. This initializes the descriptors with required default values
1878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * and is called when Axi Ethernet driver reset is called.
1888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
1898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic int axienet_dma_bd_init(struct net_device *ndev)
1908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
1918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 cr;
1928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	int i;
1938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct sk_buff *skb;
1948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
1958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
1968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Reset the indexes which are used for accessing the BDs */
1978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->tx_bd_ci = 0;
1988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->tx_bd_tail = 0;
1998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->rx_bd_ci = 0;
2008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
2018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/*
2028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * Allocate the Tx and Rx buffer descriptors.
2038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 */
2048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
2058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					 sizeof(*lp->tx_bd_v) * TX_BD_NUM,
2068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					 &lp->tx_bd_p,
2078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					 GFP_KERNEL);
2088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (!lp->tx_bd_v) {
2098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(&ndev->dev, "unable to allocate DMA Tx buffer "
2108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			"descriptors");
2118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		goto out;
2128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
2138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
2148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
2158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					 sizeof(*lp->rx_bd_v) * RX_BD_NUM,
2168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					 &lp->rx_bd_p,
2178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					 GFP_KERNEL);
2188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (!lp->rx_bd_v) {
2198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(&ndev->dev, "unable to allocate DMA Rx buffer "
2208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			"descriptors");
2218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		goto out;
2228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
2238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
2248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM);
2258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	for (i = 0; i < TX_BD_NUM; i++) {
2268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->tx_bd_v[i].next = lp->tx_bd_p +
2278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				      sizeof(*lp->tx_bd_v) *
2288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				      ((i + 1) % TX_BD_NUM);
2298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
2308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
2318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	memset(lp->rx_bd_v, 0, sizeof(*lp->rx_bd_v) * RX_BD_NUM);
2328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	for (i = 0; i < RX_BD_NUM; i++) {
2338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->rx_bd_v[i].next = lp->rx_bd_p +
2348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				      sizeof(*lp->rx_bd_v) *
2358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				      ((i + 1) % RX_BD_NUM);
2368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
2378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size);
2388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if (!skb) {
2398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			dev_err(&ndev->dev, "alloc_skb error %d\n", i);
2408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			goto out;
2418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		}
2428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
2438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->rx_bd_v[i].sw_id_offset = (u32) skb;
2448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent,
2458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net						     skb->data,
2468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net						     lp->max_frm_size,
2478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net						     DMA_FROM_DEVICE);
2488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->rx_bd_v[i].cntrl = lp->max_frm_size;
2498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
2508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
2518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Start updating the Rx channel control register */
2528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
2538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Update the interrupt coalesce count */
2548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = ((cr & ~XAXIDMA_COALESCE_MASK) |
2558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	      ((lp->coalesce_count_rx) << XAXIDMA_COALESCE_SHIFT));
2568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Update the delay timer count */
2578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = ((cr & ~XAXIDMA_DELAY_MASK) |
2588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	      (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
2598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Enable coalesce, delay timer and error interrupts */
2608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr |= XAXIDMA_IRQ_ALL_MASK;
2618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Write to the Rx channel control register */
2628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
2638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
2648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Start updating the Tx channel control register */
2658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
2668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Update the interrupt coalesce count */
2678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = (((cr & ~XAXIDMA_COALESCE_MASK)) |
2688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	      ((lp->coalesce_count_tx) << XAXIDMA_COALESCE_SHIFT));
2698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Update the delay timer count */
2708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = (((cr & ~XAXIDMA_DELAY_MASK)) |
2718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	      (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
2728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Enable coalesce, delay timer and error interrupts */
2738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr |= XAXIDMA_IRQ_ALL_MASK;
2748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Write to the Tx channel control register */
2758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
2768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
2778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Populate the tail pointer and bring the Rx Axi DMA engine out of
2788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * halted state. This will make the Rx side ready for reception.*/
2798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p);
2808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
2818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET,
2828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			  cr | XAXIDMA_CR_RUNSTOP_MASK);
2838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p +
2848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			  (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
2858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
2868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Write to the RS (Run-stop) bit in the Tx channel control register.
2878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * Tx channel is now ready to run. But only after we write to the
2888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * tail pointer register that the Tx channel will start transmitting */
2898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p);
2908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
2918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET,
2928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			  cr | XAXIDMA_CR_RUNSTOP_MASK);
2938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
2948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return 0;
2958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netout:
2968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_bd_release(ndev);
2978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return -ENOMEM;
2988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
2998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
3008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
3018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_set_mac_address - Write the MAC address
3028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to the net_device structure
3038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @address:	6 byte Address to be written as MAC address
3048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
3058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This function is called to initialize the MAC address of the Axi Ethernet
3068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * core. It writes to the UAW0 and UAW1 registers of the core.
3078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
3088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic void axienet_set_mac_address(struct net_device *ndev, void *address)
3098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
3108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
3118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
3128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (address)
3138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		memcpy(ndev->dev_addr, address, ETH_ALEN);
3148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (!is_valid_ether_addr(ndev->dev_addr))
3158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		random_ether_addr(ndev->dev_addr);
3168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
3178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Set up unicast MAC address filter set its mac address */
3188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_iow(lp, XAE_UAW0_OFFSET,
3198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		    (ndev->dev_addr[0]) |
3208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		    (ndev->dev_addr[1] << 8) |
3218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		    (ndev->dev_addr[2] << 16) |
3228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		    (ndev->dev_addr[3] << 24));
3238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_iow(lp, XAE_UAW1_OFFSET,
3248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		    (((axienet_ior(lp, XAE_UAW1_OFFSET)) &
3258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		      ~XAE_UAW1_UNICASTADDR_MASK) |
3268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		     (ndev->dev_addr[4] |
3278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		     (ndev->dev_addr[5] << 8))));
3288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
3298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
3308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
3318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * netdev_set_mac_address - Write the MAC address (from outside the driver)
3328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to the net_device structure
3338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @p:		6 byte Address to be written as MAC address
3348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
3358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * returns: 0 for all conditions. Presently, there is no failure case.
3368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
3378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This function is called to initialize the MAC address of the Axi Ethernet
3388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * core. It calls the core specific axienet_set_mac_address. This is the
3398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * function that goes into net_device_ops structure entry ndo_set_mac_address.
3408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
3418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic int netdev_set_mac_address(struct net_device *ndev, void *p)
3428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
3438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct sockaddr *addr = p;
3448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_set_mac_address(ndev, addr->sa_data);
3458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return 0;
3468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
3478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
3488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
3498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_set_multicast_list - Prepare the multicast table
3508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to the net_device structure
3518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
3528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This function is called to initialize the multicast table during
3538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * initialization. The Axi Ethernet basic multicast support has a four-entry
3548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * multicast table which is initialized here. Additionally this function
3558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * goes into the net_device_ops structure entry ndo_set_multicast_list. This
3568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * means whenever the multicast table entries need to be updated this
3578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * function gets called.
3588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
3598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic void axienet_set_multicast_list(struct net_device *ndev)
3608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
3618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	int i;
3628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 reg, af0reg, af1reg;
3638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
3648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
3658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC) ||
3668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    netdev_mc_count(ndev) > XAE_MULTICAST_CAM_TABLE_NUM) {
3678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		/* We must make the kernel realize we had to move into
3688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		 * promiscuous mode. If it was a promiscuous mode request
3698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		 * the flag is already set. If not we set it. */
3708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		ndev->flags |= IFF_PROMISC;
3718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		reg = axienet_ior(lp, XAE_FMI_OFFSET);
3728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		reg |= XAE_FMI_PM_MASK;
3738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		axienet_iow(lp, XAE_FMI_OFFSET, reg);
3748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_info(&ndev->dev, "Promiscuous mode enabled.\n");
3758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	} else if (!netdev_mc_empty(ndev)) {
3768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		struct netdev_hw_addr *ha;
3778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
3788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		i = 0;
3798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		netdev_for_each_mc_addr(ha, ndev) {
3808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			if (i >= XAE_MULTICAST_CAM_TABLE_NUM)
3818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				break;
3828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
3838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			af0reg = (ha->addr[0]);
3848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			af0reg |= (ha->addr[1] << 8);
3858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			af0reg |= (ha->addr[2] << 16);
3868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			af0reg |= (ha->addr[3] << 24);
3878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
3888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			af1reg = (ha->addr[4]);
3898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			af1reg |= (ha->addr[5] << 8);
3908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
3918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00;
3928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			reg |= i;
3938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
3948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			axienet_iow(lp, XAE_FMI_OFFSET, reg);
3958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			axienet_iow(lp, XAE_AF0_OFFSET, af0reg);
3968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			axienet_iow(lp, XAE_AF1_OFFSET, af1reg);
3978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			i++;
3988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		}
3998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	} else {
4008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		reg = axienet_ior(lp, XAE_FMI_OFFSET);
4018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		reg &= ~XAE_FMI_PM_MASK;
4028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
4038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		axienet_iow(lp, XAE_FMI_OFFSET, reg);
4048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
4058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		for (i = 0; i < XAE_MULTICAST_CAM_TABLE_NUM; i++) {
4068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00;
4078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			reg |= i;
4088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
4098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			axienet_iow(lp, XAE_FMI_OFFSET, reg);
4108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			axienet_iow(lp, XAE_AF0_OFFSET, 0);
4118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			axienet_iow(lp, XAE_AF1_OFFSET, 0);
4128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		}
4138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
4148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_info(&ndev->dev, "Promiscuous mode disabled.\n");
4158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
4168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
4178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
4188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
4198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_setoptions - Set an Axi Ethernet option
4208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to the net_device structure
4218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @options:	Option to be enabled/disabled
4228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
4238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * The Axi Ethernet core has multiple features which can be selectively turned
4248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * on or off. The typical options could be jumbo frame option, basic VLAN
4258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * option, promiscuous mode option etc. This function is used to set or clear
4268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * these options in the Axi Ethernet hardware. This is done through
4278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_option structure .
4288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
4298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic void axienet_setoptions(struct net_device *ndev, u32 options)
4308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
4318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	int reg;
4328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
4338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_option *tp = &axienet_options[0];
4348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
4358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	while (tp->opt) {
4368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		reg = ((axienet_ior(lp, tp->reg)) & ~(tp->m_or));
4378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if (options & tp->opt)
4388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			reg |= tp->m_or;
4398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		axienet_iow(lp, tp->reg, reg);
4408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		tp++;
4418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
4428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
4438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->options |= options;
4448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
4458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
4468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic void __axienet_device_reset(struct axienet_local *lp,
4478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				   struct device *dev, off_t offset)
4488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
4498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 timeout;
4508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Reset Axi DMA. This would reset Axi Ethernet core as well. The reset
4518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * process of Axi DMA takes a while to complete as all pending
4528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * commands/transfers will be flushed or completed during this
4538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * reset process. */
4548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, offset, XAXIDMA_CR_RESET_MASK);
4558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	timeout = DELAY_OF_ONE_MILLISEC;
4568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	while (axienet_dma_in32(lp, offset) & XAXIDMA_CR_RESET_MASK) {
4578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		udelay(1);
4588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if (--timeout == 0) {
4598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			dev_err(dev, "axienet_device_reset DMA "
4608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				"reset timeout!\n");
4618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			break;
4628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		}
4638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
4648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
4658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
4668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
4678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_device_reset - Reset and initialize the Axi Ethernet hardware.
4688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to the net_device structure
4698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
4708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This function is called to reset and initialize the Axi Ethernet core. This
4718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * is typically called during initialization. It does a reset of the Axi DMA
4728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * Rx/Tx channels and initializes the Axi DMA BDs. Since Axi DMA reset lines
4738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * areconnected to Axi Ethernet reset lines, this in turn resets the Axi
4748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * Ethernet core. No separate hardware reset is done for the Axi Ethernet
4758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * core.
4768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
4778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic void axienet_device_reset(struct net_device *ndev)
4788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
4798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 axienet_status;
4808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
4818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
4828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	__axienet_device_reset(lp, &ndev->dev, XAXIDMA_TX_CR_OFFSET);
4838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	__axienet_device_reset(lp, &ndev->dev, XAXIDMA_RX_CR_OFFSET);
4848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
4858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->max_frm_size = XAE_MAX_VLAN_FRAME_SIZE;
4868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->options &= (~XAE_OPTION_JUMBO);
4878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
4888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if ((ndev->mtu > XAE_MTU) &&
4898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ndev->mtu <= XAE_JUMBO_MTU) &&
4908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (lp->jumbo_support)) {
4918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->max_frm_size = ndev->mtu + XAE_HDR_VLAN_SIZE +
4928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				   XAE_TRL_SIZE;
4938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->options |= XAE_OPTION_JUMBO;
4948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
4958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
4968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (axienet_dma_bd_init(ndev)) {
4978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(&ndev->dev, "axienet_device_reset descriptor "
4988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			"allocation failed\n");
4998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
5008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
5018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_status = axienet_ior(lp, XAE_RCW1_OFFSET);
5028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_status &= ~XAE_RCW1_RX_MASK;
5038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_iow(lp, XAE_RCW1_OFFSET, axienet_status);
5048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
5058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_status = axienet_ior(lp, XAE_IP_OFFSET);
5068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (axienet_status & XAE_INT_RXRJECT_MASK)
5078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		axienet_iow(lp, XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK);
5088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
5098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_iow(lp, XAE_FCC_OFFSET, XAE_FCC_FCRX_MASK);
5108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
5118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Sync default options with HW but leave receiver and
5128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * transmitter disabled.*/
5138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_setoptions(ndev, lp->options &
5148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			   ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
5158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_set_mac_address(ndev, NULL);
5168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_set_multicast_list(ndev);
5178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_setoptions(ndev, lp->options);
5188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
5198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ndev->trans_start = jiffies;
5208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
5218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
5228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
5238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_adjust_link - Adjust the PHY link speed/duplex.
5248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to the net_device structure
5258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
5268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This function is called to change the speed and duplex setting after
5278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * auto negotiation is done by the PHY. This is the function that gets
5288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * registered with the PHY interface through the "of_phy_connect" call.
5298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
5308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic void axienet_adjust_link(struct net_device *ndev)
5318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
5328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 emmc_reg;
5338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 link_state;
5348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 setspeed = 1;
5358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
5368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct phy_device *phy = lp->phy_dev;
5378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
5388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	link_state = phy->speed | (phy->duplex << 1) | phy->link;
5398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (lp->last_link != link_state) {
5408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if ((phy->speed == SPEED_10) || (phy->speed == SPEED_100)) {
5418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			if (lp->phy_type == XAE_PHY_TYPE_1000BASE_X)
5428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				setspeed = 0;
5438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		} else {
5448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			if ((phy->speed == SPEED_1000) &&
5458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			    (lp->phy_type == XAE_PHY_TYPE_MII))
5468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				setspeed = 0;
5478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		}
5488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
5498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if (setspeed == 1) {
5508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			emmc_reg = axienet_ior(lp, XAE_EMMC_OFFSET);
5518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			emmc_reg &= ~XAE_EMMC_LINKSPEED_MASK;
5528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
5538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			switch (phy->speed) {
5548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			case SPEED_1000:
5558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				emmc_reg |= XAE_EMMC_LINKSPD_1000;
5568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				break;
5578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			case SPEED_100:
5588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				emmc_reg |= XAE_EMMC_LINKSPD_100;
5598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				break;
5608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			case SPEED_10:
5618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				emmc_reg |= XAE_EMMC_LINKSPD_10;
5628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				break;
5638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			default:
5648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				dev_err(&ndev->dev, "Speed other than 10, 100 "
5658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					"or 1Gbps is not supported\n");
5668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				break;
5678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			}
5688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
5698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			axienet_iow(lp, XAE_EMMC_OFFSET, emmc_reg);
5708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			lp->last_link = link_state;
5718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			phy_print_status(phy);
5728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		} else {
5738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			dev_err(&ndev->dev, "Error setting Axi Ethernet "
5748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				"mac speed\n");
5758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		}
5768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
5778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
5788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
5798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
5808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_start_xmit_done - Invoked once a transmit is completed by the
5818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * Axi DMA Tx channel.
5828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to the net_device structure
5838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
5848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This function is invoked from the Axi DMA Tx isr to notify the completion
5858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * of transmit operation. It clears fields in the corresponding Tx BDs and
5868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * unmaps the corresponding buffer so that CPU can regain ownership of the
5878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * buffer. It finally invokes "netif_wake_queue" to restart transmission if
5888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * required.
5898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
5908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic void axienet_start_xmit_done(struct net_device *ndev)
5918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
5928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 size = 0;
5938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 packets = 0;
5948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
5958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axidma_bd *cur_p;
5968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	unsigned int status = 0;
5978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
5988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
5998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	status = cur_p->status;
6008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	while (status & XAXIDMA_BD_STS_COMPLETE_MASK) {
6018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dma_unmap_single(ndev->dev.parent, cur_p->phys,
6028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				(cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK),
6038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				DMA_TO_DEVICE);
6048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if (cur_p->app4)
6058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			dev_kfree_skb_irq((struct sk_buff *)cur_p->app4);
6068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		/*cur_p->phys = 0;*/
6078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app0 = 0;
6088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app1 = 0;
6098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app2 = 0;
6108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app4 = 0;
6118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->status = 0;
6128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
6138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		size += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
6148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		packets++;
6158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
6168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->tx_bd_ci = ++lp->tx_bd_ci % TX_BD_NUM;
6178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
6188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		status = cur_p->status;
6198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
6208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
6218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ndev->stats.tx_packets += packets;
6228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ndev->stats.tx_bytes += size;
6238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	netif_wake_queue(ndev);
6248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
6258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
6268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
6278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_check_tx_bd_space - Checks if a BD/group of BDs are currently busy
6288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @lp:		Pointer to the axienet_local structure
6298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @num_frag:	The number of BDs to check for
6308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
6318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * returns: 0, on success
6328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *	    NETDEV_TX_BUSY, if any of the descriptors are not free
6338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
6348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This function is invoked before BDs are allocated and transmission starts.
6358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This function returns 0 if a BD or group of BDs can be allocated for
6368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * transmission. If the BD or any of the BDs are not free the function
6378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * returns a busy status. This is invoked from axienet_start_xmit.
6388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
6398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic inline int axienet_check_tx_bd_space(struct axienet_local *lp,
6408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					    int num_frag)
6418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
6428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axidma_bd *cur_p;
6438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cur_p = &lp->tx_bd_v[(lp->tx_bd_tail + num_frag) % TX_BD_NUM];
6448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (cur_p->status & XAXIDMA_BD_STS_ALL_MASK)
6458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		return NETDEV_TX_BUSY;
6468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return 0;
6478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
6488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
6498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
6508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_start_xmit - Starts the transmission.
6518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @skb:	sk_buff pointer that contains data to be Txed.
6528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure.
6538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
6548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * returns: NETDEV_TX_OK, on success
6558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *	    NETDEV_TX_BUSY, if any of the descriptors are not free
6568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
6578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This function is invoked from upper layers to initiate transmission. The
6588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * function uses the next available free BDs and populates their fields to
6598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * start the transmission. Additionally if checksum offloading is supported,
6608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * it populates AXI Stream Control fields with appropriate values.
6618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
6628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic int axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
6638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
6648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 ii;
6658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 num_frag;
6668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 csum_start_off;
6678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 csum_index_off;
6688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	skb_frag_t *frag;
6698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	dma_addr_t tail_p;
6708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
6718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axidma_bd *cur_p;
6728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
6738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	num_frag = skb_shinfo(skb)->nr_frags;
6748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
6758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
6768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (axienet_check_tx_bd_space(lp, num_frag)) {
6778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if (!netif_queue_stopped(ndev))
6788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			netif_stop_queue(ndev);
6798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		return NETDEV_TX_BUSY;
6808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
6818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
6828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (skb->ip_summed == CHECKSUM_PARTIAL) {
6838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if (lp->features & XAE_FEATURE_FULL_TX_CSUM) {
6848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			/* Tx Full Checksum Offload Enabled */
6858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			cur_p->app0 |= 2;
6868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		} else if (lp->features & XAE_FEATURE_PARTIAL_RX_CSUM) {
6878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			csum_start_off = skb_transport_offset(skb);
6888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			csum_index_off = csum_start_off + skb->csum_offset;
6898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			/* Tx Partial Checksum Offload Enabled */
6908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			cur_p->app0 |= 1;
6918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			cur_p->app1 = (csum_start_off << 16) | csum_index_off;
6928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		}
6938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	} else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
6948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app0 |= 2; /* Tx Full Checksum Offload Enabled */
6958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
6968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
6978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cur_p->cntrl = skb_headlen(skb) | XAXIDMA_BD_CTRL_TXSOF_MASK;
6988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cur_p->phys = dma_map_single(ndev->dev.parent, skb->data,
6998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				     skb_headlen(skb), DMA_TO_DEVICE);
7008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	for (ii = 0; ii < num_frag; ii++) {
7028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM;
7038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
7048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		frag = &skb_shinfo(skb)->frags[ii];
7058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->phys = dma_map_single(ndev->dev.parent,
7068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					     skb_frag_address(frag),
7078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					     skb_frag_size(frag),
7088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					     DMA_TO_DEVICE);
7098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->cntrl = skb_frag_size(frag);
7108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
7118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cur_p->cntrl |= XAXIDMA_BD_CTRL_TXEOF_MASK;
7138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cur_p->app4 = (unsigned long)skb;
7148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
7168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Start the transfer */
7178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_TX_TDESC_OFFSET, tail_p);
7188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM;
7198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return NETDEV_TX_OK;
7218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
7228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
7248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_recv - Is called from Axi DMA Rx Isr to complete the received
7258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *		  BD processing.
7268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure.
7278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
7288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This function is invoked from the Axi DMA Rx isr to process the Rx BDs. It
7298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * does minimal processing and invokes "netif_rx" to complete further
7308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * processing.
7318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
7328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic void axienet_recv(struct net_device *ndev)
7338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
7348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 length;
7358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 csumstatus;
7368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 size = 0;
7378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 packets = 0;
7388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	dma_addr_t tail_p;
7398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
7408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct sk_buff *skb, *new_skb;
7418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axidma_bd *cur_p;
7428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
7448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
7458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	while ((cur_p->status & XAXIDMA_BD_STS_COMPLETE_MASK)) {
7478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		skb = (struct sk_buff *) (cur_p->sw_id_offset);
7488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		length = cur_p->app4 & 0x0000FFFF;
7498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dma_unmap_single(ndev->dev.parent, cur_p->phys,
7518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				 lp->max_frm_size,
7528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				 DMA_FROM_DEVICE);
7538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		skb_put(skb, length);
7558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		skb->protocol = eth_type_trans(skb, ndev);
7568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		/*skb_checksum_none_assert(skb);*/
7578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		skb->ip_summed = CHECKSUM_NONE;
7588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		/* if we're doing Rx csum offload, set it up */
7608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if (lp->features & XAE_FEATURE_FULL_RX_CSUM) {
7618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			csumstatus = (cur_p->app2 &
7628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				      XAE_FULL_CSUM_STATUS_MASK) >> 3;
7638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			if ((csumstatus == XAE_IP_TCP_CSUM_VALIDATED) ||
7648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			    (csumstatus == XAE_IP_UDP_CSUM_VALIDATED)) {
7658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				skb->ip_summed = CHECKSUM_UNNECESSARY;
7668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			}
7678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		} else if ((lp->features & XAE_FEATURE_PARTIAL_RX_CSUM) != 0 &&
7688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			   skb->protocol == __constant_htons(ETH_P_IP) &&
7698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			   skb->len > 64) {
7708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			skb->csum = be32_to_cpu(cur_p->app3 & 0xFFFF);
7718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			skb->ip_summed = CHECKSUM_COMPLETE;
7728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		}
7738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		netif_rx(skb);
7758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		size += length;
7778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		packets++;
7788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		new_skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size);
7808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if (!new_skb) {
7818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			dev_err(&ndev->dev, "no memory for new sk_buff\n");
7828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			return;
7838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		}
7848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data,
7858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					     lp->max_frm_size,
7868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					     DMA_FROM_DEVICE);
7878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->cntrl = lp->max_frm_size;
7888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->status = 0;
7898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->sw_id_offset = (u32) new_skb;
7908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->rx_bd_ci = ++lp->rx_bd_ci % RX_BD_NUM;
7928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
7938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
7948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ndev->stats.rx_packets += packets;
7968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ndev->stats.rx_bytes += size;
7978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
7988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, tail_p);
7998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
8008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
8018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
8028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_tx_irq - Tx Done Isr.
8038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @irq:	irq number
8048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @_ndev:	net_device pointer
8058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
8068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * returns: IRQ_HANDLED for all cases.
8078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
8088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This is the Axi DMA Tx done Isr. It invokes "axienet_start_xmit_done"
8098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * to complete the BD processing.
8108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
8118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic irqreturn_t axienet_tx_irq(int irq, void *_ndev)
8128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
8138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 cr;
8148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	unsigned int status;
8158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct net_device *ndev = _ndev;
8168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
8178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
8188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	status = axienet_dma_in32(lp, XAXIDMA_TX_SR_OFFSET);
8198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (status & (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK)) {
8208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		axienet_start_xmit_done(lp->ndev);
8218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		goto out;
8228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
8238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (!(status & XAXIDMA_IRQ_ALL_MASK))
8248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(&ndev->dev, "No interrupts asserted in Tx path");
8258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (status & XAXIDMA_IRQ_ERROR_MASK) {
8268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(&ndev->dev, "DMA Tx error 0x%x\n", status);
8278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(&ndev->dev, "Current BD is at: 0x%x\n",
8288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			(lp->tx_bd_v[lp->tx_bd_ci]).phys);
8298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
8308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
8318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		/* Disable coalesce, delay timer and error interrupts */
8328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cr &= (~XAXIDMA_IRQ_ALL_MASK);
8338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		/* Write to the Tx channel control register */
8348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
8358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
8368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
8378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		/* Disable coalesce, delay timer and error interrupts */
8388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cr &= (~XAXIDMA_IRQ_ALL_MASK);
8398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		/* Write to the Rx channel control register */
8408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
8418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
8428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		tasklet_schedule(&lp->dma_err_tasklet);
8438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
8448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netout:
8458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_TX_SR_OFFSET, status);
8468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return IRQ_HANDLED;
8478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
8488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
8498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
8508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_rx_irq - Rx Isr.
8518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @irq:	irq number
8528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @_ndev:	net_device pointer
8538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
8548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * returns: IRQ_HANDLED for all cases.
8558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
8568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This is the Axi DMA Rx Isr. It invokes "axienet_recv" to complete the BD
8578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * processing.
8588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
8598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic irqreturn_t axienet_rx_irq(int irq, void *_ndev)
8608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
8618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 cr;
8628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	unsigned int status;
8638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct net_device *ndev = _ndev;
8648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
8658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
8668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	status = axienet_dma_in32(lp, XAXIDMA_RX_SR_OFFSET);
8678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (status & (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK)) {
8688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		axienet_recv(lp->ndev);
8698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		goto out;
8708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
8718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (!(status & XAXIDMA_IRQ_ALL_MASK))
8728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(&ndev->dev, "No interrupts asserted in Rx path");
8738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (status & XAXIDMA_IRQ_ERROR_MASK) {
8748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(&ndev->dev, "DMA Rx error 0x%x\n", status);
8758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(&ndev->dev, "Current BD is at: 0x%x\n",
8768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			(lp->rx_bd_v[lp->rx_bd_ci]).phys);
8778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
8788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
8798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		/* Disable coalesce, delay timer and error interrupts */
8808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cr &= (~XAXIDMA_IRQ_ALL_MASK);
8818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		/* Finally write to the Tx channel control register */
8828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
8838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
8848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
8858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		/* Disable coalesce, delay timer and error interrupts */
8868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cr &= (~XAXIDMA_IRQ_ALL_MASK);
8878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		/* write to the Rx channel control register */
8888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
8898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
8908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		tasklet_schedule(&lp->dma_err_tasklet);
8918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
8928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netout:
8938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_RX_SR_OFFSET, status);
8948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return IRQ_HANDLED;
8958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
8968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
8978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
8988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_open - Driver open routine.
8998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure
9008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
9018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * returns: 0, on success.
9028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *	    -ENODEV, if PHY cannot be connected to
9038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *	    non-zero error value on failure
9048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
9058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This is the driver open routine. It calls phy_start to start the PHY device.
9068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * It also allocates interrupt service routines, enables the interrupt lines
9078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * and ISR handling. Axi Ethernet core is reset through Axi DMA core. Buffer
9088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * descriptors are initialized.
9098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
9108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic int axienet_open(struct net_device *ndev)
9118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
9128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	int ret, mdio_mcreg;
9138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
9148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
9158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	dev_dbg(&ndev->dev, "axienet_open()\n");
9168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
9178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	mdio_mcreg = axienet_ior(lp, XAE_MDIO_MC_OFFSET);
9188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ret = axienet_mdio_wait_until_ready(lp);
9198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (ret < 0)
9208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		return ret;
9218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Disable the MDIO interface till Axi Ethernet Reset is completed.
9228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * When we do an Axi Ethernet reset, it resets the complete core
9238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * including the MDIO. If MDIO is not disabled when the reset
9248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * process is started, MDIO will be broken afterwards. */
9258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_iow(lp, XAE_MDIO_MC_OFFSET,
9268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		    (mdio_mcreg & (~XAE_MDIO_MC_MDIOEN_MASK)));
9278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_device_reset(ndev);
9288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Enable the MDIO */
9298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_iow(lp, XAE_MDIO_MC_OFFSET, mdio_mcreg);
9308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ret = axienet_mdio_wait_until_ready(lp);
9318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (ret < 0)
9328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		return ret;
9338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
9348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (lp->phy_node) {
9358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node,
9368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					     axienet_adjust_link, 0,
9378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					     PHY_INTERFACE_MODE_GMII);
9388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if (!lp->phy_dev) {
9398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			dev_err(lp->dev, "of_phy_connect() failed\n");
9408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			return -ENODEV;
9418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		}
9428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		phy_start(lp->phy_dev);
9438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
9448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
9458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Enable interrupts for Axi DMA Tx */
9468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev);
9478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (ret)
9488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		goto err_tx_irq;
9498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Enable interrupts for Axi DMA Rx */
9508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ret = request_irq(lp->rx_irq, axienet_rx_irq, 0, ndev->name, ndev);
9518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (ret)
9528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		goto err_rx_irq;
9538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Enable tasklets for Axi DMA error handling */
9548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	tasklet_enable(&lp->dma_err_tasklet);
9558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return 0;
9568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
9578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.neterr_rx_irq:
9588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	free_irq(lp->tx_irq, ndev);
9598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.neterr_tx_irq:
9608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (lp->phy_dev)
9618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		phy_disconnect(lp->phy_dev);
9628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->phy_dev = NULL;
9638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	dev_err(lp->dev, "request_irq() failed\n");
9648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return ret;
9658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
9668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
9678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
9688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_stop - Driver stop routine.
9698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure
9708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
9718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * returns: 0, on success.
9728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
9738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This is the driver stop routine. It calls phy_disconnect to stop the PHY
9748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * device. It also removes the interrupt handlers and disables the interrupts.
9758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * The Axi DMA Tx/Rx BDs are released.
9768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
9778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic int axienet_stop(struct net_device *ndev)
9788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
9798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 cr;
9808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
9818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
9828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	dev_dbg(&ndev->dev, "axienet_close()\n");
9838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
9848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
9858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET,
9868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			  cr & (~XAXIDMA_CR_RUNSTOP_MASK));
9878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
9888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET,
9898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			  cr & (~XAXIDMA_CR_RUNSTOP_MASK));
9908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_setoptions(ndev, lp->options &
9918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			   ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
9928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
9938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	tasklet_disable(&lp->dma_err_tasklet);
9948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
9958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	free_irq(lp->tx_irq, ndev);
9968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	free_irq(lp->rx_irq, ndev);
9978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
9988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (lp->phy_dev)
9998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		phy_disconnect(lp->phy_dev);
10008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->phy_dev = NULL;
10018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
10028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_bd_release(ndev);
10038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return 0;
10048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
10058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
10068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
10078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_change_mtu - Driver change mtu routine.
10088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure
10098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @new_mtu:	New mtu value to be applied
10108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
10118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * returns: Always returns 0 (success).
10128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
10138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This is the change mtu driver routine. It checks if the Axi Ethernet
10148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * hardware supports jumbo frames before changing the mtu. This can be
10158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * called only when the device is not up.
10168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
10178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic int axienet_change_mtu(struct net_device *ndev, int new_mtu)
10188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
10198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
10208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
10218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (netif_running(ndev))
10228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		return -EBUSY;
10238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (lp->jumbo_support) {
10248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if ((new_mtu > XAE_JUMBO_MTU) || (new_mtu < 64))
10258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			return -EINVAL;
10268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		ndev->mtu = new_mtu;
10278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	} else {
10288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if ((new_mtu > XAE_MTU) || (new_mtu < 64))
10298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			return -EINVAL;
10308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		ndev->mtu = new_mtu;
10318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
10328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
10338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return 0;
10348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
10358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
10368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#ifdef CONFIG_NET_POLL_CONTROLLER
10378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
10388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_poll_controller - Axi Ethernet poll mechanism.
10398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure
10408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
10418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This implements Rx/Tx ISR poll mechanisms. The interrupts are disabled prior
10428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * to polling the ISRs and are enabled back after the polling is done.
10438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
10448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic void axienet_poll_controller(struct net_device *ndev)
10458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
10468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
10478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	disable_irq(lp->tx_irq);
10488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	disable_irq(lp->rx_irq);
10498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_rx_irq(lp->tx_irq, ndev);
10508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_tx_irq(lp->rx_irq, ndev);
10518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	enable_irq(lp->tx_irq);
10528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	enable_irq(lp->rx_irq);
10538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
10548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#endif
10558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
10568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic const struct net_device_ops axienet_netdev_ops = {
10578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.ndo_open = axienet_open,
10588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.ndo_stop = axienet_stop,
10598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.ndo_start_xmit = axienet_start_xmit,
10608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.ndo_change_mtu	= axienet_change_mtu,
10618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.ndo_set_mac_address = netdev_set_mac_address,
10628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.ndo_validate_addr = eth_validate_addr,
10638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.ndo_set_rx_mode = axienet_set_multicast_list,
10648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#ifdef CONFIG_NET_POLL_CONTROLLER
10658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.ndo_poll_controller = axienet_poll_controller,
10668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net#endif
10678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net};
10688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
10698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
10708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_ethtools_get_settings - Get Axi Ethernet settings related to PHY.
10718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure
10728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ecmd:	Pointer to ethtool_cmd structure
10738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
10748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This implements ethtool command for getting PHY settings. If PHY could
10758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * not be found, the function returns -ENODEV. This function calls the
10768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * relevant PHY ethtool API to get the PHY settings.
10778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * Issue "ethtool ethX" under linux prompt to execute this function.
10788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
10798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic int axienet_ethtools_get_settings(struct net_device *ndev,
10808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					 struct ethtool_cmd *ecmd)
10818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
10828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
10838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct phy_device *phydev = lp->phy_dev;
10848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (!phydev)
10858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		return -ENODEV;
10868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return phy_ethtool_gset(phydev, ecmd);
10878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
10888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
10898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
10908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_ethtools_set_settings - Set PHY settings as passed in the argument.
10918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure
10928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ecmd:	Pointer to ethtool_cmd structure
10938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
10948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This implements ethtool command for setting various PHY settings. If PHY
10958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * could not be found, the function returns -ENODEV. This function calls the
10968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * relevant PHY ethtool API to set the PHY.
10978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * Issue e.g. "ethtool -s ethX speed 1000" under linux prompt to execute this
10988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * function.
10998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
11008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic int axienet_ethtools_set_settings(struct net_device *ndev,
11018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					 struct ethtool_cmd *ecmd)
11028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
11038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
11048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct phy_device *phydev = lp->phy_dev;
11058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (!phydev)
11068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		return -ENODEV;
11078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return phy_ethtool_sset(phydev, ecmd);
11088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
11098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
11108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
11118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_ethtools_get_drvinfo - Get various Axi Ethernet driver information.
11128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure
11138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ed:		Pointer to ethtool_drvinfo structure
11148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
11158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This implements ethtool command for getting the driver information.
11168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * Issue "ethtool -i ethX" under linux prompt to execute this function.
11178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
11188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic void axienet_ethtools_get_drvinfo(struct net_device *ndev,
11198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					 struct ethtool_drvinfo *ed)
11208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
11218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	memset(ed, 0, sizeof(struct ethtool_drvinfo));
11228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	strcpy(ed->driver, DRIVER_NAME);
11238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	strcpy(ed->version, DRIVER_VERSION);
11248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ed->regdump_len = sizeof(u32) * AXIENET_REGS_N;
11258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
11268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
11278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
11288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_ethtools_get_regs_len - Get the total regs length present in the
11298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *				   AxiEthernet core.
11308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure
11318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
11328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This implements ethtool command for getting the total register length
11338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * information.
11348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
11358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic int axienet_ethtools_get_regs_len(struct net_device *ndev)
11368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
11378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return sizeof(u32) * AXIENET_REGS_N;
11388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
11398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
11408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
11418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_ethtools_get_regs - Dump the contents of all registers present
11428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *			       in AxiEthernet core.
11438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure
11448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @regs:	Pointer to ethtool_regs structure
11458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ret:	Void pointer used to return the contents of the registers.
11468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
11478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This implements ethtool command for getting the Axi Ethernet register dump.
11488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * Issue "ethtool -d ethX" to execute this function.
11498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
11508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic void axienet_ethtools_get_regs(struct net_device *ndev,
11518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				      struct ethtool_regs *regs, void *ret)
11528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
11538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 *data = (u32 *) ret;
11548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	size_t len = sizeof(u32) * AXIENET_REGS_N;
11558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
11568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
11578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	regs->version = 0;
11588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	regs->len = len;
11598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
11608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	memset(data, 0, len);
11618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[0] = axienet_ior(lp, XAE_RAF_OFFSET);
11628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[1] = axienet_ior(lp, XAE_TPF_OFFSET);
11638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[2] = axienet_ior(lp, XAE_IFGP_OFFSET);
11648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[3] = axienet_ior(lp, XAE_IS_OFFSET);
11658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[4] = axienet_ior(lp, XAE_IP_OFFSET);
11668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[5] = axienet_ior(lp, XAE_IE_OFFSET);
11678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[6] = axienet_ior(lp, XAE_TTAG_OFFSET);
11688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[7] = axienet_ior(lp, XAE_RTAG_OFFSET);
11698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[8] = axienet_ior(lp, XAE_UAWL_OFFSET);
11708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[9] = axienet_ior(lp, XAE_UAWU_OFFSET);
11718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[10] = axienet_ior(lp, XAE_TPID0_OFFSET);
11728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[11] = axienet_ior(lp, XAE_TPID1_OFFSET);
11738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[12] = axienet_ior(lp, XAE_PPST_OFFSET);
11748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[13] = axienet_ior(lp, XAE_RCW0_OFFSET);
11758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[14] = axienet_ior(lp, XAE_RCW1_OFFSET);
11768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[15] = axienet_ior(lp, XAE_TC_OFFSET);
11778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[16] = axienet_ior(lp, XAE_FCC_OFFSET);
11788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[17] = axienet_ior(lp, XAE_EMMC_OFFSET);
11798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[18] = axienet_ior(lp, XAE_PHYC_OFFSET);
11808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[19] = axienet_ior(lp, XAE_MDIO_MC_OFFSET);
11818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[20] = axienet_ior(lp, XAE_MDIO_MCR_OFFSET);
11828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[21] = axienet_ior(lp, XAE_MDIO_MWD_OFFSET);
11838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[22] = axienet_ior(lp, XAE_MDIO_MRD_OFFSET);
11848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[23] = axienet_ior(lp, XAE_MDIO_MIS_OFFSET);
11858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[24] = axienet_ior(lp, XAE_MDIO_MIP_OFFSET);
11868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[25] = axienet_ior(lp, XAE_MDIO_MIE_OFFSET);
11878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[26] = axienet_ior(lp, XAE_MDIO_MIC_OFFSET);
11888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[27] = axienet_ior(lp, XAE_UAW0_OFFSET);
11898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[28] = axienet_ior(lp, XAE_UAW1_OFFSET);
11908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[29] = axienet_ior(lp, XAE_FMI_OFFSET);
11918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[30] = axienet_ior(lp, XAE_AF0_OFFSET);
11928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	data[31] = axienet_ior(lp, XAE_AF1_OFFSET);
11938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
11948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
11958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
11968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_ethtools_get_pauseparam - Get the pause parameter setting for
11978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *				     Tx and Rx paths.
11988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure
11998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @epauseparm:	Pointer to ethtool_pauseparam structure.
12008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
12018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This implements ethtool command for getting axi ethernet pause frame
12028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * setting. Issue "ethtool -a ethX" to execute this function.
12038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
12048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic void
12058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netaxienet_ethtools_get_pauseparam(struct net_device *ndev,
12068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				struct ethtool_pauseparam *epauseparm)
12078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
12088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 regval;
12098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
12108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	epauseparm->autoneg  = 0;
12118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	regval = axienet_ior(lp, XAE_FCC_OFFSET);
12128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	epauseparm->tx_pause = regval & XAE_FCC_FCTX_MASK;
12138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	epauseparm->rx_pause = regval & XAE_FCC_FCRX_MASK;
12148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
12158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
12168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
12178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_ethtools_set_pauseparam - Set device pause parameter(flow control)
12188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *				     settings.
12198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure
12208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @epauseparam:Pointer to ethtool_pauseparam structure
12218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
12228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This implements ethtool command for enabling flow control on Rx and Tx
12238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * paths. Issue "ethtool -A ethX tx on|off" under linux prompt to execute this
12248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * function.
12258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
12268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic int
12278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netaxienet_ethtools_set_pauseparam(struct net_device *ndev,
12288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				struct ethtool_pauseparam *epauseparm)
12298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
12308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 regval = 0;
12318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
12328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
12338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (netif_running(ndev)) {
12348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		printk(KERN_ERR	"%s: Please stop netif before applying "
12358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		       "configruation\n", ndev->name);
12368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		return -EFAULT;
12378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
12388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
12398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	regval = axienet_ior(lp, XAE_FCC_OFFSET);
12408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (epauseparm->tx_pause)
12418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		regval |= XAE_FCC_FCTX_MASK;
12428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	else
12438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		regval &= ~XAE_FCC_FCTX_MASK;
12448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (epauseparm->rx_pause)
12458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		regval |= XAE_FCC_FCRX_MASK;
12468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	else
12478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		regval &= ~XAE_FCC_FCRX_MASK;
12488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_iow(lp, XAE_FCC_OFFSET, regval);
12498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
12508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return 0;
12518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
12528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
12538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
12548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_ethtools_get_coalesce - Get DMA interrupt coalescing count.
12558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure
12568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ecoalesce:	Pointer to ethtool_coalesce structure
12578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
12588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This implements ethtool command for getting the DMA interrupt coalescing
12598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * count on Tx and Rx paths. Issue "ethtool -c ethX" under linux prompt to
12608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * execute this function.
12618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
12628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic int axienet_ethtools_get_coalesce(struct net_device *ndev,
12638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					 struct ethtool_coalesce *ecoalesce)
12648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
12658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 regval = 0;
12668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
12678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	regval = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
12688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ecoalesce->rx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK)
12698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					     >> XAXIDMA_COALESCE_SHIFT;
12708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	regval = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
12718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ecoalesce->tx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK)
12728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					     >> XAXIDMA_COALESCE_SHIFT;
12738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return 0;
12748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
12758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
12768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
12778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_ethtools_set_coalesce - Set DMA interrupt coalescing count.
12788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ndev:	Pointer to net_device structure
12798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @ecoalesce:	Pointer to ethtool_coalesce structure
12808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
12818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This implements ethtool command for setting the DMA interrupt coalescing
12828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * count on Tx and Rx paths. Issue "ethtool -C ethX rx-frames 5" under linux
12838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * prompt to execute this function.
12848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
12858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic int axienet_ethtools_set_coalesce(struct net_device *ndev,
12868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					 struct ethtool_coalesce *ecoalesce)
12878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
12888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
12898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
12908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (netif_running(ndev)) {
12918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		printk(KERN_ERR	"%s: Please stop netif before applying "
12928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		       "configruation\n", ndev->name);
12938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		return -EFAULT;
12948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
12958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
12968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if ((ecoalesce->rx_coalesce_usecs) ||
12978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->rx_coalesce_usecs_irq) ||
12988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->rx_max_coalesced_frames_irq) ||
12998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->tx_coalesce_usecs) ||
13008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->tx_coalesce_usecs_irq) ||
13018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->tx_max_coalesced_frames_irq) ||
13028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->stats_block_coalesce_usecs) ||
13038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->use_adaptive_rx_coalesce) ||
13048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->use_adaptive_tx_coalesce) ||
13058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->pkt_rate_low) ||
13068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->rx_coalesce_usecs_low) ||
13078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->rx_max_coalesced_frames_low) ||
13088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->tx_coalesce_usecs_low) ||
13098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->tx_max_coalesced_frames_low) ||
13108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->pkt_rate_high) ||
13118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->rx_coalesce_usecs_high) ||
13128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->rx_max_coalesced_frames_high) ||
13138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->tx_coalesce_usecs_high) ||
13148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->tx_max_coalesced_frames_high) ||
13158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	    (ecoalesce->rate_sample_interval))
13168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		return -EOPNOTSUPP;
13178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (ecoalesce->rx_max_coalesced_frames)
13188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->coalesce_count_rx = ecoalesce->rx_max_coalesced_frames;
13198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (ecoalesce->tx_max_coalesced_frames)
13208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->coalesce_count_tx = ecoalesce->tx_max_coalesced_frames;
13218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
13228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return 0;
13238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
13248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
13258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic struct ethtool_ops axienet_ethtool_ops = {
13268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.get_settings   = axienet_ethtools_get_settings,
13278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.set_settings   = axienet_ethtools_set_settings,
13288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.get_drvinfo    = axienet_ethtools_get_drvinfo,
13298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.get_regs_len   = axienet_ethtools_get_regs_len,
13308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.get_regs       = axienet_ethtools_get_regs,
13318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.get_link       = ethtool_op_get_link,
13328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.get_pauseparam = axienet_ethtools_get_pauseparam,
13338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.set_pauseparam = axienet_ethtools_set_pauseparam,
13348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.get_coalesce   = axienet_ethtools_get_coalesce,
13358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.set_coalesce   = axienet_ethtools_set_coalesce,
13368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net};
13378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
13388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
13398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_dma_err_handler - Tasklet handler for Axi DMA Error
13408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @data:	Data passed
13418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
13428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * Resets the Axi DMA and Axi Ethernet devices, and reconfigures the
13438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * Tx/Rx BDs.
13448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
13458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic void axienet_dma_err_handler(unsigned long data)
13468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
13478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 axienet_status;
13488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	u32 cr, i;
13498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	int mdio_mcreg;
13508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = (struct axienet_local *) data;
13518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct net_device *ndev = lp->ndev;
13528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axidma_bd *cur_p;
13538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
13548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_setoptions(ndev, lp->options &
13558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			   ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
13568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	mdio_mcreg = axienet_ior(lp, XAE_MDIO_MC_OFFSET);
13578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_mdio_wait_until_ready(lp);
13588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Disable the MDIO interface till Axi Ethernet Reset is completed.
13598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * When we do an Axi Ethernet reset, it resets the complete core
13608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * including the MDIO. So if MDIO is not disabled when the reset
13618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * process is started, MDIO will be broken afterwards. */
13628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_iow(lp, XAE_MDIO_MC_OFFSET, (mdio_mcreg &
13638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		    ~XAE_MDIO_MC_MDIOEN_MASK));
13648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
13658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	__axienet_device_reset(lp, &ndev->dev, XAXIDMA_TX_CR_OFFSET);
13668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	__axienet_device_reset(lp, &ndev->dev, XAXIDMA_RX_CR_OFFSET);
13678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
13688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_iow(lp, XAE_MDIO_MC_OFFSET, mdio_mcreg);
13698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_mdio_wait_until_ready(lp);
13708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
13718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	for (i = 0; i < TX_BD_NUM; i++) {
13728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p = &lp->tx_bd_v[i];
13738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if (cur_p->phys)
13748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			dma_unmap_single(ndev->dev.parent, cur_p->phys,
13758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					 (cur_p->cntrl &
13768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					  XAXIDMA_BD_CTRL_LENGTH_MASK),
13778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net					 DMA_TO_DEVICE);
13788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if (cur_p->app4)
13798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			dev_kfree_skb_irq((struct sk_buff *) cur_p->app4);
13808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->phys = 0;
13818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->cntrl = 0;
13828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->status = 0;
13838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app0 = 0;
13848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app1 = 0;
13858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app2 = 0;
13868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app3 = 0;
13878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app4 = 0;
13888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->sw_id_offset = 0;
13898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
13908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
13918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	for (i = 0; i < RX_BD_NUM; i++) {
13928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p = &lp->rx_bd_v[i];
13938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->status = 0;
13948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app0 = 0;
13958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app1 = 0;
13968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app2 = 0;
13978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app3 = 0;
13988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		cur_p->app4 = 0;
13998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
14008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
14018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->tx_bd_ci = 0;
14028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->tx_bd_tail = 0;
14038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->rx_bd_ci = 0;
14048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
14058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Start updating the Rx channel control register */
14068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
14078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Update the interrupt coalesce count */
14088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = ((cr & ~XAXIDMA_COALESCE_MASK) |
14098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	      (XAXIDMA_DFT_RX_THRESHOLD << XAXIDMA_COALESCE_SHIFT));
14108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Update the delay timer count */
14118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = ((cr & ~XAXIDMA_DELAY_MASK) |
14128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	      (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
14138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Enable coalesce, delay timer and error interrupts */
14148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr |= XAXIDMA_IRQ_ALL_MASK;
14158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Finally write to the Rx channel control register */
14168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
14178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
14188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Start updating the Tx channel control register */
14198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
14208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Update the interrupt coalesce count */
14218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = (((cr & ~XAXIDMA_COALESCE_MASK)) |
14228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	      (XAXIDMA_DFT_TX_THRESHOLD << XAXIDMA_COALESCE_SHIFT));
14238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Update the delay timer count */
14248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = (((cr & ~XAXIDMA_DELAY_MASK)) |
14258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	      (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
14268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Enable coalesce, delay timer and error interrupts */
14278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr |= XAXIDMA_IRQ_ALL_MASK;
14288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Finally write to the Tx channel control register */
14298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
14308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
14318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Populate the tail pointer and bring the Rx Axi DMA engine out of
14328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * halted state. This will make the Rx side ready for reception.*/
14338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p);
14348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
14358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET,
14368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			  cr | XAXIDMA_CR_RUNSTOP_MASK);
14378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p +
14388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			  (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
14398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
14408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Write to the RS (Run-stop) bit in the Tx channel control register.
14418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * Tx channel is now ready to run. But only after we write to the
14428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * tail pointer register that the Tx channel will start transmitting */
14438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p);
14448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
14458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET,
14468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			  cr | XAXIDMA_CR_RUNSTOP_MASK);
14478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
14488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_status = axienet_ior(lp, XAE_RCW1_OFFSET);
14498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_status &= ~XAE_RCW1_RX_MASK;
14508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_iow(lp, XAE_RCW1_OFFSET, axienet_status);
14518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
14528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_status = axienet_ior(lp, XAE_IP_OFFSET);
14538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (axienet_status & XAE_INT_RXRJECT_MASK)
14548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		axienet_iow(lp, XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK);
14558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_iow(lp, XAE_FCC_OFFSET, XAE_FCC_FCRX_MASK);
14568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
14578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Sync default options with HW but leave receiver and
14588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * transmitter disabled.*/
14598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_setoptions(ndev, lp->options &
14608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			   ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
14618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_set_mac_address(ndev, NULL);
14628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_set_multicast_list(ndev);
14638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_setoptions(ndev, lp->options);
14648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
14658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
14668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net/**
14678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_of_probe - Axi Ethernet probe function.
14688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @op:		Pointer to platform device structure.
14698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * @match:	Pointer to device id structure
14708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
14718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * returns: 0, on success
14728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *	    Non-zero error value on failure.
14738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net *
14748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * This is the probe routine for Axi Ethernet driver. This is called before
14758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * any other driver routines are invoked. It allocates and sets up the Ethernet
14768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * device. Parses through device tree and populates fields of
14778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net * axienet_local. It registers the Ethernet device.
14788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net */
14798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic int __devinit axienet_of_probe(struct platform_device *op)
14808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
14818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	__be32 *p;
14828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	int size, ret = 0;
14838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct device_node *np;
14848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp;
14858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct net_device *ndev;
14868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	const void *addr;
14878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
14888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ndev = alloc_etherdev(sizeof(*lp));
148941de8d4cff21a2e81e3d9ff66f5f7c903f9c3ab1Joe Perches	if (!ndev)
14908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		return -ENOMEM;
14918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
14928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ether_setup(ndev);
14938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	dev_set_drvdata(&op->dev, ndev);
14948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
14958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	SET_NETDEV_DEV(ndev, &op->dev);
14968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ndev->flags &= ~IFF_MULTICAST;  /* clear multicast */
14978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
14988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ndev->netdev_ops = &axienet_netdev_ops;
14998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ndev->ethtool_ops = &axienet_ethtool_ops;
15008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
15018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp = netdev_priv(ndev);
15028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->ndev = ndev;
15038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->dev = &op->dev;
15048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->options = XAE_OPTION_DEFAULTS;
15058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Map device registers */
15068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->regs = of_iomap(op->dev.of_node, 0);
15078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (!lp->regs) {
15088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(&op->dev, "could not map Axi Ethernet regs.\n");
15098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		goto nodev;
15108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
15118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Setup checksum offload, but default to off if not specified */
15128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->features = 0;
15138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
15148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,txcsum", NULL);
15158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (p) {
15168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		switch (be32_to_cpup(p)) {
15178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		case 1:
15188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			lp->csum_offload_on_tx_path =
15198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				XAE_FEATURE_PARTIAL_TX_CSUM;
15208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			lp->features |= XAE_FEATURE_PARTIAL_TX_CSUM;
15218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			/* Can checksum TCP/UDP over IPv4. */
15228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			ndev->features |= NETIF_F_IP_CSUM;
15238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			break;
15248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		case 2:
15258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			lp->csum_offload_on_tx_path =
15268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				XAE_FEATURE_FULL_TX_CSUM;
15278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			lp->features |= XAE_FEATURE_FULL_TX_CSUM;
15288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			/* Can checksum TCP/UDP over IPv4. */
15298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			ndev->features |= NETIF_F_IP_CSUM;
15308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			break;
15318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		default:
15328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			lp->csum_offload_on_tx_path = XAE_NO_CSUM_OFFLOAD;
15338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		}
15348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
15358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,rxcsum", NULL);
15368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (p) {
15378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		switch (be32_to_cpup(p)) {
15388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		case 1:
15398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			lp->csum_offload_on_rx_path =
15408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				XAE_FEATURE_PARTIAL_RX_CSUM;
15418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			lp->features |= XAE_FEATURE_PARTIAL_RX_CSUM;
15428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			break;
15438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		case 2:
15448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			lp->csum_offload_on_rx_path =
15458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				XAE_FEATURE_FULL_RX_CSUM;
15468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			lp->features |= XAE_FEATURE_FULL_RX_CSUM;
15478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			break;
15488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		default:
15498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			lp->csum_offload_on_rx_path = XAE_NO_CSUM_OFFLOAD;
15508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		}
15518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
15528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* For supporting jumbo frames, the Axi Ethernet hardware must have
15538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * a larger Rx/Tx Memory. Typically, the size must be more than or
15548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * equal to 16384 bytes, so that we can enable jumbo option and start
15558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * supporting jumbo frames. Here we check for memory allocated for
15568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * Rx/Tx in the hardware from the device-tree and accordingly set
15578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	 * flags. */
15588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,rxmem", NULL);
15598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (p) {
15608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		if ((be32_to_cpup(p)) >= 0x4000)
15618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net			lp->jumbo_support = 1;
15628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
15638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,temac-type",
15648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net				       NULL);
15658a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (p)
15668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->temac_type = be32_to_cpup(p);
15678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,phy-type", NULL);
15688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (p)
15698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		lp->phy_type = be32_to_cpup(p);
15708a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
15718a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Find the DMA node, map the DMA registers, and decode the DMA IRQs */
15728a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	np = of_parse_phandle(op->dev.of_node, "axistream-connected", 0);
15738a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (!np) {
15748a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(&op->dev, "could not find DMA node\n");
15758a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		goto err_iounmap;
15768a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
15778a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->dma_regs = of_iomap(np, 0);
15788a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (lp->dma_regs) {
15798a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_dbg(&op->dev, "MEM base: %p\n", lp->dma_regs);
15808a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	} else {
15818a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(&op->dev, "unable to map DMA registers\n");
15828a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		of_node_put(np);
15838a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
15848a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->rx_irq = irq_of_parse_and_map(np, 1);
15858a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->tx_irq = irq_of_parse_and_map(np, 0);
15868a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	of_node_put(np);
15878a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) {
15888a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(&op->dev, "could not determine irqs\n");
15898a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		ret = -ENOMEM;
15908a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		goto err_iounmap_2;
15918a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
15928a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
15938a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	/* Retrieve the MAC address */
15948a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	addr = of_get_property(op->dev.of_node, "local-mac-address", &size);
15958a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if ((!addr) || (size != 6)) {
15968a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(&op->dev, "could not find MAC address\n");
15978a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		ret = -ENODEV;
15988a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		goto err_iounmap_2;
15998a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
16008a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_set_mac_address(ndev, (void *) addr);
16018a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
16028a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
16038a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
16048a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
16058a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->phy_node = of_parse_phandle(op->dev.of_node, "phy-handle", 0);
16068a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ret = axienet_mdio_setup(lp, op->dev.of_node);
16078a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (ret)
16088a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_warn(&op->dev, "error registering MDIO bus\n");
16098a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
16108a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ret = register_netdev(lp->ndev);
16118a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (ret) {
16128a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		dev_err(lp->dev, "register_netdev() error (%i)\n", ret);
16138a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		goto err_iounmap_2;
16148a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	}
16158a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
16168a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
16178a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		     (unsigned long) lp);
16188a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	tasklet_disable(&lp->dma_err_tasklet);
16198a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
16208a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return 0;
16218a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
16228a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.neterr_iounmap_2:
16238a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (lp->dma_regs)
16248a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		iounmap(lp->dma_regs);
16258a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.neterr_iounmap:
16268a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	iounmap(lp->regs);
16278a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netnodev:
16288a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	free_netdev(ndev);
16298a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	ndev = NULL;
16308a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return ret;
16318a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
16328a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
16338a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic int __devexit axienet_of_remove(struct platform_device *op)
16348a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net{
16358a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct net_device *ndev = dev_get_drvdata(&op->dev);
16368a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	struct axienet_local *lp = netdev_priv(ndev);
16378a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
16388a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	axienet_mdio_teardown(lp);
16398a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	unregister_netdev(ndev);
16408a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
16418a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (lp->phy_node)
16428a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		of_node_put(lp->phy_node);
16438a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	lp->phy_node = NULL;
16448a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
16458a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	dev_set_drvdata(&op->dev, NULL);
16468a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
16478a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	iounmap(lp->regs);
16488a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	if (lp->dma_regs)
16498a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		iounmap(lp->dma_regs);
16508a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	free_netdev(ndev);
16518a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
16528a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	return 0;
16538a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net}
16548a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
16558a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netstatic struct platform_driver axienet_of_driver = {
16568a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.probe = axienet_of_probe,
16578a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.remove = __devexit_p(axienet_of_remove),
16588a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	.driver = {
16598a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		 .owner = THIS_MODULE,
16608a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		 .name = "xilinx_axienet",
16618a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net		 .of_match_table = axienet_of_match,
16628a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net	},
16638a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net};
16648a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
1665b4a466765d3fb05c1f63ddc5d195980ead894dedTobias Klausermodule_platform_driver(axienet_of_driver);
16668a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.net
16678a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netMODULE_DESCRIPTION("Xilinx Axi Ethernet driver");
16688a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netMODULE_AUTHOR("Xilinx");
16698a3b7a252dca9fb28c23b5bf76c49180a2b60d3bdanborkmann@iogearbox.netMODULE_LICENSE("GPL");
1670