]> git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/tsec.c
4c5e1b5d3a1325deed2634806f968543079c4cc3
[people/ms/u-boot.git] / drivers / tsec.c
1 /*
2 * tsec.c
3 * Freescale Three Speed Ethernet Controller driver
4 *
5 * This software may be used and distributed according to the
6 * terms of the GNU Public License, Version 2, incorporated
7 * herein by reference.
8 *
9 * Copyright 2004 Freescale Semiconductor.
10 * (C) Copyright 2003, Motorola, Inc.
11 * author Andy Fleming
12 *
13 */
14
15 #include <config.h>
16 #include <mpc85xx.h>
17 #include <common.h>
18 #include <malloc.h>
19 #include <net.h>
20 #include <command.h>
21
22 #if defined(CONFIG_TSEC_ENET)
23 #include "tsec.h"
24 #include "miiphy.h"
25
26 #define TX_BUF_CNT 2
27
28 static uint rxIdx; /* index of the current RX buffer */
29 static uint txIdx; /* index of the current TX buffer */
30
31 typedef volatile struct rtxbd {
32 txbd8_t txbd[TX_BUF_CNT];
33 rxbd8_t rxbd[PKTBUFSRX];
34 } RTXBD;
35
36 struct tsec_info_struct {
37 unsigned int phyaddr;
38 u32 flags;
39 unsigned int phyregidx;
40 };
41
42
43 /* The tsec_info structure contains 3 values which the
44 * driver uses to determine how to operate a given ethernet
45 * device. For now, the structure is initialized with the
46 * knowledge that all current implementations have 2 TSEC
47 * devices, and one FEC. The information needed is:
48 * phyaddr - The address of the PHY which is attached to
49 * the given device.
50 *
51 * flags - This variable indicates whether the device
52 * supports gigabit speed ethernet, and whether it should be
53 * in reduced mode.
54 *
55 * phyregidx - This variable specifies which ethernet device
56 * controls the MII Management registers which are connected
57 * to the PHY. For 8540/8560, only TSEC1 (index 0) has
58 * access to the PHYs, so all of the entries have "0".
59 *
60 * The values specified in the table are taken from the board's
61 * config file in include/configs/. When implementing a new
62 * board with ethernet capability, it is necessary to define:
63 * TSEC1_PHY_ADDR
64 * TSEC1_PHYIDX
65 * TSEC2_PHY_ADDR
66 * TSEC2_PHYIDX
67 *
68 * and for 8560:
69 * FEC_PHY_ADDR
70 * FEC_PHYIDX
71 */
72 static struct tsec_info_struct tsec_info[] = {
73 #if defined(CONFIG_MPC85XX_TSEC1) || defined(CONFIG_MPC83XX_TSEC1)
74 {TSEC1_PHY_ADDR, TSEC_GIGABIT, TSEC1_PHYIDX},
75 #else
76 { 0, 0, 0},
77 #endif
78 #if defined(CONFIG_MPC85XX_TSEC2) || defined(CONFIG_MPC83XX_TSEC2)
79 {TSEC2_PHY_ADDR, TSEC_GIGABIT, TSEC2_PHYIDX},
80 #else
81 { 0, 0, 0},
82 #endif
83 #ifdef CONFIG_MPC85XX_FEC
84 {FEC_PHY_ADDR, 0, FEC_PHYIDX},
85 #else
86 # if defined(CONFIG_MPC85XX_TSEC3) || defined(CONFIG_MPC83XX_TSEC3)
87 {TSEC3_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC3_PHYIDX},
88 # else
89 { 0, 0, 0},
90 # endif
91 # if defined(CONFIG_MPC85XX_TSEC4) || defined(CONFIG_MPC83XX_TSEC4)
92 {TSEC4_PHY_ADDR, TSEC_REDUCED, TSEC4_PHYIDX},
93 # else
94 { 0, 0, 0},
95 # endif
96 #endif
97 };
98
99 #define MAXCONTROLLERS (4)
100
101 static int relocated = 0;
102
103 static struct tsec_private *privlist[MAXCONTROLLERS];
104
105 #ifdef __GNUC__
106 static RTXBD rtx __attribute__ ((aligned(8)));
107 #else
108 #error "rtx must be 64-bit aligned"
109 #endif
110
111 static int tsec_send(struct eth_device* dev, volatile void *packet, int length);
112 static int tsec_recv(struct eth_device* dev);
113 static int tsec_init(struct eth_device* dev, bd_t * bd);
114 static void tsec_halt(struct eth_device* dev);
115 static void init_registers(volatile tsec_t *regs);
116 static void startup_tsec(struct eth_device *dev);
117 static int init_phy(struct eth_device *dev);
118 void write_phy_reg(struct tsec_private *priv, uint regnum, uint value);
119 uint read_phy_reg(struct tsec_private *priv, uint regnum);
120 struct phy_info * get_phy_info(struct eth_device *dev);
121 void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd);
122 static void adjust_link(struct eth_device *dev);
123 static void relocate_cmds(void);
124 static int tsec_miiphy_write(char *devname, unsigned char addr,
125 unsigned char reg, unsigned short value);
126 static int tsec_miiphy_read(char *devname, unsigned char addr,
127 unsigned char reg, unsigned short *value);
128
129 /* Initialize device structure. Returns success if PHY
130 * initialization succeeded (i.e. if it recognizes the PHY)
131 */
132 int tsec_initialize(bd_t *bis, int index, char *devname)
133 {
134 struct eth_device* dev;
135 int i;
136 struct tsec_private *priv;
137
138 dev = (struct eth_device*) malloc(sizeof *dev);
139
140 if(NULL == dev)
141 return 0;
142
143 memset(dev, 0, sizeof *dev);
144
145 priv = (struct tsec_private *) malloc(sizeof(*priv));
146
147 if(NULL == priv)
148 return 0;
149
150 privlist[index] = priv;
151 priv->regs = (volatile tsec_t *)(TSEC_BASE_ADDR + index*TSEC_SIZE);
152 priv->phyregs = (volatile tsec_t *)(TSEC_BASE_ADDR +
153 tsec_info[index].phyregidx*TSEC_SIZE);
154
155 priv->phyaddr = tsec_info[index].phyaddr;
156 priv->flags = tsec_info[index].flags;
157
158 sprintf(dev->name, devname);
159 dev->iobase = 0;
160 dev->priv = priv;
161 dev->init = tsec_init;
162 dev->halt = tsec_halt;
163 dev->send = tsec_send;
164 dev->recv = tsec_recv;
165
166 /* Tell u-boot to get the addr from the env */
167 for(i=0;i<6;i++)
168 dev->enetaddr[i] = 0;
169
170 eth_register(dev);
171
172
173 /* Reset the MAC */
174 priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;
175 priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
176
177 #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \
178 && !defined(BITBANGMII)
179 miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write);
180 #endif
181
182 /* Try to initialize PHY here, and return */
183 return init_phy(dev);
184 }
185
186
187 /* Initializes data structures and registers for the controller,
188 * and brings the interface up. Returns the link status, meaning
189 * that it returns success if the link is up, failure otherwise.
190 * This allows u-boot to find the first active controller. */
191 int tsec_init(struct eth_device* dev, bd_t * bd)
192 {
193 uint tempval;
194 char tmpbuf[MAC_ADDR_LEN];
195 int i;
196 struct tsec_private *priv = (struct tsec_private *)dev->priv;
197 volatile tsec_t *regs = priv->regs;
198
199 /* Make sure the controller is stopped */
200 tsec_halt(dev);
201
202 /* Init MACCFG2. Defaults to GMII */
203 regs->maccfg2 = MACCFG2_INIT_SETTINGS;
204
205 /* Init ECNTRL */
206 regs->ecntrl = ECNTRL_INIT_SETTINGS;
207
208 /* Copy the station address into the address registers.
209 * Backwards, because little endian MACS are dumb */
210 for(i=0;i<MAC_ADDR_LEN;i++) {
211 tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
212 }
213 regs->macstnaddr1 = *((uint *)(tmpbuf));
214
215 tempval = *((uint *)(tmpbuf +4));
216
217 regs->macstnaddr2 = tempval;
218
219 /* reset the indices to zero */
220 rxIdx = 0;
221 txIdx = 0;
222
223 /* Clear out (for the most part) the other registers */
224 init_registers(regs);
225
226 /* Ready the device for tx/rx */
227 startup_tsec(dev);
228
229 /* If there's no link, fail */
230 return priv->link;
231
232 }
233
234
235 /* Write value to the device's PHY through the registers
236 * specified in priv, modifying the register specified in regnum.
237 * It will wait for the write to be done (or for a timeout to
238 * expire) before exiting
239 */
240 void write_phy_reg(struct tsec_private *priv, uint regnum, uint value)
241 {
242 volatile tsec_t *regbase = priv->phyregs;
243 uint phyid = priv->phyaddr;
244 int timeout=1000000;
245
246 regbase->miimadd = (phyid << 8) | regnum;
247 regbase->miimcon = value;
248 asm("sync");
249
250 timeout=1000000;
251 while((regbase->miimind & MIIMIND_BUSY) && timeout--);
252 }
253
254
255 /* Reads register regnum on the device's PHY through the
256 * registers specified in priv. It lowers and raises the read
257 * command, and waits for the data to become valid (miimind
258 * notvalid bit cleared), and the bus to cease activity (miimind
259 * busy bit cleared), and then returns the value
260 */
261 uint read_phy_reg(struct tsec_private *priv, uint regnum)
262 {
263 uint value;
264 volatile tsec_t *regbase = priv->phyregs;
265 uint phyid = priv->phyaddr;
266
267 /* Put the address of the phy, and the register
268 * number into MIIMADD */
269 regbase->miimadd = (phyid << 8) | regnum;
270
271 /* Clear the command register, and wait */
272 regbase->miimcom = 0;
273 asm("sync");
274
275 /* Initiate a read command, and wait */
276 regbase->miimcom = MIIM_READ_COMMAND;
277 asm("sync");
278
279 /* Wait for the the indication that the read is done */
280 while((regbase->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY)));
281
282 /* Grab the value read from the PHY */
283 value = regbase->miimstat;
284
285 return value;
286 }
287
288
289 /* Discover which PHY is attached to the device, and configure it
290 * properly. If the PHY is not recognized, then return 0
291 * (failure). Otherwise, return 1
292 */
293 static int init_phy(struct eth_device *dev)
294 {
295 struct tsec_private *priv = (struct tsec_private *)dev->priv;
296 struct phy_info *curphy;
297
298 /* Assign a Physical address to the TBI */
299
300 {
301 volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR);
302 regs->tbipa = TBIPA_VALUE;
303 regs = (volatile tsec_t *)(TSEC_BASE_ADDR + TSEC_SIZE);
304 regs->tbipa = TBIPA_VALUE;
305 asm("sync");
306 }
307
308 /* Reset MII (due to new addresses) */
309 priv->phyregs->miimcfg = MIIMCFG_RESET;
310 asm("sync");
311 priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE;
312 asm("sync");
313 while(priv->phyregs->miimind & MIIMIND_BUSY);
314
315 if(0 == relocated)
316 relocate_cmds();
317
318 /* Get the cmd structure corresponding to the attached
319 * PHY */
320 curphy = get_phy_info(dev);
321
322 if(NULL == curphy) {
323 printf("%s: No PHY found\n", dev->name);
324
325 return 0;
326 }
327
328 priv->phyinfo = curphy;
329
330 phy_run_commands(priv, priv->phyinfo->config);
331
332 return 1;
333 }
334
335
336 /* Returns which value to write to the control register. */
337 /* For 10/100, the value is slightly different */
338 uint mii_cr_init(uint mii_reg, struct tsec_private *priv)
339 {
340 if(priv->flags & TSEC_GIGABIT)
341 return MIIM_CONTROL_INIT;
342 else
343 return MIIM_CR_INIT;
344 }
345
346
347 /* Parse the status register for link, and then do
348 * auto-negotiation */
349 uint mii_parse_sr(uint mii_reg, struct tsec_private *priv)
350 {
351 /*
352 * Wait if PHY is capable of autonegotiation and autonegotiation is not complete
353 */
354 mii_reg = read_phy_reg(priv, MIIM_STATUS);
355 if ((mii_reg & PHY_BMSR_AUTN_ABLE) && !(mii_reg & PHY_BMSR_AUTN_COMP)) {
356 int i = 0;
357
358 puts ("Waiting for PHY auto negotiation to complete");
359 while (!((mii_reg & PHY_BMSR_AUTN_COMP) && (mii_reg & MIIM_STATUS_LINK))) {
360 /*
361 * Timeout reached ?
362 */
363 if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
364 puts (" TIMEOUT !\n");
365 priv->link = 0;
366 break;
367 }
368
369 if ((i++ % 1000) == 0) {
370 putc ('.');
371 }
372 udelay (1000); /* 1 ms */
373 mii_reg = read_phy_reg(priv, MIIM_STATUS);
374 }
375 puts (" done\n");
376 priv->link = 1;
377 udelay (500000); /* another 500 ms (results in faster booting) */
378 } else {
379 priv->link = 1;
380 }
381
382 return 0;
383 }
384
385
386 /* Parse the 88E1011's status register for speed and duplex
387 * information */
388 uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private *priv)
389 {
390 uint speed;
391
392 mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
393
394 if (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) &&
395 (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) {
396 int i = 0;
397
398 puts ("Waiting for PHY realtime link");
399 while (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) &&
400 (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) {
401 /*
402 * Timeout reached ?
403 */
404 if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
405 puts (" TIMEOUT !\n");
406 priv->link = 0;
407 break;
408 }
409
410 if ((i++ % 1000) == 0) {
411 putc ('.');
412 }
413 udelay (1000); /* 1 ms */
414 mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
415 }
416 puts (" done\n");
417 udelay (500000); /* another 500 ms (results in faster booting) */
418 }
419
420 if(mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
421 priv->duplexity = 1;
422 else
423 priv->duplexity = 0;
424
425 speed = (mii_reg &MIIM_88E1011_PHYSTAT_SPEED);
426
427 switch(speed) {
428 case MIIM_88E1011_PHYSTAT_GBIT:
429 priv->speed = 1000;
430 break;
431 case MIIM_88E1011_PHYSTAT_100:
432 priv->speed = 100;
433 break;
434 default:
435 priv->speed = 10;
436 }
437
438 return 0;
439 }
440
441
442 /* Parse the cis8201's status register for speed and duplex
443 * information */
444 uint mii_parse_cis8201(uint mii_reg, struct tsec_private *priv)
445 {
446 uint speed;
447
448 if(mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
449 priv->duplexity = 1;
450 else
451 priv->duplexity = 0;
452
453 speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
454 switch(speed) {
455 case MIIM_CIS8201_AUXCONSTAT_GBIT:
456 priv->speed = 1000;
457 break;
458 case MIIM_CIS8201_AUXCONSTAT_100:
459 priv->speed = 100;
460 break;
461 default:
462 priv->speed = 10;
463 break;
464 }
465
466 return 0;
467 }
468
469
470 /* Parse the DM9161's status register for speed and duplex
471 * information */
472 uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private *priv)
473 {
474 if(mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H))
475 priv->speed = 100;
476 else
477 priv->speed = 10;
478
479 if(mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
480 priv->duplexity = 1;
481 else
482 priv->duplexity = 0;
483
484 return 0;
485 }
486
487
488 /* Hack to write all 4 PHYs with the LED values */
489 uint mii_cis8204_fixled(uint mii_reg, struct tsec_private *priv)
490 {
491 uint phyid;
492 volatile tsec_t *regbase = priv->phyregs;
493 int timeout=1000000;
494
495 for(phyid=0;phyid<4;phyid++) {
496 regbase->miimadd = (phyid << 8) | mii_reg;
497 regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT;
498 asm("sync");
499
500 timeout=1000000;
501 while((regbase->miimind & MIIMIND_BUSY) && timeout--);
502 }
503
504 return MIIM_CIS8204_SLEDCON_INIT;
505 }
506
507 uint mii_cis8204_setmode(uint mii_reg, struct tsec_private *priv)
508 {
509 if (priv->flags & TSEC_REDUCED)
510 return MIIM_CIS8204_EPHYCON_INIT | MIIM_CIS8204_EPHYCON_RGMII;
511 else
512 return MIIM_CIS8204_EPHYCON_INIT;
513 }
514
515 /* Initialized required registers to appropriate values, zeroing
516 * those we don't care about (unless zero is bad, in which case,
517 * choose a more appropriate value) */
518 static void init_registers(volatile tsec_t *regs)
519 {
520 /* Clear IEVENT */
521 regs->ievent = IEVENT_INIT_CLEAR;
522
523 regs->imask = IMASK_INIT_CLEAR;
524
525 regs->hash.iaddr0 = 0;
526 regs->hash.iaddr1 = 0;
527 regs->hash.iaddr2 = 0;
528 regs->hash.iaddr3 = 0;
529 regs->hash.iaddr4 = 0;
530 regs->hash.iaddr5 = 0;
531 regs->hash.iaddr6 = 0;
532 regs->hash.iaddr7 = 0;
533
534 regs->hash.gaddr0 = 0;
535 regs->hash.gaddr1 = 0;
536 regs->hash.gaddr2 = 0;
537 regs->hash.gaddr3 = 0;
538 regs->hash.gaddr4 = 0;
539 regs->hash.gaddr5 = 0;
540 regs->hash.gaddr6 = 0;
541 regs->hash.gaddr7 = 0;
542
543 regs->rctrl = 0x00000000;
544
545 /* Init RMON mib registers */
546 memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
547
548 regs->rmon.cam1 = 0xffffffff;
549 regs->rmon.cam2 = 0xffffffff;
550
551 regs->mrblr = MRBLR_INIT_SETTINGS;
552
553 regs->minflr = MINFLR_INIT_SETTINGS;
554
555 regs->attr = ATTR_INIT_SETTINGS;
556 regs->attreli = ATTRELI_INIT_SETTINGS;
557
558 }
559
560
561 /* Configure maccfg2 based on negotiated speed and duplex
562 * reported by PHY handling code */
563 static void adjust_link(struct eth_device *dev)
564 {
565 struct tsec_private *priv = (struct tsec_private *)dev->priv;
566 volatile tsec_t *regs = priv->regs;
567
568 if(priv->link) {
569 if(priv->duplexity != 0)
570 regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
571 else
572 regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX);
573
574 switch(priv->speed) {
575 case 1000:
576 regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF))
577 | MACCFG2_GMII);
578 break;
579 case 100:
580 case 10:
581 regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF))
582 | MACCFG2_MII);
583
584 /* If We're in reduced mode, we need
585 * to say whether we're 10 or 100 MB.
586 */
587 if ((priv->speed == 100)
588 && (priv->flags & TSEC_REDUCED))
589 regs->ecntrl |= ECNTRL_R100;
590 else
591 regs->ecntrl &= ~(ECNTRL_R100);
592 break;
593 default:
594 printf("%s: Speed was bad\n", dev->name);
595 break;
596 }
597
598 printf("Speed: %d, %s duplex\n", priv->speed,
599 (priv->duplexity) ? "full" : "half");
600
601 } else {
602 printf("%s: No link.\n", dev->name);
603 }
604 }
605
606
607 /* Set up the buffers and their descriptors, and bring up the
608 * interface */
609 static void startup_tsec(struct eth_device *dev)
610 {
611 int i;
612 struct tsec_private *priv = (struct tsec_private *)dev->priv;
613 volatile tsec_t *regs = priv->regs;
614
615 /* Point to the buffer descriptors */
616 regs->tbase = (unsigned int)(&rtx.txbd[txIdx]);
617 regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
618
619 /* Initialize the Rx Buffer descriptors */
620 for (i = 0; i < PKTBUFSRX; i++) {
621 rtx.rxbd[i].status = RXBD_EMPTY;
622 rtx.rxbd[i].length = 0;
623 rtx.rxbd[i].bufPtr = (uint)NetRxPackets[i];
624 }
625 rtx.rxbd[PKTBUFSRX -1].status |= RXBD_WRAP;
626
627 /* Initialize the TX Buffer Descriptors */
628 for(i=0; i<TX_BUF_CNT; i++) {
629 rtx.txbd[i].status = 0;
630 rtx.txbd[i].length = 0;
631 rtx.txbd[i].bufPtr = 0;
632 }
633 rtx.txbd[TX_BUF_CNT -1].status |= TXBD_WRAP;
634
635 /* Start up the PHY */
636 phy_run_commands(priv, priv->phyinfo->startup);
637 adjust_link(dev);
638
639 /* Enable Transmit and Receive */
640 regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
641
642 /* Tell the DMA it is clear to go */
643 regs->dmactrl |= DMACTRL_INIT_SETTINGS;
644 regs->tstat = TSTAT_CLEAR_THALT;
645 regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
646 }
647
648 /* This returns the status bits of the device. The return value
649 * is never checked, and this is what the 8260 driver did, so we
650 * do the same. Presumably, this would be zero if there were no
651 * errors */
652 static int tsec_send(struct eth_device* dev, volatile void *packet, int length)
653 {
654 int i;
655 int result = 0;
656 struct tsec_private *priv = (struct tsec_private *)dev->priv;
657 volatile tsec_t *regs = priv->regs;
658
659 /* Find an empty buffer descriptor */
660 for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
661 if (i >= TOUT_LOOP) {
662 debug ("%s: tsec: tx buffers full\n", dev->name);
663 return result;
664 }
665 }
666
667 rtx.txbd[txIdx].bufPtr = (uint)packet;
668 rtx.txbd[txIdx].length = length;
669 rtx.txbd[txIdx].status |= (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
670
671 /* Tell the DMA to go */
672 regs->tstat = TSTAT_CLEAR_THALT;
673
674 /* Wait for buffer to be transmitted */
675 for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
676 if (i >= TOUT_LOOP) {
677 debug ("%s: tsec: tx error\n", dev->name);
678 return result;
679 }
680 }
681
682 txIdx = (txIdx + 1) % TX_BUF_CNT;
683 result = rtx.txbd[txIdx].status & TXBD_STATS;
684
685 return result;
686 }
687
688 static int tsec_recv(struct eth_device* dev)
689 {
690 int length;
691 struct tsec_private *priv = (struct tsec_private *)dev->priv;
692 volatile tsec_t *regs = priv->regs;
693
694 while(!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
695
696 length = rtx.rxbd[rxIdx].length;
697
698 /* Send the packet up if there were no errors */
699 if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
700 NetReceive(NetRxPackets[rxIdx], length - 4);
701 } else {
702 printf("Got error %x\n",
703 (rtx.rxbd[rxIdx].status & RXBD_STATS));
704 }
705
706 rtx.rxbd[rxIdx].length = 0;
707
708 /* Set the wrap bit if this is the last element in the list */
709 rtx.rxbd[rxIdx].status = RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
710
711 rxIdx = (rxIdx + 1) % PKTBUFSRX;
712 }
713
714 if(regs->ievent&IEVENT_BSY) {
715 regs->ievent = IEVENT_BSY;
716 regs->rstat = RSTAT_CLEAR_RHALT;
717 }
718
719 return -1;
720
721 }
722
723
724 /* Stop the interface */
725 static void tsec_halt(struct eth_device* dev)
726 {
727 struct tsec_private *priv = (struct tsec_private *)dev->priv;
728 volatile tsec_t *regs = priv->regs;
729
730 regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
731 regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);
732
733 while(!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC)));
734
735 regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);
736
737 /* Shut down the PHY, as needed */
738 phy_run_commands(priv, priv->phyinfo->shutdown);
739 }
740
741
742 struct phy_info phy_info_M88E1011S = {
743 0x01410c6,
744 "Marvell 88E1011S",
745 4,
746 (struct phy_cmd[]) { /* config */
747 /* Reset and configure the PHY */
748 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
749 {0x1d, 0x1f, NULL},
750 {0x1e, 0x200c, NULL},
751 {0x1d, 0x5, NULL},
752 {0x1e, 0x0, NULL},
753 {0x1e, 0x100, NULL},
754 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
755 {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
756 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
757 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
758 {miim_end,}
759 },
760 (struct phy_cmd[]) { /* startup */
761 /* Status is read once to clear old link state */
762 {MIIM_STATUS, miim_read, NULL},
763 /* Auto-negotiate */
764 {MIIM_STATUS, miim_read, &mii_parse_sr},
765 /* Read the status */
766 {MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
767 {miim_end,}
768 },
769 (struct phy_cmd[]) { /* shutdown */
770 {miim_end,}
771 },
772 };
773
774 struct phy_info phy_info_M88E1111S = {
775 0x01410cc,
776 "Marvell 88E1111S",
777 4,
778 (struct phy_cmd[]) { /* config */
779 /* Reset and configure the PHY */
780 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
781 {0x1d, 0x1f, NULL},
782 {0x1e, 0x200c, NULL},
783 {0x1d, 0x5, NULL},
784 {0x1e, 0x0, NULL},
785 {0x1e, 0x100, NULL},
786 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
787 {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
788 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
789 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
790 {miim_end,}
791 },
792 (struct phy_cmd[]) { /* startup */
793 /* Status is read once to clear old link state */
794 {MIIM_STATUS, miim_read, NULL},
795 /* Auto-negotiate */
796 {MIIM_STATUS, miim_read, &mii_parse_sr},
797 /* Read the status */
798 {MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
799 {miim_end,}
800 },
801 (struct phy_cmd[]) { /* shutdown */
802 {miim_end,}
803 },
804 };
805
806 struct phy_info phy_info_cis8204 = {
807 0x3f11,
808 "Cicada Cis8204",
809 6,
810 (struct phy_cmd[]) { /* config */
811 /* Override PHY config settings */
812 {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
813 /* Configure some basic stuff */
814 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
815 {MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT, &mii_cis8204_fixled},
816 {MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT, &mii_cis8204_setmode},
817 {miim_end,}
818 },
819 (struct phy_cmd[]) { /* startup */
820 /* Read the Status (2x to make sure link is right) */
821 {MIIM_STATUS, miim_read, NULL},
822 /* Auto-negotiate */
823 {MIIM_STATUS, miim_read, &mii_parse_sr},
824 /* Read the status */
825 {MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
826 {miim_end,}
827 },
828 (struct phy_cmd[]) { /* shutdown */
829 {miim_end,}
830 },
831 };
832
833 /* Cicada 8201 */
834 struct phy_info phy_info_cis8201 = {
835 0xfc41,
836 "CIS8201",
837 4,
838 (struct phy_cmd[]) { /* config */
839 /* Override PHY config settings */
840 {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
841 /* Set up the interface mode */
842 {MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL},
843 /* Configure some basic stuff */
844 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
845 {miim_end,}
846 },
847 (struct phy_cmd[]) { /* startup */
848 /* Read the Status (2x to make sure link is right) */
849 {MIIM_STATUS, miim_read, NULL},
850 /* Auto-negotiate */
851 {MIIM_STATUS, miim_read, &mii_parse_sr},
852 /* Read the status */
853 {MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
854 {miim_end,}
855 },
856 (struct phy_cmd[]) { /* shutdown */
857 {miim_end,}
858 },
859 };
860
861
862 struct phy_info phy_info_dm9161 = {
863 0x0181b88,
864 "Davicom DM9161E",
865 4,
866 (struct phy_cmd[]) { /* config */
867 {MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL},
868 /* Do not bypass the scrambler/descrambler */
869 {MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL},
870 /* Clear 10BTCSR to default */
871 {MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, NULL},
872 /* Configure some basic stuff */
873 {MIIM_CONTROL, MIIM_CR_INIT, NULL},
874 /* Restart Auto Negotiation */
875 {MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL},
876 {miim_end,}
877 },
878 (struct phy_cmd[]) { /* startup */
879 /* Status is read once to clear old link state */
880 {MIIM_STATUS, miim_read, NULL},
881 /* Auto-negotiate */
882 {MIIM_STATUS, miim_read, &mii_parse_sr},
883 /* Read the status */
884 {MIIM_DM9161_SCSR, miim_read, &mii_parse_dm9161_scsr},
885 {miim_end,}
886 },
887 (struct phy_cmd[]) { /* shutdown */
888 {miim_end,}
889 },
890 };
891
892 uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv)
893 {
894 unsigned int speed;
895 if (priv->link) {
896 speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
897
898 switch (speed) {
899 case MIIM_LXT971_SR2_10HDX:
900 priv->speed = 10;
901 priv->duplexity = 0;
902 break;
903 case MIIM_LXT971_SR2_10FDX:
904 priv->speed = 10;
905 priv->duplexity = 1;
906 break;
907 case MIIM_LXT971_SR2_100HDX:
908 priv->speed = 100;
909 priv->duplexity = 0;
910 default:
911 priv->speed = 100;
912 priv->duplexity = 1;
913 break;
914 }
915 } else {
916 priv->speed = 0;
917 priv->duplexity = 0;
918 }
919
920 return 0;
921 }
922
923 static struct phy_info phy_info_lxt971 = {
924 0x0001378e,
925 "LXT971",
926 4,
927 (struct phy_cmd []) { /* config */
928 { MIIM_CR, MIIM_CR_INIT, mii_cr_init }, /* autonegotiate */
929 { miim_end, }
930 },
931 (struct phy_cmd []) { /* startup - enable interrupts */
932 /* { 0x12, 0x00f2, NULL }, */
933 { MIIM_STATUS, miim_read, NULL },
934 { MIIM_STATUS, miim_read, &mii_parse_sr },
935 { MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2 },
936 { miim_end, }
937 },
938 (struct phy_cmd []) { /* shutdown - disable interrupts */
939 { miim_end, }
940 },
941 };
942
943 /* Parse the DP83865's link and auto-neg status register for speed and duplex
944 * information */
945 uint mii_parse_dp83865_lanr(uint mii_reg, struct tsec_private *priv)
946 {
947 switch (mii_reg & MIIM_DP83865_SPD_MASK) {
948
949 case MIIM_DP83865_SPD_1000:
950 priv->speed = 1000;
951 break;
952
953 case MIIM_DP83865_SPD_100:
954 priv->speed = 100;
955 break;
956
957 default:
958 priv->speed = 10;
959 break;
960
961 }
962
963 if (mii_reg & MIIM_DP83865_DPX_FULL)
964 priv->duplexity = 1;
965 else
966 priv->duplexity = 0;
967
968 return 0;
969 }
970
971 struct phy_info phy_info_dp83865 = {
972 0x20005c7,
973 "NatSemi DP83865",
974 4,
975 (struct phy_cmd[]) { /* config */
976 {MIIM_CONTROL, MIIM_DP83865_CR_INIT, NULL},
977 {miim_end,}
978 },
979 (struct phy_cmd[]) { /* startup */
980 /* Status is read once to clear old link state */
981 {MIIM_STATUS, miim_read, NULL},
982 /* Auto-negotiate */
983 {MIIM_STATUS, miim_read, &mii_parse_sr},
984 /* Read the link and auto-neg status */
985 {MIIM_DP83865_LANR, miim_read, &mii_parse_dp83865_lanr},
986 {miim_end,}
987 },
988 (struct phy_cmd[]) { /* shutdown */
989 {miim_end,}
990 },
991 };
992
993 struct phy_info *phy_info[] = {
994 #if 0
995 &phy_info_cis8201,
996 #endif
997 &phy_info_cis8204,
998 &phy_info_M88E1011S,
999 &phy_info_M88E1111S,
1000 &phy_info_dm9161,
1001 &phy_info_lxt971,
1002 &phy_info_dp83865,
1003 NULL
1004 };
1005
1006
1007 /* Grab the identifier of the device's PHY, and search through
1008 * all of the known PHYs to see if one matches. If so, return
1009 * it, if not, return NULL */
1010 struct phy_info * get_phy_info(struct eth_device *dev)
1011 {
1012 struct tsec_private *priv = (struct tsec_private *)dev->priv;
1013 uint phy_reg, phy_ID;
1014 int i;
1015 struct phy_info *theInfo = NULL;
1016
1017 /* Grab the bits from PHYIR1, and put them in the upper half */
1018 phy_reg = read_phy_reg(priv, MIIM_PHYIR1);
1019 phy_ID = (phy_reg & 0xffff) << 16;
1020
1021 /* Grab the bits from PHYIR2, and put them in the lower half */
1022 phy_reg = read_phy_reg(priv, MIIM_PHYIR2);
1023 phy_ID |= (phy_reg & 0xffff);
1024
1025 /* loop through all the known PHY types, and find one that */
1026 /* matches the ID we read from the PHY. */
1027 for(i=0; phy_info[i]; i++) {
1028 if(phy_info[i]->id == (phy_ID >> phy_info[i]->shift))
1029 theInfo = phy_info[i];
1030 }
1031
1032 if(theInfo == NULL)
1033 {
1034 printf("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
1035 return NULL;
1036 } else {
1037 debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID);
1038 }
1039
1040 return theInfo;
1041 }
1042
1043
1044 /* Execute the given series of commands on the given device's
1045 * PHY, running functions as necessary*/
1046 void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
1047 {
1048 int i;
1049 uint result;
1050 volatile tsec_t *phyregs = priv->phyregs;
1051
1052 phyregs->miimcfg = MIIMCFG_RESET;
1053
1054 phyregs->miimcfg = MIIMCFG_INIT_VALUE;
1055
1056 while(phyregs->miimind & MIIMIND_BUSY);
1057
1058 for(i=0;cmd->mii_reg != miim_end;i++) {
1059 if(cmd->mii_data == miim_read) {
1060 result = read_phy_reg(priv, cmd->mii_reg);
1061
1062 if(cmd->funct != NULL)
1063 (*(cmd->funct))(result, priv);
1064
1065 } else {
1066 if(cmd->funct != NULL)
1067 result = (*(cmd->funct))(cmd->mii_reg, priv);
1068 else
1069 result = cmd->mii_data;
1070
1071 write_phy_reg(priv, cmd->mii_reg, result);
1072
1073 }
1074 cmd++;
1075 }
1076 }
1077
1078
1079 /* Relocate the function pointers in the phy cmd lists */
1080 static void relocate_cmds(void)
1081 {
1082 struct phy_cmd **cmdlistptr;
1083 struct phy_cmd *cmd;
1084 int i,j,k;
1085 DECLARE_GLOBAL_DATA_PTR;
1086
1087 for(i=0; phy_info[i]; i++) {
1088 /* First thing's first: relocate the pointers to the
1089 * PHY command structures (the structs were done) */
1090 phy_info[i] = (struct phy_info *) ((uint)phy_info[i]
1091 + gd->reloc_off);
1092 phy_info[i]->name += gd->reloc_off;
1093 phy_info[i]->config =
1094 (struct phy_cmd *)((uint)phy_info[i]->config
1095 + gd->reloc_off);
1096 phy_info[i]->startup =
1097 (struct phy_cmd *)((uint)phy_info[i]->startup
1098 + gd->reloc_off);
1099 phy_info[i]->shutdown =
1100 (struct phy_cmd *)((uint)phy_info[i]->shutdown
1101 + gd->reloc_off);
1102
1103 cmdlistptr = &phy_info[i]->config;
1104 j=0;
1105 for(;cmdlistptr <= &phy_info[i]->shutdown;cmdlistptr++) {
1106 k=0;
1107 for(cmd=*cmdlistptr;cmd->mii_reg != miim_end;cmd++) {
1108 /* Only relocate non-NULL pointers */
1109 if(cmd->funct)
1110 cmd->funct += gd->reloc_off;
1111
1112 k++;
1113 }
1114 j++;
1115 }
1116 }
1117
1118 relocated = 1;
1119 }
1120
1121
1122 #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \
1123 && !defined(BITBANGMII)
1124
1125 struct tsec_private * get_priv_for_phy(unsigned char phyaddr)
1126 {
1127 int i;
1128
1129 for(i=0;i<MAXCONTROLLERS;i++) {
1130 if(privlist[i]->phyaddr == phyaddr)
1131 return privlist[i];
1132 }
1133
1134 return NULL;
1135 }
1136
1137 /*
1138 * Read a MII PHY register.
1139 *
1140 * Returns:
1141 * 0 on success
1142 */
1143 static int tsec_miiphy_read(char *devname, unsigned char addr,
1144 unsigned char reg, unsigned short *value)
1145 {
1146 unsigned short ret;
1147 struct tsec_private *priv = get_priv_for_phy(addr);
1148
1149 if(NULL == priv) {
1150 printf("Can't read PHY at address %d\n", addr);
1151 return -1;
1152 }
1153
1154 ret = (unsigned short)read_phy_reg(priv, reg);
1155 *value = ret;
1156
1157 return 0;
1158 }
1159
1160 /*
1161 * Write a MII PHY register.
1162 *
1163 * Returns:
1164 * 0 on success
1165 */
1166 static int tsec_miiphy_write(char *devname, unsigned char addr,
1167 unsigned char reg, unsigned short value)
1168 {
1169 struct tsec_private *priv = get_priv_for_phy(addr);
1170
1171 if(NULL == priv) {
1172 printf("Can't write PHY at address %d\n", addr);
1173 return -1;
1174 }
1175
1176 write_phy_reg(priv, reg, value);
1177
1178 return 0;
1179 }
1180
1181 #endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
1182 && !defined(BITBANGMII) */
1183
1184 #endif /* CONFIG_TSEC_ENET */