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
27
28#include <common.h>
29#include <malloc.h>
30#include <asm/cpm_85xx.h>
31#include <command.h>
32#include <config.h>
33#include <net.h>
34
35#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
36#include <miiphy.h>
37#endif
38
39#if defined(CONFIG_ETHER_ON_FCC) && defined(CONFIG_CMD_NET)
40
41static struct ether_fcc_info_s
42{
43 int ether_index;
44 int proff_enet;
45 ulong cpm_cr_enet_sblock;
46 ulong cpm_cr_enet_page;
47 ulong cmxfcr_mask;
48 ulong cmxfcr_value;
49}
50 ether_fcc_info[] =
51{
52#ifdef CONFIG_ETHER_ON_FCC1
53{
54 0,
55 PROFF_FCC1,
56 CPM_CR_FCC1_SBLOCK,
57 CPM_CR_FCC1_PAGE,
58 CONFIG_SYS_CMXFCR_MASK1,
59 CONFIG_SYS_CMXFCR_VALUE1
60},
61#endif
62
63#ifdef CONFIG_ETHER_ON_FCC2
64{
65 1,
66 PROFF_FCC2,
67 CPM_CR_FCC2_SBLOCK,
68 CPM_CR_FCC2_PAGE,
69 CONFIG_SYS_CMXFCR_MASK2,
70 CONFIG_SYS_CMXFCR_VALUE2
71},
72#endif
73
74#ifdef CONFIG_ETHER_ON_FCC3
75{
76 2,
77 PROFF_FCC3,
78 CPM_CR_FCC3_SBLOCK,
79 CPM_CR_FCC3_PAGE,
80 CONFIG_SYS_CMXFCR_MASK3,
81 CONFIG_SYS_CMXFCR_VALUE3
82},
83#endif
84};
85
86
87
88
89#define PKT_MAXDMA_SIZE 1520
90
91
92#define PKT_MAXBUF_SIZE 1518
93#define PKT_MINBUF_SIZE 64
94
95
96#define PKT_MAXBLR_SIZE 1536
97
98#define TOUT_LOOP 1000000
99
100#define TX_BUF_CNT 2
101
102static uint rxIdx;
103static uint txIdx;
104
105
106
107
108
109
110
111typedef volatile struct rtxbd {
112 cbd_t rxbd[PKTBUFSRX];
113 cbd_t txbd[TX_BUF_CNT];
114} RTXBD;
115
116
117#ifdef __GNUC__
118static RTXBD rtx __attribute__ ((aligned(8)));
119#else
120#error "rtx must be 64-bit aligned"
121#endif
122
123#undef ET_DEBUG
124
125static int fec_send(struct eth_device *dev, void *packet, int length)
126{
127 int i = 0;
128 int result = 0;
129
130 if (length <= 0) {
131 printf("fec: bad packet size: %d\n", length);
132 goto out;
133 }
134
135 for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
136 if (i >= TOUT_LOOP) {
137 printf("fec: tx buffer not ready\n");
138 goto out;
139 }
140 }
141
142 rtx.txbd[txIdx].cbd_bufaddr = (uint)packet;
143 rtx.txbd[txIdx].cbd_datlen = length;
144 rtx.txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST | \
145 BD_ENET_TX_TC | BD_ENET_TX_PAD);
146
147 for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
148 if (i >= TOUT_LOOP) {
149 printf("fec: tx error\n");
150 goto out;
151 }
152 }
153
154#ifdef ET_DEBUG
155 printf("cycles: 0x%x txIdx=0x%04x status: 0x%04x\n", i, txIdx,rtx.txbd[txIdx].cbd_sc);
156 printf("packets at 0x%08x, length_in_bytes=0x%x\n",(uint)packet,length);
157 for(i=0;i<(length/16 + 1);i++) {
158 printf("%08x %08x %08x %08x\n",*((uint *)rtx.txbd[txIdx].cbd_bufaddr+i*4),\
159 *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 1),*((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 2), \
160 *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 3));
161 }
162#endif
163
164
165 result = rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_STATS;
166 txIdx = (txIdx + 1) % TX_BUF_CNT;
167
168out:
169 return result;
170}
171
172static int fec_recv(struct eth_device* dev)
173{
174 int length;
175
176 for (;;)
177 {
178 if (rtx.rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
179 length = -1;
180 break;
181 }
182 length = rtx.rxbd[rxIdx].cbd_datlen;
183
184 if (rtx.rxbd[rxIdx].cbd_sc & 0x003f) {
185 printf("fec: rx error %04x\n", rtx.rxbd[rxIdx].cbd_sc);
186 }
187 else {
188
189 net_process_received_packet(net_rx_packets[rxIdx], length - 4);
190 }
191
192
193
194 rtx.rxbd[rxIdx].cbd_datlen = 0;
195
196
197 if ((rxIdx + 1) >= PKTBUFSRX) {
198 rtx.rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
199 rxIdx = 0;
200 }
201 else {
202 rtx.rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
203 rxIdx++;
204 }
205 }
206 return length;
207}
208
209
210static int fec_init(struct eth_device* dev, bd_t *bis)
211{
212 struct ether_fcc_info_s * info = dev->priv;
213 int i;
214 volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
215 volatile ccsr_cpm_cp_t *cp = &(cpm->im_cpm_cp);
216 fcc_enet_t *pram_ptr;
217 unsigned long mem_addr;
218
219#if 0
220 mii_discover_phy();
221#endif
222
223
224
225
226 cpm->im_cpm_mux.cmxuar = 0;
227 cpm->im_cpm_mux.cmxfcr = (cpm->im_cpm_mux.cmxfcr & ~info->cmxfcr_mask) |
228 info->cmxfcr_value;
229
230
231 if(info->ether_index == 0) {
232 cpm->im_cpm_fcc1.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
233 } else if (info->ether_index == 1) {
234 cpm->im_cpm_fcc2.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
235 } else if (info->ether_index == 2) {
236 cpm->im_cpm_fcc3.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
237 }
238
239
240 if(info->ether_index == 0) {
241 cpm->im_cpm_fcc1.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
242 } else if (info->ether_index == 1){
243 cpm->im_cpm_fcc2.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
244 } else if (info->ether_index == 2){
245 cpm->im_cpm_fcc3.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
246 }
247
248
249 if(info->ether_index == 0) {
250 cpm->im_cpm_fcc1.fdsr = 0xD555;
251 } else if (info->ether_index == 1) {
252 cpm->im_cpm_fcc2.fdsr = 0xD555;
253 } else if (info->ether_index == 2) {
254 cpm->im_cpm_fcc3.fdsr = 0xD555;
255 }
256
257
258 rxIdx = 0;
259 txIdx = 0;
260
261
262 for (i = 0; i < PKTBUFSRX; i++)
263 {
264 rtx.rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
265 rtx.rxbd[i].cbd_datlen = 0;
266 rtx.rxbd[i].cbd_bufaddr = (uint)net_rx_packets[i];
267 }
268 rtx.rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
269
270
271 for (i = 0; i < TX_BUF_CNT; i++)
272 {
273 rtx.txbd[i].cbd_sc = 0;
274 rtx.txbd[i].cbd_datlen = 0;
275 rtx.txbd[i].cbd_bufaddr = 0;
276 }
277 rtx.txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
278
279
280 pram_ptr = (fcc_enet_t *)&(cpm->im_dprambase[info->proff_enet]);
281
282
283 memset((void*)pram_ptr, 0, sizeof(fcc_enet_t));
284
285
286
287
288
289
290
291
292
293
294
295 mem_addr = CPM_FCC_SPECIAL_BASE + ((info->ether_index) * 64);
296 pram_ptr->fen_genfcc.fcc_riptr = mem_addr;
297 pram_ptr->fen_genfcc.fcc_tiptr = mem_addr+32;
298
299
300
301
302 pram_ptr->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
303
304 pram_ptr->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB |
305 CONFIG_SYS_CPMFCR_RAMTYPE) << 24;
306 pram_ptr->fen_genfcc.fcc_rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
307 pram_ptr->fen_genfcc.fcc_rbdstat = 0;
308 pram_ptr->fen_genfcc.fcc_rbdlen = 0;
309 pram_ptr->fen_genfcc.fcc_rdptr = 0;
310
311 pram_ptr->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB |
312 CONFIG_SYS_CPMFCR_RAMTYPE) << 24;
313 pram_ptr->fen_genfcc.fcc_tbase = (unsigned int)(&rtx.txbd[txIdx]);
314 pram_ptr->fen_genfcc.fcc_tbdstat = 0;
315 pram_ptr->fen_genfcc.fcc_tbdlen = 0;
316 pram_ptr->fen_genfcc.fcc_tdptr = 0;
317
318
319 pram_ptr->fen_statbuf = 0x0;
320 pram_ptr->fen_cmask = 0xdebb20e3;
321 pram_ptr->fen_cpres = 0xffffffff;
322 pram_ptr->fen_crcec = 0;
323 pram_ptr->fen_alec = 0;
324 pram_ptr->fen_disfc = 0;
325 pram_ptr->fen_retlim = 15;
326 pram_ptr->fen_retcnt = 0;
327 pram_ptr->fen_pper = 0;
328 pram_ptr->fen_boffcnt = 0;
329 pram_ptr->fen_gaddrh = 0;
330 pram_ptr->fen_gaddrl = 0;
331 pram_ptr->fen_mflr = PKT_MAXBUF_SIZE;
332
333
334
335
336
337
338
339
340
341#define ea eth_get_ethaddr()
342 pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
343 pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
344 pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
345#undef ea
346 pram_ptr->fen_ibdcount = 0;
347 pram_ptr->fen_ibdstart = 0;
348 pram_ptr->fen_ibdend = 0;
349 pram_ptr->fen_txlen = 0;
350 pram_ptr->fen_iaddrh = 0;
351 pram_ptr->fen_iaddrl = 0;
352 pram_ptr->fen_minflr = PKT_MINBUF_SIZE;
353
354 pram_ptr->fen_padptr = pram_ptr->fen_genfcc.fcc_tiptr;
355 pram_ptr->fen_maxd1 = PKT_MAXDMA_SIZE;
356 pram_ptr->fen_maxd2 = PKT_MAXDMA_SIZE;
357
358#if defined(ET_DEBUG)
359 printf("parm_ptr(0xff788500) = %p\n",pram_ptr);
360 printf("pram_ptr->fen_genfcc.fcc_rbase %08x\n",
361 pram_ptr->fen_genfcc.fcc_rbase);
362 printf("pram_ptr->fen_genfcc.fcc_tbase %08x\n",
363 pram_ptr->fen_genfcc.fcc_tbase);
364#endif
365
366
367
368 if(info->ether_index == 0) {
369 cpm->im_cpm_fcc1.fcce = ~0x0;
370 cpm->im_cpm_fcc1.fccm = 0;
371 } else if (info->ether_index == 1) {
372 cpm->im_cpm_fcc2.fcce = ~0x0;
373 cpm->im_cpm_fcc2.fccm = 0;
374 } else if (info->ether_index == 2) {
375 cpm->im_cpm_fcc3.fcce = ~0x0;
376 cpm->im_cpm_fcc3.fccm = 0;
377 }
378
379
380
381
382
383
384
385
386
387 cp->cpcr = mk_cr_cmd(info->cpm_cr_enet_page,
388 info->cpm_cr_enet_sblock,
389 0x0c,
390 CPM_CR_INIT_TRX) | CPM_CR_FLG;
391 do {
392 __asm__ __volatile__ ("eieio");
393 } while (cp->cpcr & CPM_CR_FLG);
394
395
396 if(info->ether_index == 0) {
397 cpm->im_cpm_fcc1.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
398 } else if (info->ether_index == 1) {
399 cpm->im_cpm_fcc2.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
400 } else if (info->ether_index == 2) {
401 cpm->im_cpm_fcc3.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
402 }
403
404 return 1;
405}
406
407static void fec_halt(struct eth_device* dev)
408{
409 struct ether_fcc_info_s * info = dev->priv;
410 volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
411
412
413 if(info->ether_index == 0) {
414 cpm->im_cpm_fcc1.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
415 } else if(info->ether_index == 1) {
416 cpm->im_cpm_fcc2.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
417 } else if(info->ether_index == 2) {
418 cpm->im_cpm_fcc3.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
419 }
420}
421
422int fec_initialize(bd_t *bis)
423{
424 struct eth_device* dev;
425 int i;
426
427 for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++)
428 {
429 dev = (struct eth_device*) malloc(sizeof *dev);
430 memset(dev, 0, sizeof *dev);
431
432 sprintf(dev->name, "FCC%d",
433 ether_fcc_info[i].ether_index + 1);
434 dev->priv = ðer_fcc_info[i];
435 dev->init = fec_init;
436 dev->halt = fec_halt;
437 dev->send = fec_send;
438 dev->recv = fec_recv;
439
440 eth_register(dev);
441
442#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
443 && defined(CONFIG_BITBANGMII)
444 int retval;
445 struct mii_dev *mdiodev = mdio_alloc();
446 if (!mdiodev)
447 return -ENOMEM;
448 strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
449 mdiodev->read = bb_miiphy_read;
450 mdiodev->write = bb_miiphy_write;
451
452 retval = mdio_register(mdiodev);
453 if (retval < 0)
454 return retval;
455#endif
456 }
457
458 return 1;
459}
460
461#endif
462