1 /* 2 * (C) Copyright 2007-2009 Michal Simek 3 * (C) Copyright 2003 Xilinx Inc. 4 * 5 * Michal SIMEK <monstr@monstr.eu> 6 * 7 * See file CREDITS for list of people who contributed to this 8 * project. 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License as 12 * published by the Free Software Foundation; either version 2 of 13 * the License, or (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., 59 Temple Place, Suite 330, Boston, 23 * MA 02111-1307 USA 24 */ 25 26 #include <common.h> 27 #include <net.h> 28 #include <config.h> 29 #include <malloc.h> 30 #include <asm/io.h> 31 32 #undef DEBUG 33 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 struct xemaclite { 65 u32 nexttxbuffertouse; /* Next TX buffer to write to */ 66 u32 nextrxbuffertouse; /* Next RX buffer to read from */ 67 u32 txpp; /* TX ping pong buffer */ 68 u32 rxpp; /* RX ping pong buffer */ 69 }; 70 71 static u32 etherrxbuff[PKTSIZE_ALIGN/4]; /* Receive buffer */ 72 73 static void xemaclite_alignedread(u32 *srcptr, void *destptr, u32 bytecount) 74 { 75 u32 i; 76 u32 alignbuffer; 77 u32 *to32ptr; 78 u32 *from32ptr; 79 u8 *to8ptr; 80 u8 *from8ptr; 81 82 from32ptr = (u32 *) srcptr; 83 84 /* Word aligned buffer, no correction needed. */ 85 to32ptr = (u32 *) destptr; 86 while (bytecount > 3) { 87 *to32ptr++ = *from32ptr++; 88 bytecount -= 4; 89 } 90 to8ptr = (u8 *) to32ptr; 91 92 alignbuffer = *from32ptr++; 93 from8ptr = (u8 *) &alignbuffer; 94 95 for (i = 0; i < bytecount; i++) 96 *to8ptr++ = *from8ptr++; 97 } 98 99 static void xemaclite_alignedwrite(void *srcptr, u32 destptr, u32 bytecount) 100 { 101 u32 i; 102 u32 alignbuffer; 103 u32 *to32ptr = (u32 *) destptr; 104 u32 *from32ptr; 105 u8 *to8ptr; 106 u8 *from8ptr; 107 108 from32ptr = (u32 *) srcptr; 109 while (bytecount > 3) { 110 111 *to32ptr++ = *from32ptr++; 112 bytecount -= 4; 113 } 114 115 alignbuffer = 0; 116 to8ptr = (u8 *) &alignbuffer; 117 from8ptr = (u8 *) from32ptr; 118 119 for (i = 0; i < bytecount; i++) 120 *to8ptr++ = *from8ptr++; 121 122 *to32ptr++ = alignbuffer; 123 } 124 125 static void emaclite_halt(struct eth_device *dev) 126 { 127 debug("eth_halt\n"); 128 } 129 130 static int emaclite_init(struct eth_device *dev, bd_t *bis) 131 { 132 struct xemaclite *emaclite = dev->priv; 133 debug("EmacLite Initialization Started\n"); 134 135 /* 136 * TX - TX_PING & TX_PONG initialization 137 */ 138 /* Restart PING TX */ 139 out_be32 (dev->iobase + XEL_TSR_OFFSET, 0); 140 /* Copy MAC address */ 141 xemaclite_alignedwrite(dev->enetaddr, dev->iobase, ENET_ADDR_LENGTH); 142 /* Set the length */ 143 out_be32 (dev->iobase + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH); 144 /* Update the MAC address in the EMAC Lite */ 145 out_be32 (dev->iobase + XEL_TSR_OFFSET, XEL_TSR_PROG_MAC_ADDR); 146 /* Wait for EMAC Lite to finish with the MAC address update */ 147 while ((in_be32 (dev->iobase + XEL_TSR_OFFSET) & 148 XEL_TSR_PROG_MAC_ADDR) != 0) 149 ; 150 151 if (emaclite->txpp) { 152 /* The same operation with PONG TX */ 153 out_be32 (dev->iobase + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET, 0); 154 xemaclite_alignedwrite(dev->enetaddr, dev->iobase + 155 XEL_BUFFER_OFFSET, ENET_ADDR_LENGTH); 156 out_be32 (dev->iobase + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH); 157 out_be32 (dev->iobase + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET, 158 XEL_TSR_PROG_MAC_ADDR); 159 while ((in_be32 (dev->iobase + XEL_TSR_OFFSET + 160 XEL_BUFFER_OFFSET) & XEL_TSR_PROG_MAC_ADDR) != 0) 161 ; 162 } 163 164 /* 165 * RX - RX_PING & RX_PONG initialization 166 */ 167 /* Write out the value to flush the RX buffer */ 168 out_be32 (dev->iobase + XEL_RSR_OFFSET, XEL_RSR_RECV_IE_MASK); 169 170 if (emaclite->rxpp) 171 out_be32 (dev->iobase + XEL_RSR_OFFSET + XEL_BUFFER_OFFSET, 172 XEL_RSR_RECV_IE_MASK); 173 174 debug("EmacLite Initialization complete\n"); 175 return 0; 176 } 177 178 static int xemaclite_txbufferavailable(struct eth_device *dev) 179 { 180 u32 reg; 181 u32 txpingbusy; 182 u32 txpongbusy; 183 struct xemaclite *emaclite = dev->priv; 184 185 /* 186 * Read the other buffer register 187 * and determine if the other buffer is available 188 */ 189 reg = in_be32 (dev->iobase + 190 emaclite->nexttxbuffertouse + 0); 191 txpingbusy = ((reg & XEL_TSR_XMIT_BUSY_MASK) == 192 XEL_TSR_XMIT_BUSY_MASK); 193 194 reg = in_be32 (dev->iobase + 195 (emaclite->nexttxbuffertouse ^ XEL_TSR_OFFSET) + 0); 196 txpongbusy = ((reg & XEL_TSR_XMIT_BUSY_MASK) == 197 XEL_TSR_XMIT_BUSY_MASK); 198 199 return !(txpingbusy && txpongbusy); 200 } 201 202 static int emaclite_send(struct eth_device *dev, volatile void *ptr, int len) 203 { 204 u32 reg; 205 u32 baseaddress; 206 struct xemaclite *emaclite = dev->priv; 207 208 u32 maxtry = 1000; 209 210 if (len > PKTSIZE) 211 len = PKTSIZE; 212 213 while (!xemaclite_txbufferavailable(dev) && maxtry) { 214 udelay(10); 215 maxtry--; 216 } 217 218 if (!maxtry) { 219 printf("Error: Timeout waiting for ethernet TX buffer\n"); 220 /* Restart PING TX */ 221 out_be32 (dev->iobase + XEL_TSR_OFFSET, 0); 222 if (emaclite->txpp) { 223 out_be32 (dev->iobase + XEL_TSR_OFFSET + 224 XEL_BUFFER_OFFSET, 0); 225 } 226 return -1; 227 } 228 229 /* Determine the expected TX buffer address */ 230 baseaddress = (dev->iobase + emaclite->nexttxbuffertouse); 231 232 /* Determine if the expected buffer address is empty */ 233 reg = in_be32 (baseaddress + XEL_TSR_OFFSET); 234 if (((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) 235 && ((in_be32 ((baseaddress) + XEL_TSR_OFFSET) 236 & XEL_TSR_XMIT_ACTIVE_MASK) == 0)) { 237 238 if (emaclite->txpp) 239 emaclite->nexttxbuffertouse ^= XEL_BUFFER_OFFSET; 240 241 debug("Send packet from 0x%x\n", baseaddress); 242 /* Write the frame to the buffer */ 243 xemaclite_alignedwrite((void *) ptr, baseaddress, len); 244 out_be32 (baseaddress + XEL_TPLR_OFFSET,(len & 245 (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO))); 246 reg = in_be32 (baseaddress + XEL_TSR_OFFSET); 247 reg |= XEL_TSR_XMIT_BUSY_MASK; 248 if ((reg & XEL_TSR_XMIT_IE_MASK) != 0) 249 reg |= XEL_TSR_XMIT_ACTIVE_MASK; 250 out_be32 (baseaddress + XEL_TSR_OFFSET, reg); 251 return 0; 252 } 253 254 if (emaclite->txpp) { 255 /* Switch to second buffer */ 256 baseaddress ^= XEL_BUFFER_OFFSET; 257 /* Determine if the expected buffer address is empty */ 258 reg = in_be32 (baseaddress + XEL_TSR_OFFSET); 259 if (((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) 260 && ((in_be32 ((baseaddress) + XEL_TSR_OFFSET) 261 & XEL_TSR_XMIT_ACTIVE_MASK) == 0)) { 262 debug("Send packet from 0x%x\n", baseaddress); 263 /* Write the frame to the buffer */ 264 xemaclite_alignedwrite((void *) ptr, baseaddress, len); 265 out_be32 (baseaddress + XEL_TPLR_OFFSET, (len & 266 (XEL_TPLR_LENGTH_MASK_HI | 267 XEL_TPLR_LENGTH_MASK_LO))); 268 reg = in_be32 (baseaddress + XEL_TSR_OFFSET); 269 reg |= XEL_TSR_XMIT_BUSY_MASK; 270 if ((reg & XEL_TSR_XMIT_IE_MASK) != 0) 271 reg |= XEL_TSR_XMIT_ACTIVE_MASK; 272 out_be32 (baseaddress + XEL_TSR_OFFSET, reg); 273 return 0; 274 } 275 } 276 277 puts("Error while sending frame\n"); 278 return -1; 279 } 280 281 static int emaclite_recv(struct eth_device *dev) 282 { 283 u32 length; 284 u32 reg; 285 u32 baseaddress; 286 struct xemaclite *emaclite = dev->priv; 287 288 baseaddress = dev->iobase + emaclite->nextrxbuffertouse; 289 reg = in_be32 (baseaddress + XEL_RSR_OFFSET); 290 debug("Testing data at address 0x%x\n", baseaddress); 291 if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) { 292 if (emaclite->rxpp) 293 emaclite->nextrxbuffertouse ^= XEL_BUFFER_OFFSET; 294 } else { 295 296 if (!emaclite->rxpp) { 297 debug("No data was available - address 0x%x\n", 298 baseaddress); 299 return 0; 300 } else { 301 baseaddress ^= XEL_BUFFER_OFFSET; 302 reg = in_be32 (baseaddress + XEL_RSR_OFFSET); 303 if ((reg & XEL_RSR_RECV_DONE_MASK) != 304 XEL_RSR_RECV_DONE_MASK) { 305 debug("No data was available - address 0x%x\n", 306 baseaddress); 307 return 0; 308 } 309 } 310 } 311 /* Get the length of the frame that arrived */ 312 switch(((ntohl(in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0xC))) & 313 0xFFFF0000 ) >> 16) { 314 case 0x806: 315 length = 42 + 20; /* FIXME size of ARP */ 316 debug("ARP Packet\n"); 317 break; 318 case 0x800: 319 length = 14 + 14 + 320 (((ntohl(in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 321 0x10))) & 0xFFFF0000) >> 16); 322 /* FIXME size of IP packet */ 323 debug ("IP Packet\n"); 324 break; 325 default: 326 debug("Other Packet\n"); 327 length = PKTSIZE; 328 break; 329 } 330 331 xemaclite_alignedread((u32 *) (baseaddress + XEL_RXBUFF_OFFSET), 332 etherrxbuff, length); 333 334 /* Acknowledge the frame */ 335 reg = in_be32 (baseaddress + XEL_RSR_OFFSET); 336 reg &= ~XEL_RSR_RECV_DONE_MASK; 337 out_be32 (baseaddress + XEL_RSR_OFFSET, reg); 338 339 debug("Packet receive from 0x%x, length %dB\n", baseaddress, length); 340 NetReceive((uchar *) etherrxbuff, length); 341 return length; 342 343 } 344 345 int xilinx_emaclite_initialize (bd_t *bis, int base_addr) 346 { 347 struct eth_device *dev; 348 struct xemaclite *emaclite; 349 350 dev = calloc(1, sizeof(*dev)); 351 if (dev == NULL) 352 return -1; 353 354 emaclite = calloc(1, sizeof(struct xemaclite)); 355 if (emaclite == NULL) { 356 free(dev); 357 return -1; 358 } 359 360 dev->priv = emaclite; 361 362 #ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG 363 emaclite->txpp = 1; 364 #endif 365 #ifdef CONFIG_XILINX_EMACLITE_RX_PING_PONG 366 emaclite->rxpp = 1; 367 #endif 368 369 sprintf(dev->name, "Xelite.%x", base_addr); 370 371 dev->iobase = base_addr; 372 dev->init = emaclite_init; 373 dev->halt = emaclite_halt; 374 dev->send = emaclite_send; 375 dev->recv = emaclite_recv; 376 377 eth_register(dev); 378 379 return 1; 380 } 381