1 /****************************************************************************** 2 * 3 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" 4 * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND 5 * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, 6 * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, 7 * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION 8 * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, 9 * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE 10 * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY 11 * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE 12 * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR 13 * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF 14 * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 15 * FOR A PARTICULAR PURPOSE. 16 * 17 * (C) Copyright 2007-2008 Michal Simek 18 * Michal SIMEK <monstr@monstr.eu> 19 * 20 * (c) Copyright 2003 Xilinx Inc. 21 * All rights reserved. 22 * 23 ******************************************************************************/ 24 25 #include <common.h> 26 #include <net.h> 27 #include <config.h> 28 #include <asm/io.h> 29 30 #undef DEBUG 31 32 #define ENET_MAX_MTU PKTSIZE 33 #define ENET_MAX_MTU_ALIGNED PKTSIZE_ALIGN 34 #define ENET_ADDR_LENGTH 6 35 36 /* EmacLite constants */ 37 #define XEL_BUFFER_OFFSET 0x0800 /* Next buffer's offset */ 38 #define XEL_TPLR_OFFSET 0x07F4 /* Tx packet length */ 39 #define XEL_TSR_OFFSET 0x07FC /* Tx status */ 40 #define XEL_RSR_OFFSET 0x17FC /* Rx status */ 41 #define XEL_RXBUFF_OFFSET 0x1000 /* Receive Buffer */ 42 43 /* Xmit complete */ 44 #define XEL_TSR_XMIT_BUSY_MASK 0x00000001UL 45 /* Xmit interrupt enable bit */ 46 #define XEL_TSR_XMIT_IE_MASK 0x00000008UL 47 /* Buffer is active, SW bit only */ 48 #define XEL_TSR_XMIT_ACTIVE_MASK 0x80000000UL 49 /* Program the MAC address */ 50 #define XEL_TSR_PROGRAM_MASK 0x00000002UL 51 /* define for programming the MAC address into the EMAC Lite */ 52 #define XEL_TSR_PROG_MAC_ADDR (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_PROGRAM_MASK) 53 54 /* Transmit packet length upper byte */ 55 #define XEL_TPLR_LENGTH_MASK_HI 0x0000FF00UL 56 /* Transmit packet length lower byte */ 57 #define XEL_TPLR_LENGTH_MASK_LO 0x000000FFUL 58 59 /* Recv complete */ 60 #define XEL_RSR_RECV_DONE_MASK 0x00000001UL 61 /* Recv interrupt enable bit */ 62 #define XEL_RSR_RECV_IE_MASK 0x00000008UL 63 64 typedef struct { 65 unsigned int baseaddress; /* Base address for device (IPIF) */ 66 unsigned int nexttxbuffertouse; /* Next TX buffer to write to */ 67 unsigned int nextrxbuffertouse; /* Next RX buffer to read from */ 68 unsigned char deviceid; /* Unique ID of device - for future */ 69 } xemaclite; 70 71 static xemaclite emaclite; 72 73 static u32 etherrxbuff[PKTSIZE_ALIGN/4]; /* Receive buffer */ 74 75 /* hardcoded MAC address for the Xilinx EMAC Core when env is nowhere*/ 76 #ifdef CONFIG_ENV_IS_NOWHERE 77 static u8 emacaddr[ENET_ADDR_LENGTH] = { 0x00, 0x0a, 0x35, 0x00, 0x22, 0x01 }; 78 #else 79 static u8 emacaddr[ENET_ADDR_LENGTH]; 80 #endif 81 82 void xemaclite_alignedread (u32 * srcptr, void *destptr, unsigned bytecount) 83 { 84 unsigned int i; 85 u32 alignbuffer; 86 u32 *to32ptr; 87 u32 *from32ptr; 88 u8 *to8ptr; 89 u8 *from8ptr; 90 91 from32ptr = (u32 *) srcptr; 92 93 /* Word aligned buffer, no correction needed. */ 94 to32ptr = (u32 *) destptr; 95 while (bytecount > 3) { 96 *to32ptr++ = *from32ptr++; 97 bytecount -= 4; 98 } 99 to8ptr = (u8 *) to32ptr; 100 101 alignbuffer = *from32ptr++; 102 from8ptr = (u8 *) & alignbuffer; 103 104 for (i = 0; i < bytecount; i++) { 105 *to8ptr++ = *from8ptr++; 106 } 107 } 108 109 void xemaclite_alignedwrite (void *srcptr, u32 destptr, unsigned bytecount) 110 { 111 unsigned i; 112 u32 alignbuffer; 113 u32 *to32ptr = (u32 *) destptr; 114 u32 *from32ptr; 115 u8 *to8ptr; 116 u8 *from8ptr; 117 118 from32ptr = (u32 *) srcptr; 119 while (bytecount > 3) { 120 121 *to32ptr++ = *from32ptr++; 122 bytecount -= 4; 123 } 124 125 alignbuffer = 0; 126 to8ptr = (u8 *) & alignbuffer; 127 from8ptr = (u8 *) from32ptr; 128 129 for (i = 0; i < bytecount; i++) { 130 *to8ptr++ = *from8ptr++; 131 } 132 133 *to32ptr++ = alignbuffer; 134 } 135 136 void eth_halt (void) 137 { 138 debug ("eth_halt\n"); 139 } 140 141 int eth_init (bd_t * bis) 142 { 143 uchar enetaddr[6]; 144 145 debug ("EmacLite Initialization Started\n"); 146 memset (&emaclite, 0, sizeof (xemaclite)); 147 emaclite.baseaddress = XILINX_EMACLITE_BASEADDR; 148 149 if (!eth_getenv_enetaddr("ethaddr", enetaddr)) { 150 memcpy(enetaddr, emacaddr, ENET_ADDR_LENGTH); 151 eth_setenv_enetaddr("ethaddr", enetaddr); 152 } 153 154 /* 155 * TX - TX_PING & TX_PONG initialization 156 */ 157 /* Restart PING TX */ 158 out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, 0); 159 /* Copy MAC address */ 160 xemaclite_alignedwrite (enetaddr, 161 emaclite.baseaddress, ENET_ADDR_LENGTH); 162 /* Set the length */ 163 out_be32 (emaclite.baseaddress + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH); 164 /* Update the MAC address in the EMAC Lite */ 165 out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, XEL_TSR_PROG_MAC_ADDR); 166 /* Wait for EMAC Lite to finish with the MAC address update */ 167 while ((in_be32 (emaclite.baseaddress + XEL_TSR_OFFSET) & 168 XEL_TSR_PROG_MAC_ADDR) != 0) ; 169 170 #ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG 171 /* The same operation with PONG TX */ 172 out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET, 0); 173 xemaclite_alignedwrite (enetaddr, emaclite.baseaddress + 174 XEL_BUFFER_OFFSET, ENET_ADDR_LENGTH); 175 out_be32 (emaclite.baseaddress + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH); 176 out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET, 177 XEL_TSR_PROG_MAC_ADDR); 178 while ((in_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + 179 XEL_BUFFER_OFFSET) & XEL_TSR_PROG_MAC_ADDR) != 0) ; 180 #endif 181 182 /* 183 * RX - RX_PING & RX_PONG initialization 184 */ 185 /* Write out the value to flush the RX buffer */ 186 out_be32 (emaclite.baseaddress + XEL_RSR_OFFSET, XEL_RSR_RECV_IE_MASK); 187 #ifdef CONFIG_XILINX_EMACLITE_RX_PING_PONG 188 out_be32 (emaclite.baseaddress + XEL_RSR_OFFSET + XEL_BUFFER_OFFSET, 189 XEL_RSR_RECV_IE_MASK); 190 #endif 191 192 debug ("EmacLite Initialization complete\n"); 193 return 0; 194 } 195 196 int xemaclite_txbufferavailable (xemaclite * instanceptr) 197 { 198 u32 reg; 199 u32 txpingbusy; 200 u32 txpongbusy; 201 /* 202 * Read the other buffer register 203 * and determine if the other buffer is available 204 */ 205 reg = in_be32 (instanceptr->baseaddress + 206 instanceptr->nexttxbuffertouse + 0); 207 txpingbusy = ((reg & XEL_TSR_XMIT_BUSY_MASK) == 208 XEL_TSR_XMIT_BUSY_MASK); 209 210 reg = in_be32 (instanceptr->baseaddress + 211 (instanceptr->nexttxbuffertouse ^ XEL_TSR_OFFSET) + 0); 212 txpongbusy = ((reg & XEL_TSR_XMIT_BUSY_MASK) == 213 XEL_TSR_XMIT_BUSY_MASK); 214 215 return (!(txpingbusy && txpongbusy)); 216 } 217 218 int eth_send (volatile void *ptr, int len) { 219 220 unsigned int reg; 221 unsigned int baseaddress; 222 223 unsigned maxtry = 1000; 224 225 if (len > ENET_MAX_MTU) 226 len = ENET_MAX_MTU; 227 228 while (!xemaclite_txbufferavailable (&emaclite) && maxtry) { 229 udelay (10); 230 maxtry--; 231 } 232 233 if (!maxtry) { 234 printf ("Error: Timeout waiting for ethernet TX buffer\n"); 235 /* Restart PING TX */ 236 out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, 0); 237 #ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG 238 out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + 239 XEL_BUFFER_OFFSET, 0); 240 #endif 241 return 0; 242 } 243 244 /* Determine the expected TX buffer address */ 245 baseaddress = (emaclite.baseaddress + emaclite.nexttxbuffertouse); 246 247 /* Determine if the expected buffer address is empty */ 248 reg = in_be32 (baseaddress + XEL_TSR_OFFSET); 249 if (((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) 250 && ((in_be32 ((baseaddress) + XEL_TSR_OFFSET) 251 & XEL_TSR_XMIT_ACTIVE_MASK) == 0)) { 252 253 #ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG 254 emaclite.nexttxbuffertouse ^= XEL_BUFFER_OFFSET; 255 #endif 256 debug ("Send packet from 0x%x\n", baseaddress); 257 /* Write the frame to the buffer */ 258 xemaclite_alignedwrite ((void *) ptr, baseaddress, len); 259 out_be32 (baseaddress + XEL_TPLR_OFFSET,(len & 260 (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO))); 261 reg = in_be32 (baseaddress + XEL_TSR_OFFSET); 262 reg |= XEL_TSR_XMIT_BUSY_MASK; 263 if ((reg & XEL_TSR_XMIT_IE_MASK) != 0) { 264 reg |= XEL_TSR_XMIT_ACTIVE_MASK; 265 } 266 out_be32 (baseaddress + XEL_TSR_OFFSET, reg); 267 return 1; 268 } 269 #ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG 270 /* Switch to second buffer */ 271 baseaddress ^= XEL_BUFFER_OFFSET; 272 /* Determine if the expected buffer address is empty */ 273 reg = in_be32 (baseaddress + XEL_TSR_OFFSET); 274 if (((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) 275 && ((in_be32 ((baseaddress) + XEL_TSR_OFFSET) 276 & XEL_TSR_XMIT_ACTIVE_MASK) == 0)) { 277 debug ("Send packet from 0x%x\n", baseaddress); 278 /* Write the frame to the buffer */ 279 xemaclite_alignedwrite ((void *) ptr, baseaddress, len); 280 out_be32 (baseaddress + XEL_TPLR_OFFSET,(len & 281 (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO))); 282 reg = in_be32 (baseaddress + XEL_TSR_OFFSET); 283 reg |= XEL_TSR_XMIT_BUSY_MASK; 284 if ((reg & XEL_TSR_XMIT_IE_MASK) != 0) { 285 reg |= XEL_TSR_XMIT_ACTIVE_MASK; 286 } 287 out_be32 (baseaddress + XEL_TSR_OFFSET, reg); 288 return 1; 289 } 290 #endif 291 puts ("Error while sending frame\n"); 292 return 0; 293 } 294 295 int eth_rx (void) 296 { 297 unsigned int length; 298 unsigned int reg; 299 unsigned int baseaddress; 300 301 baseaddress = emaclite.baseaddress + emaclite.nextrxbuffertouse; 302 reg = in_be32 (baseaddress + XEL_RSR_OFFSET); 303 debug ("Testing data at address 0x%x\n", baseaddress); 304 if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) { 305 #ifdef CONFIG_XILINX_EMACLITE_RX_PING_PONG 306 emaclite.nextrxbuffertouse ^= XEL_BUFFER_OFFSET; 307 #endif 308 } else { 309 #ifndef CONFIG_XILINX_EMACLITE_RX_PING_PONG 310 debug ("No data was available - address 0x%x\n", baseaddress); 311 return 0; 312 #else 313 baseaddress ^= XEL_BUFFER_OFFSET; 314 reg = in_be32 (baseaddress + XEL_RSR_OFFSET); 315 if ((reg & XEL_RSR_RECV_DONE_MASK) != 316 XEL_RSR_RECV_DONE_MASK) { 317 debug ("No data was available - address 0x%x\n", 318 baseaddress); 319 return 0; 320 } 321 #endif 322 } 323 /* Get the length of the frame that arrived */ 324 switch(((in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0xC)) & 325 0xFFFF0000 ) >> 16) { 326 case 0x806: 327 length = 42 + 20; /* FIXME size of ARP */ 328 debug ("ARP Packet\n"); 329 break; 330 case 0x800: 331 length = 14 + 14 + 332 (((in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0x10)) & 333 0xFFFF0000) >> 16); /* FIXME size of IP packet */ 334 debug ("IP Packet\n"); 335 break; 336 default: 337 debug ("Other Packet\n"); 338 length = ENET_MAX_MTU; 339 break; 340 } 341 342 xemaclite_alignedread ((u32 *) (baseaddress + XEL_RXBUFF_OFFSET), 343 etherrxbuff, length); 344 345 /* Acknowledge the frame */ 346 reg = in_be32 (baseaddress + XEL_RSR_OFFSET); 347 reg &= ~XEL_RSR_RECV_DONE_MASK; 348 out_be32 (baseaddress + XEL_RSR_OFFSET, reg); 349 350 debug ("Packet receive from 0x%x, length %dB\n", baseaddress, length); 351 NetReceive ((uchar *) etherrxbuff, length); 352 return 1; 353 354 } 355