| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * DaVinci Ethernet Medium Access Controller | 
|  | 3 | * | 
|  | 4 | * DaVinci EMAC is based upon CPPI 3.0 TI DMA engine | 
|  | 5 | * | 
|  | 6 | * Copyright (C) 2009 Texas Instruments. | 
|  | 7 | * | 
|  | 8 | * --------------------------------------------------------------------------- | 
|  | 9 | * | 
|  | 10 | * This program is free software; you can redistribute it and/or modify | 
|  | 11 | * it under the terms of the GNU General Public License as published by | 
|  | 12 | * the Free Software Foundation; either version 2 of the License, or | 
|  | 13 | * (at your option) any later version. | 
|  | 14 | * | 
|  | 15 | * This program is distributed in the hope that it will be useful, | 
|  | 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 18 | * GNU General Public License for more details. | 
|  | 19 | * | 
|  | 20 | * You should have received a copy of the GNU General Public License | 
|  | 21 | * along with this program; if not, write to the Free Software | 
|  | 22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
|  | 23 | * --------------------------------------------------------------------------- | 
|  | 24 | * History: | 
|  | 25 | * 0-5 A number of folks worked on this driver in bits and pieces but the major | 
|  | 26 | *     contribution came from Suraj Iyer and Anant Gole | 
|  | 27 | * 6.0 Anant Gole - rewrote the driver as per Linux conventions | 
|  | 28 | * 6.1 Chaithrika U S - added support for Gigabit and RMII features, | 
|  | 29 | *     PHY layer usage | 
|  | 30 | */ | 
|  | 31 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 32 | #include <linux/module.h> | 
|  | 33 | #include <linux/kernel.h> | 
|  | 34 | #include <linux/sched.h> | 
|  | 35 | #include <linux/string.h> | 
|  | 36 | #include <linux/timer.h> | 
|  | 37 | #include <linux/errno.h> | 
|  | 38 | #include <linux/in.h> | 
|  | 39 | #include <linux/ioport.h> | 
|  | 40 | #include <linux/slab.h> | 
|  | 41 | #include <linux/mm.h> | 
|  | 42 | #include <linux/interrupt.h> | 
|  | 43 | #include <linux/init.h> | 
|  | 44 | #include <linux/netdevice.h> | 
|  | 45 | #include <linux/etherdevice.h> | 
|  | 46 | #include <linux/skbuff.h> | 
|  | 47 | #include <linux/ethtool.h> | 
|  | 48 | #include <linux/highmem.h> | 
|  | 49 | #include <linux/proc_fs.h> | 
|  | 50 | #include <linux/ctype.h> | 
|  | 51 | #include <linux/version.h> | 
|  | 52 | #include <linux/spinlock.h> | 
|  | 53 | #include <linux/dma-mapping.h> | 
|  | 54 | #include <linux/clk.h> | 
|  | 55 | #include <linux/platform_device.h> | 
|  | 56 | #include <linux/semaphore.h> | 
|  | 57 | #include <linux/phy.h> | 
|  | 58 | #include <linux/bitops.h> | 
|  | 59 | #include <linux/io.h> | 
|  | 60 | #include <linux/uaccess.h> | 
| Sriramakrishnan | 8ee2bf9 | 2009-11-19 15:58:25 +0530 | [diff] [blame] | 61 | #include <linux/davinci_emac.h> | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 62 |  | 
|  | 63 | #include <asm/irq.h> | 
|  | 64 | #include <asm/page.h> | 
|  | 65 |  | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 66 | #include "davinci_cpdma.h" | 
|  | 67 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 68 | static int debug_level; | 
|  | 69 | module_param(debug_level, int, 0); | 
|  | 70 | MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)"); | 
|  | 71 |  | 
|  | 72 | /* Netif debug messages possible */ | 
|  | 73 | #define DAVINCI_EMAC_DEBUG	(NETIF_MSG_DRV | \ | 
|  | 74 | NETIF_MSG_PROBE | \ | 
|  | 75 | NETIF_MSG_LINK | \ | 
|  | 76 | NETIF_MSG_TIMER | \ | 
|  | 77 | NETIF_MSG_IFDOWN | \ | 
|  | 78 | NETIF_MSG_IFUP | \ | 
|  | 79 | NETIF_MSG_RX_ERR | \ | 
|  | 80 | NETIF_MSG_TX_ERR | \ | 
|  | 81 | NETIF_MSG_TX_QUEUED | \ | 
|  | 82 | NETIF_MSG_INTR | \ | 
|  | 83 | NETIF_MSG_TX_DONE | \ | 
|  | 84 | NETIF_MSG_RX_STATUS | \ | 
|  | 85 | NETIF_MSG_PKTDATA | \ | 
|  | 86 | NETIF_MSG_HW | \ | 
|  | 87 | NETIF_MSG_WOL) | 
|  | 88 |  | 
|  | 89 | /* version info */ | 
|  | 90 | #define EMAC_MAJOR_VERSION	6 | 
|  | 91 | #define EMAC_MINOR_VERSION	1 | 
|  | 92 | #define EMAC_MODULE_VERSION	"6.1" | 
|  | 93 | MODULE_VERSION(EMAC_MODULE_VERSION); | 
|  | 94 | static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; | 
|  | 95 |  | 
|  | 96 | /* Configuration items */ | 
| Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 97 | #define EMAC_DEF_PASS_CRC		(0) /* Do not pass CRC up to frames */ | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 98 | #define EMAC_DEF_QOS_EN			(0) /* EMAC proprietary QoS disabled */ | 
|  | 99 | #define EMAC_DEF_NO_BUFF_CHAIN		(0) /* No buffer chain */ | 
|  | 100 | #define EMAC_DEF_MACCTRL_FRAME_EN	(0) /* Discard Maccontrol frames */ | 
|  | 101 | #define EMAC_DEF_SHORT_FRAME_EN		(0) /* Discard short frames */ | 
|  | 102 | #define EMAC_DEF_ERROR_FRAME_EN		(0) /* Discard error frames */ | 
| Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 103 | #define EMAC_DEF_PROM_EN		(0) /* Promiscuous disabled */ | 
|  | 104 | #define EMAC_DEF_PROM_CH		(0) /* Promiscuous channel is 0 */ | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 105 | #define EMAC_DEF_BCAST_EN		(1) /* Broadcast enabled */ | 
|  | 106 | #define EMAC_DEF_BCAST_CH		(0) /* Broadcast channel is 0 */ | 
|  | 107 | #define EMAC_DEF_MCAST_EN		(1) /* Multicast enabled */ | 
|  | 108 | #define EMAC_DEF_MCAST_CH		(0) /* Multicast channel is 0 */ | 
|  | 109 |  | 
|  | 110 | #define EMAC_DEF_TXPRIO_FIXED		(1) /* TX Priority is fixed */ | 
|  | 111 | #define EMAC_DEF_TXPACING_EN		(0) /* TX pacing NOT supported*/ | 
|  | 112 |  | 
|  | 113 | #define EMAC_DEF_BUFFER_OFFSET		(0) /* Buffer offset to DMA (future) */ | 
|  | 114 | #define EMAC_DEF_MIN_ETHPKTSIZE		(60) /* Minimum ethernet pkt size */ | 
|  | 115 | #define EMAC_DEF_MAX_FRAME_SIZE		(1500 + 14 + 4 + 4) | 
|  | 116 | #define EMAC_DEF_TX_CH			(0) /* Default 0th channel */ | 
|  | 117 | #define EMAC_DEF_RX_CH			(0) /* Default 0th channel */ | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 118 | #define EMAC_DEF_RX_NUM_DESC		(128) | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 119 | #define EMAC_DEF_MAX_TX_CH		(1) /* Max TX channels configured */ | 
|  | 120 | #define EMAC_DEF_MAX_RX_CH		(1) /* Max RX channels configured */ | 
|  | 121 | #define EMAC_POLL_WEIGHT		(64) /* Default NAPI poll weight */ | 
|  | 122 |  | 
|  | 123 | /* Buffer descriptor parameters */ | 
|  | 124 | #define EMAC_DEF_TX_MAX_SERVICE		(32) /* TX max service BD's */ | 
|  | 125 | #define EMAC_DEF_RX_MAX_SERVICE		(64) /* should = netdev->weight */ | 
|  | 126 |  | 
|  | 127 | /* EMAC register related defines */ | 
|  | 128 | #define EMAC_ALL_MULTI_REG_VALUE	(0xFFFFFFFF) | 
|  | 129 | #define EMAC_NUM_MULTICAST_BITS		(64) | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 130 | #define EMAC_TX_CONTROL_TX_ENABLE_VAL	(0x1) | 
|  | 131 | #define EMAC_RX_CONTROL_RX_ENABLE_VAL	(0x1) | 
|  | 132 | #define EMAC_MAC_HOST_ERR_INTMASK_VAL	(0x2) | 
|  | 133 | #define EMAC_RX_UNICAST_CLEAR_ALL	(0xFF) | 
|  | 134 | #define EMAC_INT_MASK_CLEAR		(0xFF) | 
|  | 135 |  | 
|  | 136 | /* RX MBP register bit positions */ | 
|  | 137 | #define EMAC_RXMBP_PASSCRC_MASK		BIT(30) | 
|  | 138 | #define EMAC_RXMBP_QOSEN_MASK		BIT(29) | 
|  | 139 | #define EMAC_RXMBP_NOCHAIN_MASK		BIT(28) | 
|  | 140 | #define EMAC_RXMBP_CMFEN_MASK		BIT(24) | 
|  | 141 | #define EMAC_RXMBP_CSFEN_MASK		BIT(23) | 
|  | 142 | #define EMAC_RXMBP_CEFEN_MASK		BIT(22) | 
|  | 143 | #define EMAC_RXMBP_CAFEN_MASK		BIT(21) | 
|  | 144 | #define EMAC_RXMBP_PROMCH_SHIFT		(16) | 
|  | 145 | #define EMAC_RXMBP_PROMCH_MASK		(0x7 << 16) | 
|  | 146 | #define EMAC_RXMBP_BROADEN_MASK		BIT(13) | 
|  | 147 | #define EMAC_RXMBP_BROADCH_SHIFT	(8) | 
|  | 148 | #define EMAC_RXMBP_BROADCH_MASK		(0x7 << 8) | 
|  | 149 | #define EMAC_RXMBP_MULTIEN_MASK		BIT(5) | 
|  | 150 | #define EMAC_RXMBP_MULTICH_SHIFT	(0) | 
|  | 151 | #define EMAC_RXMBP_MULTICH_MASK		(0x7) | 
|  | 152 | #define EMAC_RXMBP_CHMASK		(0x7) | 
|  | 153 |  | 
|  | 154 | /* EMAC register definitions/bit maps used */ | 
|  | 155 | # define EMAC_MBP_RXPROMISC		(0x00200000) | 
|  | 156 | # define EMAC_MBP_PROMISCCH(ch)		(((ch) & 0x7) << 16) | 
|  | 157 | # define EMAC_MBP_RXBCAST		(0x00002000) | 
|  | 158 | # define EMAC_MBP_BCASTCHAN(ch)		(((ch) & 0x7) << 8) | 
|  | 159 | # define EMAC_MBP_RXMCAST		(0x00000020) | 
|  | 160 | # define EMAC_MBP_MCASTCHAN(ch)		((ch) & 0x7) | 
|  | 161 |  | 
|  | 162 | /* EMAC mac_control register */ | 
| chaithrika@ti.com | 69ef969 | 2009-10-01 10:25:19 +0000 | [diff] [blame] | 163 | #define EMAC_MACCONTROL_TXPTYPE		BIT(9) | 
|  | 164 | #define EMAC_MACCONTROL_TXPACEEN	BIT(6) | 
|  | 165 | #define EMAC_MACCONTROL_GMIIEN		BIT(5) | 
|  | 166 | #define EMAC_MACCONTROL_GIGABITEN	BIT(7) | 
|  | 167 | #define EMAC_MACCONTROL_FULLDUPLEXEN	BIT(0) | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 168 | #define EMAC_MACCONTROL_RMIISPEED_MASK	BIT(15) | 
|  | 169 |  | 
|  | 170 | /* GIGABIT MODE related bits */ | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 171 | #define EMAC_DM646X_MACCONTORL_GIG	BIT(7) | 
|  | 172 | #define EMAC_DM646X_MACCONTORL_GIGFORCE	BIT(17) | 
|  | 173 |  | 
|  | 174 | /* EMAC mac_status register */ | 
|  | 175 | #define EMAC_MACSTATUS_TXERRCODE_MASK	(0xF00000) | 
|  | 176 | #define EMAC_MACSTATUS_TXERRCODE_SHIFT	(20) | 
|  | 177 | #define EMAC_MACSTATUS_TXERRCH_MASK	(0x7) | 
|  | 178 | #define EMAC_MACSTATUS_TXERRCH_SHIFT	(16) | 
|  | 179 | #define EMAC_MACSTATUS_RXERRCODE_MASK	(0xF000) | 
|  | 180 | #define EMAC_MACSTATUS_RXERRCODE_SHIFT	(12) | 
|  | 181 | #define EMAC_MACSTATUS_RXERRCH_MASK	(0x7) | 
|  | 182 | #define EMAC_MACSTATUS_RXERRCH_SHIFT	(8) | 
|  | 183 |  | 
|  | 184 | /* EMAC RX register masks */ | 
|  | 185 | #define EMAC_RX_MAX_LEN_MASK		(0xFFFF) | 
|  | 186 | #define EMAC_RX_BUFFER_OFFSET_MASK	(0xFFFF) | 
|  | 187 |  | 
|  | 188 | /* MAC_IN_VECTOR (0x180) register bit fields */ | 
| chaithrika@ti.com | 69ef969 | 2009-10-01 10:25:19 +0000 | [diff] [blame] | 189 | #define EMAC_DM644X_MAC_IN_VECTOR_HOST_INT	BIT(17) | 
|  | 190 | #define EMAC_DM644X_MAC_IN_VECTOR_STATPEND_INT	BIT(16) | 
|  | 191 | #define EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC	BIT(8) | 
|  | 192 | #define EMAC_DM644X_MAC_IN_VECTOR_TX_INT_VEC	BIT(0) | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 193 |  | 
|  | 194 | /** NOTE:: For DM646x the IN_VECTOR has changed */ | 
|  | 195 | #define EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC	BIT(EMAC_DEF_RX_CH) | 
|  | 196 | #define EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC	BIT(16 + EMAC_DEF_TX_CH) | 
| Sriram | 43c2ed8 | 2009-09-24 19:15:18 +0000 | [diff] [blame] | 197 | #define EMAC_DM646X_MAC_IN_VECTOR_HOST_INT	BIT(26) | 
|  | 198 | #define EMAC_DM646X_MAC_IN_VECTOR_STATPEND_INT	BIT(27) | 
|  | 199 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 200 | /* CPPI bit positions */ | 
|  | 201 | #define EMAC_CPPI_SOP_BIT		BIT(31) | 
|  | 202 | #define EMAC_CPPI_EOP_BIT		BIT(30) | 
|  | 203 | #define EMAC_CPPI_OWNERSHIP_BIT		BIT(29) | 
|  | 204 | #define EMAC_CPPI_EOQ_BIT		BIT(28) | 
|  | 205 | #define EMAC_CPPI_TEARDOWN_COMPLETE_BIT BIT(27) | 
|  | 206 | #define EMAC_CPPI_PASS_CRC_BIT		BIT(26) | 
|  | 207 | #define EMAC_RX_BD_BUF_SIZE		(0xFFFF) | 
|  | 208 | #define EMAC_BD_LENGTH_FOR_CACHE	(16) /* only CPPI bytes */ | 
|  | 209 | #define EMAC_RX_BD_PKT_LENGTH_MASK	(0xFFFF) | 
|  | 210 |  | 
|  | 211 | /* Max hardware defines */ | 
|  | 212 | #define EMAC_MAX_TXRX_CHANNELS		 (8)  /* Max hardware channels */ | 
|  | 213 | #define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */ | 
|  | 214 |  | 
|  | 215 | /* EMAC Peripheral Device Register Memory Layout structure */ | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 216 | #define EMAC_MACINVECTOR	0x90 | 
|  | 217 |  | 
|  | 218 | #define EMAC_DM646X_MACEOIVECTOR	0x94 | 
|  | 219 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 220 | #define EMAC_MACINTSTATRAW	0xB0 | 
|  | 221 | #define EMAC_MACINTSTATMASKED	0xB4 | 
|  | 222 | #define EMAC_MACINTMASKSET	0xB8 | 
|  | 223 | #define EMAC_MACINTMASKCLEAR	0xBC | 
|  | 224 |  | 
|  | 225 | #define EMAC_RXMBPENABLE	0x100 | 
|  | 226 | #define EMAC_RXUNICASTSET	0x104 | 
|  | 227 | #define EMAC_RXUNICASTCLEAR	0x108 | 
|  | 228 | #define EMAC_RXMAXLEN		0x10C | 
|  | 229 | #define EMAC_RXBUFFEROFFSET	0x110 | 
|  | 230 | #define EMAC_RXFILTERLOWTHRESH	0x114 | 
|  | 231 |  | 
|  | 232 | #define EMAC_MACCONTROL		0x160 | 
|  | 233 | #define EMAC_MACSTATUS		0x164 | 
|  | 234 | #define EMAC_EMCONTROL		0x168 | 
|  | 235 | #define EMAC_FIFOCONTROL	0x16C | 
|  | 236 | #define EMAC_MACCONFIG		0x170 | 
|  | 237 | #define EMAC_SOFTRESET		0x174 | 
|  | 238 | #define EMAC_MACSRCADDRLO	0x1D0 | 
|  | 239 | #define EMAC_MACSRCADDRHI	0x1D4 | 
|  | 240 | #define EMAC_MACHASH1		0x1D8 | 
|  | 241 | #define EMAC_MACHASH2		0x1DC | 
|  | 242 | #define EMAC_MACADDRLO		0x500 | 
|  | 243 | #define EMAC_MACADDRHI		0x504 | 
|  | 244 | #define EMAC_MACINDEX		0x508 | 
|  | 245 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 246 | /* EMAC statistics registers */ | 
|  | 247 | #define EMAC_RXGOODFRAMES	0x200 | 
|  | 248 | #define EMAC_RXBCASTFRAMES	0x204 | 
|  | 249 | #define EMAC_RXMCASTFRAMES	0x208 | 
|  | 250 | #define EMAC_RXPAUSEFRAMES	0x20C | 
|  | 251 | #define EMAC_RXCRCERRORS	0x210 | 
|  | 252 | #define EMAC_RXALIGNCODEERRORS	0x214 | 
|  | 253 | #define EMAC_RXOVERSIZED	0x218 | 
|  | 254 | #define EMAC_RXJABBER		0x21C | 
|  | 255 | #define EMAC_RXUNDERSIZED	0x220 | 
|  | 256 | #define EMAC_RXFRAGMENTS	0x224 | 
|  | 257 | #define EMAC_RXFILTERED		0x228 | 
|  | 258 | #define EMAC_RXQOSFILTERED	0x22C | 
|  | 259 | #define EMAC_RXOCTETS		0x230 | 
|  | 260 | #define EMAC_TXGOODFRAMES	0x234 | 
|  | 261 | #define EMAC_TXBCASTFRAMES	0x238 | 
|  | 262 | #define EMAC_TXMCASTFRAMES	0x23C | 
|  | 263 | #define EMAC_TXPAUSEFRAMES	0x240 | 
|  | 264 | #define EMAC_TXDEFERRED		0x244 | 
|  | 265 | #define EMAC_TXCOLLISION	0x248 | 
|  | 266 | #define EMAC_TXSINGLECOLL	0x24C | 
|  | 267 | #define EMAC_TXMULTICOLL	0x250 | 
|  | 268 | #define EMAC_TXEXCESSIVECOLL	0x254 | 
|  | 269 | #define EMAC_TXLATECOLL		0x258 | 
|  | 270 | #define EMAC_TXUNDERRUN		0x25C | 
|  | 271 | #define EMAC_TXCARRIERSENSE	0x260 | 
|  | 272 | #define EMAC_TXOCTETS		0x264 | 
|  | 273 | #define EMAC_NETOCTETS		0x280 | 
|  | 274 | #define EMAC_RXSOFOVERRUNS	0x284 | 
|  | 275 | #define EMAC_RXMOFOVERRUNS	0x288 | 
|  | 276 | #define EMAC_RXDMAOVERRUNS	0x28C | 
|  | 277 |  | 
|  | 278 | /* EMAC DM644x control registers */ | 
|  | 279 | #define EMAC_CTRL_EWCTL		(0x4) | 
|  | 280 | #define EMAC_CTRL_EWINTTCNT	(0x8) | 
|  | 281 |  | 
| Sriram | 84da265 | 2010-07-29 02:33:58 +0000 | [diff] [blame] | 282 | /* EMAC DM644x control module masks */ | 
|  | 283 | #define EMAC_DM644X_EWINTCNT_MASK	0x1FFFF | 
|  | 284 | #define EMAC_DM644X_INTMIN_INTVL	0x1 | 
|  | 285 | #define EMAC_DM644X_INTMAX_INTVL	(EMAC_DM644X_EWINTCNT_MASK) | 
|  | 286 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 287 | /* EMAC DM646X control module registers */ | 
| Sriram | 84da265 | 2010-07-29 02:33:58 +0000 | [diff] [blame] | 288 | #define EMAC_DM646X_CMINTCTRL	0x0C | 
|  | 289 | #define EMAC_DM646X_CMRXINTEN	0x14 | 
|  | 290 | #define EMAC_DM646X_CMTXINTEN	0x18 | 
|  | 291 | #define EMAC_DM646X_CMRXINTMAX	0x70 | 
|  | 292 | #define EMAC_DM646X_CMTXINTMAX	0x74 | 
|  | 293 |  | 
|  | 294 | /* EMAC DM646X control module masks */ | 
|  | 295 | #define EMAC_DM646X_INTPACEEN		(0x3 << 16) | 
|  | 296 | #define EMAC_DM646X_INTPRESCALE_MASK	(0x7FF << 0) | 
|  | 297 | #define EMAC_DM646X_CMINTMAX_CNT	63 | 
|  | 298 | #define EMAC_DM646X_CMINTMIN_CNT	2 | 
|  | 299 | #define EMAC_DM646X_CMINTMAX_INTVL	(1000 / EMAC_DM646X_CMINTMIN_CNT) | 
|  | 300 | #define EMAC_DM646X_CMINTMIN_INTVL	((1000 / EMAC_DM646X_CMINTMAX_CNT) + 1) | 
|  | 301 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 302 |  | 
|  | 303 | /* EMAC EOI codes for C0 */ | 
|  | 304 | #define EMAC_DM646X_MAC_EOI_C0_RXEN	(0x01) | 
|  | 305 | #define EMAC_DM646X_MAC_EOI_C0_TXEN	(0x02) | 
|  | 306 |  | 
| Sriram | 0fe7463 | 2009-10-07 02:44:30 +0000 | [diff] [blame] | 307 | /* EMAC Stats Clear Mask */ | 
|  | 308 | #define EMAC_STATS_CLR_MASK    (0xFFFFFFFF) | 
|  | 309 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 310 | /* emac_priv: EMAC private data structure | 
|  | 311 | * | 
|  | 312 | * EMAC adapter private data structure | 
|  | 313 | */ | 
|  | 314 | struct emac_priv { | 
|  | 315 | u32 msg_enable; | 
|  | 316 | struct net_device *ndev; | 
|  | 317 | struct platform_device *pdev; | 
|  | 318 | struct napi_struct napi; | 
|  | 319 | char mac_addr[6]; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 320 | void __iomem *remap_addr; | 
|  | 321 | u32 emac_base_phys; | 
|  | 322 | void __iomem *emac_base; | 
|  | 323 | void __iomem *ctrl_base; | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 324 | struct cpdma_ctlr *dma; | 
|  | 325 | struct cpdma_chan *txchan; | 
|  | 326 | struct cpdma_chan *rxchan; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 327 | u32 link; /* 1=link on, 0=link off */ | 
|  | 328 | u32 speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */ | 
|  | 329 | u32 duplex; /* Link duplex: 0=Half, 1=Full */ | 
|  | 330 | u32 rx_buf_size; | 
|  | 331 | u32 isr_count; | 
| Sriram | 84da265 | 2010-07-29 02:33:58 +0000 | [diff] [blame] | 332 | u32 coal_intvl; | 
|  | 333 | u32 bus_freq_mhz; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 334 | u8 rmii_en; | 
|  | 335 | u8 version; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 336 | u32 mac_hash1; | 
|  | 337 | u32 mac_hash2; | 
|  | 338 | u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS]; | 
|  | 339 | u32 rx_addr_type; | 
| Cyril Chemparathy | 5d69e00 | 2010-09-15 10:11:24 -0400 | [diff] [blame] | 340 | const char *phy_id; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 341 | struct phy_device *phydev; | 
|  | 342 | spinlock_t lock; | 
| Sriramakrishnan | 01a9af3 | 2009-11-19 15:58:26 +0530 | [diff] [blame] | 343 | /*platform specific members*/ | 
|  | 344 | void (*int_enable) (void); | 
|  | 345 | void (*int_disable) (void); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 346 | }; | 
|  | 347 |  | 
|  | 348 | /* clock frequency for EMAC */ | 
|  | 349 | static struct clk *emac_clk; | 
|  | 350 | static unsigned long emac_bus_frequency; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 351 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 352 | /* EMAC TX Host Error description strings */ | 
|  | 353 | static char *emac_txhost_errcodes[16] = { | 
|  | 354 | "No error", "SOP error", "Ownership bit not set in SOP buffer", | 
|  | 355 | "Zero Next Buffer Descriptor Pointer Without EOP", | 
|  | 356 | "Zero Buffer Pointer", "Zero Buffer Length", "Packet Length Error", | 
|  | 357 | "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", | 
|  | 358 | "Reserved", "Reserved", "Reserved", "Reserved" | 
|  | 359 | }; | 
|  | 360 |  | 
|  | 361 | /* EMAC RX Host Error description strings */ | 
|  | 362 | static char *emac_rxhost_errcodes[16] = { | 
|  | 363 | "No error", "Reserved", "Ownership bit not set in input buffer", | 
|  | 364 | "Reserved", "Zero Buffer Pointer", "Reserved", "Reserved", | 
|  | 365 | "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", | 
|  | 366 | "Reserved", "Reserved", "Reserved", "Reserved" | 
|  | 367 | }; | 
|  | 368 |  | 
|  | 369 | /* Helper macros */ | 
|  | 370 | #define emac_read(reg)		  ioread32(priv->emac_base + (reg)) | 
|  | 371 | #define emac_write(reg, val)      iowrite32(val, priv->emac_base + (reg)) | 
|  | 372 |  | 
|  | 373 | #define emac_ctrl_read(reg)	  ioread32((priv->ctrl_base + (reg))) | 
|  | 374 | #define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg))) | 
|  | 375 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 376 | /** | 
|  | 377 | * emac_dump_regs: Dump important EMAC registers to debug terminal | 
|  | 378 | * @priv: The DaVinci EMAC private adapter structure | 
|  | 379 | * | 
|  | 380 | * Executes ethtool set cmd & sets phy mode | 
|  | 381 | * | 
|  | 382 | */ | 
|  | 383 | static void emac_dump_regs(struct emac_priv *priv) | 
|  | 384 | { | 
|  | 385 | struct device *emac_dev = &priv->ndev->dev; | 
|  | 386 |  | 
|  | 387 | /* Print important registers in EMAC */ | 
|  | 388 | dev_info(emac_dev, "EMAC Basic registers\n"); | 
| Sriram | e994762 | 2010-07-29 02:34:00 +0000 | [diff] [blame] | 389 | if (priv->version == EMAC_VERSION_1) { | 
|  | 390 | dev_info(emac_dev, "EMAC: EWCTL: %08X, EWINTTCNT: %08X\n", | 
|  | 391 | emac_ctrl_read(EMAC_CTRL_EWCTL), | 
|  | 392 | emac_ctrl_read(EMAC_CTRL_EWINTTCNT)); | 
|  | 393 | } | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 394 | dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n", | 
|  | 395 | emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL)); | 
|  | 396 | dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\ | 
|  | 397 | "RXMaxLen=%08X\n", emac_read(EMAC_RXMBPENABLE), | 
|  | 398 | emac_read(EMAC_RXUNICASTSET), emac_read(EMAC_RXMAXLEN)); | 
|  | 399 | dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\ | 
|  | 400 | "MacConfig=%08X\n", emac_read(EMAC_MACCONTROL), | 
|  | 401 | emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG)); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 402 | dev_info(emac_dev, "EMAC Statistics\n"); | 
|  | 403 | dev_info(emac_dev, "EMAC: rx_good_frames:%d\n", | 
|  | 404 | emac_read(EMAC_RXGOODFRAMES)); | 
|  | 405 | dev_info(emac_dev, "EMAC: rx_broadcast_frames:%d\n", | 
|  | 406 | emac_read(EMAC_RXBCASTFRAMES)); | 
|  | 407 | dev_info(emac_dev, "EMAC: rx_multicast_frames:%d\n", | 
|  | 408 | emac_read(EMAC_RXMCASTFRAMES)); | 
|  | 409 | dev_info(emac_dev, "EMAC: rx_pause_frames:%d\n", | 
|  | 410 | emac_read(EMAC_RXPAUSEFRAMES)); | 
|  | 411 | dev_info(emac_dev, "EMAC: rx_crcerrors:%d\n", | 
|  | 412 | emac_read(EMAC_RXCRCERRORS)); | 
|  | 413 | dev_info(emac_dev, "EMAC: rx_align_code_errors:%d\n", | 
|  | 414 | emac_read(EMAC_RXALIGNCODEERRORS)); | 
|  | 415 | dev_info(emac_dev, "EMAC: rx_oversized_frames:%d\n", | 
|  | 416 | emac_read(EMAC_RXOVERSIZED)); | 
|  | 417 | dev_info(emac_dev, "EMAC: rx_jabber_frames:%d\n", | 
|  | 418 | emac_read(EMAC_RXJABBER)); | 
|  | 419 | dev_info(emac_dev, "EMAC: rx_undersized_frames:%d\n", | 
|  | 420 | emac_read(EMAC_RXUNDERSIZED)); | 
|  | 421 | dev_info(emac_dev, "EMAC: rx_fragments:%d\n", | 
|  | 422 | emac_read(EMAC_RXFRAGMENTS)); | 
|  | 423 | dev_info(emac_dev, "EMAC: rx_filtered_frames:%d\n", | 
|  | 424 | emac_read(EMAC_RXFILTERED)); | 
|  | 425 | dev_info(emac_dev, "EMAC: rx_qos_filtered_frames:%d\n", | 
|  | 426 | emac_read(EMAC_RXQOSFILTERED)); | 
|  | 427 | dev_info(emac_dev, "EMAC: rx_octets:%d\n", | 
|  | 428 | emac_read(EMAC_RXOCTETS)); | 
|  | 429 | dev_info(emac_dev, "EMAC: tx_goodframes:%d\n", | 
|  | 430 | emac_read(EMAC_TXGOODFRAMES)); | 
|  | 431 | dev_info(emac_dev, "EMAC: tx_bcastframes:%d\n", | 
|  | 432 | emac_read(EMAC_TXBCASTFRAMES)); | 
|  | 433 | dev_info(emac_dev, "EMAC: tx_mcastframes:%d\n", | 
|  | 434 | emac_read(EMAC_TXMCASTFRAMES)); | 
|  | 435 | dev_info(emac_dev, "EMAC: tx_pause_frames:%d\n", | 
|  | 436 | emac_read(EMAC_TXPAUSEFRAMES)); | 
|  | 437 | dev_info(emac_dev, "EMAC: tx_deferred_frames:%d\n", | 
|  | 438 | emac_read(EMAC_TXDEFERRED)); | 
|  | 439 | dev_info(emac_dev, "EMAC: tx_collision_frames:%d\n", | 
|  | 440 | emac_read(EMAC_TXCOLLISION)); | 
|  | 441 | dev_info(emac_dev, "EMAC: tx_single_coll_frames:%d\n", | 
|  | 442 | emac_read(EMAC_TXSINGLECOLL)); | 
|  | 443 | dev_info(emac_dev, "EMAC: tx_mult_coll_frames:%d\n", | 
|  | 444 | emac_read(EMAC_TXMULTICOLL)); | 
|  | 445 | dev_info(emac_dev, "EMAC: tx_excessive_collisions:%d\n", | 
|  | 446 | emac_read(EMAC_TXEXCESSIVECOLL)); | 
|  | 447 | dev_info(emac_dev, "EMAC: tx_late_collisions:%d\n", | 
|  | 448 | emac_read(EMAC_TXLATECOLL)); | 
|  | 449 | dev_info(emac_dev, "EMAC: tx_underrun:%d\n", | 
|  | 450 | emac_read(EMAC_TXUNDERRUN)); | 
|  | 451 | dev_info(emac_dev, "EMAC: tx_carrier_sense_errors:%d\n", | 
|  | 452 | emac_read(EMAC_TXCARRIERSENSE)); | 
|  | 453 | dev_info(emac_dev, "EMAC: tx_octets:%d\n", | 
|  | 454 | emac_read(EMAC_TXOCTETS)); | 
|  | 455 | dev_info(emac_dev, "EMAC: net_octets:%d\n", | 
|  | 456 | emac_read(EMAC_NETOCTETS)); | 
|  | 457 | dev_info(emac_dev, "EMAC: rx_sof_overruns:%d\n", | 
|  | 458 | emac_read(EMAC_RXSOFOVERRUNS)); | 
|  | 459 | dev_info(emac_dev, "EMAC: rx_mof_overruns:%d\n", | 
|  | 460 | emac_read(EMAC_RXMOFOVERRUNS)); | 
|  | 461 | dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n", | 
|  | 462 | emac_read(EMAC_RXDMAOVERRUNS)); | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 463 |  | 
|  | 464 | cpdma_ctlr_dump(priv->dma); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 465 | } | 
|  | 466 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 467 | /** | 
|  | 468 | * emac_get_drvinfo: Get EMAC driver information | 
|  | 469 | * @ndev: The DaVinci EMAC network adapter | 
|  | 470 | * @info: ethtool info structure containing name and version | 
|  | 471 | * | 
|  | 472 | * Returns EMAC driver information (name and version) | 
|  | 473 | * | 
|  | 474 | */ | 
|  | 475 | static void emac_get_drvinfo(struct net_device *ndev, | 
|  | 476 | struct ethtool_drvinfo *info) | 
|  | 477 | { | 
|  | 478 | strcpy(info->driver, emac_version_string); | 
|  | 479 | strcpy(info->version, EMAC_MODULE_VERSION); | 
|  | 480 | } | 
|  | 481 |  | 
|  | 482 | /** | 
|  | 483 | * emac_get_settings: Get EMAC settings | 
|  | 484 | * @ndev: The DaVinci EMAC network adapter | 
|  | 485 | * @ecmd: ethtool command | 
|  | 486 | * | 
|  | 487 | * Executes ethool get command | 
|  | 488 | * | 
|  | 489 | */ | 
|  | 490 | static int emac_get_settings(struct net_device *ndev, | 
|  | 491 | struct ethtool_cmd *ecmd) | 
|  | 492 | { | 
|  | 493 | struct emac_priv *priv = netdev_priv(ndev); | 
| Cyril Chemparathy | 5d69e00 | 2010-09-15 10:11:24 -0400 | [diff] [blame] | 494 | if (priv->phydev) | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 495 | return phy_ethtool_gset(priv->phydev, ecmd); | 
|  | 496 | else | 
|  | 497 | return -EOPNOTSUPP; | 
|  | 498 |  | 
|  | 499 | } | 
|  | 500 |  | 
|  | 501 | /** | 
|  | 502 | * emac_set_settings: Set EMAC settings | 
|  | 503 | * @ndev: The DaVinci EMAC network adapter | 
|  | 504 | * @ecmd: ethtool command | 
|  | 505 | * | 
|  | 506 | * Executes ethool set command | 
|  | 507 | * | 
|  | 508 | */ | 
|  | 509 | static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) | 
|  | 510 | { | 
|  | 511 | struct emac_priv *priv = netdev_priv(ndev); | 
| Cyril Chemparathy | 5d69e00 | 2010-09-15 10:11:24 -0400 | [diff] [blame] | 512 | if (priv->phydev) | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 513 | return phy_ethtool_sset(priv->phydev, ecmd); | 
|  | 514 | else | 
|  | 515 | return -EOPNOTSUPP; | 
|  | 516 |  | 
|  | 517 | } | 
|  | 518 |  | 
|  | 519 | /** | 
| Sriram | 84da265 | 2010-07-29 02:33:58 +0000 | [diff] [blame] | 520 | * emac_get_coalesce : Get interrupt coalesce settings for this device | 
|  | 521 | * @ndev : The DaVinci EMAC network adapter | 
|  | 522 | * @coal : ethtool coalesce settings structure | 
|  | 523 | * | 
|  | 524 | * Fetch the current interrupt coalesce settings | 
|  | 525 | * | 
|  | 526 | */ | 
|  | 527 | static int emac_get_coalesce(struct net_device *ndev, | 
|  | 528 | struct ethtool_coalesce *coal) | 
|  | 529 | { | 
|  | 530 | struct emac_priv *priv = netdev_priv(ndev); | 
|  | 531 |  | 
|  | 532 | coal->rx_coalesce_usecs = priv->coal_intvl; | 
|  | 533 | return 0; | 
|  | 534 |  | 
|  | 535 | } | 
|  | 536 |  | 
|  | 537 | /** | 
|  | 538 | * emac_set_coalesce : Set interrupt coalesce settings for this device | 
|  | 539 | * @ndev : The DaVinci EMAC network adapter | 
|  | 540 | * @coal : ethtool coalesce settings structure | 
|  | 541 | * | 
|  | 542 | * Set interrupt coalesce parameters | 
|  | 543 | * | 
|  | 544 | */ | 
|  | 545 | static int emac_set_coalesce(struct net_device *ndev, | 
|  | 546 | struct ethtool_coalesce *coal) | 
|  | 547 | { | 
|  | 548 | struct emac_priv *priv = netdev_priv(ndev); | 
|  | 549 | u32 int_ctrl, num_interrupts = 0; | 
|  | 550 | u32 prescale = 0, addnl_dvdr = 1, coal_intvl = 0; | 
|  | 551 |  | 
|  | 552 | if (!coal->rx_coalesce_usecs) | 
|  | 553 | return -EINVAL; | 
|  | 554 |  | 
|  | 555 | coal_intvl = coal->rx_coalesce_usecs; | 
|  | 556 |  | 
|  | 557 | switch (priv->version) { | 
|  | 558 | case EMAC_VERSION_2: | 
|  | 559 | int_ctrl =  emac_ctrl_read(EMAC_DM646X_CMINTCTRL); | 
|  | 560 | prescale = priv->bus_freq_mhz * 4; | 
|  | 561 |  | 
|  | 562 | if (coal_intvl < EMAC_DM646X_CMINTMIN_INTVL) | 
|  | 563 | coal_intvl = EMAC_DM646X_CMINTMIN_INTVL; | 
|  | 564 |  | 
|  | 565 | if (coal_intvl > EMAC_DM646X_CMINTMAX_INTVL) { | 
|  | 566 | /* | 
|  | 567 | * Interrupt pacer works with 4us Pulse, we can | 
|  | 568 | * throttle further by dilating the 4us pulse. | 
|  | 569 | */ | 
|  | 570 | addnl_dvdr = EMAC_DM646X_INTPRESCALE_MASK / prescale; | 
|  | 571 |  | 
|  | 572 | if (addnl_dvdr > 1) { | 
|  | 573 | prescale *= addnl_dvdr; | 
|  | 574 | if (coal_intvl > (EMAC_DM646X_CMINTMAX_INTVL | 
|  | 575 | * addnl_dvdr)) | 
|  | 576 | coal_intvl = (EMAC_DM646X_CMINTMAX_INTVL | 
|  | 577 | * addnl_dvdr); | 
|  | 578 | } else { | 
|  | 579 | addnl_dvdr = 1; | 
|  | 580 | coal_intvl = EMAC_DM646X_CMINTMAX_INTVL; | 
|  | 581 | } | 
|  | 582 | } | 
|  | 583 |  | 
|  | 584 | num_interrupts = (1000 * addnl_dvdr) / coal_intvl; | 
|  | 585 |  | 
|  | 586 | int_ctrl |= EMAC_DM646X_INTPACEEN; | 
|  | 587 | int_ctrl &= (~EMAC_DM646X_INTPRESCALE_MASK); | 
|  | 588 | int_ctrl |= (prescale & EMAC_DM646X_INTPRESCALE_MASK); | 
|  | 589 | emac_ctrl_write(EMAC_DM646X_CMINTCTRL, int_ctrl); | 
|  | 590 |  | 
|  | 591 | emac_ctrl_write(EMAC_DM646X_CMRXINTMAX, num_interrupts); | 
|  | 592 | emac_ctrl_write(EMAC_DM646X_CMTXINTMAX, num_interrupts); | 
|  | 593 |  | 
|  | 594 | break; | 
|  | 595 | default: | 
|  | 596 | int_ctrl = emac_ctrl_read(EMAC_CTRL_EWINTTCNT); | 
|  | 597 | int_ctrl &= (~EMAC_DM644X_EWINTCNT_MASK); | 
|  | 598 | prescale = coal_intvl * priv->bus_freq_mhz; | 
|  | 599 | if (prescale > EMAC_DM644X_EWINTCNT_MASK) { | 
|  | 600 | prescale = EMAC_DM644X_EWINTCNT_MASK; | 
|  | 601 | coal_intvl = prescale / priv->bus_freq_mhz; | 
|  | 602 | } | 
|  | 603 | emac_ctrl_write(EMAC_CTRL_EWINTTCNT, (int_ctrl | prescale)); | 
|  | 604 |  | 
|  | 605 | break; | 
|  | 606 | } | 
|  | 607 |  | 
|  | 608 | printk(KERN_INFO"Set coalesce to %d usecs.\n", coal_intvl); | 
|  | 609 | priv->coal_intvl = coal_intvl; | 
|  | 610 |  | 
|  | 611 | return 0; | 
|  | 612 |  | 
|  | 613 | } | 
|  | 614 |  | 
|  | 615 |  | 
|  | 616 | /** | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 617 | * ethtool_ops: DaVinci EMAC Ethtool structure | 
|  | 618 | * | 
|  | 619 | * Ethtool support for EMAC adapter | 
|  | 620 | * | 
|  | 621 | */ | 
|  | 622 | static const struct ethtool_ops ethtool_ops = { | 
|  | 623 | .get_drvinfo = emac_get_drvinfo, | 
|  | 624 | .get_settings = emac_get_settings, | 
|  | 625 | .set_settings = emac_set_settings, | 
|  | 626 | .get_link = ethtool_op_get_link, | 
| Sriram | 84da265 | 2010-07-29 02:33:58 +0000 | [diff] [blame] | 627 | .get_coalesce = emac_get_coalesce, | 
|  | 628 | .set_coalesce =  emac_set_coalesce, | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 629 | }; | 
|  | 630 |  | 
|  | 631 | /** | 
|  | 632 | * emac_update_phystatus: Update Phy status | 
|  | 633 | * @priv: The DaVinci EMAC private adapter structure | 
|  | 634 | * | 
|  | 635 | * Updates phy status and takes action for network queue if required | 
|  | 636 | * based upon link status | 
|  | 637 | * | 
|  | 638 | */ | 
|  | 639 | static void emac_update_phystatus(struct emac_priv *priv) | 
|  | 640 | { | 
|  | 641 | u32 mac_control; | 
|  | 642 | u32 new_duplex; | 
|  | 643 | u32 cur_duplex; | 
|  | 644 | struct net_device *ndev = priv->ndev; | 
|  | 645 |  | 
|  | 646 | mac_control = emac_read(EMAC_MACCONTROL); | 
|  | 647 | cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ? | 
|  | 648 | DUPLEX_FULL : DUPLEX_HALF; | 
| Cyril Chemparathy | 5d69e00 | 2010-09-15 10:11:24 -0400 | [diff] [blame] | 649 | if (priv->phydev) | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 650 | new_duplex = priv->phydev->duplex; | 
|  | 651 | else | 
|  | 652 | new_duplex = DUPLEX_FULL; | 
|  | 653 |  | 
|  | 654 | /* We get called only if link has changed (speed/duplex/status) */ | 
|  | 655 | if ((priv->link) && (new_duplex != cur_duplex)) { | 
|  | 656 | priv->duplex = new_duplex; | 
|  | 657 | if (DUPLEX_FULL == priv->duplex) | 
|  | 658 | mac_control |= (EMAC_MACCONTROL_FULLDUPLEXEN); | 
|  | 659 | else | 
|  | 660 | mac_control &= ~(EMAC_MACCONTROL_FULLDUPLEXEN); | 
|  | 661 | } | 
|  | 662 |  | 
|  | 663 | if (priv->speed == SPEED_1000 && (priv->version == EMAC_VERSION_2)) { | 
|  | 664 | mac_control = emac_read(EMAC_MACCONTROL); | 
| chaithrika@ti.com | 69ef969 | 2009-10-01 10:25:19 +0000 | [diff] [blame] | 665 | mac_control |= (EMAC_DM646X_MACCONTORL_GIG | | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 666 | EMAC_DM646X_MACCONTORL_GIGFORCE); | 
|  | 667 | } else { | 
|  | 668 | /* Clear the GIG bit and GIGFORCE bit */ | 
|  | 669 | mac_control &= ~(EMAC_DM646X_MACCONTORL_GIGFORCE | | 
|  | 670 | EMAC_DM646X_MACCONTORL_GIG); | 
|  | 671 |  | 
|  | 672 | if (priv->rmii_en && (priv->speed == SPEED_100)) | 
|  | 673 | mac_control |= EMAC_MACCONTROL_RMIISPEED_MASK; | 
|  | 674 | else | 
|  | 675 | mac_control &= ~EMAC_MACCONTROL_RMIISPEED_MASK; | 
|  | 676 | } | 
|  | 677 |  | 
|  | 678 | /* Update mac_control if changed */ | 
|  | 679 | emac_write(EMAC_MACCONTROL, mac_control); | 
|  | 680 |  | 
|  | 681 | if (priv->link) { | 
|  | 682 | /* link ON */ | 
|  | 683 | if (!netif_carrier_ok(ndev)) | 
|  | 684 | netif_carrier_on(ndev); | 
|  | 685 | /* reactivate the transmit queue if it is stopped */ | 
|  | 686 | if (netif_running(ndev) && netif_queue_stopped(ndev)) | 
|  | 687 | netif_wake_queue(ndev); | 
|  | 688 | } else { | 
|  | 689 | /* link OFF */ | 
|  | 690 | if (netif_carrier_ok(ndev)) | 
|  | 691 | netif_carrier_off(ndev); | 
|  | 692 | if (!netif_queue_stopped(ndev)) | 
|  | 693 | netif_stop_queue(ndev); | 
|  | 694 | } | 
|  | 695 | } | 
|  | 696 |  | 
|  | 697 | /** | 
|  | 698 | * hash_get: Calculate hash value from mac address | 
|  | 699 | * @addr: mac address to delete from hash table | 
|  | 700 | * | 
|  | 701 | * Calculates hash value from mac address | 
|  | 702 | * | 
|  | 703 | */ | 
|  | 704 | static u32 hash_get(u8 *addr) | 
|  | 705 | { | 
|  | 706 | u32 hash; | 
|  | 707 | u8 tmpval; | 
|  | 708 | int cnt; | 
|  | 709 | hash = 0; | 
|  | 710 |  | 
|  | 711 | for (cnt = 0; cnt < 2; cnt++) { | 
|  | 712 | tmpval = *addr++; | 
|  | 713 | hash ^= (tmpval >> 2) ^ (tmpval << 4); | 
|  | 714 | tmpval = *addr++; | 
|  | 715 | hash ^= (tmpval >> 4) ^ (tmpval << 2); | 
|  | 716 | tmpval = *addr++; | 
|  | 717 | hash ^= (tmpval >> 6) ^ (tmpval); | 
|  | 718 | } | 
|  | 719 |  | 
|  | 720 | return hash & 0x3F; | 
|  | 721 | } | 
|  | 722 |  | 
|  | 723 | /** | 
|  | 724 | * hash_add: Hash function to add mac addr from hash table | 
|  | 725 | * @priv: The DaVinci EMAC private adapter structure | 
|  | 726 | * mac_addr: mac address to delete from hash table | 
|  | 727 | * | 
|  | 728 | * Adds mac address to the internal hash table | 
|  | 729 | * | 
|  | 730 | */ | 
|  | 731 | static int hash_add(struct emac_priv *priv, u8 *mac_addr) | 
|  | 732 | { | 
|  | 733 | struct device *emac_dev = &priv->ndev->dev; | 
|  | 734 | u32 rc = 0; | 
|  | 735 | u32 hash_bit; | 
|  | 736 | u32 hash_value = hash_get(mac_addr); | 
|  | 737 |  | 
|  | 738 | if (hash_value >= EMAC_NUM_MULTICAST_BITS) { | 
|  | 739 | if (netif_msg_drv(priv)) { | 
|  | 740 | dev_err(emac_dev, "DaVinci EMAC: hash_add(): Invalid "\ | 
|  | 741 | "Hash %08x, should not be greater than %08x", | 
|  | 742 | hash_value, (EMAC_NUM_MULTICAST_BITS - 1)); | 
|  | 743 | } | 
|  | 744 | return -1; | 
|  | 745 | } | 
|  | 746 |  | 
|  | 747 | /* set the hash bit only if not previously set */ | 
|  | 748 | if (priv->multicast_hash_cnt[hash_value] == 0) { | 
|  | 749 | rc = 1; /* hash value changed */ | 
|  | 750 | if (hash_value < 32) { | 
|  | 751 | hash_bit = BIT(hash_value); | 
|  | 752 | priv->mac_hash1 |= hash_bit; | 
|  | 753 | } else { | 
|  | 754 | hash_bit = BIT((hash_value - 32)); | 
|  | 755 | priv->mac_hash2 |= hash_bit; | 
|  | 756 | } | 
|  | 757 | } | 
|  | 758 |  | 
|  | 759 | /* incr counter for num of mcast addr's mapped to "this" hash bit */ | 
|  | 760 | ++priv->multicast_hash_cnt[hash_value]; | 
|  | 761 |  | 
|  | 762 | return rc; | 
|  | 763 | } | 
|  | 764 |  | 
|  | 765 | /** | 
|  | 766 | * hash_del: Hash function to delete mac addr from hash table | 
|  | 767 | * @priv: The DaVinci EMAC private adapter structure | 
|  | 768 | * mac_addr: mac address to delete from hash table | 
|  | 769 | * | 
|  | 770 | * Removes mac address from the internal hash table | 
|  | 771 | * | 
|  | 772 | */ | 
|  | 773 | static int hash_del(struct emac_priv *priv, u8 *mac_addr) | 
|  | 774 | { | 
|  | 775 | u32 hash_value; | 
|  | 776 | u32 hash_bit; | 
|  | 777 |  | 
|  | 778 | hash_value = hash_get(mac_addr); | 
|  | 779 | if (priv->multicast_hash_cnt[hash_value] > 0) { | 
|  | 780 | /* dec cntr for num of mcast addr's mapped to this hash bit */ | 
|  | 781 | --priv->multicast_hash_cnt[hash_value]; | 
|  | 782 | } | 
|  | 783 |  | 
|  | 784 | /* if counter still > 0, at least one multicast address refers | 
|  | 785 | * to this hash bit. so return 0 */ | 
|  | 786 | if (priv->multicast_hash_cnt[hash_value] > 0) | 
|  | 787 | return 0; | 
|  | 788 |  | 
|  | 789 | if (hash_value < 32) { | 
|  | 790 | hash_bit = BIT(hash_value); | 
|  | 791 | priv->mac_hash1 &= ~hash_bit; | 
|  | 792 | } else { | 
|  | 793 | hash_bit = BIT((hash_value - 32)); | 
|  | 794 | priv->mac_hash2 &= ~hash_bit; | 
|  | 795 | } | 
|  | 796 |  | 
|  | 797 | /* return 1 to indicate change in mac_hash registers reqd */ | 
|  | 798 | return 1; | 
|  | 799 | } | 
|  | 800 |  | 
|  | 801 | /* EMAC multicast operation */ | 
|  | 802 | #define EMAC_MULTICAST_ADD	0 | 
|  | 803 | #define EMAC_MULTICAST_DEL	1 | 
|  | 804 | #define EMAC_ALL_MULTI_SET	2 | 
|  | 805 | #define EMAC_ALL_MULTI_CLR	3 | 
|  | 806 |  | 
|  | 807 | /** | 
|  | 808 | * emac_add_mcast: Set multicast address in the EMAC adapter (Internal) | 
|  | 809 | * @priv: The DaVinci EMAC private adapter structure | 
|  | 810 | * @action: multicast operation to perform | 
|  | 811 | * mac_addr: mac address to set | 
|  | 812 | * | 
|  | 813 | * Set multicast addresses in EMAC adapter - internal function | 
|  | 814 | * | 
|  | 815 | */ | 
|  | 816 | static void emac_add_mcast(struct emac_priv *priv, u32 action, u8 *mac_addr) | 
|  | 817 | { | 
|  | 818 | struct device *emac_dev = &priv->ndev->dev; | 
|  | 819 | int update = -1; | 
|  | 820 |  | 
|  | 821 | switch (action) { | 
|  | 822 | case EMAC_MULTICAST_ADD: | 
|  | 823 | update = hash_add(priv, mac_addr); | 
|  | 824 | break; | 
|  | 825 | case EMAC_MULTICAST_DEL: | 
|  | 826 | update = hash_del(priv, mac_addr); | 
|  | 827 | break; | 
|  | 828 | case EMAC_ALL_MULTI_SET: | 
|  | 829 | update = 1; | 
|  | 830 | priv->mac_hash1 = EMAC_ALL_MULTI_REG_VALUE; | 
|  | 831 | priv->mac_hash2 = EMAC_ALL_MULTI_REG_VALUE; | 
|  | 832 | break; | 
|  | 833 | case EMAC_ALL_MULTI_CLR: | 
|  | 834 | update = 1; | 
|  | 835 | priv->mac_hash1 = 0; | 
|  | 836 | priv->mac_hash2 = 0; | 
|  | 837 | memset(&(priv->multicast_hash_cnt[0]), 0, | 
|  | 838 | sizeof(priv->multicast_hash_cnt[0]) * | 
|  | 839 | EMAC_NUM_MULTICAST_BITS); | 
|  | 840 | break; | 
|  | 841 | default: | 
|  | 842 | if (netif_msg_drv(priv)) | 
|  | 843 | dev_err(emac_dev, "DaVinci EMAC: add_mcast"\ | 
|  | 844 | ": bad operation %d", action); | 
|  | 845 | break; | 
|  | 846 | } | 
|  | 847 |  | 
|  | 848 | /* write to the hardware only if the register status chances */ | 
|  | 849 | if (update > 0) { | 
|  | 850 | emac_write(EMAC_MACHASH1, priv->mac_hash1); | 
|  | 851 | emac_write(EMAC_MACHASH2, priv->mac_hash2); | 
|  | 852 | } | 
|  | 853 | } | 
|  | 854 |  | 
|  | 855 | /** | 
|  | 856 | * emac_dev_mcast_set: Set multicast address in the EMAC adapter | 
|  | 857 | * @ndev: The DaVinci EMAC network adapter | 
|  | 858 | * | 
|  | 859 | * Set multicast addresses in EMAC adapter | 
|  | 860 | * | 
|  | 861 | */ | 
|  | 862 | static void emac_dev_mcast_set(struct net_device *ndev) | 
|  | 863 | { | 
|  | 864 | u32 mbp_enable; | 
|  | 865 | struct emac_priv *priv = netdev_priv(ndev); | 
|  | 866 |  | 
|  | 867 | mbp_enable = emac_read(EMAC_RXMBPENABLE); | 
|  | 868 | if (ndev->flags & IFF_PROMISC) { | 
|  | 869 | mbp_enable &= (~EMAC_MBP_PROMISCCH(EMAC_DEF_PROM_CH)); | 
|  | 870 | mbp_enable |= (EMAC_MBP_RXPROMISC); | 
|  | 871 | } else { | 
|  | 872 | mbp_enable = (mbp_enable & ~EMAC_MBP_RXPROMISC); | 
|  | 873 | if ((ndev->flags & IFF_ALLMULTI) || | 
| Jiri Pirko | 4cd24ea | 2010-02-08 04:30:35 +0000 | [diff] [blame] | 874 | netdev_mc_count(ndev) > EMAC_DEF_MAX_MULTICAST_ADDRESSES) { | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 875 | mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); | 
|  | 876 | emac_add_mcast(priv, EMAC_ALL_MULTI_SET, NULL); | 
|  | 877 | } | 
| Jiri Pirko | 4cd24ea | 2010-02-08 04:30:35 +0000 | [diff] [blame] | 878 | if (!netdev_mc_empty(ndev)) { | 
| Jiri Pirko | 22bedad | 2010-04-01 21:22:57 +0000 | [diff] [blame] | 879 | struct netdev_hw_addr *ha; | 
|  | 880 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 881 | mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); | 
|  | 882 | emac_add_mcast(priv, EMAC_ALL_MULTI_CLR, NULL); | 
|  | 883 | /* program multicast address list into EMAC hardware */ | 
| Jiri Pirko | 22bedad | 2010-04-01 21:22:57 +0000 | [diff] [blame] | 884 | netdev_for_each_mc_addr(ha, ndev) { | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 885 | emac_add_mcast(priv, EMAC_MULTICAST_ADD, | 
| Jiri Pirko | 22bedad | 2010-04-01 21:22:57 +0000 | [diff] [blame] | 886 | (u8 *) ha->addr); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 887 | } | 
|  | 888 | } else { | 
|  | 889 | mbp_enable = (mbp_enable & ~EMAC_MBP_RXMCAST); | 
|  | 890 | emac_add_mcast(priv, EMAC_ALL_MULTI_CLR, NULL); | 
|  | 891 | } | 
|  | 892 | } | 
|  | 893 | /* Set mbp config register */ | 
|  | 894 | emac_write(EMAC_RXMBPENABLE, mbp_enable); | 
|  | 895 | } | 
|  | 896 |  | 
|  | 897 | /************************************************************************* | 
|  | 898 | *  EMAC Hardware manipulation | 
|  | 899 | *************************************************************************/ | 
|  | 900 |  | 
|  | 901 | /** | 
|  | 902 | * emac_int_disable: Disable EMAC module interrupt (from adapter) | 
|  | 903 | * @priv: The DaVinci EMAC private adapter structure | 
|  | 904 | * | 
|  | 905 | * Disable EMAC interrupt on the adapter | 
|  | 906 | * | 
|  | 907 | */ | 
|  | 908 | static void emac_int_disable(struct emac_priv *priv) | 
|  | 909 | { | 
|  | 910 | if (priv->version == EMAC_VERSION_2) { | 
|  | 911 | unsigned long flags; | 
|  | 912 |  | 
|  | 913 | local_irq_save(flags); | 
|  | 914 |  | 
|  | 915 | /* Program C0_Int_En to zero to turn off | 
|  | 916 | * interrupts to the CPU */ | 
|  | 917 | emac_ctrl_write(EMAC_DM646X_CMRXINTEN, 0x0); | 
|  | 918 | emac_ctrl_write(EMAC_DM646X_CMTXINTEN, 0x0); | 
|  | 919 | /* NOTE: Rx Threshold and Misc interrupts are not disabled */ | 
| Sriramakrishnan | 01a9af3 | 2009-11-19 15:58:26 +0530 | [diff] [blame] | 920 | if (priv->int_disable) | 
|  | 921 | priv->int_disable(); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 922 |  | 
|  | 923 | local_irq_restore(flags); | 
|  | 924 |  | 
|  | 925 | } else { | 
|  | 926 | /* Set DM644x control registers for interrupt control */ | 
|  | 927 | emac_ctrl_write(EMAC_CTRL_EWCTL, 0x0); | 
|  | 928 | } | 
|  | 929 | } | 
|  | 930 |  | 
|  | 931 | /** | 
|  | 932 | * emac_int_enable: Enable EMAC module interrupt (from adapter) | 
|  | 933 | * @priv: The DaVinci EMAC private adapter structure | 
|  | 934 | * | 
|  | 935 | * Enable EMAC interrupt on the adapter | 
|  | 936 | * | 
|  | 937 | */ | 
|  | 938 | static void emac_int_enable(struct emac_priv *priv) | 
|  | 939 | { | 
|  | 940 | if (priv->version == EMAC_VERSION_2) { | 
| Sriramakrishnan | 01a9af3 | 2009-11-19 15:58:26 +0530 | [diff] [blame] | 941 | if (priv->int_enable) | 
|  | 942 | priv->int_enable(); | 
|  | 943 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 944 | emac_ctrl_write(EMAC_DM646X_CMRXINTEN, 0xff); | 
|  | 945 | emac_ctrl_write(EMAC_DM646X_CMTXINTEN, 0xff); | 
|  | 946 |  | 
|  | 947 | /* In addition to turning on interrupt Enable, we need | 
|  | 948 | * ack by writing appropriate values to the EOI | 
|  | 949 | * register */ | 
|  | 950 |  | 
|  | 951 | /* NOTE: Rx Threshold and Misc interrupts are not enabled */ | 
|  | 952 |  | 
|  | 953 | /* ack rxen only then a new pulse will be generated */ | 
|  | 954 | emac_write(EMAC_DM646X_MACEOIVECTOR, | 
|  | 955 | EMAC_DM646X_MAC_EOI_C0_RXEN); | 
|  | 956 |  | 
|  | 957 | /* ack txen- only then a new pulse will be generated */ | 
|  | 958 | emac_write(EMAC_DM646X_MACEOIVECTOR, | 
|  | 959 | EMAC_DM646X_MAC_EOI_C0_TXEN); | 
|  | 960 |  | 
|  | 961 | } else { | 
|  | 962 | /* Set DM644x control registers for interrupt control */ | 
|  | 963 | emac_ctrl_write(EMAC_CTRL_EWCTL, 0x1); | 
|  | 964 | } | 
|  | 965 | } | 
|  | 966 |  | 
|  | 967 | /** | 
|  | 968 | * emac_irq: EMAC interrupt handler | 
|  | 969 | * @irq: interrupt number | 
|  | 970 | * @dev_id: EMAC network adapter data structure ptr | 
|  | 971 | * | 
|  | 972 | * EMAC Interrupt handler - we only schedule NAPI and not process any packets | 
|  | 973 | * here. EVen the interrupt status is checked (TX/RX/Err) in NAPI poll function | 
|  | 974 | * | 
|  | 975 | * Returns interrupt handled condition | 
|  | 976 | */ | 
|  | 977 | static irqreturn_t emac_irq(int irq, void *dev_id) | 
|  | 978 | { | 
|  | 979 | struct net_device *ndev = (struct net_device *)dev_id; | 
|  | 980 | struct emac_priv *priv = netdev_priv(ndev); | 
|  | 981 |  | 
|  | 982 | ++priv->isr_count; | 
|  | 983 | if (likely(netif_running(priv->ndev))) { | 
|  | 984 | emac_int_disable(priv); | 
|  | 985 | napi_schedule(&priv->napi); | 
|  | 986 | } else { | 
|  | 987 | /* we are closing down, so dont process anything */ | 
|  | 988 | } | 
|  | 989 | return IRQ_HANDLED; | 
|  | 990 | } | 
|  | 991 |  | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 992 | static struct sk_buff *emac_rx_alloc(struct emac_priv *priv) | 
|  | 993 | { | 
|  | 994 | struct sk_buff *skb = dev_alloc_skb(priv->rx_buf_size); | 
|  | 995 | if (WARN_ON(!skb)) | 
|  | 996 | return NULL; | 
|  | 997 | skb->dev = priv->ndev; | 
|  | 998 | skb_reserve(skb, NET_IP_ALIGN); | 
|  | 999 | return skb; | 
|  | 1000 | } | 
|  | 1001 |  | 
|  | 1002 | static void emac_rx_handler(void *token, int len, int status) | 
|  | 1003 | { | 
|  | 1004 | struct sk_buff		*skb = token; | 
|  | 1005 | struct net_device	*ndev = skb->dev; | 
|  | 1006 | struct emac_priv	*priv = netdev_priv(ndev); | 
|  | 1007 | struct device		*emac_dev = &ndev->dev; | 
|  | 1008 | int			ret; | 
|  | 1009 |  | 
|  | 1010 | /* free and bail if we are shutting down */ | 
| Hegde, Vinay | 0a5f384 | 2011-02-24 23:56:28 +0000 | [diff] [blame] | 1011 | if (unlikely(!netif_running(ndev) || !netif_carrier_ok(ndev))) { | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1012 | dev_kfree_skb_any(skb); | 
|  | 1013 | return; | 
|  | 1014 | } | 
|  | 1015 |  | 
| Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 1016 | /* recycle on receive error */ | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1017 | if (status < 0) { | 
|  | 1018 | ndev->stats.rx_errors++; | 
|  | 1019 | goto recycle; | 
|  | 1020 | } | 
|  | 1021 |  | 
|  | 1022 | /* feed received packet up the stack */ | 
|  | 1023 | skb_put(skb, len); | 
|  | 1024 | skb->protocol = eth_type_trans(skb, ndev); | 
|  | 1025 | netif_receive_skb(skb); | 
|  | 1026 | ndev->stats.rx_bytes += len; | 
|  | 1027 | ndev->stats.rx_packets++; | 
|  | 1028 |  | 
|  | 1029 | /* alloc a new packet for receive */ | 
|  | 1030 | skb = emac_rx_alloc(priv); | 
|  | 1031 | if (!skb) { | 
|  | 1032 | if (netif_msg_rx_err(priv) && net_ratelimit()) | 
|  | 1033 | dev_err(emac_dev, "failed rx buffer alloc\n"); | 
|  | 1034 | return; | 
|  | 1035 | } | 
|  | 1036 |  | 
|  | 1037 | recycle: | 
|  | 1038 | ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, | 
|  | 1039 | skb_tailroom(skb), GFP_KERNEL); | 
|  | 1040 | if (WARN_ON(ret < 0)) | 
|  | 1041 | dev_kfree_skb_any(skb); | 
|  | 1042 | } | 
|  | 1043 |  | 
|  | 1044 | static void emac_tx_handler(void *token, int len, int status) | 
|  | 1045 | { | 
|  | 1046 | struct sk_buff		*skb = token; | 
|  | 1047 | struct net_device	*ndev = skb->dev; | 
|  | 1048 |  | 
|  | 1049 | if (unlikely(netif_queue_stopped(ndev))) | 
|  | 1050 | netif_start_queue(ndev); | 
|  | 1051 | ndev->stats.tx_packets++; | 
|  | 1052 | ndev->stats.tx_bytes += len; | 
|  | 1053 | dev_kfree_skb_any(skb); | 
|  | 1054 | } | 
|  | 1055 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1056 | /** | 
|  | 1057 | * emac_dev_xmit: EMAC Transmit function | 
|  | 1058 | * @skb: SKB pointer | 
|  | 1059 | * @ndev: The DaVinci EMAC network adapter | 
|  | 1060 | * | 
|  | 1061 | * Called by the system to transmit a packet  - we queue the packet in | 
|  | 1062 | * EMAC hardware transmit queue | 
|  | 1063 | * | 
|  | 1064 | * Returns success(NETDEV_TX_OK) or error code (typically out of desc's) | 
|  | 1065 | */ | 
|  | 1066 | static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) | 
|  | 1067 | { | 
|  | 1068 | struct device *emac_dev = &ndev->dev; | 
|  | 1069 | int ret_code; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1070 | struct emac_priv *priv = netdev_priv(ndev); | 
|  | 1071 |  | 
|  | 1072 | /* If no link, return */ | 
|  | 1073 | if (unlikely(!priv->link)) { | 
|  | 1074 | if (netif_msg_tx_err(priv) && net_ratelimit()) | 
|  | 1075 | dev_err(emac_dev, "DaVinci EMAC: No link to transmit"); | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1076 | goto fail_tx; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1077 | } | 
|  | 1078 |  | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1079 | ret_code = skb_padto(skb, EMAC_DEF_MIN_ETHPKTSIZE); | 
|  | 1080 | if (unlikely(ret_code < 0)) { | 
|  | 1081 | if (netif_msg_tx_err(priv) && net_ratelimit()) | 
|  | 1082 | dev_err(emac_dev, "DaVinci EMAC: packet pad failed"); | 
|  | 1083 | goto fail_tx; | 
|  | 1084 | } | 
|  | 1085 |  | 
|  | 1086 | ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len, | 
|  | 1087 | GFP_KERNEL); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1088 | if (unlikely(ret_code != 0)) { | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1089 | if (netif_msg_tx_err(priv) && net_ratelimit()) | 
|  | 1090 | dev_err(emac_dev, "DaVinci EMAC: desc submit failed"); | 
|  | 1091 | goto fail_tx; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1092 | } | 
|  | 1093 |  | 
|  | 1094 | return NETDEV_TX_OK; | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1095 |  | 
|  | 1096 | fail_tx: | 
|  | 1097 | ndev->stats.tx_dropped++; | 
|  | 1098 | netif_stop_queue(ndev); | 
|  | 1099 | return NETDEV_TX_BUSY; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1100 | } | 
|  | 1101 |  | 
|  | 1102 | /** | 
|  | 1103 | * emac_dev_tx_timeout: EMAC Transmit timeout function | 
|  | 1104 | * @ndev: The DaVinci EMAC network adapter | 
|  | 1105 | * | 
|  | 1106 | * Called when system detects that a skb timeout period has expired | 
|  | 1107 | * potentially due to a fault in the adapter in not being able to send | 
|  | 1108 | * it out on the wire. We teardown the TX channel assuming a hardware | 
|  | 1109 | * error and re-initialize the TX channel for hardware operation | 
|  | 1110 | * | 
|  | 1111 | */ | 
|  | 1112 | static void emac_dev_tx_timeout(struct net_device *ndev) | 
|  | 1113 | { | 
|  | 1114 | struct emac_priv *priv = netdev_priv(ndev); | 
|  | 1115 | struct device *emac_dev = &ndev->dev; | 
|  | 1116 |  | 
|  | 1117 | if (netif_msg_tx_err(priv)) | 
|  | 1118 | dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX"); | 
|  | 1119 |  | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1120 | emac_dump_regs(priv); | 
|  | 1121 |  | 
| Kulikov Vasiliy | 78e8c53 | 2010-07-05 02:13:26 +0000 | [diff] [blame] | 1122 | ndev->stats.tx_errors++; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1123 | emac_int_disable(priv); | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1124 | cpdma_chan_stop(priv->txchan); | 
|  | 1125 | cpdma_chan_start(priv->txchan); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1126 | emac_int_enable(priv); | 
|  | 1127 | } | 
|  | 1128 |  | 
|  | 1129 | /** | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1130 | * emac_set_type0addr: Set EMAC Type0 mac address | 
|  | 1131 | * @priv: The DaVinci EMAC private adapter structure | 
|  | 1132 | * @ch: RX channel number | 
|  | 1133 | * @mac_addr: MAC address to set in device | 
|  | 1134 | * | 
|  | 1135 | * Called internally to set Type0 mac address of the adapter (Device) | 
|  | 1136 | * | 
|  | 1137 | * Returns success (0) or appropriate error code (none as of now) | 
|  | 1138 | */ | 
|  | 1139 | static void emac_set_type0addr(struct emac_priv *priv, u32 ch, char *mac_addr) | 
|  | 1140 | { | 
|  | 1141 | u32 val; | 
|  | 1142 | val = ((mac_addr[5] << 8) | (mac_addr[4])); | 
|  | 1143 | emac_write(EMAC_MACSRCADDRLO, val); | 
|  | 1144 |  | 
|  | 1145 | val = ((mac_addr[3] << 24) | (mac_addr[2] << 16) | \ | 
|  | 1146 | (mac_addr[1] << 8) | (mac_addr[0])); | 
|  | 1147 | emac_write(EMAC_MACSRCADDRHI, val); | 
|  | 1148 | val = emac_read(EMAC_RXUNICASTSET); | 
|  | 1149 | val |= BIT(ch); | 
|  | 1150 | emac_write(EMAC_RXUNICASTSET, val); | 
|  | 1151 | val = emac_read(EMAC_RXUNICASTCLEAR); | 
|  | 1152 | val &= ~BIT(ch); | 
|  | 1153 | emac_write(EMAC_RXUNICASTCLEAR, val); | 
|  | 1154 | } | 
|  | 1155 |  | 
|  | 1156 | /** | 
|  | 1157 | * emac_set_type1addr: Set EMAC Type1 mac address | 
|  | 1158 | * @priv: The DaVinci EMAC private adapter structure | 
|  | 1159 | * @ch: RX channel number | 
|  | 1160 | * @mac_addr: MAC address to set in device | 
|  | 1161 | * | 
|  | 1162 | * Called internally to set Type1 mac address of the adapter (Device) | 
|  | 1163 | * | 
|  | 1164 | * Returns success (0) or appropriate error code (none as of now) | 
|  | 1165 | */ | 
|  | 1166 | static void emac_set_type1addr(struct emac_priv *priv, u32 ch, char *mac_addr) | 
|  | 1167 | { | 
|  | 1168 | u32 val; | 
|  | 1169 | emac_write(EMAC_MACINDEX, ch); | 
|  | 1170 | val = ((mac_addr[5] << 8) | mac_addr[4]); | 
|  | 1171 | emac_write(EMAC_MACADDRLO, val); | 
|  | 1172 | val = ((mac_addr[3] << 24) | (mac_addr[2] << 16) | \ | 
|  | 1173 | (mac_addr[1] << 8) | (mac_addr[0])); | 
|  | 1174 | emac_write(EMAC_MACADDRHI, val); | 
|  | 1175 | emac_set_type0addr(priv, ch, mac_addr); | 
|  | 1176 | } | 
|  | 1177 |  | 
|  | 1178 | /** | 
|  | 1179 | * emac_set_type2addr: Set EMAC Type2 mac address | 
|  | 1180 | * @priv: The DaVinci EMAC private adapter structure | 
|  | 1181 | * @ch: RX channel number | 
|  | 1182 | * @mac_addr: MAC address to set in device | 
|  | 1183 | * @index: index into RX address entries | 
|  | 1184 | * @match: match parameter for RX address matching logic | 
|  | 1185 | * | 
|  | 1186 | * Called internally to set Type2 mac address of the adapter (Device) | 
|  | 1187 | * | 
|  | 1188 | * Returns success (0) or appropriate error code (none as of now) | 
|  | 1189 | */ | 
|  | 1190 | static void emac_set_type2addr(struct emac_priv *priv, u32 ch, | 
|  | 1191 | char *mac_addr, int index, int match) | 
|  | 1192 | { | 
|  | 1193 | u32 val; | 
|  | 1194 | emac_write(EMAC_MACINDEX, index); | 
|  | 1195 | val = ((mac_addr[3] << 24) | (mac_addr[2] << 16) | \ | 
|  | 1196 | (mac_addr[1] << 8) | (mac_addr[0])); | 
|  | 1197 | emac_write(EMAC_MACADDRHI, val); | 
|  | 1198 | val = ((mac_addr[5] << 8) | mac_addr[4] | ((ch & 0x7) << 16) | \ | 
|  | 1199 | (match << 19) | BIT(20)); | 
|  | 1200 | emac_write(EMAC_MACADDRLO, val); | 
|  | 1201 | emac_set_type0addr(priv, ch, mac_addr); | 
|  | 1202 | } | 
|  | 1203 |  | 
|  | 1204 | /** | 
|  | 1205 | * emac_setmac: Set mac address in the adapter (internal function) | 
|  | 1206 | * @priv: The DaVinci EMAC private adapter structure | 
|  | 1207 | * @ch: RX channel number | 
|  | 1208 | * @mac_addr: MAC address to set in device | 
|  | 1209 | * | 
|  | 1210 | * Called internally to set the mac address of the adapter (Device) | 
|  | 1211 | * | 
|  | 1212 | * Returns success (0) or appropriate error code (none as of now) | 
|  | 1213 | */ | 
|  | 1214 | static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr) | 
|  | 1215 | { | 
|  | 1216 | struct device *emac_dev = &priv->ndev->dev; | 
|  | 1217 |  | 
|  | 1218 | if (priv->rx_addr_type == 0) { | 
|  | 1219 | emac_set_type0addr(priv, ch, mac_addr); | 
|  | 1220 | } else if (priv->rx_addr_type == 1) { | 
|  | 1221 | u32 cnt; | 
|  | 1222 | for (cnt = 0; cnt < EMAC_MAX_TXRX_CHANNELS; cnt++) | 
|  | 1223 | emac_set_type1addr(priv, ch, mac_addr); | 
|  | 1224 | } else if (priv->rx_addr_type == 2) { | 
|  | 1225 | emac_set_type2addr(priv, ch, mac_addr, ch, 1); | 
|  | 1226 | emac_set_type0addr(priv, ch, mac_addr); | 
|  | 1227 | } else { | 
|  | 1228 | if (netif_msg_drv(priv)) | 
|  | 1229 | dev_err(emac_dev, "DaVinci EMAC: Wrong addressing\n"); | 
|  | 1230 | } | 
|  | 1231 | } | 
|  | 1232 |  | 
|  | 1233 | /** | 
|  | 1234 | * emac_dev_setmac_addr: Set mac address in the adapter | 
|  | 1235 | * @ndev: The DaVinci EMAC network adapter | 
|  | 1236 | * @addr: MAC address to set in device | 
|  | 1237 | * | 
|  | 1238 | * Called by the system to set the mac address of the adapter (Device) | 
|  | 1239 | * | 
|  | 1240 | * Returns success (0) or appropriate error code (none as of now) | 
|  | 1241 | */ | 
|  | 1242 | static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) | 
|  | 1243 | { | 
|  | 1244 | struct emac_priv *priv = netdev_priv(ndev); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1245 | struct device *emac_dev = &priv->ndev->dev; | 
|  | 1246 | struct sockaddr *sa = addr; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1247 |  | 
| Pablo Bitton | 64c8165 | 2009-07-07 19:11:10 -0700 | [diff] [blame] | 1248 | if (!is_valid_ether_addr(sa->sa_data)) | 
|  | 1249 | return -EINVAL; | 
|  | 1250 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1251 | /* Store mac addr in priv and rx channel and set it in EMAC hw */ | 
|  | 1252 | memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1253 | memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); | 
| Pablo Bitton | 64c8165 | 2009-07-07 19:11:10 -0700 | [diff] [blame] | 1254 |  | 
| Pablo Bitton | 64c8165 | 2009-07-07 19:11:10 -0700 | [diff] [blame] | 1255 | /* MAC address is configured only after the interface is enabled. */ | 
|  | 1256 | if (netif_running(ndev)) { | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1257 | memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); | 
|  | 1258 | emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); | 
| Pablo Bitton | 64c8165 | 2009-07-07 19:11:10 -0700 | [diff] [blame] | 1259 | } | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1260 |  | 
|  | 1261 | if (netif_msg_drv(priv)) | 
| Chaithrika U S | 5c72616 | 2009-06-03 21:54:29 -0700 | [diff] [blame] | 1262 | dev_notice(emac_dev, "DaVinci EMAC: emac_dev_setmac_addr %pM\n", | 
|  | 1263 | priv->mac_addr); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1264 |  | 
|  | 1265 | return 0; | 
|  | 1266 | } | 
|  | 1267 |  | 
|  | 1268 | /** | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1269 | * emac_hw_enable: Enable EMAC hardware for packet transmission/reception | 
|  | 1270 | * @priv: The DaVinci EMAC private adapter structure | 
|  | 1271 | * | 
|  | 1272 | * Enables EMAC hardware for packet processing - enables PHY, enables RX | 
|  | 1273 | * for packet reception and enables device interrupts and then NAPI | 
|  | 1274 | * | 
|  | 1275 | * Returns success (0) or appropriate error code (none right now) | 
|  | 1276 | */ | 
|  | 1277 | static int emac_hw_enable(struct emac_priv *priv) | 
|  | 1278 | { | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1279 | u32 val, mbp_enable, mac_control; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1280 |  | 
|  | 1281 | /* Soft reset */ | 
|  | 1282 | emac_write(EMAC_SOFTRESET, 1); | 
|  | 1283 | while (emac_read(EMAC_SOFTRESET)) | 
|  | 1284 | cpu_relax(); | 
|  | 1285 |  | 
|  | 1286 | /* Disable interrupt & Set pacing for more interrupts initially */ | 
|  | 1287 | emac_int_disable(priv); | 
|  | 1288 |  | 
|  | 1289 | /* Full duplex enable bit set when auto negotiation happens */ | 
|  | 1290 | mac_control = | 
|  | 1291 | (((EMAC_DEF_TXPRIO_FIXED) ? (EMAC_MACCONTROL_TXPTYPE) : 0x0) | | 
|  | 1292 | ((priv->speed == 1000) ? EMAC_MACCONTROL_GIGABITEN : 0x0) | | 
|  | 1293 | ((EMAC_DEF_TXPACING_EN) ? (EMAC_MACCONTROL_TXPACEEN) : 0x0) | | 
|  | 1294 | ((priv->duplex == DUPLEX_FULL) ? 0x1 : 0)); | 
|  | 1295 | emac_write(EMAC_MACCONTROL, mac_control); | 
|  | 1296 |  | 
|  | 1297 | mbp_enable = | 
|  | 1298 | (((EMAC_DEF_PASS_CRC) ? (EMAC_RXMBP_PASSCRC_MASK) : 0x0) | | 
|  | 1299 | ((EMAC_DEF_QOS_EN) ? (EMAC_RXMBP_QOSEN_MASK) : 0x0) | | 
|  | 1300 | ((EMAC_DEF_NO_BUFF_CHAIN) ? (EMAC_RXMBP_NOCHAIN_MASK) : 0x0) | | 
|  | 1301 | ((EMAC_DEF_MACCTRL_FRAME_EN) ? (EMAC_RXMBP_CMFEN_MASK) : 0x0) | | 
|  | 1302 | ((EMAC_DEF_SHORT_FRAME_EN) ? (EMAC_RXMBP_CSFEN_MASK) : 0x0) | | 
|  | 1303 | ((EMAC_DEF_ERROR_FRAME_EN) ? (EMAC_RXMBP_CEFEN_MASK) : 0x0) | | 
|  | 1304 | ((EMAC_DEF_PROM_EN) ? (EMAC_RXMBP_CAFEN_MASK) : 0x0) | | 
|  | 1305 | ((EMAC_DEF_PROM_CH & EMAC_RXMBP_CHMASK) << \ | 
|  | 1306 | EMAC_RXMBP_PROMCH_SHIFT) | | 
|  | 1307 | ((EMAC_DEF_BCAST_EN) ? (EMAC_RXMBP_BROADEN_MASK) : 0x0) | | 
|  | 1308 | ((EMAC_DEF_BCAST_CH & EMAC_RXMBP_CHMASK) << \ | 
|  | 1309 | EMAC_RXMBP_BROADCH_SHIFT) | | 
|  | 1310 | ((EMAC_DEF_MCAST_EN) ? (EMAC_RXMBP_MULTIEN_MASK) : 0x0) | | 
|  | 1311 | ((EMAC_DEF_MCAST_CH & EMAC_RXMBP_CHMASK) << \ | 
|  | 1312 | EMAC_RXMBP_MULTICH_SHIFT)); | 
|  | 1313 | emac_write(EMAC_RXMBPENABLE, mbp_enable); | 
|  | 1314 | emac_write(EMAC_RXMAXLEN, (EMAC_DEF_MAX_FRAME_SIZE & | 
|  | 1315 | EMAC_RX_MAX_LEN_MASK)); | 
|  | 1316 | emac_write(EMAC_RXBUFFEROFFSET, (EMAC_DEF_BUFFER_OFFSET & | 
|  | 1317 | EMAC_RX_BUFFER_OFFSET_MASK)); | 
|  | 1318 | emac_write(EMAC_RXFILTERLOWTHRESH, 0); | 
|  | 1319 | emac_write(EMAC_RXUNICASTCLEAR, EMAC_RX_UNICAST_CLEAR_ALL); | 
|  | 1320 | priv->rx_addr_type = (emac_read(EMAC_MACCONFIG) >> 8) & 0xFF; | 
|  | 1321 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1322 | emac_write(EMAC_MACINTMASKSET, EMAC_MAC_HOST_ERR_INTMASK_VAL); | 
|  | 1323 |  | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1324 | emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1325 |  | 
|  | 1326 | /* Enable MII */ | 
|  | 1327 | val = emac_read(EMAC_MACCONTROL); | 
| chaithrika@ti.com | 69ef969 | 2009-10-01 10:25:19 +0000 | [diff] [blame] | 1328 | val |= (EMAC_MACCONTROL_GMIIEN); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1329 | emac_write(EMAC_MACCONTROL, val); | 
|  | 1330 |  | 
|  | 1331 | /* Enable NAPI and interrupts */ | 
|  | 1332 | napi_enable(&priv->napi); | 
|  | 1333 | emac_int_enable(priv); | 
|  | 1334 | return 0; | 
|  | 1335 |  | 
|  | 1336 | } | 
|  | 1337 |  | 
|  | 1338 | /** | 
|  | 1339 | * emac_poll: EMAC NAPI Poll function | 
|  | 1340 | * @ndev: The DaVinci EMAC network adapter | 
|  | 1341 | * @budget: Number of receive packets to process (as told by NAPI layer) | 
|  | 1342 | * | 
|  | 1343 | * NAPI Poll function implemented to process packets as per budget. We check | 
|  | 1344 | * the type of interrupt on the device and accordingly call the TX or RX | 
|  | 1345 | * packet processing functions. We follow the budget for RX processing and | 
|  | 1346 | * also put a cap on number of TX pkts processed through config param. The | 
|  | 1347 | * NAPI schedule function is called if more packets pending. | 
|  | 1348 | * | 
|  | 1349 | * Returns number of packets received (in most cases; else TX pkts - rarely) | 
|  | 1350 | */ | 
|  | 1351 | static int emac_poll(struct napi_struct *napi, int budget) | 
|  | 1352 | { | 
|  | 1353 | unsigned int mask; | 
|  | 1354 | struct emac_priv *priv = container_of(napi, struct emac_priv, napi); | 
|  | 1355 | struct net_device *ndev = priv->ndev; | 
|  | 1356 | struct device *emac_dev = &ndev->dev; | 
|  | 1357 | u32 status = 0; | 
| Sriram | 3725b1f | 2010-07-29 02:33:59 +0000 | [diff] [blame] | 1358 | u32 num_tx_pkts = 0, num_rx_pkts = 0; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1359 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1360 | /* Check interrupt vectors and call packet processing */ | 
|  | 1361 | status = emac_read(EMAC_MACINVECTOR); | 
|  | 1362 |  | 
|  | 1363 | mask = EMAC_DM644X_MAC_IN_VECTOR_TX_INT_VEC; | 
|  | 1364 |  | 
|  | 1365 | if (priv->version == EMAC_VERSION_2) | 
|  | 1366 | mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC; | 
|  | 1367 |  | 
|  | 1368 | if (status & mask) { | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1369 | num_tx_pkts = cpdma_chan_process(priv->txchan, | 
|  | 1370 | EMAC_DEF_TX_MAX_SERVICE); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1371 | } /* TX processing */ | 
|  | 1372 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1373 | mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC; | 
|  | 1374 |  | 
|  | 1375 | if (priv->version == EMAC_VERSION_2) | 
|  | 1376 | mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC; | 
|  | 1377 |  | 
|  | 1378 | if (status & mask) { | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1379 | num_rx_pkts = cpdma_chan_process(priv->rxchan, budget); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1380 | } /* RX processing */ | 
|  | 1381 |  | 
| Sriram | 43c2ed8 | 2009-09-24 19:15:18 +0000 | [diff] [blame] | 1382 | mask = EMAC_DM644X_MAC_IN_VECTOR_HOST_INT; | 
|  | 1383 | if (priv->version == EMAC_VERSION_2) | 
|  | 1384 | mask = EMAC_DM646X_MAC_IN_VECTOR_HOST_INT; | 
|  | 1385 |  | 
|  | 1386 | if (unlikely(status & mask)) { | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1387 | u32 ch, cause; | 
|  | 1388 | dev_err(emac_dev, "DaVinci EMAC: Fatal Hardware Error\n"); | 
|  | 1389 | netif_stop_queue(ndev); | 
|  | 1390 | napi_disable(&priv->napi); | 
|  | 1391 |  | 
|  | 1392 | status = emac_read(EMAC_MACSTATUS); | 
|  | 1393 | cause = ((status & EMAC_MACSTATUS_TXERRCODE_MASK) >> | 
|  | 1394 | EMAC_MACSTATUS_TXERRCODE_SHIFT); | 
|  | 1395 | if (cause) { | 
|  | 1396 | ch = ((status & EMAC_MACSTATUS_TXERRCH_MASK) >> | 
|  | 1397 | EMAC_MACSTATUS_TXERRCH_SHIFT); | 
|  | 1398 | if (net_ratelimit()) { | 
|  | 1399 | dev_err(emac_dev, "TX Host error %s on ch=%d\n", | 
|  | 1400 | &emac_txhost_errcodes[cause][0], ch); | 
|  | 1401 | } | 
|  | 1402 | } | 
|  | 1403 | cause = ((status & EMAC_MACSTATUS_RXERRCODE_MASK) >> | 
|  | 1404 | EMAC_MACSTATUS_RXERRCODE_SHIFT); | 
|  | 1405 | if (cause) { | 
|  | 1406 | ch = ((status & EMAC_MACSTATUS_RXERRCH_MASK) >> | 
|  | 1407 | EMAC_MACSTATUS_RXERRCH_SHIFT); | 
|  | 1408 | if (netif_msg_hw(priv) && net_ratelimit()) | 
|  | 1409 | dev_err(emac_dev, "RX Host error %s on ch=%d\n", | 
|  | 1410 | &emac_rxhost_errcodes[cause][0], ch); | 
|  | 1411 | } | 
| Sriram | 3725b1f | 2010-07-29 02:33:59 +0000 | [diff] [blame] | 1412 | } else if (num_rx_pkts < budget) { | 
|  | 1413 | napi_complete(napi); | 
|  | 1414 | emac_int_enable(priv); | 
|  | 1415 | } | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1416 |  | 
| Sriram | 3725b1f | 2010-07-29 02:33:59 +0000 | [diff] [blame] | 1417 | return num_rx_pkts; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1418 | } | 
|  | 1419 |  | 
|  | 1420 | #ifdef CONFIG_NET_POLL_CONTROLLER | 
|  | 1421 | /** | 
|  | 1422 | * emac_poll_controller: EMAC Poll controller function | 
|  | 1423 | * @ndev: The DaVinci EMAC network adapter | 
|  | 1424 | * | 
|  | 1425 | * Polled functionality used by netconsole and others in non interrupt mode | 
|  | 1426 | * | 
|  | 1427 | */ | 
|  | 1428 | void emac_poll_controller(struct net_device *ndev) | 
|  | 1429 | { | 
|  | 1430 | struct emac_priv *priv = netdev_priv(ndev); | 
|  | 1431 |  | 
|  | 1432 | emac_int_disable(priv); | 
| Tonyliu | c8ee553 | 2009-11-04 05:45:02 -0800 | [diff] [blame] | 1433 | emac_irq(ndev->irq, ndev); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1434 | emac_int_enable(priv); | 
|  | 1435 | } | 
|  | 1436 | #endif | 
|  | 1437 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1438 | static void emac_adjust_link(struct net_device *ndev) | 
|  | 1439 | { | 
|  | 1440 | struct emac_priv *priv = netdev_priv(ndev); | 
|  | 1441 | struct phy_device *phydev = priv->phydev; | 
|  | 1442 | unsigned long flags; | 
|  | 1443 | int new_state = 0; | 
|  | 1444 |  | 
|  | 1445 | spin_lock_irqsave(&priv->lock, flags); | 
|  | 1446 |  | 
|  | 1447 | if (phydev->link) { | 
|  | 1448 | /* check the mode of operation - full/half duplex */ | 
|  | 1449 | if (phydev->duplex != priv->duplex) { | 
|  | 1450 | new_state = 1; | 
|  | 1451 | priv->duplex = phydev->duplex; | 
|  | 1452 | } | 
|  | 1453 | if (phydev->speed != priv->speed) { | 
|  | 1454 | new_state = 1; | 
|  | 1455 | priv->speed = phydev->speed; | 
|  | 1456 | } | 
|  | 1457 | if (!priv->link) { | 
|  | 1458 | new_state = 1; | 
|  | 1459 | priv->link = 1; | 
|  | 1460 | } | 
|  | 1461 |  | 
|  | 1462 | } else if (priv->link) { | 
|  | 1463 | new_state = 1; | 
|  | 1464 | priv->link = 0; | 
|  | 1465 | priv->speed = 0; | 
|  | 1466 | priv->duplex = ~0; | 
|  | 1467 | } | 
|  | 1468 | if (new_state) { | 
|  | 1469 | emac_update_phystatus(priv); | 
|  | 1470 | phy_print_status(priv->phydev); | 
|  | 1471 | } | 
|  | 1472 |  | 
|  | 1473 | spin_unlock_irqrestore(&priv->lock, flags); | 
|  | 1474 | } | 
|  | 1475 |  | 
|  | 1476 | /************************************************************************* | 
|  | 1477 | *  Linux Driver Model | 
|  | 1478 | *************************************************************************/ | 
|  | 1479 |  | 
|  | 1480 | /** | 
|  | 1481 | * emac_devioctl: EMAC adapter ioctl | 
|  | 1482 | * @ndev: The DaVinci EMAC network adapter | 
|  | 1483 | * @ifrq: request parameter | 
|  | 1484 | * @cmd: command parameter | 
|  | 1485 | * | 
|  | 1486 | * EMAC driver ioctl function | 
|  | 1487 | * | 
|  | 1488 | * Returns success(0) or appropriate error code | 
|  | 1489 | */ | 
|  | 1490 | static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) | 
|  | 1491 | { | 
|  | 1492 | dev_warn(&ndev->dev, "DaVinci EMAC: ioctl not supported\n"); | 
|  | 1493 |  | 
|  | 1494 | if (!(netif_running(ndev))) | 
|  | 1495 | return -EINVAL; | 
|  | 1496 |  | 
|  | 1497 | /* TODO: Add phy read and write and private statistics get feature */ | 
|  | 1498 |  | 
|  | 1499 | return -EOPNOTSUPP; | 
|  | 1500 | } | 
|  | 1501 |  | 
| Cyril Chemparathy | 5d69e00 | 2010-09-15 10:11:24 -0400 | [diff] [blame] | 1502 | static int match_first_device(struct device *dev, void *data) | 
|  | 1503 | { | 
|  | 1504 | return 1; | 
|  | 1505 | } | 
|  | 1506 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1507 | /** | 
|  | 1508 | * emac_dev_open: EMAC device open | 
|  | 1509 | * @ndev: The DaVinci EMAC network adapter | 
|  | 1510 | * | 
|  | 1511 | * Called when system wants to start the interface. We init TX/RX channels | 
|  | 1512 | * and enable the hardware for packet reception/transmission and start the | 
|  | 1513 | * network queue. | 
|  | 1514 | * | 
|  | 1515 | * Returns 0 for a successful open, or appropriate error code | 
|  | 1516 | */ | 
|  | 1517 | static int emac_dev_open(struct net_device *ndev) | 
|  | 1518 | { | 
|  | 1519 | struct device *emac_dev = &ndev->dev; | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1520 | u32 cnt; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1521 | struct resource *res; | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1522 | int q, m, ret; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1523 | int i = 0; | 
|  | 1524 | int k = 0; | 
|  | 1525 | struct emac_priv *priv = netdev_priv(ndev); | 
|  | 1526 |  | 
|  | 1527 | netif_carrier_off(ndev); | 
| Dan Carpenter | 4d27b87 | 2010-03-02 21:07:24 +0000 | [diff] [blame] | 1528 | for (cnt = 0; cnt < ETH_ALEN; cnt++) | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1529 | ndev->dev_addr[cnt] = priv->mac_addr[cnt]; | 
|  | 1530 |  | 
|  | 1531 | /* Configuration items */ | 
|  | 1532 | priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN; | 
|  | 1533 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1534 | priv->mac_hash1 = 0; | 
|  | 1535 | priv->mac_hash2 = 0; | 
|  | 1536 | emac_write(EMAC_MACHASH1, 0); | 
|  | 1537 | emac_write(EMAC_MACHASH2, 0); | 
|  | 1538 |  | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1539 | for (i = 0; i < EMAC_DEF_RX_NUM_DESC; i++) { | 
|  | 1540 | struct sk_buff *skb = emac_rx_alloc(priv); | 
|  | 1541 |  | 
|  | 1542 | if (!skb) | 
|  | 1543 | break; | 
|  | 1544 |  | 
|  | 1545 | ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, | 
|  | 1546 | skb_tailroom(skb), GFP_KERNEL); | 
|  | 1547 | if (WARN_ON(ret < 0)) | 
|  | 1548 | break; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1549 | } | 
|  | 1550 |  | 
|  | 1551 | /* Request IRQ */ | 
|  | 1552 |  | 
|  | 1553 | while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) { | 
|  | 1554 | for (i = res->start; i <= res->end; i++) { | 
|  | 1555 | if (request_irq(i, emac_irq, IRQF_DISABLED, | 
|  | 1556 | ndev->name, ndev)) | 
|  | 1557 | goto rollback; | 
|  | 1558 | } | 
|  | 1559 | k++; | 
|  | 1560 | } | 
|  | 1561 |  | 
|  | 1562 | /* Start/Enable EMAC hardware */ | 
|  | 1563 | emac_hw_enable(priv); | 
|  | 1564 |  | 
| Sriram | 84da265 | 2010-07-29 02:33:58 +0000 | [diff] [blame] | 1565 | /* Enable Interrupt pacing if configured */ | 
|  | 1566 | if (priv->coal_intvl != 0) { | 
|  | 1567 | struct ethtool_coalesce coal; | 
|  | 1568 |  | 
|  | 1569 | coal.rx_coalesce_usecs = (priv->coal_intvl << 4); | 
|  | 1570 | emac_set_coalesce(ndev, &coal); | 
|  | 1571 | } | 
|  | 1572 |  | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1573 | cpdma_ctlr_start(priv->dma); | 
|  | 1574 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1575 | priv->phydev = NULL; | 
| Cyril Chemparathy | 5d69e00 | 2010-09-15 10:11:24 -0400 | [diff] [blame] | 1576 | /* use the first phy on the bus if pdata did not give us a phy id */ | 
|  | 1577 | if (!priv->phy_id) { | 
|  | 1578 | struct device *phy; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1579 |  | 
| Cyril Chemparathy | 5d69e00 | 2010-09-15 10:11:24 -0400 | [diff] [blame] | 1580 | phy = bus_find_device(&mdio_bus_type, NULL, NULL, | 
|  | 1581 | match_first_device); | 
|  | 1582 | if (phy) | 
|  | 1583 | priv->phy_id = dev_name(phy); | 
|  | 1584 | } | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1585 |  | 
| Cyril Chemparathy | 5d69e00 | 2010-09-15 10:11:24 -0400 | [diff] [blame] | 1586 | if (priv->phy_id && *priv->phy_id) { | 
|  | 1587 | priv->phydev = phy_connect(ndev, priv->phy_id, | 
|  | 1588 | &emac_adjust_link, 0, | 
|  | 1589 | PHY_INTERFACE_MODE_MII); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1590 |  | 
|  | 1591 | if (IS_ERR(priv->phydev)) { | 
| Cyril Chemparathy | 5d69e00 | 2010-09-15 10:11:24 -0400 | [diff] [blame] | 1592 | dev_err(emac_dev, "could not connect to phy %s\n", | 
|  | 1593 | priv->phy_id); | 
|  | 1594 | priv->phydev = NULL; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1595 | return PTR_ERR(priv->phydev); | 
|  | 1596 | } | 
|  | 1597 |  | 
|  | 1598 | priv->link = 0; | 
|  | 1599 | priv->speed = 0; | 
|  | 1600 | priv->duplex = ~0; | 
|  | 1601 |  | 
| Cyril Chemparathy | 5d69e00 | 2010-09-15 10:11:24 -0400 | [diff] [blame] | 1602 | dev_info(emac_dev, "attached PHY driver [%s] " | 
|  | 1603 | "(mii_bus:phy_addr=%s, id=%x)\n", | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1604 | priv->phydev->drv->name, dev_name(&priv->phydev->dev), | 
|  | 1605 | priv->phydev->phy_id); | 
| Cyril Chemparathy | 5d69e00 | 2010-09-15 10:11:24 -0400 | [diff] [blame] | 1606 | } else { | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1607 | /* No PHY , fix the link, speed and duplex settings */ | 
| Cyril Chemparathy | 5d69e00 | 2010-09-15 10:11:24 -0400 | [diff] [blame] | 1608 | dev_notice(emac_dev, "no phy, defaulting to 100/full\n"); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1609 | priv->link = 1; | 
|  | 1610 | priv->speed = SPEED_100; | 
|  | 1611 | priv->duplex = DUPLEX_FULL; | 
|  | 1612 | emac_update_phystatus(priv); | 
|  | 1613 | } | 
|  | 1614 |  | 
|  | 1615 | if (!netif_running(ndev)) /* debug only - to avoid compiler warning */ | 
|  | 1616 | emac_dump_regs(priv); | 
|  | 1617 |  | 
|  | 1618 | if (netif_msg_drv(priv)) | 
|  | 1619 | dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name); | 
|  | 1620 |  | 
| Cyril Chemparathy | 5d69e00 | 2010-09-15 10:11:24 -0400 | [diff] [blame] | 1621 | if (priv->phydev) | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1622 | phy_start(priv->phydev); | 
|  | 1623 |  | 
|  | 1624 | return 0; | 
|  | 1625 |  | 
|  | 1626 | rollback: | 
|  | 1627 |  | 
|  | 1628 | dev_err(emac_dev, "DaVinci EMAC: request_irq() failed"); | 
|  | 1629 |  | 
|  | 1630 | for (q = k; k >= 0; k--) { | 
|  | 1631 | for (m = i; m >= res->start; m--) | 
|  | 1632 | free_irq(m, ndev); | 
|  | 1633 | res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k-1); | 
|  | 1634 | m = res->end; | 
|  | 1635 | } | 
|  | 1636 | return -EBUSY; | 
|  | 1637 | } | 
|  | 1638 |  | 
|  | 1639 | /** | 
|  | 1640 | * emac_dev_stop: EMAC device stop | 
|  | 1641 | * @ndev: The DaVinci EMAC network adapter | 
|  | 1642 | * | 
|  | 1643 | * Called when system wants to stop or down the interface. We stop the network | 
|  | 1644 | * queue, disable interrupts and cleanup TX/RX channels. | 
|  | 1645 | * | 
|  | 1646 | * We return the statistics in net_device_stats structure pulled from emac | 
|  | 1647 | */ | 
|  | 1648 | static int emac_dev_stop(struct net_device *ndev) | 
|  | 1649 | { | 
|  | 1650 | struct resource *res; | 
|  | 1651 | int i = 0; | 
|  | 1652 | int irq_num; | 
|  | 1653 | struct emac_priv *priv = netdev_priv(ndev); | 
|  | 1654 | struct device *emac_dev = &ndev->dev; | 
|  | 1655 |  | 
|  | 1656 | /* inform the upper layers. */ | 
|  | 1657 | netif_stop_queue(ndev); | 
|  | 1658 | napi_disable(&priv->napi); | 
|  | 1659 |  | 
|  | 1660 | netif_carrier_off(ndev); | 
|  | 1661 | emac_int_disable(priv); | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1662 | cpdma_ctlr_stop(priv->dma); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1663 | emac_write(EMAC_SOFTRESET, 1); | 
|  | 1664 |  | 
|  | 1665 | if (priv->phydev) | 
|  | 1666 | phy_disconnect(priv->phydev); | 
|  | 1667 |  | 
|  | 1668 | /* Free IRQ */ | 
|  | 1669 | while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, i))) { | 
|  | 1670 | for (irq_num = res->start; irq_num <= res->end; irq_num++) | 
|  | 1671 | free_irq(irq_num, priv->ndev); | 
|  | 1672 | i++; | 
|  | 1673 | } | 
|  | 1674 |  | 
|  | 1675 | if (netif_msg_drv(priv)) | 
|  | 1676 | dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name); | 
|  | 1677 |  | 
|  | 1678 | return 0; | 
|  | 1679 | } | 
|  | 1680 |  | 
|  | 1681 | /** | 
|  | 1682 | * emac_dev_getnetstats: EMAC get statistics function | 
|  | 1683 | * @ndev: The DaVinci EMAC network adapter | 
|  | 1684 | * | 
|  | 1685 | * Called when system wants to get statistics from the device. | 
|  | 1686 | * | 
|  | 1687 | * We return the statistics in net_device_stats structure pulled from emac | 
|  | 1688 | */ | 
|  | 1689 | static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev) | 
|  | 1690 | { | 
|  | 1691 | struct emac_priv *priv = netdev_priv(ndev); | 
| Sriram | 0fe7463 | 2009-10-07 02:44:30 +0000 | [diff] [blame] | 1692 | u32 mac_control; | 
|  | 1693 | u32 stats_clear_mask; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1694 |  | 
|  | 1695 | /* update emac hardware stats and reset the registers*/ | 
|  | 1696 |  | 
| Sriram | 0fe7463 | 2009-10-07 02:44:30 +0000 | [diff] [blame] | 1697 | mac_control = emac_read(EMAC_MACCONTROL); | 
|  | 1698 |  | 
|  | 1699 | if (mac_control & EMAC_MACCONTROL_GMIIEN) | 
|  | 1700 | stats_clear_mask = EMAC_STATS_CLR_MASK; | 
|  | 1701 | else | 
|  | 1702 | stats_clear_mask = 0; | 
|  | 1703 |  | 
| Kulikov Vasiliy | 78e8c53 | 2010-07-05 02:13:26 +0000 | [diff] [blame] | 1704 | ndev->stats.multicast += emac_read(EMAC_RXMCASTFRAMES); | 
| Sriram | 0fe7463 | 2009-10-07 02:44:30 +0000 | [diff] [blame] | 1705 | emac_write(EMAC_RXMCASTFRAMES, stats_clear_mask); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1706 |  | 
| Kulikov Vasiliy | 78e8c53 | 2010-07-05 02:13:26 +0000 | [diff] [blame] | 1707 | ndev->stats.collisions += (emac_read(EMAC_TXCOLLISION) + | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1708 | emac_read(EMAC_TXSINGLECOLL) + | 
|  | 1709 | emac_read(EMAC_TXMULTICOLL)); | 
| Sriram | 0fe7463 | 2009-10-07 02:44:30 +0000 | [diff] [blame] | 1710 | emac_write(EMAC_TXCOLLISION, stats_clear_mask); | 
|  | 1711 | emac_write(EMAC_TXSINGLECOLL, stats_clear_mask); | 
|  | 1712 | emac_write(EMAC_TXMULTICOLL, stats_clear_mask); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1713 |  | 
| Kulikov Vasiliy | 78e8c53 | 2010-07-05 02:13:26 +0000 | [diff] [blame] | 1714 | ndev->stats.rx_length_errors += (emac_read(EMAC_RXOVERSIZED) + | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1715 | emac_read(EMAC_RXJABBER) + | 
|  | 1716 | emac_read(EMAC_RXUNDERSIZED)); | 
| Sriram | 0fe7463 | 2009-10-07 02:44:30 +0000 | [diff] [blame] | 1717 | emac_write(EMAC_RXOVERSIZED, stats_clear_mask); | 
|  | 1718 | emac_write(EMAC_RXJABBER, stats_clear_mask); | 
|  | 1719 | emac_write(EMAC_RXUNDERSIZED, stats_clear_mask); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1720 |  | 
| Kulikov Vasiliy | 78e8c53 | 2010-07-05 02:13:26 +0000 | [diff] [blame] | 1721 | ndev->stats.rx_over_errors += (emac_read(EMAC_RXSOFOVERRUNS) + | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1722 | emac_read(EMAC_RXMOFOVERRUNS)); | 
| Sriram | 0fe7463 | 2009-10-07 02:44:30 +0000 | [diff] [blame] | 1723 | emac_write(EMAC_RXSOFOVERRUNS, stats_clear_mask); | 
|  | 1724 | emac_write(EMAC_RXMOFOVERRUNS, stats_clear_mask); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1725 |  | 
| Kulikov Vasiliy | 78e8c53 | 2010-07-05 02:13:26 +0000 | [diff] [blame] | 1726 | ndev->stats.rx_fifo_errors += emac_read(EMAC_RXDMAOVERRUNS); | 
| Sriram | 0fe7463 | 2009-10-07 02:44:30 +0000 | [diff] [blame] | 1727 | emac_write(EMAC_RXDMAOVERRUNS, stats_clear_mask); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1728 |  | 
| Kulikov Vasiliy | 78e8c53 | 2010-07-05 02:13:26 +0000 | [diff] [blame] | 1729 | ndev->stats.tx_carrier_errors += | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1730 | emac_read(EMAC_TXCARRIERSENSE); | 
| Sriram | 0fe7463 | 2009-10-07 02:44:30 +0000 | [diff] [blame] | 1731 | emac_write(EMAC_TXCARRIERSENSE, stats_clear_mask); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1732 |  | 
| Thomas Lange | 60aeba2 | 2011-03-09 04:41:16 +0000 | [diff] [blame] | 1733 | ndev->stats.tx_fifo_errors += emac_read(EMAC_TXUNDERRUN); | 
| Sriram | 0fe7463 | 2009-10-07 02:44:30 +0000 | [diff] [blame] | 1734 | emac_write(EMAC_TXUNDERRUN, stats_clear_mask); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1735 |  | 
| Kulikov Vasiliy | 78e8c53 | 2010-07-05 02:13:26 +0000 | [diff] [blame] | 1736 | return &ndev->stats; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1737 | } | 
|  | 1738 |  | 
|  | 1739 | static const struct net_device_ops emac_netdev_ops = { | 
|  | 1740 | .ndo_open		= emac_dev_open, | 
|  | 1741 | .ndo_stop		= emac_dev_stop, | 
|  | 1742 | .ndo_start_xmit		= emac_dev_xmit, | 
|  | 1743 | .ndo_set_multicast_list	= emac_dev_mcast_set, | 
|  | 1744 | .ndo_set_mac_address	= emac_dev_setmac_addr, | 
|  | 1745 | .ndo_do_ioctl		= emac_devioctl, | 
|  | 1746 | .ndo_tx_timeout		= emac_dev_tx_timeout, | 
|  | 1747 | .ndo_get_stats		= emac_dev_getnetstats, | 
|  | 1748 | #ifdef CONFIG_NET_POLL_CONTROLLER | 
|  | 1749 | .ndo_poll_controller	= emac_poll_controller, | 
|  | 1750 | #endif | 
|  | 1751 | }; | 
|  | 1752 |  | 
|  | 1753 | /** | 
|  | 1754 | * davinci_emac_probe: EMAC device probe | 
|  | 1755 | * @pdev: The DaVinci EMAC device that we are removing | 
|  | 1756 | * | 
|  | 1757 | * Called when probing for emac devicesr. We get details of instances and | 
|  | 1758 | * resource information from platform init and register a network device | 
|  | 1759 | * and allocate resources necessary for driver to perform | 
|  | 1760 | */ | 
|  | 1761 | static int __devinit davinci_emac_probe(struct platform_device *pdev) | 
|  | 1762 | { | 
|  | 1763 | int rc = 0; | 
|  | 1764 | struct resource *res; | 
|  | 1765 | struct net_device *ndev; | 
|  | 1766 | struct emac_priv *priv; | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1767 | unsigned long size, hw_ram_addr; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1768 | struct emac_platform_data *pdata; | 
|  | 1769 | struct device *emac_dev; | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1770 | struct cpdma_params dma_params; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1771 |  | 
|  | 1772 | /* obtain emac clock from kernel */ | 
|  | 1773 | emac_clk = clk_get(&pdev->dev, NULL); | 
|  | 1774 | if (IS_ERR(emac_clk)) { | 
| Johan Hovold | 240b262 | 2011-05-26 04:37:32 +0000 | [diff] [blame] | 1775 | dev_err(&pdev->dev, "failed to get EMAC clock\n"); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1776 | return -EBUSY; | 
|  | 1777 | } | 
|  | 1778 | emac_bus_frequency = clk_get_rate(emac_clk); | 
|  | 1779 | /* TODO: Probe PHY here if possible */ | 
|  | 1780 |  | 
|  | 1781 | ndev = alloc_etherdev(sizeof(struct emac_priv)); | 
|  | 1782 | if (!ndev) { | 
| Johan Hovold | 240b262 | 2011-05-26 04:37:32 +0000 | [diff] [blame] | 1783 | dev_err(&pdev->dev, "error allocating net_device\n"); | 
| Julia Lawall | b722dbf | 2011-06-01 07:10:10 +0000 | [diff] [blame] | 1784 | rc = -ENOMEM; | 
|  | 1785 | goto free_clk; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1786 | } | 
|  | 1787 |  | 
|  | 1788 | platform_set_drvdata(pdev, ndev); | 
|  | 1789 | priv = netdev_priv(ndev); | 
|  | 1790 | priv->pdev = pdev; | 
|  | 1791 | priv->ndev = ndev; | 
|  | 1792 | priv->msg_enable = netif_msg_init(debug_level, DAVINCI_EMAC_DEBUG); | 
|  | 1793 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1794 | spin_lock_init(&priv->lock); | 
|  | 1795 |  | 
|  | 1796 | pdata = pdev->dev.platform_data; | 
|  | 1797 | if (!pdata) { | 
| Johan Hovold | 240b262 | 2011-05-26 04:37:32 +0000 | [diff] [blame] | 1798 | dev_err(&pdev->dev, "no platform data\n"); | 
| Julia Lawall | b722dbf | 2011-06-01 07:10:10 +0000 | [diff] [blame] | 1799 | rc = -ENODEV; | 
|  | 1800 | goto probe_quit; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1801 | } | 
|  | 1802 |  | 
|  | 1803 | /* MAC addr and PHY mask , RMII enable info from platform_data */ | 
|  | 1804 | memcpy(priv->mac_addr, pdata->mac_addr, 6); | 
| Cyril Chemparathy | 5d69e00 | 2010-09-15 10:11:24 -0400 | [diff] [blame] | 1805 | priv->phy_id = pdata->phy_id; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1806 | priv->rmii_en = pdata->rmii_en; | 
|  | 1807 | priv->version = pdata->version; | 
| Sriramakrishnan | 01a9af3 | 2009-11-19 15:58:26 +0530 | [diff] [blame] | 1808 | priv->int_enable = pdata->interrupt_enable; | 
|  | 1809 | priv->int_disable = pdata->interrupt_disable; | 
|  | 1810 |  | 
| Sriram | 84da265 | 2010-07-29 02:33:58 +0000 | [diff] [blame] | 1811 | priv->coal_intvl = 0; | 
|  | 1812 | priv->bus_freq_mhz = (u32)(emac_bus_frequency / 1000000); | 
|  | 1813 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1814 | emac_dev = &ndev->dev; | 
|  | 1815 | /* Get EMAC platform data */ | 
|  | 1816 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 
|  | 1817 | if (!res) { | 
| Johan Hovold | 240b262 | 2011-05-26 04:37:32 +0000 | [diff] [blame] | 1818 | dev_err(&pdev->dev,"error getting res\n"); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1819 | rc = -ENOENT; | 
|  | 1820 | goto probe_quit; | 
|  | 1821 | } | 
|  | 1822 |  | 
|  | 1823 | priv->emac_base_phys = res->start + pdata->ctrl_reg_offset; | 
|  | 1824 | size = res->end - res->start + 1; | 
|  | 1825 | if (!request_mem_region(res->start, size, ndev->name)) { | 
| Johan Hovold | 240b262 | 2011-05-26 04:37:32 +0000 | [diff] [blame] | 1826 | dev_err(&pdev->dev, "failed request_mem_region() for regs\n"); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1827 | rc = -ENXIO; | 
|  | 1828 | goto probe_quit; | 
|  | 1829 | } | 
|  | 1830 |  | 
|  | 1831 | priv->remap_addr = ioremap(res->start, size); | 
|  | 1832 | if (!priv->remap_addr) { | 
| Johan Hovold | 240b262 | 2011-05-26 04:37:32 +0000 | [diff] [blame] | 1833 | dev_err(&pdev->dev, "unable to map IO\n"); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1834 | rc = -ENOMEM; | 
|  | 1835 | release_mem_region(res->start, size); | 
|  | 1836 | goto probe_quit; | 
|  | 1837 | } | 
|  | 1838 | priv->emac_base = priv->remap_addr + pdata->ctrl_reg_offset; | 
|  | 1839 | ndev->base_addr = (unsigned long)priv->remap_addr; | 
|  | 1840 |  | 
|  | 1841 | priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset; | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1842 |  | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1843 | hw_ram_addr = pdata->hw_ram_addr; | 
|  | 1844 | if (!hw_ram_addr) | 
|  | 1845 | hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset; | 
|  | 1846 |  | 
|  | 1847 | memset(&dma_params, 0, sizeof(dma_params)); | 
|  | 1848 | dma_params.dev			= emac_dev; | 
|  | 1849 | dma_params.dmaregs		= priv->emac_base; | 
|  | 1850 | dma_params.rxthresh		= priv->emac_base + 0x120; | 
|  | 1851 | dma_params.rxfree		= priv->emac_base + 0x140; | 
|  | 1852 | dma_params.txhdp		= priv->emac_base + 0x600; | 
|  | 1853 | dma_params.rxhdp		= priv->emac_base + 0x620; | 
|  | 1854 | dma_params.txcp			= priv->emac_base + 0x640; | 
|  | 1855 | dma_params.rxcp			= priv->emac_base + 0x660; | 
|  | 1856 | dma_params.num_chan		= EMAC_MAX_TXRX_CHANNELS; | 
|  | 1857 | dma_params.min_packet_size	= EMAC_DEF_MIN_ETHPKTSIZE; | 
| Sriram | 6a1fef6 | 2011-03-22 02:31:03 +0000 | [diff] [blame] | 1858 | dma_params.desc_hw_addr		= hw_ram_addr; | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1859 | dma_params.desc_mem_size	= pdata->ctrl_ram_size; | 
|  | 1860 | dma_params.desc_align		= 16; | 
|  | 1861 |  | 
| Sriram | 6a1fef6 | 2011-03-22 02:31:03 +0000 | [diff] [blame] | 1862 | dma_params.desc_mem_phys = pdata->no_bd_ram ? 0 : | 
|  | 1863 | (u32 __force)res->start + pdata->ctrl_ram_offset; | 
|  | 1864 |  | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1865 | priv->dma = cpdma_ctlr_create(&dma_params); | 
|  | 1866 | if (!priv->dma) { | 
| Johan Hovold | 240b262 | 2011-05-26 04:37:32 +0000 | [diff] [blame] | 1867 | dev_err(&pdev->dev, "error initializing DMA\n"); | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1868 | rc = -ENOMEM; | 
|  | 1869 | goto no_dma; | 
|  | 1870 | } | 
|  | 1871 |  | 
|  | 1872 | priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH), | 
|  | 1873 | emac_tx_handler); | 
|  | 1874 | priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH), | 
|  | 1875 | emac_rx_handler); | 
|  | 1876 | if (WARN_ON(!priv->txchan || !priv->rxchan)) { | 
|  | 1877 | rc = -ENOMEM; | 
|  | 1878 | goto no_irq_res; | 
|  | 1879 | } | 
| Sriramakrishnan | ad021ae | 2009-11-19 15:58:27 +0530 | [diff] [blame] | 1880 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1881 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 
|  | 1882 | if (!res) { | 
| Johan Hovold | 240b262 | 2011-05-26 04:37:32 +0000 | [diff] [blame] | 1883 | dev_err(&pdev->dev, "error getting irq res\n"); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1884 | rc = -ENOENT; | 
|  | 1885 | goto no_irq_res; | 
|  | 1886 | } | 
|  | 1887 | ndev->irq = res->start; | 
|  | 1888 |  | 
|  | 1889 | if (!is_valid_ether_addr(priv->mac_addr)) { | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1890 | /* Use random MAC if none passed */ | 
|  | 1891 | random_ether_addr(priv->mac_addr); | 
| Johan Hovold | 240b262 | 2011-05-26 04:37:32 +0000 | [diff] [blame] | 1892 | dev_warn(&pdev->dev, "using random MAC addr: %pM\n", | 
|  | 1893 | priv->mac_addr); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1894 | } | 
|  | 1895 |  | 
|  | 1896 | ndev->netdev_ops = &emac_netdev_ops; | 
|  | 1897 | SET_ETHTOOL_OPS(ndev, ðtool_ops); | 
|  | 1898 | netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT); | 
|  | 1899 |  | 
| Sriram | 1ca518b | 2010-01-07 00:22:37 +0000 | [diff] [blame] | 1900 | clk_enable(emac_clk); | 
|  | 1901 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1902 | /* register the network device */ | 
|  | 1903 | SET_NETDEV_DEV(ndev, &pdev->dev); | 
|  | 1904 | rc = register_netdev(ndev); | 
|  | 1905 | if (rc) { | 
| Johan Hovold | 240b262 | 2011-05-26 04:37:32 +0000 | [diff] [blame] | 1906 | dev_err(&pdev->dev, "error in register_netdev\n"); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1907 | rc = -ENODEV; | 
|  | 1908 | goto netdev_reg_err; | 
|  | 1909 | } | 
|  | 1910 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1911 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1912 | if (netif_msg_probe(priv)) { | 
|  | 1913 | dev_notice(emac_dev, "DaVinci EMAC Probe found device "\ | 
|  | 1914 | "(regs: %p, irq: %d)\n", | 
|  | 1915 | (void *)priv->emac_base_phys, ndev->irq); | 
|  | 1916 | } | 
|  | 1917 | return 0; | 
|  | 1918 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1919 | netdev_reg_err: | 
| Sriram | 1ca518b | 2010-01-07 00:22:37 +0000 | [diff] [blame] | 1920 | clk_disable(emac_clk); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1921 | no_irq_res: | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1922 | if (priv->txchan) | 
|  | 1923 | cpdma_chan_destroy(priv->txchan); | 
|  | 1924 | if (priv->rxchan) | 
|  | 1925 | cpdma_chan_destroy(priv->rxchan); | 
|  | 1926 | cpdma_ctlr_destroy(priv->dma); | 
|  | 1927 | no_dma: | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1928 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 
|  | 1929 | release_mem_region(res->start, res->end - res->start + 1); | 
|  | 1930 | iounmap(priv->remap_addr); | 
|  | 1931 |  | 
|  | 1932 | probe_quit: | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1933 | free_netdev(ndev); | 
| Julia Lawall | b722dbf | 2011-06-01 07:10:10 +0000 | [diff] [blame] | 1934 | free_clk: | 
|  | 1935 | clk_put(emac_clk); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1936 | return rc; | 
|  | 1937 | } | 
|  | 1938 |  | 
|  | 1939 | /** | 
|  | 1940 | * davinci_emac_remove: EMAC device remove | 
|  | 1941 | * @pdev: The DaVinci EMAC device that we are removing | 
|  | 1942 | * | 
|  | 1943 | * Called when removing the device driver. We disable clock usage and release | 
|  | 1944 | * the resources taken up by the driver and unregister network device | 
|  | 1945 | */ | 
|  | 1946 | static int __devexit davinci_emac_remove(struct platform_device *pdev) | 
|  | 1947 | { | 
|  | 1948 | struct resource *res; | 
|  | 1949 | struct net_device *ndev = platform_get_drvdata(pdev); | 
|  | 1950 | struct emac_priv *priv = netdev_priv(ndev); | 
|  | 1951 |  | 
|  | 1952 | dev_notice(&ndev->dev, "DaVinci EMAC: davinci_emac_remove()\n"); | 
|  | 1953 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1954 | platform_set_drvdata(pdev, NULL); | 
|  | 1955 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1956 |  | 
| Cyril Chemparathy | 3ef0fdb | 2010-09-15 10:11:29 -0400 | [diff] [blame] | 1957 | if (priv->txchan) | 
|  | 1958 | cpdma_chan_destroy(priv->txchan); | 
|  | 1959 | if (priv->rxchan) | 
|  | 1960 | cpdma_chan_destroy(priv->rxchan); | 
|  | 1961 | cpdma_ctlr_destroy(priv->dma); | 
|  | 1962 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1963 | release_mem_region(res->start, res->end - res->start + 1); | 
|  | 1964 |  | 
|  | 1965 | unregister_netdev(ndev); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1966 | iounmap(priv->remap_addr); | 
| Stefan Weil | 2a1bc0d | 2010-08-03 08:53:45 +0000 | [diff] [blame] | 1967 | free_netdev(ndev); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 1968 |  | 
|  | 1969 | clk_disable(emac_clk); | 
|  | 1970 | clk_put(emac_clk); | 
|  | 1971 |  | 
|  | 1972 | return 0; | 
|  | 1973 | } | 
|  | 1974 |  | 
| chaithrika@ti.com | d4fdcd9 | 2010-03-10 22:37:56 +0000 | [diff] [blame] | 1975 | static int davinci_emac_suspend(struct device *dev) | 
| Ranjith Lohithakshan | 8d044fe | 2009-11-04 22:06:20 -0800 | [diff] [blame] | 1976 | { | 
| chaithrika@ti.com | d4fdcd9 | 2010-03-10 22:37:56 +0000 | [diff] [blame] | 1977 | struct platform_device *pdev = to_platform_device(dev); | 
|  | 1978 | struct net_device *ndev = platform_get_drvdata(pdev); | 
| Ranjith Lohithakshan | 8d044fe | 2009-11-04 22:06:20 -0800 | [diff] [blame] | 1979 |  | 
| chaithrika@ti.com | d4fdcd9 | 2010-03-10 22:37:56 +0000 | [diff] [blame] | 1980 | if (netif_running(ndev)) | 
|  | 1981 | emac_dev_stop(ndev); | 
| Ranjith Lohithakshan | 8d044fe | 2009-11-04 22:06:20 -0800 | [diff] [blame] | 1982 |  | 
|  | 1983 | clk_disable(emac_clk); | 
|  | 1984 |  | 
|  | 1985 | return 0; | 
|  | 1986 | } | 
|  | 1987 |  | 
| chaithrika@ti.com | d4fdcd9 | 2010-03-10 22:37:56 +0000 | [diff] [blame] | 1988 | static int davinci_emac_resume(struct device *dev) | 
| Ranjith Lohithakshan | 8d044fe | 2009-11-04 22:06:20 -0800 | [diff] [blame] | 1989 | { | 
| chaithrika@ti.com | d4fdcd9 | 2010-03-10 22:37:56 +0000 | [diff] [blame] | 1990 | struct platform_device *pdev = to_platform_device(dev); | 
|  | 1991 | struct net_device *ndev = platform_get_drvdata(pdev); | 
| Ranjith Lohithakshan | 8d044fe | 2009-11-04 22:06:20 -0800 | [diff] [blame] | 1992 |  | 
|  | 1993 | clk_enable(emac_clk); | 
|  | 1994 |  | 
| chaithrika@ti.com | d4fdcd9 | 2010-03-10 22:37:56 +0000 | [diff] [blame] | 1995 | if (netif_running(ndev)) | 
|  | 1996 | emac_dev_open(ndev); | 
| Ranjith Lohithakshan | 8d044fe | 2009-11-04 22:06:20 -0800 | [diff] [blame] | 1997 |  | 
|  | 1998 | return 0; | 
|  | 1999 | } | 
|  | 2000 |  | 
| chaithrika@ti.com | d4fdcd9 | 2010-03-10 22:37:56 +0000 | [diff] [blame] | 2001 | static const struct dev_pm_ops davinci_emac_pm_ops = { | 
|  | 2002 | .suspend	= davinci_emac_suspend, | 
|  | 2003 | .resume		= davinci_emac_resume, | 
|  | 2004 | }; | 
|  | 2005 |  | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 2006 | /** | 
|  | 2007 | * davinci_emac_driver: EMAC platform driver structure | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 2008 | */ | 
|  | 2009 | static struct platform_driver davinci_emac_driver = { | 
|  | 2010 | .driver = { | 
|  | 2011 | .name	 = "davinci_emac", | 
|  | 2012 | .owner	 = THIS_MODULE, | 
| chaithrika@ti.com | d4fdcd9 | 2010-03-10 22:37:56 +0000 | [diff] [blame] | 2013 | .pm	 = &davinci_emac_pm_ops, | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 2014 | }, | 
|  | 2015 | .probe = davinci_emac_probe, | 
|  | 2016 | .remove = __devexit_p(davinci_emac_remove), | 
|  | 2017 | }; | 
|  | 2018 |  | 
|  | 2019 | /** | 
|  | 2020 | * davinci_emac_init: EMAC driver module init | 
|  | 2021 | * | 
|  | 2022 | * Called when initializing the driver. We register the driver with | 
|  | 2023 | * the platform. | 
|  | 2024 | */ | 
|  | 2025 | static int __init davinci_emac_init(void) | 
|  | 2026 | { | 
|  | 2027 | return platform_driver_register(&davinci_emac_driver); | 
|  | 2028 | } | 
| Rajashekhara, Sudhakar | 2db9517 | 2009-08-19 10:39:55 +0000 | [diff] [blame] | 2029 | late_initcall(davinci_emac_init); | 
| Anant Gole | a6286ee | 2009-05-18 15:19:01 -0700 | [diff] [blame] | 2030 |  | 
|  | 2031 | /** | 
|  | 2032 | * davinci_emac_exit: EMAC driver module exit | 
|  | 2033 | * | 
|  | 2034 | * Called when exiting the driver completely. We unregister the driver with | 
|  | 2035 | * the platform and exit | 
|  | 2036 | */ | 
|  | 2037 | static void __exit davinci_emac_exit(void) | 
|  | 2038 | { | 
|  | 2039 | platform_driver_unregister(&davinci_emac_driver); | 
|  | 2040 | } | 
|  | 2041 | module_exit(davinci_emac_exit); | 
|  | 2042 |  | 
|  | 2043 | MODULE_LICENSE("GPL"); | 
|  | 2044 | MODULE_AUTHOR("DaVinci EMAC Maintainer: Anant Gole <anantgole@ti.com>"); | 
|  | 2045 | MODULE_AUTHOR("DaVinci EMAC Maintainer: Chaithrika U S <chaithrika@ti.com>"); | 
|  | 2046 | MODULE_DESCRIPTION("DaVinci EMAC Ethernet driver"); |