diff options
Diffstat (limited to 'drivers/net/bfin_mac.c')
-rw-r--r-- | drivers/net/bfin_mac.c | 559 |
1 files changed, 515 insertions, 44 deletions
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 587f93cf03f6..39a54bad397f 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/dma.h> | 33 | #include <asm/dma.h> |
34 | #include <linux/dma-mapping.h> | 34 | #include <linux/dma-mapping.h> |
35 | 35 | ||
36 | #include <asm/div64.h> | ||
36 | #include <asm/dpmc.h> | 37 | #include <asm/dpmc.h> |
37 | #include <asm/blackfin.h> | 38 | #include <asm/blackfin.h> |
38 | #include <asm/cacheflush.h> | 39 | #include <asm/cacheflush.h> |
@@ -80,9 +81,6 @@ static u16 pin_req[] = P_RMII0; | |||
80 | static u16 pin_req[] = P_MII0; | 81 | static u16 pin_req[] = P_MII0; |
81 | #endif | 82 | #endif |
82 | 83 | ||
83 | static void bfin_mac_disable(void); | ||
84 | static void bfin_mac_enable(void); | ||
85 | |||
86 | static void desc_list_free(void) | 84 | static void desc_list_free(void) |
87 | { | 85 | { |
88 | struct net_dma_desc_rx *r; | 86 | struct net_dma_desc_rx *r; |
@@ -202,6 +200,11 @@ static int desc_list_init(void) | |||
202 | goto init_error; | 200 | goto init_error; |
203 | } | 201 | } |
204 | skb_reserve(new_skb, NET_IP_ALIGN); | 202 | skb_reserve(new_skb, NET_IP_ALIGN); |
203 | /* Invidate the data cache of skb->data range when it is write back | ||
204 | * cache. It will prevent overwritting the new data from DMA | ||
205 | */ | ||
206 | blackfin_dcache_invalidate_range((unsigned long)new_skb->head, | ||
207 | (unsigned long)new_skb->end); | ||
205 | r->skb = new_skb; | 208 | r->skb = new_skb; |
206 | 209 | ||
207 | /* | 210 | /* |
@@ -254,7 +257,7 @@ init_error: | |||
254 | * MII operations | 257 | * MII operations |
255 | */ | 258 | */ |
256 | /* Wait until the previous MDC/MDIO transaction has completed */ | 259 | /* Wait until the previous MDC/MDIO transaction has completed */ |
257 | static void bfin_mdio_poll(void) | 260 | static int bfin_mdio_poll(void) |
258 | { | 261 | { |
259 | int timeout_cnt = MAX_TIMEOUT_CNT; | 262 | int timeout_cnt = MAX_TIMEOUT_CNT; |
260 | 263 | ||
@@ -264,22 +267,30 @@ static void bfin_mdio_poll(void) | |||
264 | if (timeout_cnt-- < 0) { | 267 | if (timeout_cnt-- < 0) { |
265 | printk(KERN_ERR DRV_NAME | 268 | printk(KERN_ERR DRV_NAME |
266 | ": wait MDC/MDIO transaction to complete timeout\n"); | 269 | ": wait MDC/MDIO transaction to complete timeout\n"); |
267 | break; | 270 | return -ETIMEDOUT; |
268 | } | 271 | } |
269 | } | 272 | } |
273 | |||
274 | return 0; | ||
270 | } | 275 | } |
271 | 276 | ||
272 | /* Read an off-chip register in a PHY through the MDC/MDIO port */ | 277 | /* Read an off-chip register in a PHY through the MDC/MDIO port */ |
273 | static int bfin_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum) | 278 | static int bfin_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum) |
274 | { | 279 | { |
275 | bfin_mdio_poll(); | 280 | int ret; |
281 | |||
282 | ret = bfin_mdio_poll(); | ||
283 | if (ret) | ||
284 | return ret; | ||
276 | 285 | ||
277 | /* read mode */ | 286 | /* read mode */ |
278 | bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) | | 287 | bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) | |
279 | SET_REGAD((u16) regnum) | | 288 | SET_REGAD((u16) regnum) | |
280 | STABUSY); | 289 | STABUSY); |
281 | 290 | ||
282 | bfin_mdio_poll(); | 291 | ret = bfin_mdio_poll(); |
292 | if (ret) | ||
293 | return ret; | ||
283 | 294 | ||
284 | return (int) bfin_read_EMAC_STADAT(); | 295 | return (int) bfin_read_EMAC_STADAT(); |
285 | } | 296 | } |
@@ -288,7 +299,11 @@ static int bfin_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum) | |||
288 | static int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, | 299 | static int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, |
289 | u16 value) | 300 | u16 value) |
290 | { | 301 | { |
291 | bfin_mdio_poll(); | 302 | int ret; |
303 | |||
304 | ret = bfin_mdio_poll(); | ||
305 | if (ret) | ||
306 | return ret; | ||
292 | 307 | ||
293 | bfin_write_EMAC_STADAT((u32) value); | 308 | bfin_write_EMAC_STADAT((u32) value); |
294 | 309 | ||
@@ -298,9 +313,7 @@ static int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, | |||
298 | STAOP | | 313 | STAOP | |
299 | STABUSY); | 314 | STABUSY); |
300 | 315 | ||
301 | bfin_mdio_poll(); | 316 | return bfin_mdio_poll(); |
302 | |||
303 | return 0; | ||
304 | } | 317 | } |
305 | 318 | ||
306 | static int bfin_mdiobus_reset(struct mii_bus *bus) | 319 | static int bfin_mdiobus_reset(struct mii_bus *bus) |
@@ -458,6 +471,14 @@ static int mii_probe(struct net_device *dev) | |||
458 | * Ethtool support | 471 | * Ethtool support |
459 | */ | 472 | */ |
460 | 473 | ||
474 | /* | ||
475 | * interrupt routine for magic packet wakeup | ||
476 | */ | ||
477 | static irqreturn_t bfin_mac_wake_interrupt(int irq, void *dev_id) | ||
478 | { | ||
479 | return IRQ_HANDLED; | ||
480 | } | ||
481 | |||
461 | static int | 482 | static int |
462 | bfin_mac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) | 483 | bfin_mac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) |
463 | { | 484 | { |
@@ -492,11 +513,57 @@ static void bfin_mac_ethtool_getdrvinfo(struct net_device *dev, | |||
492 | strcpy(info->bus_info, dev_name(&dev->dev)); | 513 | strcpy(info->bus_info, dev_name(&dev->dev)); |
493 | } | 514 | } |
494 | 515 | ||
516 | static void bfin_mac_ethtool_getwol(struct net_device *dev, | ||
517 | struct ethtool_wolinfo *wolinfo) | ||
518 | { | ||
519 | struct bfin_mac_local *lp = netdev_priv(dev); | ||
520 | |||
521 | wolinfo->supported = WAKE_MAGIC; | ||
522 | wolinfo->wolopts = lp->wol; | ||
523 | } | ||
524 | |||
525 | static int bfin_mac_ethtool_setwol(struct net_device *dev, | ||
526 | struct ethtool_wolinfo *wolinfo) | ||
527 | { | ||
528 | struct bfin_mac_local *lp = netdev_priv(dev); | ||
529 | int rc; | ||
530 | |||
531 | if (wolinfo->wolopts & (WAKE_MAGICSECURE | | ||
532 | WAKE_UCAST | | ||
533 | WAKE_MCAST | | ||
534 | WAKE_BCAST | | ||
535 | WAKE_ARP)) | ||
536 | return -EOPNOTSUPP; | ||
537 | |||
538 | lp->wol = wolinfo->wolopts; | ||
539 | |||
540 | if (lp->wol && !lp->irq_wake_requested) { | ||
541 | /* register wake irq handler */ | ||
542 | rc = request_irq(IRQ_MAC_WAKEDET, bfin_mac_wake_interrupt, | ||
543 | IRQF_DISABLED, "EMAC_WAKE", dev); | ||
544 | if (rc) | ||
545 | return rc; | ||
546 | lp->irq_wake_requested = true; | ||
547 | } | ||
548 | |||
549 | if (!lp->wol && lp->irq_wake_requested) { | ||
550 | free_irq(IRQ_MAC_WAKEDET, dev); | ||
551 | lp->irq_wake_requested = false; | ||
552 | } | ||
553 | |||
554 | /* Make sure the PHY driver doesn't suspend */ | ||
555 | device_init_wakeup(&dev->dev, lp->wol); | ||
556 | |||
557 | return 0; | ||
558 | } | ||
559 | |||
495 | static const struct ethtool_ops bfin_mac_ethtool_ops = { | 560 | static const struct ethtool_ops bfin_mac_ethtool_ops = { |
496 | .get_settings = bfin_mac_ethtool_getsettings, | 561 | .get_settings = bfin_mac_ethtool_getsettings, |
497 | .set_settings = bfin_mac_ethtool_setsettings, | 562 | .set_settings = bfin_mac_ethtool_setsettings, |
498 | .get_link = ethtool_op_get_link, | 563 | .get_link = ethtool_op_get_link, |
499 | .get_drvinfo = bfin_mac_ethtool_getdrvinfo, | 564 | .get_drvinfo = bfin_mac_ethtool_getdrvinfo, |
565 | .get_wol = bfin_mac_ethtool_getwol, | ||
566 | .set_wol = bfin_mac_ethtool_setwol, | ||
500 | }; | 567 | }; |
501 | 568 | ||
502 | /**************************************************************************/ | 569 | /**************************************************************************/ |
@@ -509,10 +576,11 @@ void setup_system_regs(struct net_device *dev) | |||
509 | * Configure checksum support and rcve frame word alignment | 576 | * Configure checksum support and rcve frame word alignment |
510 | */ | 577 | */ |
511 | sysctl = bfin_read_EMAC_SYSCTL(); | 578 | sysctl = bfin_read_EMAC_SYSCTL(); |
579 | sysctl |= RXDWA; | ||
512 | #if defined(BFIN_MAC_CSUM_OFFLOAD) | 580 | #if defined(BFIN_MAC_CSUM_OFFLOAD) |
513 | sysctl |= RXDWA | RXCKS; | 581 | sysctl |= RXCKS; |
514 | #else | 582 | #else |
515 | sysctl |= RXDWA; | 583 | sysctl &= ~RXCKS; |
516 | #endif | 584 | #endif |
517 | bfin_write_EMAC_SYSCTL(sysctl); | 585 | bfin_write_EMAC_SYSCTL(sysctl); |
518 | 586 | ||
@@ -551,6 +619,309 @@ static int bfin_mac_set_mac_address(struct net_device *dev, void *p) | |||
551 | return 0; | 619 | return 0; |
552 | } | 620 | } |
553 | 621 | ||
622 | #ifdef CONFIG_BFIN_MAC_USE_HWSTAMP | ||
623 | #define bfin_mac_hwtstamp_is_none(cfg) ((cfg) == HWTSTAMP_FILTER_NONE) | ||
624 | |||
625 | static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, | ||
626 | struct ifreq *ifr, int cmd) | ||
627 | { | ||
628 | struct hwtstamp_config config; | ||
629 | struct bfin_mac_local *lp = netdev_priv(netdev); | ||
630 | u16 ptpctl; | ||
631 | u32 ptpfv1, ptpfv2, ptpfv3, ptpfoff; | ||
632 | |||
633 | if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) | ||
634 | return -EFAULT; | ||
635 | |||
636 | pr_debug("%s config flag:0x%x, tx_type:0x%x, rx_filter:0x%x\n", | ||
637 | __func__, config.flags, config.tx_type, config.rx_filter); | ||
638 | |||
639 | /* reserved for future extensions */ | ||
640 | if (config.flags) | ||
641 | return -EINVAL; | ||
642 | |||
643 | if ((config.tx_type != HWTSTAMP_TX_OFF) && | ||
644 | (config.tx_type != HWTSTAMP_TX_ON)) | ||
645 | return -ERANGE; | ||
646 | |||
647 | ptpctl = bfin_read_EMAC_PTP_CTL(); | ||
648 | |||
649 | switch (config.rx_filter) { | ||
650 | case HWTSTAMP_FILTER_NONE: | ||
651 | /* | ||
652 | * Dont allow any timestamping | ||
653 | */ | ||
654 | ptpfv3 = 0xFFFFFFFF; | ||
655 | bfin_write_EMAC_PTP_FV3(ptpfv3); | ||
656 | break; | ||
657 | case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: | ||
658 | case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: | ||
659 | case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: | ||
660 | /* | ||
661 | * Clear the five comparison mask bits (bits[12:8]) in EMAC_PTP_CTL) | ||
662 | * to enable all the field matches. | ||
663 | */ | ||
664 | ptpctl &= ~0x1F00; | ||
665 | bfin_write_EMAC_PTP_CTL(ptpctl); | ||
666 | /* | ||
667 | * Keep the default values of the EMAC_PTP_FOFF register. | ||
668 | */ | ||
669 | ptpfoff = 0x4A24170C; | ||
670 | bfin_write_EMAC_PTP_FOFF(ptpfoff); | ||
671 | /* | ||
672 | * Keep the default values of the EMAC_PTP_FV1 and EMAC_PTP_FV2 | ||
673 | * registers. | ||
674 | */ | ||
675 | ptpfv1 = 0x11040800; | ||
676 | bfin_write_EMAC_PTP_FV1(ptpfv1); | ||
677 | ptpfv2 = 0x0140013F; | ||
678 | bfin_write_EMAC_PTP_FV2(ptpfv2); | ||
679 | /* | ||
680 | * The default value (0xFFFC) allows the timestamping of both | ||
681 | * received Sync messages and Delay_Req messages. | ||
682 | */ | ||
683 | ptpfv3 = 0xFFFFFFFC; | ||
684 | bfin_write_EMAC_PTP_FV3(ptpfv3); | ||
685 | |||
686 | config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; | ||
687 | break; | ||
688 | case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: | ||
689 | case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: | ||
690 | case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: | ||
691 | /* Clear all five comparison mask bits (bits[12:8]) in the | ||
692 | * EMAC_PTP_CTL register to enable all the field matches. | ||
693 | */ | ||
694 | ptpctl &= ~0x1F00; | ||
695 | bfin_write_EMAC_PTP_CTL(ptpctl); | ||
696 | /* | ||
697 | * Keep the default values of the EMAC_PTP_FOFF register, except set | ||
698 | * the PTPCOF field to 0x2A. | ||
699 | */ | ||
700 | ptpfoff = 0x2A24170C; | ||
701 | bfin_write_EMAC_PTP_FOFF(ptpfoff); | ||
702 | /* | ||
703 | * Keep the default values of the EMAC_PTP_FV1 and EMAC_PTP_FV2 | ||
704 | * registers. | ||
705 | */ | ||
706 | ptpfv1 = 0x11040800; | ||
707 | bfin_write_EMAC_PTP_FV1(ptpfv1); | ||
708 | ptpfv2 = 0x0140013F; | ||
709 | bfin_write_EMAC_PTP_FV2(ptpfv2); | ||
710 | /* | ||
711 | * To allow the timestamping of Pdelay_Req and Pdelay_Resp, set | ||
712 | * the value to 0xFFF0. | ||
713 | */ | ||
714 | ptpfv3 = 0xFFFFFFF0; | ||
715 | bfin_write_EMAC_PTP_FV3(ptpfv3); | ||
716 | |||
717 | config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; | ||
718 | break; | ||
719 | case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: | ||
720 | case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: | ||
721 | case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: | ||
722 | /* | ||
723 | * Clear bits 8 and 12 of the EMAC_PTP_CTL register to enable only the | ||
724 | * EFTM and PTPCM field comparison. | ||
725 | */ | ||
726 | ptpctl &= ~0x1100; | ||
727 | bfin_write_EMAC_PTP_CTL(ptpctl); | ||
728 | /* | ||
729 | * Keep the default values of all the fields of the EMAC_PTP_FOFF | ||
730 | * register, except set the PTPCOF field to 0x0E. | ||
731 | */ | ||
732 | ptpfoff = 0x0E24170C; | ||
733 | bfin_write_EMAC_PTP_FOFF(ptpfoff); | ||
734 | /* | ||
735 | * Program bits [15:0] of the EMAC_PTP_FV1 register to 0x88F7, which | ||
736 | * corresponds to PTP messages on the MAC layer. | ||
737 | */ | ||
738 | ptpfv1 = 0x110488F7; | ||
739 | bfin_write_EMAC_PTP_FV1(ptpfv1); | ||
740 | ptpfv2 = 0x0140013F; | ||
741 | bfin_write_EMAC_PTP_FV2(ptpfv2); | ||
742 | /* | ||
743 | * To allow the timestamping of Pdelay_Req and Pdelay_Resp | ||
744 | * messages, set the value to 0xFFF0. | ||
745 | */ | ||
746 | ptpfv3 = 0xFFFFFFF0; | ||
747 | bfin_write_EMAC_PTP_FV3(ptpfv3); | ||
748 | |||
749 | config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; | ||
750 | break; | ||
751 | default: | ||
752 | return -ERANGE; | ||
753 | } | ||
754 | |||
755 | if (config.tx_type == HWTSTAMP_TX_OFF && | ||
756 | bfin_mac_hwtstamp_is_none(config.rx_filter)) { | ||
757 | ptpctl &= ~PTP_EN; | ||
758 | bfin_write_EMAC_PTP_CTL(ptpctl); | ||
759 | |||
760 | SSYNC(); | ||
761 | } else { | ||
762 | ptpctl |= PTP_EN; | ||
763 | bfin_write_EMAC_PTP_CTL(ptpctl); | ||
764 | |||
765 | /* | ||
766 | * clear any existing timestamp | ||
767 | */ | ||
768 | bfin_read_EMAC_PTP_RXSNAPLO(); | ||
769 | bfin_read_EMAC_PTP_RXSNAPHI(); | ||
770 | |||
771 | bfin_read_EMAC_PTP_TXSNAPLO(); | ||
772 | bfin_read_EMAC_PTP_TXSNAPHI(); | ||
773 | |||
774 | /* | ||
775 | * Set registers so that rollover occurs soon to test this. | ||
776 | */ | ||
777 | bfin_write_EMAC_PTP_TIMELO(0x00000000); | ||
778 | bfin_write_EMAC_PTP_TIMEHI(0xFF800000); | ||
779 | |||
780 | SSYNC(); | ||
781 | |||
782 | lp->compare.last_update = 0; | ||
783 | timecounter_init(&lp->clock, | ||
784 | &lp->cycles, | ||
785 | ktime_to_ns(ktime_get_real())); | ||
786 | timecompare_update(&lp->compare, 0); | ||
787 | } | ||
788 | |||
789 | lp->stamp_cfg = config; | ||
790 | return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? | ||
791 | -EFAULT : 0; | ||
792 | } | ||
793 | |||
794 | static void bfin_dump_hwtamp(char *s, ktime_t *hw, ktime_t *ts, struct timecompare *cmp) | ||
795 | { | ||
796 | ktime_t sys = ktime_get_real(); | ||
797 | |||
798 | pr_debug("%s %s hardware:%d,%d transform system:%d,%d system:%d,%d, cmp:%lld, %lld\n", | ||
799 | __func__, s, hw->tv.sec, hw->tv.nsec, ts->tv.sec, ts->tv.nsec, sys.tv.sec, | ||
800 | sys.tv.nsec, cmp->offset, cmp->skew); | ||
801 | } | ||
802 | |||
803 | static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) | ||
804 | { | ||
805 | struct bfin_mac_local *lp = netdev_priv(netdev); | ||
806 | union skb_shared_tx *shtx = skb_tx(skb); | ||
807 | |||
808 | if (shtx->hardware) { | ||
809 | int timeout_cnt = MAX_TIMEOUT_CNT; | ||
810 | |||
811 | /* When doing time stamping, keep the connection to the socket | ||
812 | * a while longer | ||
813 | */ | ||
814 | shtx->in_progress = 1; | ||
815 | |||
816 | /* | ||
817 | * The timestamping is done at the EMAC module's MII/RMII interface | ||
818 | * when the module sees the Start of Frame of an event message packet. This | ||
819 | * interface is the closest possible place to the physical Ethernet transmission | ||
820 | * medium, providing the best timing accuracy. | ||
821 | */ | ||
822 | while ((!(bfin_read_EMAC_PTP_ISTAT() & TXTL)) && (--timeout_cnt)) | ||
823 | udelay(1); | ||
824 | if (timeout_cnt == 0) | ||
825 | printk(KERN_ERR DRV_NAME | ||
826 | ": fails to timestamp the TX packet\n"); | ||
827 | else { | ||
828 | struct skb_shared_hwtstamps shhwtstamps; | ||
829 | u64 ns; | ||
830 | u64 regval; | ||
831 | |||
832 | regval = bfin_read_EMAC_PTP_TXSNAPLO(); | ||
833 | regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32; | ||
834 | memset(&shhwtstamps, 0, sizeof(shhwtstamps)); | ||
835 | ns = timecounter_cyc2time(&lp->clock, | ||
836 | regval); | ||
837 | timecompare_update(&lp->compare, ns); | ||
838 | shhwtstamps.hwtstamp = ns_to_ktime(ns); | ||
839 | shhwtstamps.syststamp = | ||
840 | timecompare_transform(&lp->compare, ns); | ||
841 | skb_tstamp_tx(skb, &shhwtstamps); | ||
842 | |||
843 | bfin_dump_hwtamp("TX", &shhwtstamps.hwtstamp, &shhwtstamps.syststamp, &lp->compare); | ||
844 | } | ||
845 | } | ||
846 | } | ||
847 | |||
848 | static void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) | ||
849 | { | ||
850 | struct bfin_mac_local *lp = netdev_priv(netdev); | ||
851 | u32 valid; | ||
852 | u64 regval, ns; | ||
853 | struct skb_shared_hwtstamps *shhwtstamps; | ||
854 | |||
855 | if (bfin_mac_hwtstamp_is_none(lp->stamp_cfg.rx_filter)) | ||
856 | return; | ||
857 | |||
858 | valid = bfin_read_EMAC_PTP_ISTAT() & RXEL; | ||
859 | if (!valid) | ||
860 | return; | ||
861 | |||
862 | shhwtstamps = skb_hwtstamps(skb); | ||
863 | |||
864 | regval = bfin_read_EMAC_PTP_RXSNAPLO(); | ||
865 | regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32; | ||
866 | ns = timecounter_cyc2time(&lp->clock, regval); | ||
867 | timecompare_update(&lp->compare, ns); | ||
868 | memset(shhwtstamps, 0, sizeof(*shhwtstamps)); | ||
869 | shhwtstamps->hwtstamp = ns_to_ktime(ns); | ||
870 | shhwtstamps->syststamp = timecompare_transform(&lp->compare, ns); | ||
871 | |||
872 | bfin_dump_hwtamp("RX", &shhwtstamps->hwtstamp, &shhwtstamps->syststamp, &lp->compare); | ||
873 | } | ||
874 | |||
875 | /* | ||
876 | * bfin_read_clock - read raw cycle counter (to be used by time counter) | ||
877 | */ | ||
878 | static cycle_t bfin_read_clock(const struct cyclecounter *tc) | ||
879 | { | ||
880 | u64 stamp; | ||
881 | |||
882 | stamp = bfin_read_EMAC_PTP_TIMELO(); | ||
883 | stamp |= (u64)bfin_read_EMAC_PTP_TIMEHI() << 32ULL; | ||
884 | |||
885 | return stamp; | ||
886 | } | ||
887 | |||
888 | #define PTP_CLK 25000000 | ||
889 | |||
890 | static void bfin_mac_hwtstamp_init(struct net_device *netdev) | ||
891 | { | ||
892 | struct bfin_mac_local *lp = netdev_priv(netdev); | ||
893 | u64 append; | ||
894 | |||
895 | /* Initialize hardware timer */ | ||
896 | append = PTP_CLK * (1ULL << 32); | ||
897 | do_div(append, get_sclk()); | ||
898 | bfin_write_EMAC_PTP_ADDEND((u32)append); | ||
899 | |||
900 | memset(&lp->cycles, 0, sizeof(lp->cycles)); | ||
901 | lp->cycles.read = bfin_read_clock; | ||
902 | lp->cycles.mask = CLOCKSOURCE_MASK(64); | ||
903 | lp->cycles.mult = 1000000000 / PTP_CLK; | ||
904 | lp->cycles.shift = 0; | ||
905 | |||
906 | /* Synchronize our NIC clock against system wall clock */ | ||
907 | memset(&lp->compare, 0, sizeof(lp->compare)); | ||
908 | lp->compare.source = &lp->clock; | ||
909 | lp->compare.target = ktime_get_real; | ||
910 | lp->compare.num_samples = 10; | ||
911 | |||
912 | /* Initialize hwstamp config */ | ||
913 | lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE; | ||
914 | lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF; | ||
915 | } | ||
916 | |||
917 | #else | ||
918 | # define bfin_mac_hwtstamp_is_none(cfg) 0 | ||
919 | # define bfin_mac_hwtstamp_init(dev) | ||
920 | # define bfin_mac_hwtstamp_ioctl(dev, ifr, cmd) (-EOPNOTSUPP) | ||
921 | # define bfin_rx_hwtstamp(dev, skb) | ||
922 | # define bfin_tx_hwtstamp(dev, skb) | ||
923 | #endif | ||
924 | |||
554 | static void adjust_tx_list(void) | 925 | static void adjust_tx_list(void) |
555 | { | 926 | { |
556 | int timeout_cnt = MAX_TIMEOUT_CNT; | 927 | int timeout_cnt = MAX_TIMEOUT_CNT; |
@@ -608,18 +979,32 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb, | |||
608 | { | 979 | { |
609 | u16 *data; | 980 | u16 *data; |
610 | u32 data_align = (unsigned long)(skb->data) & 0x3; | 981 | u32 data_align = (unsigned long)(skb->data) & 0x3; |
982 | union skb_shared_tx *shtx = skb_tx(skb); | ||
983 | |||
611 | current_tx_ptr->skb = skb; | 984 | current_tx_ptr->skb = skb; |
612 | 985 | ||
613 | if (data_align == 0x2) { | 986 | if (data_align == 0x2) { |
614 | /* move skb->data to current_tx_ptr payload */ | 987 | /* move skb->data to current_tx_ptr payload */ |
615 | data = (u16 *)(skb->data) - 1; | 988 | data = (u16 *)(skb->data) - 1; |
616 | *data = (u16)(skb->len); | 989 | *data = (u16)(skb->len); |
990 | /* | ||
991 | * When transmitting an Ethernet packet, the PTP_TSYNC module requires | ||
992 | * a DMA_Length_Word field associated with the packet. The lower 12 bits | ||
993 | * of this field are the length of the packet payload in bytes and the higher | ||
994 | * 4 bits are the timestamping enable field. | ||
995 | */ | ||
996 | if (shtx->hardware) | ||
997 | *data |= 0x1000; | ||
998 | |||
617 | current_tx_ptr->desc_a.start_addr = (u32)data; | 999 | current_tx_ptr->desc_a.start_addr = (u32)data; |
618 | /* this is important! */ | 1000 | /* this is important! */ |
619 | blackfin_dcache_flush_range((u32)data, | 1001 | blackfin_dcache_flush_range((u32)data, |
620 | (u32)((u8 *)data + skb->len + 4)); | 1002 | (u32)((u8 *)data + skb->len + 4)); |
621 | } else { | 1003 | } else { |
622 | *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); | 1004 | *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); |
1005 | /* enable timestamping for the sent packet */ | ||
1006 | if (shtx->hardware) | ||
1007 | *((u16 *)(current_tx_ptr->packet)) |= 0x1000; | ||
623 | memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, | 1008 | memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, |
624 | skb->len); | 1009 | skb->len); |
625 | current_tx_ptr->desc_a.start_addr = | 1010 | current_tx_ptr->desc_a.start_addr = |
@@ -653,20 +1038,42 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb, | |||
653 | 1038 | ||
654 | out: | 1039 | out: |
655 | adjust_tx_list(); | 1040 | adjust_tx_list(); |
1041 | |||
1042 | bfin_tx_hwtstamp(dev, skb); | ||
1043 | |||
656 | current_tx_ptr = current_tx_ptr->next; | 1044 | current_tx_ptr = current_tx_ptr->next; |
657 | dev->trans_start = jiffies; | ||
658 | dev->stats.tx_packets++; | 1045 | dev->stats.tx_packets++; |
659 | dev->stats.tx_bytes += (skb->len); | 1046 | dev->stats.tx_bytes += (skb->len); |
660 | return NETDEV_TX_OK; | 1047 | return NETDEV_TX_OK; |
661 | } | 1048 | } |
662 | 1049 | ||
1050 | #define IP_HEADER_OFF 0 | ||
1051 | #define RX_ERROR_MASK (RX_LONG | RX_ALIGN | RX_CRC | RX_LEN | \ | ||
1052 | RX_FRAG | RX_ADDR | RX_DMAO | RX_PHY | RX_LATE | RX_RANGE) | ||
1053 | |||
663 | static void bfin_mac_rx(struct net_device *dev) | 1054 | static void bfin_mac_rx(struct net_device *dev) |
664 | { | 1055 | { |
665 | struct sk_buff *skb, *new_skb; | 1056 | struct sk_buff *skb, *new_skb; |
666 | unsigned short len; | 1057 | unsigned short len; |
1058 | struct bfin_mac_local *lp __maybe_unused = netdev_priv(dev); | ||
1059 | #if defined(BFIN_MAC_CSUM_OFFLOAD) | ||
1060 | unsigned int i; | ||
1061 | unsigned char fcs[ETH_FCS_LEN + 1]; | ||
1062 | #endif | ||
1063 | |||
1064 | /* check if frame status word reports an error condition | ||
1065 | * we which case we simply drop the packet | ||
1066 | */ | ||
1067 | if (current_rx_ptr->status.status_word & RX_ERROR_MASK) { | ||
1068 | printk(KERN_NOTICE DRV_NAME | ||
1069 | ": rx: receive error - packet dropped\n"); | ||
1070 | dev->stats.rx_dropped++; | ||
1071 | goto out; | ||
1072 | } | ||
667 | 1073 | ||
668 | /* allocate a new skb for next time receive */ | 1074 | /* allocate a new skb for next time receive */ |
669 | skb = current_rx_ptr->skb; | 1075 | skb = current_rx_ptr->skb; |
1076 | |||
670 | new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN); | 1077 | new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN); |
671 | if (!new_skb) { | 1078 | if (!new_skb) { |
672 | printk(KERN_NOTICE DRV_NAME | 1079 | printk(KERN_NOTICE DRV_NAME |
@@ -676,34 +1083,59 @@ static void bfin_mac_rx(struct net_device *dev) | |||
676 | } | 1083 | } |
677 | /* reserve 2 bytes for RXDWA padding */ | 1084 | /* reserve 2 bytes for RXDWA padding */ |
678 | skb_reserve(new_skb, NET_IP_ALIGN); | 1085 | skb_reserve(new_skb, NET_IP_ALIGN); |
679 | current_rx_ptr->skb = new_skb; | ||
680 | current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2; | ||
681 | |||
682 | /* Invidate the data cache of skb->data range when it is write back | 1086 | /* Invidate the data cache of skb->data range when it is write back |
683 | * cache. It will prevent overwritting the new data from DMA | 1087 | * cache. It will prevent overwritting the new data from DMA |
684 | */ | 1088 | */ |
685 | blackfin_dcache_invalidate_range((unsigned long)new_skb->head, | 1089 | blackfin_dcache_invalidate_range((unsigned long)new_skb->head, |
686 | (unsigned long)new_skb->end); | 1090 | (unsigned long)new_skb->end); |
687 | 1091 | ||
1092 | current_rx_ptr->skb = new_skb; | ||
1093 | current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2; | ||
1094 | |||
688 | len = (unsigned short)((current_rx_ptr->status.status_word) & RX_FRLEN); | 1095 | len = (unsigned short)((current_rx_ptr->status.status_word) & RX_FRLEN); |
1096 | /* Deduce Ethernet FCS length from Ethernet payload length */ | ||
1097 | len -= ETH_FCS_LEN; | ||
689 | skb_put(skb, len); | 1098 | skb_put(skb, len); |
690 | blackfin_dcache_invalidate_range((unsigned long)skb->head, | ||
691 | (unsigned long)skb->tail); | ||
692 | 1099 | ||
693 | skb->protocol = eth_type_trans(skb, dev); | 1100 | skb->protocol = eth_type_trans(skb, dev); |
1101 | |||
1102 | bfin_rx_hwtstamp(dev, skb); | ||
1103 | |||
694 | #if defined(BFIN_MAC_CSUM_OFFLOAD) | 1104 | #if defined(BFIN_MAC_CSUM_OFFLOAD) |
695 | skb->csum = current_rx_ptr->status.ip_payload_csum; | 1105 | /* Checksum offloading only works for IPv4 packets with the standard IP header |
696 | skb->ip_summed = CHECKSUM_COMPLETE; | 1106 | * length of 20 bytes, because the blackfin MAC checksum calculation is |
1107 | * based on that assumption. We must NOT use the calculated checksum if our | ||
1108 | * IP version or header break that assumption. | ||
1109 | */ | ||
1110 | if (skb->data[IP_HEADER_OFF] == 0x45) { | ||
1111 | skb->csum = current_rx_ptr->status.ip_payload_csum; | ||
1112 | /* | ||
1113 | * Deduce Ethernet FCS from hardware generated IP payload checksum. | ||
1114 | * IP checksum is based on 16-bit one's complement algorithm. | ||
1115 | * To deduce a value from checksum is equal to add its inversion. | ||
1116 | * If the IP payload len is odd, the inversed FCS should also | ||
1117 | * begin from odd address and leave first byte zero. | ||
1118 | */ | ||
1119 | if (skb->len % 2) { | ||
1120 | fcs[0] = 0; | ||
1121 | for (i = 0; i < ETH_FCS_LEN; i++) | ||
1122 | fcs[i + 1] = ~skb->data[skb->len + i]; | ||
1123 | skb->csum = csum_partial(fcs, ETH_FCS_LEN + 1, skb->csum); | ||
1124 | } else { | ||
1125 | for (i = 0; i < ETH_FCS_LEN; i++) | ||
1126 | fcs[i] = ~skb->data[skb->len + i]; | ||
1127 | skb->csum = csum_partial(fcs, ETH_FCS_LEN, skb->csum); | ||
1128 | } | ||
1129 | skb->ip_summed = CHECKSUM_COMPLETE; | ||
1130 | } | ||
697 | #endif | 1131 | #endif |
698 | 1132 | ||
699 | netif_rx(skb); | 1133 | netif_rx(skb); |
700 | dev->stats.rx_packets++; | 1134 | dev->stats.rx_packets++; |
701 | dev->stats.rx_bytes += len; | 1135 | dev->stats.rx_bytes += len; |
1136 | out: | ||
702 | current_rx_ptr->status.status_word = 0x00000000; | 1137 | current_rx_ptr->status.status_word = 0x00000000; |
703 | current_rx_ptr = current_rx_ptr->next; | 1138 | current_rx_ptr = current_rx_ptr->next; |
704 | |||
705 | out: | ||
706 | return; | ||
707 | } | 1139 | } |
708 | 1140 | ||
709 | /* interrupt routine to handle rx and error signal */ | 1141 | /* interrupt routine to handle rx and error signal */ |
@@ -755,8 +1187,9 @@ static void bfin_mac_disable(void) | |||
755 | /* | 1187 | /* |
756 | * Enable Interrupts, Receive, and Transmit | 1188 | * Enable Interrupts, Receive, and Transmit |
757 | */ | 1189 | */ |
758 | static void bfin_mac_enable(void) | 1190 | static int bfin_mac_enable(void) |
759 | { | 1191 | { |
1192 | int ret; | ||
760 | u32 opmode; | 1193 | u32 opmode; |
761 | 1194 | ||
762 | pr_debug("%s: %s\n", DRV_NAME, __func__); | 1195 | pr_debug("%s: %s\n", DRV_NAME, __func__); |
@@ -766,7 +1199,9 @@ static void bfin_mac_enable(void) | |||
766 | bfin_write_DMA1_CONFIG(rx_list_head->desc_a.config); | 1199 | bfin_write_DMA1_CONFIG(rx_list_head->desc_a.config); |
767 | 1200 | ||
768 | /* Wait MII done */ | 1201 | /* Wait MII done */ |
769 | bfin_mdio_poll(); | 1202 | ret = bfin_mdio_poll(); |
1203 | if (ret) | ||
1204 | return ret; | ||
770 | 1205 | ||
771 | /* We enable only RX here */ | 1206 | /* We enable only RX here */ |
772 | /* ASTP : Enable Automatic Pad Stripping | 1207 | /* ASTP : Enable Automatic Pad Stripping |
@@ -790,6 +1225,8 @@ static void bfin_mac_enable(void) | |||
790 | #endif | 1225 | #endif |
791 | /* Turn on the EMAC rx */ | 1226 | /* Turn on the EMAC rx */ |
792 | bfin_write_EMAC_OPMODE(opmode); | 1227 | bfin_write_EMAC_OPMODE(opmode); |
1228 | |||
1229 | return 0; | ||
793 | } | 1230 | } |
794 | 1231 | ||
795 | /* Our watchdog timed out. Called by the networking layer */ | 1232 | /* Our watchdog timed out. Called by the networking layer */ |
@@ -805,21 +1242,21 @@ static void bfin_mac_timeout(struct net_device *dev) | |||
805 | bfin_mac_enable(); | 1242 | bfin_mac_enable(); |
806 | 1243 | ||
807 | /* We can accept TX packets again */ | 1244 | /* We can accept TX packets again */ |
808 | dev->trans_start = jiffies; | 1245 | dev->trans_start = jiffies; /* prevent tx timeout */ |
809 | netif_wake_queue(dev); | 1246 | netif_wake_queue(dev); |
810 | } | 1247 | } |
811 | 1248 | ||
812 | static void bfin_mac_multicast_hash(struct net_device *dev) | 1249 | static void bfin_mac_multicast_hash(struct net_device *dev) |
813 | { | 1250 | { |
814 | u32 emac_hashhi, emac_hashlo; | 1251 | u32 emac_hashhi, emac_hashlo; |
815 | struct dev_mc_list *dmi; | 1252 | struct netdev_hw_addr *ha; |
816 | char *addrs; | 1253 | char *addrs; |
817 | u32 crc; | 1254 | u32 crc; |
818 | 1255 | ||
819 | emac_hashhi = emac_hashlo = 0; | 1256 | emac_hashhi = emac_hashlo = 0; |
820 | 1257 | ||
821 | netdev_for_each_mc_addr(dmi, dev) { | 1258 | netdev_for_each_mc_addr(ha, dev) { |
822 | addrs = dmi->dmi_addr; | 1259 | addrs = ha->addr; |
823 | 1260 | ||
824 | /* skip non-multicast addresses */ | 1261 | /* skip non-multicast addresses */ |
825 | if (!(*addrs & 1)) | 1262 | if (!(*addrs & 1)) |
@@ -836,8 +1273,6 @@ static void bfin_mac_multicast_hash(struct net_device *dev) | |||
836 | 1273 | ||
837 | bfin_write_EMAC_HASHHI(emac_hashhi); | 1274 | bfin_write_EMAC_HASHHI(emac_hashhi); |
838 | bfin_write_EMAC_HASHLO(emac_hashlo); | 1275 | bfin_write_EMAC_HASHLO(emac_hashlo); |
839 | |||
840 | return; | ||
841 | } | 1276 | } |
842 | 1277 | ||
843 | /* | 1278 | /* |
@@ -853,7 +1288,7 @@ static void bfin_mac_set_multicast_list(struct net_device *dev) | |||
853 | if (dev->flags & IFF_PROMISC) { | 1288 | if (dev->flags & IFF_PROMISC) { |
854 | printk(KERN_INFO "%s: set to promisc mode\n", dev->name); | 1289 | printk(KERN_INFO "%s: set to promisc mode\n", dev->name); |
855 | sysctl = bfin_read_EMAC_OPMODE(); | 1290 | sysctl = bfin_read_EMAC_OPMODE(); |
856 | sysctl |= RAF; | 1291 | sysctl |= PR; |
857 | bfin_write_EMAC_OPMODE(sysctl); | 1292 | bfin_write_EMAC_OPMODE(sysctl); |
858 | } else if (dev->flags & IFF_ALLMULTI) { | 1293 | } else if (dev->flags & IFF_ALLMULTI) { |
859 | /* accept all multicast */ | 1294 | /* accept all multicast */ |
@@ -874,6 +1309,16 @@ static void bfin_mac_set_multicast_list(struct net_device *dev) | |||
874 | } | 1309 | } |
875 | } | 1310 | } |
876 | 1311 | ||
1312 | static int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | ||
1313 | { | ||
1314 | switch (cmd) { | ||
1315 | case SIOCSHWTSTAMP: | ||
1316 | return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd); | ||
1317 | default: | ||
1318 | return -EOPNOTSUPP; | ||
1319 | } | ||
1320 | } | ||
1321 | |||
877 | /* | 1322 | /* |
878 | * this puts the device in an inactive state | 1323 | * this puts the device in an inactive state |
879 | */ | 1324 | */ |
@@ -894,7 +1339,7 @@ static void bfin_mac_shutdown(struct net_device *dev) | |||
894 | static int bfin_mac_open(struct net_device *dev) | 1339 | static int bfin_mac_open(struct net_device *dev) |
895 | { | 1340 | { |
896 | struct bfin_mac_local *lp = netdev_priv(dev); | 1341 | struct bfin_mac_local *lp = netdev_priv(dev); |
897 | int retval; | 1342 | int ret; |
898 | pr_debug("%s: %s\n", dev->name, __func__); | 1343 | pr_debug("%s: %s\n", dev->name, __func__); |
899 | 1344 | ||
900 | /* | 1345 | /* |
@@ -908,18 +1353,21 @@ static int bfin_mac_open(struct net_device *dev) | |||
908 | } | 1353 | } |
909 | 1354 | ||
910 | /* initial rx and tx list */ | 1355 | /* initial rx and tx list */ |
911 | retval = desc_list_init(); | 1356 | ret = desc_list_init(); |
912 | 1357 | if (ret) | |
913 | if (retval) | 1358 | return ret; |
914 | return retval; | ||
915 | 1359 | ||
916 | phy_start(lp->phydev); | 1360 | phy_start(lp->phydev); |
917 | phy_write(lp->phydev, MII_BMCR, BMCR_RESET); | 1361 | phy_write(lp->phydev, MII_BMCR, BMCR_RESET); |
918 | setup_system_regs(dev); | 1362 | setup_system_regs(dev); |
919 | setup_mac_addr(dev->dev_addr); | 1363 | setup_mac_addr(dev->dev_addr); |
1364 | |||
920 | bfin_mac_disable(); | 1365 | bfin_mac_disable(); |
921 | bfin_mac_enable(); | 1366 | ret = bfin_mac_enable(); |
1367 | if (ret) | ||
1368 | return ret; | ||
922 | pr_debug("hardware init finished\n"); | 1369 | pr_debug("hardware init finished\n"); |
1370 | |||
923 | netif_start_queue(dev); | 1371 | netif_start_queue(dev); |
924 | netif_carrier_on(dev); | 1372 | netif_carrier_on(dev); |
925 | 1373 | ||
@@ -958,6 +1406,7 @@ static const struct net_device_ops bfin_mac_netdev_ops = { | |||
958 | .ndo_set_mac_address = bfin_mac_set_mac_address, | 1406 | .ndo_set_mac_address = bfin_mac_set_mac_address, |
959 | .ndo_tx_timeout = bfin_mac_timeout, | 1407 | .ndo_tx_timeout = bfin_mac_timeout, |
960 | .ndo_set_multicast_list = bfin_mac_set_multicast_list, | 1408 | .ndo_set_multicast_list = bfin_mac_set_multicast_list, |
1409 | .ndo_do_ioctl = bfin_mac_ioctl, | ||
961 | .ndo_validate_addr = eth_validate_addr, | 1410 | .ndo_validate_addr = eth_validate_addr, |
962 | .ndo_change_mtu = eth_change_mtu, | 1411 | .ndo_change_mtu = eth_change_mtu, |
963 | #ifdef CONFIG_NET_POLL_CONTROLLER | 1412 | #ifdef CONFIG_NET_POLL_CONTROLLER |
@@ -1017,6 +1466,11 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) | |||
1017 | } | 1466 | } |
1018 | pd = pdev->dev.platform_data; | 1467 | pd = pdev->dev.platform_data; |
1019 | lp->mii_bus = platform_get_drvdata(pd); | 1468 | lp->mii_bus = platform_get_drvdata(pd); |
1469 | if (!lp->mii_bus) { | ||
1470 | dev_err(&pdev->dev, "Cannot get mii_bus!\n"); | ||
1471 | rc = -ENODEV; | ||
1472 | goto out_err_mii_bus_probe; | ||
1473 | } | ||
1020 | lp->mii_bus->priv = ndev; | 1474 | lp->mii_bus->priv = ndev; |
1021 | 1475 | ||
1022 | rc = mii_probe(ndev); | 1476 | rc = mii_probe(ndev); |
@@ -1049,6 +1503,8 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) | |||
1049 | goto out_err_reg_ndev; | 1503 | goto out_err_reg_ndev; |
1050 | } | 1504 | } |
1051 | 1505 | ||
1506 | bfin_mac_hwtstamp_init(ndev); | ||
1507 | |||
1052 | /* now, print out the card info, in a short format.. */ | 1508 | /* now, print out the card info, in a short format.. */ |
1053 | dev_info(&pdev->dev, "%s, Version %s\n", DRV_DESC, DRV_VERSION); | 1509 | dev_info(&pdev->dev, "%s, Version %s\n", DRV_DESC, DRV_VERSION); |
1054 | 1510 | ||
@@ -1060,6 +1516,7 @@ out_err_request_irq: | |||
1060 | out_err_mii_probe: | 1516 | out_err_mii_probe: |
1061 | mdiobus_unregister(lp->mii_bus); | 1517 | mdiobus_unregister(lp->mii_bus); |
1062 | mdiobus_free(lp->mii_bus); | 1518 | mdiobus_free(lp->mii_bus); |
1519 | out_err_mii_bus_probe: | ||
1063 | peripheral_free_list(pin_req); | 1520 | peripheral_free_list(pin_req); |
1064 | out_err_probe_mac: | 1521 | out_err_probe_mac: |
1065 | platform_set_drvdata(pdev, NULL); | 1522 | platform_set_drvdata(pdev, NULL); |
@@ -1092,9 +1549,16 @@ static int __devexit bfin_mac_remove(struct platform_device *pdev) | |||
1092 | static int bfin_mac_suspend(struct platform_device *pdev, pm_message_t mesg) | 1549 | static int bfin_mac_suspend(struct platform_device *pdev, pm_message_t mesg) |
1093 | { | 1550 | { |
1094 | struct net_device *net_dev = platform_get_drvdata(pdev); | 1551 | struct net_device *net_dev = platform_get_drvdata(pdev); |
1552 | struct bfin_mac_local *lp = netdev_priv(net_dev); | ||
1095 | 1553 | ||
1096 | if (netif_running(net_dev)) | 1554 | if (lp->wol) { |
1097 | bfin_mac_close(net_dev); | 1555 | bfin_write_EMAC_OPMODE((bfin_read_EMAC_OPMODE() & ~TE) | RE); |
1556 | bfin_write_EMAC_WKUP_CTL(MPKE); | ||
1557 | enable_irq_wake(IRQ_MAC_WAKEDET); | ||
1558 | } else { | ||
1559 | if (netif_running(net_dev)) | ||
1560 | bfin_mac_close(net_dev); | ||
1561 | } | ||
1098 | 1562 | ||
1099 | return 0; | 1563 | return 0; |
1100 | } | 1564 | } |
@@ -1102,9 +1566,16 @@ static int bfin_mac_suspend(struct platform_device *pdev, pm_message_t mesg) | |||
1102 | static int bfin_mac_resume(struct platform_device *pdev) | 1566 | static int bfin_mac_resume(struct platform_device *pdev) |
1103 | { | 1567 | { |
1104 | struct net_device *net_dev = platform_get_drvdata(pdev); | 1568 | struct net_device *net_dev = platform_get_drvdata(pdev); |
1569 | struct bfin_mac_local *lp = netdev_priv(net_dev); | ||
1105 | 1570 | ||
1106 | if (netif_running(net_dev)) | 1571 | if (lp->wol) { |
1107 | bfin_mac_open(net_dev); | 1572 | bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE); |
1573 | bfin_write_EMAC_WKUP_CTL(0); | ||
1574 | disable_irq_wake(IRQ_MAC_WAKEDET); | ||
1575 | } else { | ||
1576 | if (netif_running(net_dev)) | ||
1577 | bfin_mac_open(net_dev); | ||
1578 | } | ||
1108 | 1579 | ||
1109 | return 0; | 1580 | return 0; |
1110 | } | 1581 | } |