1 /* 2 * (C) Copyright 2007-2009 Michal Simek 3 * (C) Copyright 2003 Xilinx Inc. 4 * 5 * Michal SIMEK <monstr@monstr.eu> 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10 #include <common.h> 11 #include <net.h> 12 #include <config.h> 13 #include <malloc.h> 14 #include <asm/io.h> 15 #include <fdtdec.h> 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 #undef DEBUG 20 21 #define ENET_ADDR_LENGTH 6 22 23 /* EmacLite constants */ 24 #define XEL_BUFFER_OFFSET 0x0800 /* Next buffer's offset */ 25 #define XEL_TPLR_OFFSET 0x07F4 /* Tx packet length */ 26 #define XEL_TSR_OFFSET 0x07FC /* Tx status */ 27 #define XEL_RSR_OFFSET 0x17FC /* Rx status */ 28 #define XEL_RXBUFF_OFFSET 0x1000 /* Receive Buffer */ 29 30 /* Xmit complete */ 31 #define XEL_TSR_XMIT_BUSY_MASK 0x00000001UL 32 /* Xmit interrupt enable bit */ 33 #define XEL_TSR_XMIT_IE_MASK 0x00000008UL 34 /* Buffer is active, SW bit only */ 35 #define XEL_TSR_XMIT_ACTIVE_MASK 0x80000000UL 36 /* Program the MAC address */ 37 #define XEL_TSR_PROGRAM_MASK 0x00000002UL 38 /* define for programming the MAC address into the EMAC Lite */ 39 #define XEL_TSR_PROG_MAC_ADDR (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_PROGRAM_MASK) 40 41 /* Transmit packet length upper byte */ 42 #define XEL_TPLR_LENGTH_MASK_HI 0x0000FF00UL 43 /* Transmit packet length lower byte */ 44 #define XEL_TPLR_LENGTH_MASK_LO 0x000000FFUL 45 46 /* Recv complete */ 47 #define XEL_RSR_RECV_DONE_MASK 0x00000001UL 48 /* Recv interrupt enable bit */ 49 #define XEL_RSR_RECV_IE_MASK 0x00000008UL 50 51 struct xemaclite { 52 u32 nexttxbuffertouse; /* Next TX buffer to write to */ 53 u32 nextrxbuffertouse; /* Next RX buffer to read from */ 54 u32 txpp; /* TX ping pong buffer */ 55 u32 rxpp; /* RX ping pong buffer */ 56 }; 57 58 static u32 etherrxbuff[PKTSIZE_ALIGN/4]; /* Receive buffer */ 59 60 static void xemaclite_alignedread(u32 *srcptr, void *destptr, u32 bytecount) 61 { 62 u32 i; 63 u32 alignbuffer; 64 u32 *to32ptr; 65 u32 *from32ptr; 66 u8 *to8ptr; 67 u8 *from8ptr; 68 69 from32ptr = (u32 *) srcptr; 70 71 /* Word aligned buffer, no correction needed. */ 72 to32ptr = (u32 *) destptr; 73 while (bytecount > 3) { 74 *to32ptr++ = *from32ptr++; 75 bytecount -= 4; 76 } 77 to8ptr = (u8 *) to32ptr; 78 79 alignbuffer = *from32ptr++; 80 from8ptr = (u8 *) &alignbuffer; 81 82 for (i = 0; i < bytecount; i++) 83 *to8ptr++ = *from8ptr++; 84 } 85 86 static void xemaclite_alignedwrite(void *srcptr, u32 destptr, u32 bytecount) 87 { 88 u32 i; 89 u32 alignbuffer; 90 u32 *to32ptr = (u32 *) destptr; 91 u32 *from32ptr; 92 u8 *to8ptr; 93 u8 *from8ptr; 94 95 from32ptr = (u32 *) srcptr; 96 while (bytecount > 3) { 97 98 *to32ptr++ = *from32ptr++; 99 bytecount -= 4; 100 } 101 102 alignbuffer = 0; 103 to8ptr = (u8 *) &alignbuffer; 104 from8ptr = (u8 *) from32ptr; 105 106 for (i = 0; i < bytecount; i++) 107 *to8ptr++ = *from8ptr++; 108 109 *to32ptr++ = alignbuffer; 110 } 111 112 static void emaclite_halt(struct eth_device *dev) 113 { 114 debug("eth_halt\n"); 115 } 116 117 static int emaclite_init(struct eth_device *dev, bd_t *bis) 118 { 119 struct xemaclite *emaclite = dev->priv; 120 debug("EmacLite Initialization Started\n"); 121 122 /* 123 * TX - TX_PING & TX_PONG initialization 124 */ 125 /* Restart PING TX */ 126 out_be32 (dev->iobase + XEL_TSR_OFFSET, 0); 127 /* Copy MAC address */ 128 xemaclite_alignedwrite(dev->enetaddr, dev->iobase, ENET_ADDR_LENGTH); 129 /* Set the length */ 130 out_be32 (dev->iobase + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH); 131 /* Update the MAC address in the EMAC Lite */ 132 out_be32 (dev->iobase + XEL_TSR_OFFSET, XEL_TSR_PROG_MAC_ADDR); 133 /* Wait for EMAC Lite to finish with the MAC address update */ 134 while ((in_be32 (dev->iobase + XEL_TSR_OFFSET) & 135 XEL_TSR_PROG_MAC_ADDR) != 0) 136 ; 137 138 if (emaclite->txpp) { 139 /* The same operation with PONG TX */ 140 out_be32 (dev->iobase + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET, 0); 141 xemaclite_alignedwrite(dev->enetaddr, dev->iobase + 142 XEL_BUFFER_OFFSET, ENET_ADDR_LENGTH); 143 out_be32 (dev->iobase + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH); 144 out_be32 (dev->iobase + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET, 145 XEL_TSR_PROG_MAC_ADDR); 146 while ((in_be32 (dev->iobase + XEL_TSR_OFFSET + 147 XEL_BUFFER_OFFSET) & XEL_TSR_PROG_MAC_ADDR) != 0) 148 ; 149 } 150 151 /* 152 * RX - RX_PING & RX_PONG initialization 153 */ 154 /* Write out the value to flush the RX buffer */ 155 out_be32 (dev->iobase + XEL_RSR_OFFSET, XEL_RSR_RECV_IE_MASK); 156 157 if (emaclite->rxpp) 158 out_be32 (dev->iobase + XEL_RSR_OFFSET + XEL_BUFFER_OFFSET, 159 XEL_RSR_RECV_IE_MASK); 160 161 debug("EmacLite Initialization complete\n"); 162 return 0; 163 } 164 165 static int xemaclite_txbufferavailable(struct eth_device *dev) 166 { 167 u32 reg; 168 u32 txpingbusy; 169 u32 txpongbusy; 170 struct xemaclite *emaclite = dev->priv; 171 172 /* 173 * Read the other buffer register 174 * and determine if the other buffer is available 175 */ 176 reg = in_be32 (dev->iobase + 177 emaclite->nexttxbuffertouse + 0); 178 txpingbusy = ((reg & XEL_TSR_XMIT_BUSY_MASK) == 179 XEL_TSR_XMIT_BUSY_MASK); 180 181 reg = in_be32 (dev->iobase + 182 (emaclite->nexttxbuffertouse ^ XEL_TSR_OFFSET) + 0); 183 txpongbusy = ((reg & XEL_TSR_XMIT_BUSY_MASK) == 184 XEL_TSR_XMIT_BUSY_MASK); 185 186 return !(txpingbusy && txpongbusy); 187 } 188 189 static int emaclite_send(struct eth_device *dev, void *ptr, int len) 190 { 191 u32 reg; 192 u32 baseaddress; 193 struct xemaclite *emaclite = dev->priv; 194 195 u32 maxtry = 1000; 196 197 if (len > PKTSIZE) 198 len = PKTSIZE; 199 200 while (!xemaclite_txbufferavailable(dev) && maxtry) { 201 udelay(10); 202 maxtry--; 203 } 204 205 if (!maxtry) { 206 printf("Error: Timeout waiting for ethernet TX buffer\n"); 207 /* Restart PING TX */ 208 out_be32 (dev->iobase + XEL_TSR_OFFSET, 0); 209 if (emaclite->txpp) { 210 out_be32 (dev->iobase + XEL_TSR_OFFSET + 211 XEL_BUFFER_OFFSET, 0); 212 } 213 return -1; 214 } 215 216 /* Determine the expected TX buffer address */ 217 baseaddress = (dev->iobase + emaclite->nexttxbuffertouse); 218 219 /* Determine if the expected buffer address is empty */ 220 reg = in_be32 (baseaddress + XEL_TSR_OFFSET); 221 if (((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) 222 && ((in_be32 ((baseaddress) + XEL_TSR_OFFSET) 223 & XEL_TSR_XMIT_ACTIVE_MASK) == 0)) { 224 225 if (emaclite->txpp) 226 emaclite->nexttxbuffertouse ^= XEL_BUFFER_OFFSET; 227 228 debug("Send packet from 0x%x\n", baseaddress); 229 /* Write the frame to the buffer */ 230 xemaclite_alignedwrite(ptr, baseaddress, len); 231 out_be32 (baseaddress + XEL_TPLR_OFFSET,(len & 232 (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO))); 233 reg = in_be32 (baseaddress + XEL_TSR_OFFSET); 234 reg |= XEL_TSR_XMIT_BUSY_MASK; 235 if ((reg & XEL_TSR_XMIT_IE_MASK) != 0) 236 reg |= XEL_TSR_XMIT_ACTIVE_MASK; 237 out_be32 (baseaddress + XEL_TSR_OFFSET, reg); 238 return 0; 239 } 240 241 if (emaclite->txpp) { 242 /* Switch to second buffer */ 243 baseaddress ^= XEL_BUFFER_OFFSET; 244 /* Determine if the expected buffer address is empty */ 245 reg = in_be32 (baseaddress + XEL_TSR_OFFSET); 246 if (((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) 247 && ((in_be32 ((baseaddress) + XEL_TSR_OFFSET) 248 & XEL_TSR_XMIT_ACTIVE_MASK) == 0)) { 249 debug("Send packet from 0x%x\n", baseaddress); 250 /* Write the frame to the buffer */ 251 xemaclite_alignedwrite(ptr, baseaddress, len); 252 out_be32 (baseaddress + XEL_TPLR_OFFSET, (len & 253 (XEL_TPLR_LENGTH_MASK_HI | 254 XEL_TPLR_LENGTH_MASK_LO))); 255 reg = in_be32 (baseaddress + XEL_TSR_OFFSET); 256 reg |= XEL_TSR_XMIT_BUSY_MASK; 257 if ((reg & XEL_TSR_XMIT_IE_MASK) != 0) 258 reg |= XEL_TSR_XMIT_ACTIVE_MASK; 259 out_be32 (baseaddress + XEL_TSR_OFFSET, reg); 260 return 0; 261 } 262 } 263 264 puts("Error while sending frame\n"); 265 return -1; 266 } 267 268 static int emaclite_recv(struct eth_device *dev) 269 { 270 u32 length; 271 u32 reg; 272 u32 baseaddress; 273 struct xemaclite *emaclite = dev->priv; 274 275 baseaddress = dev->iobase + emaclite->nextrxbuffertouse; 276 reg = in_be32 (baseaddress + XEL_RSR_OFFSET); 277 debug("Testing data at address 0x%x\n", baseaddress); 278 if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) { 279 if (emaclite->rxpp) 280 emaclite->nextrxbuffertouse ^= XEL_BUFFER_OFFSET; 281 } else { 282 283 if (!emaclite->rxpp) { 284 debug("No data was available - address 0x%x\n", 285 baseaddress); 286 return 0; 287 } else { 288 baseaddress ^= XEL_BUFFER_OFFSET; 289 reg = in_be32 (baseaddress + XEL_RSR_OFFSET); 290 if ((reg & XEL_RSR_RECV_DONE_MASK) != 291 XEL_RSR_RECV_DONE_MASK) { 292 debug("No data was available - address 0x%x\n", 293 baseaddress); 294 return 0; 295 } 296 } 297 } 298 /* Get the length of the frame that arrived */ 299 switch(((ntohl(in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0xC))) & 300 0xFFFF0000 ) >> 16) { 301 case 0x806: 302 length = 42 + 20; /* FIXME size of ARP */ 303 debug("ARP Packet\n"); 304 break; 305 case 0x800: 306 length = 14 + 14 + 307 (((ntohl(in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 308 0x10))) & 0xFFFF0000) >> 16); 309 /* FIXME size of IP packet */ 310 debug ("IP Packet\n"); 311 break; 312 default: 313 debug("Other Packet\n"); 314 length = PKTSIZE; 315 break; 316 } 317 318 xemaclite_alignedread((u32 *) (baseaddress + XEL_RXBUFF_OFFSET), 319 etherrxbuff, length); 320 321 /* Acknowledge the frame */ 322 reg = in_be32 (baseaddress + XEL_RSR_OFFSET); 323 reg &= ~XEL_RSR_RECV_DONE_MASK; 324 out_be32 (baseaddress + XEL_RSR_OFFSET, reg); 325 326 debug("Packet receive from 0x%x, length %dB\n", baseaddress, length); 327 NetReceive((uchar *) etherrxbuff, length); 328 return length; 329 330 } 331 332 int xilinx_emaclite_initialize(bd_t *bis, unsigned long base_addr, 333 int txpp, int rxpp) 334 { 335 struct eth_device *dev; 336 struct xemaclite *emaclite; 337 338 dev = calloc(1, sizeof(*dev)); 339 if (dev == NULL) 340 return -1; 341 342 emaclite = calloc(1, sizeof(struct xemaclite)); 343 if (emaclite == NULL) { 344 free(dev); 345 return -1; 346 } 347 348 dev->priv = emaclite; 349 350 emaclite->txpp = txpp; 351 emaclite->rxpp = rxpp; 352 353 sprintf(dev->name, "Xelite.%lx", base_addr); 354 355 dev->iobase = base_addr; 356 dev->init = emaclite_init; 357 dev->halt = emaclite_halt; 358 dev->send = emaclite_send; 359 dev->recv = emaclite_recv; 360 361 eth_register(dev); 362 363 return 1; 364 } 365 366 #ifdef CONFIG_OF_CONTROL 367 int xilinx_emaclite_init(bd_t *bis) 368 { 369 int offset = 0; 370 u32 ret = 0; 371 u32 reg; 372 373 do { 374 offset = fdt_node_offset_by_compatible(gd->fdt_blob, offset, 375 "xlnx,xps-ethernetlite-1.00.a"); 376 if (offset != -1) { 377 reg = fdtdec_get_addr(gd->fdt_blob, offset, "reg"); 378 if (reg != FDT_ADDR_T_NONE) { 379 u32 rxpp = fdtdec_get_int(gd->fdt_blob, offset, 380 "xlnx,rx-ping-pong", 0); 381 u32 txpp = fdtdec_get_int(gd->fdt_blob, offset, 382 "xlnx,tx-ping-pong", 0); 383 ret |= xilinx_emaclite_initialize(bis, reg, 384 txpp, rxpp); 385 } 386 } 387 } while (offset != -1); 388 389 return ret; 390 } 391 #endif 392