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