diff options
Diffstat (limited to 'drivers/net/fec.c')
-rw-r--r-- | drivers/net/fec.c | 310 |
1 files changed, 245 insertions, 65 deletions
diff --git a/drivers/net/fec.c b/drivers/net/fec.c index bd6983d1afba..db694c832989 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * Copyright (c) 2001-2005 Greg Ungerer (gerg@snapgear.com) | 22 | * Copyright (c) 2001-2005 Greg Ungerer (gerg@snapgear.com) |
23 | * | 23 | * |
24 | * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be) | 24 | * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be) |
25 | * Copyright (c) 2004-2005 Macq Electronique SA. | 25 | * Copyright (c) 2004-2006 Macq Electronique SA. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/config.h> | 28 | #include <linux/config.h> |
@@ -51,7 +51,7 @@ | |||
51 | 51 | ||
52 | #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \ | 52 | #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \ |
53 | defined(CONFIG_M5272) || defined(CONFIG_M528x) || \ | 53 | defined(CONFIG_M5272) || defined(CONFIG_M528x) || \ |
54 | defined(CONFIG_M520x) | 54 | defined(CONFIG_M520x) || defined(CONFIG_M532x) |
55 | #include <asm/coldfire.h> | 55 | #include <asm/coldfire.h> |
56 | #include <asm/mcfsim.h> | 56 | #include <asm/mcfsim.h> |
57 | #include "fec.h" | 57 | #include "fec.h" |
@@ -80,6 +80,8 @@ static unsigned int fec_hw[] = { | |||
80 | (MCF_MBAR + 0x1000), | 80 | (MCF_MBAR + 0x1000), |
81 | #elif defined(CONFIG_M520x) | 81 | #elif defined(CONFIG_M520x) |
82 | (MCF_MBAR+0x30000), | 82 | (MCF_MBAR+0x30000), |
83 | #elif defined(CONFIG_M532x) | ||
84 | (MCF_MBAR+0xfc030000), | ||
83 | #else | 85 | #else |
84 | &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec), | 86 | &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec), |
85 | #endif | 87 | #endif |
@@ -143,7 +145,7 @@ typedef struct { | |||
143 | #define TX_RING_MOD_MASK 15 /* for this to work */ | 145 | #define TX_RING_MOD_MASK 15 /* for this to work */ |
144 | 146 | ||
145 | #if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE) | 147 | #if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE) |
146 | #error "FEC: descriptor ring size contants too large" | 148 | #error "FEC: descriptor ring size constants too large" |
147 | #endif | 149 | #endif |
148 | 150 | ||
149 | /* Interrupt events/masks. | 151 | /* Interrupt events/masks. |
@@ -167,12 +169,12 @@ typedef struct { | |||
167 | 169 | ||
168 | 170 | ||
169 | /* | 171 | /* |
170 | * The 5270/5271/5280/5282 RX control register also contains maximum frame | 172 | * The 5270/5271/5280/5282/532x RX control register also contains maximum frame |
171 | * size bits. Other FEC hardware does not, so we need to take that into | 173 | * size bits. Other FEC hardware does not, so we need to take that into |
172 | * account when setting it. | 174 | * account when setting it. |
173 | */ | 175 | */ |
174 | #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ | 176 | #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ |
175 | defined(CONFIG_M520x) | 177 | defined(CONFIG_M520x) || defined(CONFIG_M532x) |
176 | #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) | 178 | #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) |
177 | #else | 179 | #else |
178 | #define OPT_FRAME_SIZE 0 | 180 | #define OPT_FRAME_SIZE 0 |
@@ -308,6 +310,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
308 | struct fec_enet_private *fep; | 310 | struct fec_enet_private *fep; |
309 | volatile fec_t *fecp; | 311 | volatile fec_t *fecp; |
310 | volatile cbd_t *bdp; | 312 | volatile cbd_t *bdp; |
313 | unsigned short status; | ||
311 | 314 | ||
312 | fep = netdev_priv(dev); | 315 | fep = netdev_priv(dev); |
313 | fecp = (volatile fec_t*)dev->base_addr; | 316 | fecp = (volatile fec_t*)dev->base_addr; |
@@ -320,8 +323,9 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
320 | /* Fill in a Tx ring entry */ | 323 | /* Fill in a Tx ring entry */ |
321 | bdp = fep->cur_tx; | 324 | bdp = fep->cur_tx; |
322 | 325 | ||
326 | status = bdp->cbd_sc; | ||
323 | #ifndef final_version | 327 | #ifndef final_version |
324 | if (bdp->cbd_sc & BD_ENET_TX_READY) { | 328 | if (status & BD_ENET_TX_READY) { |
325 | /* Ooops. All transmit buffers are full. Bail out. | 329 | /* Ooops. All transmit buffers are full. Bail out. |
326 | * This should not happen, since dev->tbusy should be set. | 330 | * This should not happen, since dev->tbusy should be set. |
327 | */ | 331 | */ |
@@ -332,7 +336,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
332 | 336 | ||
333 | /* Clear all of the status flags. | 337 | /* Clear all of the status flags. |
334 | */ | 338 | */ |
335 | bdp->cbd_sc &= ~BD_ENET_TX_STATS; | 339 | status &= ~BD_ENET_TX_STATS; |
336 | 340 | ||
337 | /* Set buffer length and buffer pointer. | 341 | /* Set buffer length and buffer pointer. |
338 | */ | 342 | */ |
@@ -366,21 +370,22 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
366 | 370 | ||
367 | spin_lock_irq(&fep->lock); | 371 | spin_lock_irq(&fep->lock); |
368 | 372 | ||
369 | /* Send it on its way. Tell FEC its ready, interrupt when done, | 373 | /* Send it on its way. Tell FEC it's ready, interrupt when done, |
370 | * its the last BD of the frame, and to put the CRC on the end. | 374 | * it's the last BD of the frame, and to put the CRC on the end. |
371 | */ | 375 | */ |
372 | 376 | ||
373 | bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | 377 | status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR |
374 | | BD_ENET_TX_LAST | BD_ENET_TX_TC); | 378 | | BD_ENET_TX_LAST | BD_ENET_TX_TC); |
379 | bdp->cbd_sc = status; | ||
375 | 380 | ||
376 | dev->trans_start = jiffies; | 381 | dev->trans_start = jiffies; |
377 | 382 | ||
378 | /* Trigger transmission start */ | 383 | /* Trigger transmission start */ |
379 | fecp->fec_x_des_active = 0x01000000; | 384 | fecp->fec_x_des_active = 0; |
380 | 385 | ||
381 | /* If this was the last BD in the ring, start at the beginning again. | 386 | /* If this was the last BD in the ring, start at the beginning again. |
382 | */ | 387 | */ |
383 | if (bdp->cbd_sc & BD_ENET_TX_WRAP) { | 388 | if (status & BD_ENET_TX_WRAP) { |
384 | bdp = fep->tx_bd_base; | 389 | bdp = fep->tx_bd_base; |
385 | } else { | 390 | } else { |
386 | bdp++; | 391 | bdp++; |
@@ -491,43 +496,44 @@ fec_enet_tx(struct net_device *dev) | |||
491 | { | 496 | { |
492 | struct fec_enet_private *fep; | 497 | struct fec_enet_private *fep; |
493 | volatile cbd_t *bdp; | 498 | volatile cbd_t *bdp; |
499 | unsigned short status; | ||
494 | struct sk_buff *skb; | 500 | struct sk_buff *skb; |
495 | 501 | ||
496 | fep = netdev_priv(dev); | 502 | fep = netdev_priv(dev); |
497 | spin_lock(&fep->lock); | 503 | spin_lock(&fep->lock); |
498 | bdp = fep->dirty_tx; | 504 | bdp = fep->dirty_tx; |
499 | 505 | ||
500 | while ((bdp->cbd_sc&BD_ENET_TX_READY) == 0) { | 506 | while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) { |
501 | if (bdp == fep->cur_tx && fep->tx_full == 0) break; | 507 | if (bdp == fep->cur_tx && fep->tx_full == 0) break; |
502 | 508 | ||
503 | skb = fep->tx_skbuff[fep->skb_dirty]; | 509 | skb = fep->tx_skbuff[fep->skb_dirty]; |
504 | /* Check for errors. */ | 510 | /* Check for errors. */ |
505 | if (bdp->cbd_sc & (BD_ENET_TX_HB | BD_ENET_TX_LC | | 511 | if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | |
506 | BD_ENET_TX_RL | BD_ENET_TX_UN | | 512 | BD_ENET_TX_RL | BD_ENET_TX_UN | |
507 | BD_ENET_TX_CSL)) { | 513 | BD_ENET_TX_CSL)) { |
508 | fep->stats.tx_errors++; | 514 | fep->stats.tx_errors++; |
509 | if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */ | 515 | if (status & BD_ENET_TX_HB) /* No heartbeat */ |
510 | fep->stats.tx_heartbeat_errors++; | 516 | fep->stats.tx_heartbeat_errors++; |
511 | if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */ | 517 | if (status & BD_ENET_TX_LC) /* Late collision */ |
512 | fep->stats.tx_window_errors++; | 518 | fep->stats.tx_window_errors++; |
513 | if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */ | 519 | if (status & BD_ENET_TX_RL) /* Retrans limit */ |
514 | fep->stats.tx_aborted_errors++; | 520 | fep->stats.tx_aborted_errors++; |
515 | if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */ | 521 | if (status & BD_ENET_TX_UN) /* Underrun */ |
516 | fep->stats.tx_fifo_errors++; | 522 | fep->stats.tx_fifo_errors++; |
517 | if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */ | 523 | if (status & BD_ENET_TX_CSL) /* Carrier lost */ |
518 | fep->stats.tx_carrier_errors++; | 524 | fep->stats.tx_carrier_errors++; |
519 | } else { | 525 | } else { |
520 | fep->stats.tx_packets++; | 526 | fep->stats.tx_packets++; |
521 | } | 527 | } |
522 | 528 | ||
523 | #ifndef final_version | 529 | #ifndef final_version |
524 | if (bdp->cbd_sc & BD_ENET_TX_READY) | 530 | if (status & BD_ENET_TX_READY) |
525 | printk("HEY! Enet xmit interrupt and TX_READY.\n"); | 531 | printk("HEY! Enet xmit interrupt and TX_READY.\n"); |
526 | #endif | 532 | #endif |
527 | /* Deferred means some collisions occurred during transmit, | 533 | /* Deferred means some collisions occurred during transmit, |
528 | * but we eventually sent the packet OK. | 534 | * but we eventually sent the packet OK. |
529 | */ | 535 | */ |
530 | if (bdp->cbd_sc & BD_ENET_TX_DEF) | 536 | if (status & BD_ENET_TX_DEF) |
531 | fep->stats.collisions++; | 537 | fep->stats.collisions++; |
532 | 538 | ||
533 | /* Free the sk buffer associated with this last transmit. | 539 | /* Free the sk buffer associated with this last transmit. |
@@ -538,7 +544,7 @@ fec_enet_tx(struct net_device *dev) | |||
538 | 544 | ||
539 | /* Update pointer to next buffer descriptor to be transmitted. | 545 | /* Update pointer to next buffer descriptor to be transmitted. |
540 | */ | 546 | */ |
541 | if (bdp->cbd_sc & BD_ENET_TX_WRAP) | 547 | if (status & BD_ENET_TX_WRAP) |
542 | bdp = fep->tx_bd_base; | 548 | bdp = fep->tx_bd_base; |
543 | else | 549 | else |
544 | bdp++; | 550 | bdp++; |
@@ -568,9 +574,14 @@ fec_enet_rx(struct net_device *dev) | |||
568 | struct fec_enet_private *fep; | 574 | struct fec_enet_private *fep; |
569 | volatile fec_t *fecp; | 575 | volatile fec_t *fecp; |
570 | volatile cbd_t *bdp; | 576 | volatile cbd_t *bdp; |
577 | unsigned short status; | ||
571 | struct sk_buff *skb; | 578 | struct sk_buff *skb; |
572 | ushort pkt_len; | 579 | ushort pkt_len; |
573 | __u8 *data; | 580 | __u8 *data; |
581 | |||
582 | #ifdef CONFIG_M532x | ||
583 | flush_cache_all(); | ||
584 | #endif | ||
574 | 585 | ||
575 | fep = netdev_priv(dev); | 586 | fep = netdev_priv(dev); |
576 | fecp = (volatile fec_t*)dev->base_addr; | 587 | fecp = (volatile fec_t*)dev->base_addr; |
@@ -580,13 +591,13 @@ fec_enet_rx(struct net_device *dev) | |||
580 | */ | 591 | */ |
581 | bdp = fep->cur_rx; | 592 | bdp = fep->cur_rx; |
582 | 593 | ||
583 | while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) { | 594 | while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { |
584 | 595 | ||
585 | #ifndef final_version | 596 | #ifndef final_version |
586 | /* Since we have allocated space to hold a complete frame, | 597 | /* Since we have allocated space to hold a complete frame, |
587 | * the last indicator should be set. | 598 | * the last indicator should be set. |
588 | */ | 599 | */ |
589 | if ((bdp->cbd_sc & BD_ENET_RX_LAST) == 0) | 600 | if ((status & BD_ENET_RX_LAST) == 0) |
590 | printk("FEC ENET: rcv is not +last\n"); | 601 | printk("FEC ENET: rcv is not +last\n"); |
591 | #endif | 602 | #endif |
592 | 603 | ||
@@ -594,26 +605,26 @@ while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) { | |||
594 | goto rx_processing_done; | 605 | goto rx_processing_done; |
595 | 606 | ||
596 | /* Check for errors. */ | 607 | /* Check for errors. */ |
597 | if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | | 608 | if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | |
598 | BD_ENET_RX_CR | BD_ENET_RX_OV)) { | 609 | BD_ENET_RX_CR | BD_ENET_RX_OV)) { |
599 | fep->stats.rx_errors++; | 610 | fep->stats.rx_errors++; |
600 | if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH)) { | 611 | if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) { |
601 | /* Frame too long or too short. */ | 612 | /* Frame too long or too short. */ |
602 | fep->stats.rx_length_errors++; | 613 | fep->stats.rx_length_errors++; |
603 | } | 614 | } |
604 | if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */ | 615 | if (status & BD_ENET_RX_NO) /* Frame alignment */ |
605 | fep->stats.rx_frame_errors++; | 616 | fep->stats.rx_frame_errors++; |
606 | if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */ | 617 | if (status & BD_ENET_RX_CR) /* CRC Error */ |
607 | fep->stats.rx_crc_errors++; | ||
608 | if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */ | ||
609 | fep->stats.rx_crc_errors++; | 618 | fep->stats.rx_crc_errors++; |
619 | if (status & BD_ENET_RX_OV) /* FIFO overrun */ | ||
620 | fep->stats.rx_fifo_errors++; | ||
610 | } | 621 | } |
611 | 622 | ||
612 | /* Report late collisions as a frame error. | 623 | /* Report late collisions as a frame error. |
613 | * On this error, the BD is closed, but we don't know what we | 624 | * On this error, the BD is closed, but we don't know what we |
614 | * have in the buffer. So, just drop this frame on the floor. | 625 | * have in the buffer. So, just drop this frame on the floor. |
615 | */ | 626 | */ |
616 | if (bdp->cbd_sc & BD_ENET_RX_CL) { | 627 | if (status & BD_ENET_RX_CL) { |
617 | fep->stats.rx_errors++; | 628 | fep->stats.rx_errors++; |
618 | fep->stats.rx_frame_errors++; | 629 | fep->stats.rx_frame_errors++; |
619 | goto rx_processing_done; | 630 | goto rx_processing_done; |
@@ -639,9 +650,7 @@ while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) { | |||
639 | } else { | 650 | } else { |
640 | skb->dev = dev; | 651 | skb->dev = dev; |
641 | skb_put(skb,pkt_len-4); /* Make room */ | 652 | skb_put(skb,pkt_len-4); /* Make room */ |
642 | eth_copy_and_sum(skb, | 653 | eth_copy_and_sum(skb, data, pkt_len-4, 0); |
643 | (unsigned char *)__va(bdp->cbd_bufaddr), | ||
644 | pkt_len-4, 0); | ||
645 | skb->protocol=eth_type_trans(skb,dev); | 654 | skb->protocol=eth_type_trans(skb,dev); |
646 | netif_rx(skb); | 655 | netif_rx(skb); |
647 | } | 656 | } |
@@ -649,15 +658,16 @@ while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) { | |||
649 | 658 | ||
650 | /* Clear the status flags for this buffer. | 659 | /* Clear the status flags for this buffer. |
651 | */ | 660 | */ |
652 | bdp->cbd_sc &= ~BD_ENET_RX_STATS; | 661 | status &= ~BD_ENET_RX_STATS; |
653 | 662 | ||
654 | /* Mark the buffer empty. | 663 | /* Mark the buffer empty. |
655 | */ | 664 | */ |
656 | bdp->cbd_sc |= BD_ENET_RX_EMPTY; | 665 | status |= BD_ENET_RX_EMPTY; |
666 | bdp->cbd_sc = status; | ||
657 | 667 | ||
658 | /* Update BD pointer to next entry. | 668 | /* Update BD pointer to next entry. |
659 | */ | 669 | */ |
660 | if (bdp->cbd_sc & BD_ENET_RX_WRAP) | 670 | if (status & BD_ENET_RX_WRAP) |
661 | bdp = fep->rx_bd_base; | 671 | bdp = fep->rx_bd_base; |
662 | else | 672 | else |
663 | bdp++; | 673 | bdp++; |
@@ -667,9 +677,9 @@ while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) { | |||
667 | * incoming frames. On a heavily loaded network, we should be | 677 | * incoming frames. On a heavily loaded network, we should be |
668 | * able to keep up at the expense of system resources. | 678 | * able to keep up at the expense of system resources. |
669 | */ | 679 | */ |
670 | fecp->fec_r_des_active = 0x01000000; | 680 | fecp->fec_r_des_active = 0; |
671 | #endif | 681 | #endif |
672 | } /* while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) */ | 682 | } /* while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) */ |
673 | fep->cur_rx = (cbd_t *)bdp; | 683 | fep->cur_rx = (cbd_t *)bdp; |
674 | 684 | ||
675 | #if 0 | 685 | #if 0 |
@@ -680,11 +690,12 @@ while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) { | |||
680 | * our way back to the interrupt return only to come right back | 690 | * our way back to the interrupt return only to come right back |
681 | * here. | 691 | * here. |
682 | */ | 692 | */ |
683 | fecp->fec_r_des_active = 0x01000000; | 693 | fecp->fec_r_des_active = 0; |
684 | #endif | 694 | #endif |
685 | } | 695 | } |
686 | 696 | ||
687 | 697 | ||
698 | /* called from interrupt context */ | ||
688 | static void | 699 | static void |
689 | fec_enet_mii(struct net_device *dev) | 700 | fec_enet_mii(struct net_device *dev) |
690 | { | 701 | { |
@@ -696,10 +707,12 @@ fec_enet_mii(struct net_device *dev) | |||
696 | fep = netdev_priv(dev); | 707 | fep = netdev_priv(dev); |
697 | ep = fep->hwp; | 708 | ep = fep->hwp; |
698 | mii_reg = ep->fec_mii_data; | 709 | mii_reg = ep->fec_mii_data; |
710 | |||
711 | spin_lock(&fep->lock); | ||
699 | 712 | ||
700 | if ((mip = mii_head) == NULL) { | 713 | if ((mip = mii_head) == NULL) { |
701 | printk("MII and no head!\n"); | 714 | printk("MII and no head!\n"); |
702 | return; | 715 | goto unlock; |
703 | } | 716 | } |
704 | 717 | ||
705 | if (mip->mii_func != NULL) | 718 | if (mip->mii_func != NULL) |
@@ -711,6 +724,9 @@ fec_enet_mii(struct net_device *dev) | |||
711 | 724 | ||
712 | if ((mip = mii_head) != NULL) | 725 | if ((mip = mii_head) != NULL) |
713 | ep->fec_mii_data = mip->mii_regval; | 726 | ep->fec_mii_data = mip->mii_regval; |
727 | |||
728 | unlock: | ||
729 | spin_unlock(&fep->lock); | ||
714 | } | 730 | } |
715 | 731 | ||
716 | static int | 732 | static int |
@@ -728,8 +744,7 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi | |||
728 | 744 | ||
729 | retval = 0; | 745 | retval = 0; |
730 | 746 | ||
731 | save_flags(flags); | 747 | spin_lock_irqsave(&fep->lock,flags); |
732 | cli(); | ||
733 | 748 | ||
734 | if ((mip = mii_free) != NULL) { | 749 | if ((mip = mii_free) != NULL) { |
735 | mii_free = mip->mii_next; | 750 | mii_free = mip->mii_next; |
@@ -749,7 +764,7 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi | |||
749 | retval = 1; | 764 | retval = 1; |
750 | } | 765 | } |
751 | 766 | ||
752 | restore_flags(flags); | 767 | spin_unlock_irqrestore(&fep->lock,flags); |
753 | 768 | ||
754 | return(retval); | 769 | return(retval); |
755 | } | 770 | } |
@@ -1216,7 +1231,7 @@ static phy_info_t const * const phy_info[] = { | |||
1216 | }; | 1231 | }; |
1217 | 1232 | ||
1218 | /* ------------------------------------------------------------------------- */ | 1233 | /* ------------------------------------------------------------------------- */ |
1219 | 1234 | #if !defined(CONFIG_M532x) | |
1220 | #ifdef CONFIG_RPXCLASSIC | 1235 | #ifdef CONFIG_RPXCLASSIC |
1221 | static void | 1236 | static void |
1222 | mii_link_interrupt(void *dev_id); | 1237 | mii_link_interrupt(void *dev_id); |
@@ -1224,6 +1239,7 @@ mii_link_interrupt(void *dev_id); | |||
1224 | static irqreturn_t | 1239 | static irqreturn_t |
1225 | mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs); | 1240 | mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs); |
1226 | #endif | 1241 | #endif |
1242 | #endif | ||
1227 | 1243 | ||
1228 | #if defined(CONFIG_M5272) | 1244 | #if defined(CONFIG_M5272) |
1229 | 1245 | ||
@@ -1384,13 +1400,13 @@ static void __inline__ fec_request_intrs(struct net_device *dev) | |||
1384 | { | 1400 | { |
1385 | volatile unsigned char *icrp; | 1401 | volatile unsigned char *icrp; |
1386 | volatile unsigned long *imrp; | 1402 | volatile unsigned long *imrp; |
1387 | int i; | 1403 | int i, ilip; |
1388 | 1404 | ||
1389 | b = (fep->index) ? MCFICM_INTC1 : MCFICM_INTC0; | 1405 | b = (fep->index) ? MCFICM_INTC1 : MCFICM_INTC0; |
1390 | icrp = (volatile unsigned char *) (MCF_IPSBAR + b + | 1406 | icrp = (volatile unsigned char *) (MCF_IPSBAR + b + |
1391 | MCFINTC_ICR0); | 1407 | MCFINTC_ICR0); |
1392 | for (i = 23; (i < 36); i++) | 1408 | for (i = 23, ilip = 0x28; (i < 36); i++) |
1393 | icrp[i] = 0x23; | 1409 | icrp[i] = ilip--; |
1394 | 1410 | ||
1395 | imrp = (volatile unsigned long *) (MCF_IPSBAR + b + | 1411 | imrp = (volatile unsigned long *) (MCF_IPSBAR + b + |
1396 | MCFINTC_IMRH); | 1412 | MCFINTC_IMRH); |
@@ -1618,6 +1634,159 @@ static void __inline__ fec_uncache(unsigned long addr) | |||
1618 | 1634 | ||
1619 | /* ------------------------------------------------------------------------- */ | 1635 | /* ------------------------------------------------------------------------- */ |
1620 | 1636 | ||
1637 | #elif defined(CONFIG_M532x) | ||
1638 | /* | ||
1639 | * Code specific for M532x | ||
1640 | */ | ||
1641 | static void __inline__ fec_request_intrs(struct net_device *dev) | ||
1642 | { | ||
1643 | struct fec_enet_private *fep; | ||
1644 | int b; | ||
1645 | static const struct idesc { | ||
1646 | char *name; | ||
1647 | unsigned short irq; | ||
1648 | } *idp, id[] = { | ||
1649 | { "fec(TXF)", 36 }, | ||
1650 | { "fec(TXB)", 37 }, | ||
1651 | { "fec(TXFIFO)", 38 }, | ||
1652 | { "fec(TXCR)", 39 }, | ||
1653 | { "fec(RXF)", 40 }, | ||
1654 | { "fec(RXB)", 41 }, | ||
1655 | { "fec(MII)", 42 }, | ||
1656 | { "fec(LC)", 43 }, | ||
1657 | { "fec(HBERR)", 44 }, | ||
1658 | { "fec(GRA)", 45 }, | ||
1659 | { "fec(EBERR)", 46 }, | ||
1660 | { "fec(BABT)", 47 }, | ||
1661 | { "fec(BABR)", 48 }, | ||
1662 | { NULL }, | ||
1663 | }; | ||
1664 | |||
1665 | fep = netdev_priv(dev); | ||
1666 | b = (fep->index) ? 128 : 64; | ||
1667 | |||
1668 | /* Setup interrupt handlers. */ | ||
1669 | for (idp = id; idp->name; idp++) { | ||
1670 | if (request_irq(b+idp->irq,fec_enet_interrupt,0,idp->name,dev)!=0) | ||
1671 | printk("FEC: Could not allocate %s IRQ(%d)!\n", | ||
1672 | idp->name, b+idp->irq); | ||
1673 | } | ||
1674 | |||
1675 | /* Unmask interrupts */ | ||
1676 | MCF_INTC0_ICR36 = 0x2; | ||
1677 | MCF_INTC0_ICR37 = 0x2; | ||
1678 | MCF_INTC0_ICR38 = 0x2; | ||
1679 | MCF_INTC0_ICR39 = 0x2; | ||
1680 | MCF_INTC0_ICR40 = 0x2; | ||
1681 | MCF_INTC0_ICR41 = 0x2; | ||
1682 | MCF_INTC0_ICR42 = 0x2; | ||
1683 | MCF_INTC0_ICR43 = 0x2; | ||
1684 | MCF_INTC0_ICR44 = 0x2; | ||
1685 | MCF_INTC0_ICR45 = 0x2; | ||
1686 | MCF_INTC0_ICR46 = 0x2; | ||
1687 | MCF_INTC0_ICR47 = 0x2; | ||
1688 | MCF_INTC0_ICR48 = 0x2; | ||
1689 | |||
1690 | MCF_INTC0_IMRH &= ~( | ||
1691 | MCF_INTC_IMRH_INT_MASK36 | | ||
1692 | MCF_INTC_IMRH_INT_MASK37 | | ||
1693 | MCF_INTC_IMRH_INT_MASK38 | | ||
1694 | MCF_INTC_IMRH_INT_MASK39 | | ||
1695 | MCF_INTC_IMRH_INT_MASK40 | | ||
1696 | MCF_INTC_IMRH_INT_MASK41 | | ||
1697 | MCF_INTC_IMRH_INT_MASK42 | | ||
1698 | MCF_INTC_IMRH_INT_MASK43 | | ||
1699 | MCF_INTC_IMRH_INT_MASK44 | | ||
1700 | MCF_INTC_IMRH_INT_MASK45 | | ||
1701 | MCF_INTC_IMRH_INT_MASK46 | | ||
1702 | MCF_INTC_IMRH_INT_MASK47 | | ||
1703 | MCF_INTC_IMRH_INT_MASK48 ); | ||
1704 | |||
1705 | /* Set up gpio outputs for MII lines */ | ||
1706 | MCF_GPIO_PAR_FECI2C |= (0 | | ||
1707 | MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC | | ||
1708 | MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO); | ||
1709 | MCF_GPIO_PAR_FEC = (0 | | ||
1710 | MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC | | ||
1711 | MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC); | ||
1712 | } | ||
1713 | |||
1714 | static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) | ||
1715 | { | ||
1716 | volatile fec_t *fecp; | ||
1717 | |||
1718 | fecp = fep->hwp; | ||
1719 | fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04; | ||
1720 | fecp->fec_x_cntrl = 0x00; | ||
1721 | |||
1722 | /* | ||
1723 | * Set MII speed to 2.5 MHz | ||
1724 | */ | ||
1725 | fep->phy_speed = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2; | ||
1726 | fecp->fec_mii_speed = fep->phy_speed; | ||
1727 | |||
1728 | fec_restart(dev, 0); | ||
1729 | } | ||
1730 | |||
1731 | static void __inline__ fec_get_mac(struct net_device *dev) | ||
1732 | { | ||
1733 | struct fec_enet_private *fep = netdev_priv(dev); | ||
1734 | volatile fec_t *fecp; | ||
1735 | unsigned char *iap, tmpaddr[ETH_ALEN]; | ||
1736 | |||
1737 | fecp = fep->hwp; | ||
1738 | |||
1739 | if (FEC_FLASHMAC) { | ||
1740 | /* | ||
1741 | * Get MAC address from FLASH. | ||
1742 | * If it is all 1's or 0's, use the default. | ||
1743 | */ | ||
1744 | iap = FEC_FLASHMAC; | ||
1745 | if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && | ||
1746 | (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) | ||
1747 | iap = fec_mac_default; | ||
1748 | if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) && | ||
1749 | (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff)) | ||
1750 | iap = fec_mac_default; | ||
1751 | } else { | ||
1752 | *((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low; | ||
1753 | *((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16); | ||
1754 | iap = &tmpaddr[0]; | ||
1755 | } | ||
1756 | |||
1757 | memcpy(dev->dev_addr, iap, ETH_ALEN); | ||
1758 | |||
1759 | /* Adjust MAC if using default MAC address */ | ||
1760 | if (iap == fec_mac_default) | ||
1761 | dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index; | ||
1762 | } | ||
1763 | |||
1764 | static void __inline__ fec_enable_phy_intr(void) | ||
1765 | { | ||
1766 | } | ||
1767 | |||
1768 | static void __inline__ fec_disable_phy_intr(void) | ||
1769 | { | ||
1770 | } | ||
1771 | |||
1772 | static void __inline__ fec_phy_ack_intr(void) | ||
1773 | { | ||
1774 | } | ||
1775 | |||
1776 | static void __inline__ fec_localhw_setup(void) | ||
1777 | { | ||
1778 | } | ||
1779 | |||
1780 | /* | ||
1781 | * Do not need to make region uncached on 532x. | ||
1782 | */ | ||
1783 | static void __inline__ fec_uncache(unsigned long addr) | ||
1784 | { | ||
1785 | } | ||
1786 | |||
1787 | /* ------------------------------------------------------------------------- */ | ||
1788 | |||
1789 | |||
1621 | #else | 1790 | #else |
1622 | 1791 | ||
1623 | /* | 1792 | /* |
@@ -1985,9 +2154,12 @@ fec_enet_open(struct net_device *dev) | |||
1985 | mii_do_cmd(dev, fep->phy->config); | 2154 | mii_do_cmd(dev, fep->phy->config); |
1986 | mii_do_cmd(dev, phy_cmd_config); /* display configuration */ | 2155 | mii_do_cmd(dev, phy_cmd_config); /* display configuration */ |
1987 | 2156 | ||
1988 | /* FIXME: use netif_carrier_{on,off} ; this polls | 2157 | /* Poll until the PHY tells us its configuration |
1989 | * until link is up which is wrong... could be | 2158 | * (not link state). |
1990 | * 30 seconds or more we are trapped in here. -jgarzik | 2159 | * Request is initiated by mii_do_cmd above, but answer |
2160 | * comes by interrupt. | ||
2161 | * This should take about 25 usec per register at 2.5 MHz, | ||
2162 | * and we read approximately 5 registers. | ||
1991 | */ | 2163 | */ |
1992 | while(!fep->sequence_done) | 2164 | while(!fep->sequence_done) |
1993 | schedule(); | 2165 | schedule(); |
@@ -2253,15 +2425,11 @@ int __init fec_enet_init(struct net_device *dev) | |||
2253 | */ | 2425 | */ |
2254 | fec_request_intrs(dev); | 2426 | fec_request_intrs(dev); |
2255 | 2427 | ||
2256 | /* Clear and enable interrupts */ | ||
2257 | fecp->fec_ievent = 0xffc00000; | ||
2258 | fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | | ||
2259 | FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); | ||
2260 | fecp->fec_hash_table_high = 0; | 2428 | fecp->fec_hash_table_high = 0; |
2261 | fecp->fec_hash_table_low = 0; | 2429 | fecp->fec_hash_table_low = 0; |
2262 | fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; | 2430 | fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; |
2263 | fecp->fec_ecntrl = 2; | 2431 | fecp->fec_ecntrl = 2; |
2264 | fecp->fec_r_des_active = 0x01000000; | 2432 | fecp->fec_r_des_active = 0; |
2265 | 2433 | ||
2266 | dev->base_addr = (unsigned long)fecp; | 2434 | dev->base_addr = (unsigned long)fecp; |
2267 | 2435 | ||
@@ -2281,6 +2449,11 @@ int __init fec_enet_init(struct net_device *dev) | |||
2281 | /* setup MII interface */ | 2449 | /* setup MII interface */ |
2282 | fec_set_mii(dev, fep); | 2450 | fec_set_mii(dev, fep); |
2283 | 2451 | ||
2452 | /* Clear and enable interrupts */ | ||
2453 | fecp->fec_ievent = 0xffc00000; | ||
2454 | fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | | ||
2455 | FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); | ||
2456 | |||
2284 | /* Queue up command to detect the PHY and initialize the | 2457 | /* Queue up command to detect the PHY and initialize the |
2285 | * remainder of the interface. | 2458 | * remainder of the interface. |
2286 | */ | 2459 | */ |
@@ -2312,11 +2485,6 @@ fec_restart(struct net_device *dev, int duplex) | |||
2312 | fecp->fec_ecntrl = 1; | 2485 | fecp->fec_ecntrl = 1; |
2313 | udelay(10); | 2486 | udelay(10); |
2314 | 2487 | ||
2315 | /* Enable interrupts we wish to service. | ||
2316 | */ | ||
2317 | fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | | ||
2318 | FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); | ||
2319 | |||
2320 | /* Clear any outstanding interrupt. | 2488 | /* Clear any outstanding interrupt. |
2321 | */ | 2489 | */ |
2322 | fecp->fec_ievent = 0xffc00000; | 2490 | fecp->fec_ievent = 0xffc00000; |
@@ -2408,7 +2576,12 @@ fec_restart(struct net_device *dev, int duplex) | |||
2408 | /* And last, enable the transmit and receive processing. | 2576 | /* And last, enable the transmit and receive processing. |
2409 | */ | 2577 | */ |
2410 | fecp->fec_ecntrl = 2; | 2578 | fecp->fec_ecntrl = 2; |
2411 | fecp->fec_r_des_active = 0x01000000; | 2579 | fecp->fec_r_des_active = 0; |
2580 | |||
2581 | /* Enable interrupts we wish to service. | ||
2582 | */ | ||
2583 | fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | | ||
2584 | FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); | ||
2412 | } | 2585 | } |
2413 | 2586 | ||
2414 | static void | 2587 | static void |
@@ -2420,9 +2593,16 @@ fec_stop(struct net_device *dev) | |||
2420 | fep = netdev_priv(dev); | 2593 | fep = netdev_priv(dev); |
2421 | fecp = fep->hwp; | 2594 | fecp = fep->hwp; |
2422 | 2595 | ||
2423 | fecp->fec_x_cntrl = 0x01; /* Graceful transmit stop */ | 2596 | /* |
2424 | 2597 | ** We cannot expect a graceful transmit stop without link !!! | |
2425 | while(!(fecp->fec_ievent & FEC_ENET_GRA)); | 2598 | */ |
2599 | if (fep->link) | ||
2600 | { | ||
2601 | fecp->fec_x_cntrl = 0x01; /* Graceful transmit stop */ | ||
2602 | udelay(10); | ||
2603 | if (!(fecp->fec_ievent & FEC_ENET_GRA)) | ||
2604 | printk("fec_stop : Graceful transmit stop did not complete !\n"); | ||
2605 | } | ||
2426 | 2606 | ||
2427 | /* Whack a reset. We should wait for this. | 2607 | /* Whack a reset. We should wait for this. |
2428 | */ | 2608 | */ |