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