aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bfin_mac.c
diff options
context:
space:
mode:
authorBarry Song <barry.song@analog.com>2010-05-17 20:19:40 -0400
committerDavid S. Miller <davem@davemloft.net>2010-05-17 20:19:40 -0400
commitfe92afedee23e1d91f0133360a24d2bf48270739 (patch)
tree20564c377f57af2a94644abcd18b953a6aba8c7c /drivers/net/bfin_mac.c
parentab6e3feba1f1bc3b9418b854da6f481408d243de (diff)
netdev: bfin_mac: add support for IEEE 1588 PTP
Newer on-chip MAC peripherals support IEEE 1588 PTP in the hardware, so extend the driver to support this functionality. Signed-off-by: Barry Song <barry.song@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bfin_mac.c')
-rw-r--r--drivers/net/bfin_mac.c341
1 files changed, 340 insertions, 1 deletions
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index 35548701899f..a173d8a40484 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>
@@ -551,6 +552,309 @@ static int bfin_mac_set_mac_address(struct net_device *dev, void *p)
551 return 0; 552 return 0;
552} 553}
553 554
555#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
556#define bfin_mac_hwtstamp_is_none(cfg) ((cfg) == HWTSTAMP_FILTER_NONE)
557
558static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
559 struct ifreq *ifr, int cmd)
560{
561 struct hwtstamp_config config;
562 struct bfin_mac_local *lp = netdev_priv(netdev);
563 u16 ptpctl;
564 u32 ptpfv1, ptpfv2, ptpfv3, ptpfoff;
565
566 if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
567 return -EFAULT;
568
569 pr_debug("%s config flag:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
570 __func__, config.flags, config.tx_type, config.rx_filter);
571
572 /* reserved for future extensions */
573 if (config.flags)
574 return -EINVAL;
575
576 if ((config.tx_type != HWTSTAMP_TX_OFF) &&
577 (config.tx_type != HWTSTAMP_TX_ON))
578 return -ERANGE;
579
580 ptpctl = bfin_read_EMAC_PTP_CTL();
581
582 switch (config.rx_filter) {
583 case HWTSTAMP_FILTER_NONE:
584 /*
585 * Dont allow any timestamping
586 */
587 ptpfv3 = 0xFFFFFFFF;
588 bfin_write_EMAC_PTP_FV3(ptpfv3);
589 break;
590 case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
591 case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
592 case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
593 /*
594 * Clear the five comparison mask bits (bits[12:8]) in EMAC_PTP_CTL)
595 * to enable all the field matches.
596 */
597 ptpctl &= ~0x1F00;
598 bfin_write_EMAC_PTP_CTL(ptpctl);
599 /*
600 * Keep the default values of the EMAC_PTP_FOFF register.
601 */
602 ptpfoff = 0x4A24170C;
603 bfin_write_EMAC_PTP_FOFF(ptpfoff);
604 /*
605 * Keep the default values of the EMAC_PTP_FV1 and EMAC_PTP_FV2
606 * registers.
607 */
608 ptpfv1 = 0x11040800;
609 bfin_write_EMAC_PTP_FV1(ptpfv1);
610 ptpfv2 = 0x0140013F;
611 bfin_write_EMAC_PTP_FV2(ptpfv2);
612 /*
613 * The default value (0xFFFC) allows the timestamping of both
614 * received Sync messages and Delay_Req messages.
615 */
616 ptpfv3 = 0xFFFFFFFC;
617 bfin_write_EMAC_PTP_FV3(ptpfv3);
618
619 config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
620 break;
621 case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
622 case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
623 case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
624 /* Clear all five comparison mask bits (bits[12:8]) in the
625 * EMAC_PTP_CTL register to enable all the field matches.
626 */
627 ptpctl &= ~0x1F00;
628 bfin_write_EMAC_PTP_CTL(ptpctl);
629 /*
630 * Keep the default values of the EMAC_PTP_FOFF register, except set
631 * the PTPCOF field to 0x2A.
632 */
633 ptpfoff = 0x2A24170C;
634 bfin_write_EMAC_PTP_FOFF(ptpfoff);
635 /*
636 * Keep the default values of the EMAC_PTP_FV1 and EMAC_PTP_FV2
637 * registers.
638 */
639 ptpfv1 = 0x11040800;
640 bfin_write_EMAC_PTP_FV1(ptpfv1);
641 ptpfv2 = 0x0140013F;
642 bfin_write_EMAC_PTP_FV2(ptpfv2);
643 /*
644 * To allow the timestamping of Pdelay_Req and Pdelay_Resp, set
645 * the value to 0xFFF0.
646 */
647 ptpfv3 = 0xFFFFFFF0;
648 bfin_write_EMAC_PTP_FV3(ptpfv3);
649
650 config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
651 break;
652 case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
653 case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
654 case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
655 /*
656 * Clear bits 8 and 12 of the EMAC_PTP_CTL register to enable only the
657 * EFTM and PTPCM field comparison.
658 */
659 ptpctl &= ~0x1100;
660 bfin_write_EMAC_PTP_CTL(ptpctl);
661 /*
662 * Keep the default values of all the fields of the EMAC_PTP_FOFF
663 * register, except set the PTPCOF field to 0x0E.
664 */
665 ptpfoff = 0x0E24170C;
666 bfin_write_EMAC_PTP_FOFF(ptpfoff);
667 /*
668 * Program bits [15:0] of the EMAC_PTP_FV1 register to 0x88F7, which
669 * corresponds to PTP messages on the MAC layer.
670 */
671 ptpfv1 = 0x110488F7;
672 bfin_write_EMAC_PTP_FV1(ptpfv1);
673 ptpfv2 = 0x0140013F;
674 bfin_write_EMAC_PTP_FV2(ptpfv2);
675 /*
676 * To allow the timestamping of Pdelay_Req and Pdelay_Resp
677 * messages, set the value to 0xFFF0.
678 */
679 ptpfv3 = 0xFFFFFFF0;
680 bfin_write_EMAC_PTP_FV3(ptpfv3);
681
682 config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
683 break;
684 default:
685 return -ERANGE;
686 }
687
688 if (config.tx_type == HWTSTAMP_TX_OFF &&
689 bfin_mac_hwtstamp_is_none(config.rx_filter)) {
690 ptpctl &= ~PTP_EN;
691 bfin_write_EMAC_PTP_CTL(ptpctl);
692
693 SSYNC();
694 } else {
695 ptpctl |= PTP_EN;
696 bfin_write_EMAC_PTP_CTL(ptpctl);
697
698 /*
699 * clear any existing timestamp
700 */
701 bfin_read_EMAC_PTP_RXSNAPLO();
702 bfin_read_EMAC_PTP_RXSNAPHI();
703
704 bfin_read_EMAC_PTP_TXSNAPLO();
705 bfin_read_EMAC_PTP_TXSNAPHI();
706
707 /*
708 * Set registers so that rollover occurs soon to test this.
709 */
710 bfin_write_EMAC_PTP_TIMELO(0x00000000);
711 bfin_write_EMAC_PTP_TIMEHI(0xFF800000);
712
713 SSYNC();
714
715 lp->compare.last_update = 0;
716 timecounter_init(&lp->clock,
717 &lp->cycles,
718 ktime_to_ns(ktime_get_real()));
719 timecompare_update(&lp->compare, 0);
720 }
721
722 lp->stamp_cfg = config;
723 return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
724 -EFAULT : 0;
725}
726
727static void bfin_dump_hwtamp(char *s, ktime_t *hw, ktime_t *ts, struct timecompare *cmp)
728{
729 ktime_t sys = ktime_get_real();
730
731 pr_debug("%s %s hardware:%d,%d transform system:%d,%d system:%d,%d, cmp:%lld, %lld\n",
732 __func__, s, hw->tv.sec, hw->tv.nsec, ts->tv.sec, ts->tv.nsec, sys.tv.sec,
733 sys.tv.nsec, cmp->offset, cmp->skew);
734}
735
736static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
737{
738 struct bfin_mac_local *lp = netdev_priv(netdev);
739 union skb_shared_tx *shtx = skb_tx(skb);
740
741 if (shtx->hardware) {
742 int timeout_cnt = MAX_TIMEOUT_CNT;
743
744 /* When doing time stamping, keep the connection to the socket
745 * a while longer
746 */
747 shtx->in_progress = 1;
748
749 /*
750 * The timestamping is done at the EMAC module's MII/RMII interface
751 * when the module sees the Start of Frame of an event message packet. This
752 * interface is the closest possible place to the physical Ethernet transmission
753 * medium, providing the best timing accuracy.
754 */
755 while ((!(bfin_read_EMAC_PTP_ISTAT() & TXTL)) && (--timeout_cnt))
756 udelay(1);
757 if (timeout_cnt == 0)
758 printk(KERN_ERR DRV_NAME
759 ": fails to timestamp the TX packet\n");
760 else {
761 struct skb_shared_hwtstamps shhwtstamps;
762 u64 ns;
763 u64 regval;
764
765 regval = bfin_read_EMAC_PTP_TXSNAPLO();
766 regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32;
767 memset(&shhwtstamps, 0, sizeof(shhwtstamps));
768 ns = timecounter_cyc2time(&lp->clock,
769 regval);
770 timecompare_update(&lp->compare, ns);
771 shhwtstamps.hwtstamp = ns_to_ktime(ns);
772 shhwtstamps.syststamp =
773 timecompare_transform(&lp->compare, ns);
774 skb_tstamp_tx(skb, &shhwtstamps);
775
776 bfin_dump_hwtamp("TX", &shhwtstamps.hwtstamp, &shhwtstamps.syststamp, &lp->compare);
777 }
778 }
779}
780
781static void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
782{
783 struct bfin_mac_local *lp = netdev_priv(netdev);
784 u32 valid;
785 u64 regval, ns;
786 struct skb_shared_hwtstamps *shhwtstamps;
787
788 if (bfin_mac_hwtstamp_is_none(lp->stamp_cfg.rx_filter))
789 return;
790
791 valid = bfin_read_EMAC_PTP_ISTAT() & RXEL;
792 if (!valid)
793 return;
794
795 shhwtstamps = skb_hwtstamps(skb);
796
797 regval = bfin_read_EMAC_PTP_RXSNAPLO();
798 regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32;
799 ns = timecounter_cyc2time(&lp->clock, regval);
800 timecompare_update(&lp->compare, ns);
801 memset(shhwtstamps, 0, sizeof(*shhwtstamps));
802 shhwtstamps->hwtstamp = ns_to_ktime(ns);
803 shhwtstamps->syststamp = timecompare_transform(&lp->compare, ns);
804
805 bfin_dump_hwtamp("RX", &shhwtstamps->hwtstamp, &shhwtstamps->syststamp, &lp->compare);
806}
807
808/*
809 * bfin_read_clock - read raw cycle counter (to be used by time counter)
810 */
811static cycle_t bfin_read_clock(const struct cyclecounter *tc)
812{
813 u64 stamp;
814
815 stamp = bfin_read_EMAC_PTP_TIMELO();
816 stamp |= (u64)bfin_read_EMAC_PTP_TIMEHI() << 32ULL;
817
818 return stamp;
819}
820
821#define PTP_CLK 25000000
822
823static void bfin_mac_hwtstamp_init(struct net_device *netdev)
824{
825 struct bfin_mac_local *lp = netdev_priv(netdev);
826 u64 append;
827
828 /* Initialize hardware timer */
829 append = PTP_CLK * (1ULL << 32);
830 do_div(append, get_sclk());
831 bfin_write_EMAC_PTP_ADDEND((u32)append);
832
833 memset(&lp->cycles, 0, sizeof(lp->cycles));
834 lp->cycles.read = bfin_read_clock;
835 lp->cycles.mask = CLOCKSOURCE_MASK(64);
836 lp->cycles.mult = 1000000000 / PTP_CLK;
837 lp->cycles.shift = 0;
838
839 /* Synchronize our NIC clock against system wall clock */
840 memset(&lp->compare, 0, sizeof(lp->compare));
841 lp->compare.source = &lp->clock;
842 lp->compare.target = ktime_get_real;
843 lp->compare.num_samples = 10;
844
845 /* Initialize hwstamp config */
846 lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
847 lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF;
848}
849
850#else
851# define bfin_mac_hwtstamp_is_none(cfg) 0
852# define bfin_mac_hwtstamp_init(dev)
853# define bfin_mac_hwtstamp_ioctl(dev, ifr, cmd) (-EOPNOTSUPP)
854# define bfin_rx_hwtstamp(dev, skb)
855# define bfin_tx_hwtstamp(dev, skb)
856#endif
857
554static void adjust_tx_list(void) 858static void adjust_tx_list(void)
555{ 859{
556 int timeout_cnt = MAX_TIMEOUT_CNT; 860 int timeout_cnt = MAX_TIMEOUT_CNT;
@@ -608,18 +912,32 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
608{ 912{
609 u16 *data; 913 u16 *data;
610 u32 data_align = (unsigned long)(skb->data) & 0x3; 914 u32 data_align = (unsigned long)(skb->data) & 0x3;
915 union skb_shared_tx *shtx = skb_tx(skb);
916
611 current_tx_ptr->skb = skb; 917 current_tx_ptr->skb = skb;
612 918
613 if (data_align == 0x2) { 919 if (data_align == 0x2) {
614 /* move skb->data to current_tx_ptr payload */ 920 /* move skb->data to current_tx_ptr payload */
615 data = (u16 *)(skb->data) - 1; 921 data = (u16 *)(skb->data) - 1;
616 *data = (u16)(skb->len); 922 *data = (u16)(skb->len);
923 /*
924 * When transmitting an Ethernet packet, the PTP_TSYNC module requires
925 * a DMA_Length_Word field associated with the packet. The lower 12 bits
926 * of this field are the length of the packet payload in bytes and the higher
927 * 4 bits are the timestamping enable field.
928 */
929 if (shtx->hardware)
930 *data |= 0x1000;
931
617 current_tx_ptr->desc_a.start_addr = (u32)data; 932 current_tx_ptr->desc_a.start_addr = (u32)data;
618 /* this is important! */ 933 /* this is important! */
619 blackfin_dcache_flush_range((u32)data, 934 blackfin_dcache_flush_range((u32)data,
620 (u32)((u8 *)data + skb->len + 4)); 935 (u32)((u8 *)data + skb->len + 4));
621 } else { 936 } else {
622 *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); 937 *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
938 /* enable timestamping for the sent packet */
939 if (shtx->hardware)
940 *((u16 *)(current_tx_ptr->packet)) |= 0x1000;
623 memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, 941 memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
624 skb->len); 942 skb->len);
625 current_tx_ptr->desc_a.start_addr = 943 current_tx_ptr->desc_a.start_addr =
@@ -653,6 +971,9 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
653 971
654out: 972out:
655 adjust_tx_list(); 973 adjust_tx_list();
974
975 bfin_tx_hwtstamp(dev, skb);
976
656 current_tx_ptr = current_tx_ptr->next; 977 current_tx_ptr = current_tx_ptr->next;
657 dev->stats.tx_packets++; 978 dev->stats.tx_packets++;
658 dev->stats.tx_bytes += (skb->len); 979 dev->stats.tx_bytes += (skb->len);
@@ -663,9 +984,11 @@ static void bfin_mac_rx(struct net_device *dev)
663{ 984{
664 struct sk_buff *skb, *new_skb; 985 struct sk_buff *skb, *new_skb;
665 unsigned short len; 986 unsigned short len;
987 struct bfin_mac_local *lp __maybe_unused = netdev_priv(dev);
666 988
667 /* allocate a new skb for next time receive */ 989 /* allocate a new skb for next time receive */
668 skb = current_rx_ptr->skb; 990 skb = current_rx_ptr->skb;
991
669 new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN); 992 new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
670 if (!new_skb) { 993 if (!new_skb) {
671 printk(KERN_NOTICE DRV_NAME 994 printk(KERN_NOTICE DRV_NAME
@@ -690,6 +1013,9 @@ static void bfin_mac_rx(struct net_device *dev)
690 (unsigned long)skb->tail); 1013 (unsigned long)skb->tail);
691 1014
692 skb->protocol = eth_type_trans(skb, dev); 1015 skb->protocol = eth_type_trans(skb, dev);
1016
1017 bfin_rx_hwtstamp(dev, skb);
1018
693#if defined(BFIN_MAC_CSUM_OFFLOAD) 1019#if defined(BFIN_MAC_CSUM_OFFLOAD)
694 skb->csum = current_rx_ptr->status.ip_payload_csum; 1020 skb->csum = current_rx_ptr->status.ip_payload_csum;
695 skb->ip_summed = CHECKSUM_COMPLETE; 1021 skb->ip_summed = CHECKSUM_COMPLETE;
@@ -871,6 +1197,16 @@ static void bfin_mac_set_multicast_list(struct net_device *dev)
871 } 1197 }
872} 1198}
873 1199
1200static int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
1201{
1202 switch (cmd) {
1203 case SIOCSHWTSTAMP:
1204 return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd);
1205 default:
1206 return -EOPNOTSUPP;
1207 }
1208}
1209
874/* 1210/*
875 * this puts the device in an inactive state 1211 * this puts the device in an inactive state
876 */ 1212 */
@@ -955,6 +1291,7 @@ static const struct net_device_ops bfin_mac_netdev_ops = {
955 .ndo_set_mac_address = bfin_mac_set_mac_address, 1291 .ndo_set_mac_address = bfin_mac_set_mac_address,
956 .ndo_tx_timeout = bfin_mac_timeout, 1292 .ndo_tx_timeout = bfin_mac_timeout,
957 .ndo_set_multicast_list = bfin_mac_set_multicast_list, 1293 .ndo_set_multicast_list = bfin_mac_set_multicast_list,
1294 .ndo_do_ioctl = bfin_mac_ioctl,
958 .ndo_validate_addr = eth_validate_addr, 1295 .ndo_validate_addr = eth_validate_addr,
959 .ndo_change_mtu = eth_change_mtu, 1296 .ndo_change_mtu = eth_change_mtu,
960#ifdef CONFIG_NET_POLL_CONTROLLER 1297#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1046,6 +1383,8 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
1046 goto out_err_reg_ndev; 1383 goto out_err_reg_ndev;
1047 } 1384 }
1048 1385
1386 bfin_mac_hwtstamp_init(ndev);
1387
1049 /* now, print out the card info, in a short format.. */ 1388 /* now, print out the card info, in a short format.. */
1050 dev_info(&pdev->dev, "%s, Version %s\n", DRV_DESC, DRV_VERSION); 1389 dev_info(&pdev->dev, "%s, Version %s\n", DRV_DESC, DRV_VERSION);
1051 1390