1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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_MAX_MTU PKTSIZE
35#define ENET_MAX_MTU_ALIGNED PKTSIZE_ALIGN
36#define ENET_ADDR_LENGTH 6
37
38
39#define XEL_BUFFER_OFFSET 0x0800
40#define XEL_TPLR_OFFSET 0x07F4
41#define XEL_TSR_OFFSET 0x07FC
42#define XEL_RSR_OFFSET 0x17FC
43#define XEL_RXBUFF_OFFSET 0x1000
44
45
46#define XEL_TSR_XMIT_BUSY_MASK 0x00000001UL
47
48#define XEL_TSR_XMIT_IE_MASK 0x00000008UL
49
50#define XEL_TSR_XMIT_ACTIVE_MASK 0x80000000UL
51
52#define XEL_TSR_PROGRAM_MASK 0x00000002UL
53
54#define XEL_TSR_PROG_MAC_ADDR (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_PROGRAM_MASK)
55
56
57#define XEL_TPLR_LENGTH_MASK_HI 0x0000FF00UL
58
59#define XEL_TPLR_LENGTH_MASK_LO 0x000000FFUL
60
61
62#define XEL_RSR_RECV_DONE_MASK 0x00000001UL
63
64#define XEL_RSR_RECV_IE_MASK 0x00000008UL
65
66typedef struct {
67 u32 baseaddress;
68 u32 nexttxbuffertouse;
69 u32 nextrxbuffertouse;
70 uchar deviceid;
71} xemaclite;
72
73static xemaclite emaclite;
74
75static u32 etherrxbuff[PKTSIZE_ALIGN/4];
76
77static void xemaclite_alignedread (u32 *srcptr, void *destptr, u32 bytecount)
78{
79 u32 i;
80 u32 alignbuffer;
81 u32 *to32ptr;
82 u32 *from32ptr;
83 u8 *to8ptr;
84 u8 *from8ptr;
85
86 from32ptr = (u32 *) srcptr;
87
88
89 to32ptr = (u32 *) destptr;
90 while (bytecount > 3) {
91 *to32ptr++ = *from32ptr++;
92 bytecount -= 4;
93 }
94 to8ptr = (u8 *) to32ptr;
95
96 alignbuffer = *from32ptr++;
97 from8ptr = (u8 *) & alignbuffer;
98
99 for (i = 0; i < bytecount; i++) {
100 *to8ptr++ = *from8ptr++;
101 }
102}
103
104static void xemaclite_alignedwrite (void *srcptr, u32 destptr, u32 bytecount)
105{
106 u32 i;
107 u32 alignbuffer;
108 u32 *to32ptr = (u32 *) destptr;
109 u32 *from32ptr;
110 u8 *to8ptr;
111 u8 *from8ptr;
112
113 from32ptr = (u32 *) srcptr;
114 while (bytecount > 3) {
115
116 *to32ptr++ = *from32ptr++;
117 bytecount -= 4;
118 }
119
120 alignbuffer = 0;
121 to8ptr = (u8 *) & alignbuffer;
122 from8ptr = (u8 *) from32ptr;
123
124 for (i = 0; i < bytecount; i++) {
125 *to8ptr++ = *from8ptr++;
126 }
127
128 *to32ptr++ = alignbuffer;
129}
130
131static void emaclite_halt(struct eth_device *dev)
132{
133 debug ("eth_halt\n");
134}
135
136static int emaclite_init(struct eth_device *dev, bd_t *bis)
137{
138 debug ("EmacLite Initialization Started\n");
139 memset (&emaclite, 0, sizeof (xemaclite));
140 emaclite.baseaddress = dev->iobase;
141
142
143
144
145
146 out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, 0);
147
148 xemaclite_alignedwrite (dev->enetaddr,
149 emaclite.baseaddress, ENET_ADDR_LENGTH);
150
151 out_be32 (emaclite.baseaddress + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH);
152
153 out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, XEL_TSR_PROG_MAC_ADDR);
154
155 while ((in_be32 (emaclite.baseaddress + XEL_TSR_OFFSET) &
156 XEL_TSR_PROG_MAC_ADDR) != 0) ;
157
158#ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG
159
160 out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET, 0);
161 xemaclite_alignedwrite (dev->enetaddr, emaclite.baseaddress +
162 XEL_BUFFER_OFFSET, ENET_ADDR_LENGTH);
163 out_be32 (emaclite.baseaddress + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH);
164 out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET,
165 XEL_TSR_PROG_MAC_ADDR);
166 while ((in_be32 (emaclite.baseaddress + XEL_TSR_OFFSET +
167 XEL_BUFFER_OFFSET) & XEL_TSR_PROG_MAC_ADDR) != 0) ;
168#endif
169
170
171
172
173
174 out_be32 (emaclite.baseaddress + XEL_RSR_OFFSET, XEL_RSR_RECV_IE_MASK);
175#ifdef CONFIG_XILINX_EMACLITE_RX_PING_PONG
176 out_be32 (emaclite.baseaddress + XEL_RSR_OFFSET + XEL_BUFFER_OFFSET,
177 XEL_RSR_RECV_IE_MASK);
178#endif
179
180 debug ("EmacLite Initialization complete\n");
181 return 0;
182}
183
184static int xemaclite_txbufferavailable (xemaclite *instanceptr)
185{
186 u32 reg;
187 u32 txpingbusy;
188 u32 txpongbusy;
189
190
191
192
193 reg = in_be32 (instanceptr->baseaddress +
194 instanceptr->nexttxbuffertouse + 0);
195 txpingbusy = ((reg & XEL_TSR_XMIT_BUSY_MASK) ==
196 XEL_TSR_XMIT_BUSY_MASK);
197
198 reg = in_be32 (instanceptr->baseaddress +
199 (instanceptr->nexttxbuffertouse ^ XEL_TSR_OFFSET) + 0);
200 txpongbusy = ((reg & XEL_TSR_XMIT_BUSY_MASK) ==
201 XEL_TSR_XMIT_BUSY_MASK);
202
203 return (!(txpingbusy && txpongbusy));
204}
205
206static int emaclite_send (struct eth_device *dev, volatile void *ptr, int len)
207{
208 u32 reg;
209 u32 baseaddress;
210
211 u32 maxtry = 1000;
212
213 if (len > ENET_MAX_MTU)
214 len = ENET_MAX_MTU;
215
216 while (!xemaclite_txbufferavailable (&emaclite) && maxtry) {
217 udelay (10);
218 maxtry--;
219 }
220
221 if (!maxtry) {
222 printf ("Error: Timeout waiting for ethernet TX buffer\n");
223
224 out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, 0);
225#ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG
226 out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET +
227 XEL_BUFFER_OFFSET, 0);
228#endif
229 return 0;
230 }
231
232
233 baseaddress = (emaclite.baseaddress + emaclite.nexttxbuffertouse);
234
235
236 reg = in_be32 (baseaddress + XEL_TSR_OFFSET);
237 if (((reg & XEL_TSR_XMIT_BUSY_MASK) == 0)
238 && ((in_be32 ((baseaddress) + XEL_TSR_OFFSET)
239 & XEL_TSR_XMIT_ACTIVE_MASK) == 0)) {
240
241#ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG
242 emaclite.nexttxbuffertouse ^= XEL_BUFFER_OFFSET;
243#endif
244 debug ("Send packet from 0x%x\n", baseaddress);
245
246 xemaclite_alignedwrite ((void *) ptr, baseaddress, len);
247 out_be32 (baseaddress + XEL_TPLR_OFFSET,(len &
248 (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO)));
249 reg = in_be32 (baseaddress + XEL_TSR_OFFSET);
250 reg |= XEL_TSR_XMIT_BUSY_MASK;
251 if ((reg & XEL_TSR_XMIT_IE_MASK) != 0) {
252 reg |= XEL_TSR_XMIT_ACTIVE_MASK;
253 }
254 out_be32 (baseaddress + XEL_TSR_OFFSET, reg);
255 return 1;
256 }
257#ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG
258
259 baseaddress ^= XEL_BUFFER_OFFSET;
260
261 reg = in_be32 (baseaddress + XEL_TSR_OFFSET);
262 if (((reg & XEL_TSR_XMIT_BUSY_MASK) == 0)
263 && ((in_be32 ((baseaddress) + XEL_TSR_OFFSET)
264 & XEL_TSR_XMIT_ACTIVE_MASK) == 0)) {
265 debug ("Send packet from 0x%x\n", baseaddress);
266
267 xemaclite_alignedwrite ((void *) ptr, baseaddress, len);
268 out_be32 (baseaddress + XEL_TPLR_OFFSET,(len &
269 (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO)));
270 reg = in_be32 (baseaddress + XEL_TSR_OFFSET);
271 reg |= XEL_TSR_XMIT_BUSY_MASK;
272 if ((reg & XEL_TSR_XMIT_IE_MASK) != 0) {
273 reg |= XEL_TSR_XMIT_ACTIVE_MASK;
274 }
275 out_be32 (baseaddress + XEL_TSR_OFFSET, reg);
276 return 1;
277 }
278#endif
279 puts ("Error while sending frame\n");
280 return 0;
281}
282
283static int emaclite_recv(struct eth_device *dev)
284{
285 u32 length;
286 u32 reg;
287 u32 baseaddress;
288
289 baseaddress = emaclite.baseaddress + emaclite.nextrxbuffertouse;
290 reg = in_be32 (baseaddress + XEL_RSR_OFFSET);
291 debug ("Testing data at address 0x%x\n", baseaddress);
292 if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
293#ifdef CONFIG_XILINX_EMACLITE_RX_PING_PONG
294 emaclite.nextrxbuffertouse ^= XEL_BUFFER_OFFSET;
295#endif
296 } else {
297#ifndef CONFIG_XILINX_EMACLITE_RX_PING_PONG
298 debug ("No data was available - address 0x%x\n", 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#endif
310 }
311
312 switch(((ntohl(in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0xC))) &
313 0xFFFF0000 ) >> 16) {
314 case 0x806:
315 length = 42 + 20;
316 debug ("ARP Packet\n");
317 break;
318 case 0x800:
319 length = 14 + 14 +
320 (((ntohl(in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0x10))) &
321 0xFFFF0000) >> 16);
322 debug ("IP Packet\n");
323 break;
324 default:
325 debug ("Other Packet\n");
326 length = ENET_MAX_MTU;
327 break;
328 }
329
330 xemaclite_alignedread ((u32 *) (baseaddress + XEL_RXBUFF_OFFSET),
331 etherrxbuff, length);
332
333
334 reg = in_be32 (baseaddress + XEL_RSR_OFFSET);
335 reg &= ~XEL_RSR_RECV_DONE_MASK;
336 out_be32 (baseaddress + XEL_RSR_OFFSET, reg);
337
338 debug ("Packet receive from 0x%x, length %dB\n", baseaddress, length);
339 NetReceive ((uchar *) etherrxbuff, length);
340 return 1;
341
342}
343
344int xilinx_emaclite_initialize (bd_t *bis, int base_addr)
345{
346 struct eth_device *dev;
347
348 dev = malloc(sizeof(*dev));
349 if (dev == NULL)
350 hang();
351
352 memset(dev, 0, sizeof(*dev));
353 sprintf(dev->name, "Xilinx_Emaclite");
354
355 dev->iobase = base_addr;
356 dev->priv = 0;
357 dev->init = emaclite_init;
358 dev->halt = emaclite_halt;
359 dev->send = emaclite_send;
360 dev->recv = emaclite_recv;
361
362 eth_register(dev);
363
364 return 0;
365}
366