diff options
author | Richard Cochran <richardcochran@gmail.com> | 2012-10-31 02:27:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-11-01 11:41:35 -0400 |
commit | bc3c5f634de23ca767c2d04d356ddf5bbe2144e2 (patch) | |
tree | cb152135d7336f280762ed2aaa6450e6d9d4d688 /drivers/net/ethernet/adi | |
parent | 85c153d2c7e51efcf0f715118c3c30b62c5fce68 (diff) |
bfin_mac: replace sys time stamps with raw ones instead.
This patch replaces the sys time stamps and timecompare code with simple
raw hardware time stamps in nanosecond resolution. The only tricky bit is
to find a PTP Hardware Clock period slower than the input clock period
and a power of two.
Compile tested only.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Tested-by: Bob Liu <lliubbo@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/adi')
-rw-r--r-- | drivers/net/ethernet/adi/bfin_mac.c | 91 | ||||
-rw-r--r-- | drivers/net/ethernet/adi/bfin_mac.h | 7 |
2 files changed, 28 insertions, 70 deletions
diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c index 2349abba33d8..885fa80e9220 100644 --- a/drivers/net/ethernet/adi/bfin_mac.c +++ b/drivers/net/ethernet/adi/bfin_mac.c | |||
@@ -555,7 +555,7 @@ static int bfin_mac_ethtool_get_ts_info(struct net_device *dev, | |||
555 | info->so_timestamping = | 555 | info->so_timestamping = |
556 | SOF_TIMESTAMPING_TX_HARDWARE | | 556 | SOF_TIMESTAMPING_TX_HARDWARE | |
557 | SOF_TIMESTAMPING_RX_HARDWARE | | 557 | SOF_TIMESTAMPING_RX_HARDWARE | |
558 | SOF_TIMESTAMPING_SYS_HARDWARE; | 558 | SOF_TIMESTAMPING_RAW_HARDWARE; |
559 | info->phc_index = -1; | 559 | info->phc_index = -1; |
560 | info->tx_types = | 560 | info->tx_types = |
561 | (1 << HWTSTAMP_TX_OFF) | | 561 | (1 << HWTSTAMP_TX_OFF) | |
@@ -653,6 +653,20 @@ static int bfin_mac_set_mac_address(struct net_device *dev, void *p) | |||
653 | #ifdef CONFIG_BFIN_MAC_USE_HWSTAMP | 653 | #ifdef CONFIG_BFIN_MAC_USE_HWSTAMP |
654 | #define bfin_mac_hwtstamp_is_none(cfg) ((cfg) == HWTSTAMP_FILTER_NONE) | 654 | #define bfin_mac_hwtstamp_is_none(cfg) ((cfg) == HWTSTAMP_FILTER_NONE) |
655 | 655 | ||
656 | static u32 bfin_select_phc_clock(u32 input_clk, unsigned int *shift_result) | ||
657 | { | ||
658 | u32 ipn = 1000000000UL / input_clk; | ||
659 | u32 ppn = 1; | ||
660 | unsigned int shift = 0; | ||
661 | |||
662 | while (ppn <= ipn) { | ||
663 | ppn <<= 1; | ||
664 | shift++; | ||
665 | } | ||
666 | *shift_result = shift; | ||
667 | return 1000000000UL / ppn; | ||
668 | } | ||
669 | |||
656 | static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, | 670 | static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, |
657 | struct ifreq *ifr, int cmd) | 671 | struct ifreq *ifr, int cmd) |
658 | { | 672 | { |
@@ -802,19 +816,7 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, | |||
802 | bfin_read_EMAC_PTP_TXSNAPLO(); | 816 | bfin_read_EMAC_PTP_TXSNAPLO(); |
803 | bfin_read_EMAC_PTP_TXSNAPHI(); | 817 | bfin_read_EMAC_PTP_TXSNAPHI(); |
804 | 818 | ||
805 | /* | ||
806 | * Set registers so that rollover occurs soon to test this. | ||
807 | */ | ||
808 | bfin_write_EMAC_PTP_TIMELO(0x00000000); | ||
809 | bfin_write_EMAC_PTP_TIMEHI(0xFF800000); | ||
810 | |||
811 | SSYNC(); | 819 | SSYNC(); |
812 | |||
813 | lp->compare.last_update = 0; | ||
814 | timecounter_init(&lp->clock, | ||
815 | &lp->cycles, | ||
816 | ktime_to_ns(ktime_get_real())); | ||
817 | timecompare_update(&lp->compare, 0); | ||
818 | } | 820 | } |
819 | 821 | ||
820 | lp->stamp_cfg = config; | 822 | lp->stamp_cfg = config; |
@@ -822,15 +824,6 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, | |||
822 | -EFAULT : 0; | 824 | -EFAULT : 0; |
823 | } | 825 | } |
824 | 826 | ||
825 | static void bfin_dump_hwtamp(char *s, ktime_t *hw, ktime_t *ts, struct timecompare *cmp) | ||
826 | { | ||
827 | ktime_t sys = ktime_get_real(); | ||
828 | |||
829 | pr_debug("%s %s hardware:%d,%d transform system:%d,%d system:%d,%d, cmp:%lld, %lld\n", | ||
830 | __func__, s, hw->tv.sec, hw->tv.nsec, ts->tv.sec, ts->tv.nsec, sys.tv.sec, | ||
831 | sys.tv.nsec, cmp->offset, cmp->skew); | ||
832 | } | ||
833 | |||
834 | static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) | 827 | static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) |
835 | { | 828 | { |
836 | struct bfin_mac_local *lp = netdev_priv(netdev); | 829 | struct bfin_mac_local *lp = netdev_priv(netdev); |
@@ -861,15 +854,9 @@ static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) | |||
861 | regval = bfin_read_EMAC_PTP_TXSNAPLO(); | 854 | regval = bfin_read_EMAC_PTP_TXSNAPLO(); |
862 | regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32; | 855 | regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32; |
863 | memset(&shhwtstamps, 0, sizeof(shhwtstamps)); | 856 | memset(&shhwtstamps, 0, sizeof(shhwtstamps)); |
864 | ns = timecounter_cyc2time(&lp->clock, | 857 | ns = regval << lp->shift; |
865 | regval); | ||
866 | timecompare_update(&lp->compare, ns); | ||
867 | shhwtstamps.hwtstamp = ns_to_ktime(ns); | 858 | shhwtstamps.hwtstamp = ns_to_ktime(ns); |
868 | shhwtstamps.syststamp = | ||
869 | timecompare_transform(&lp->compare, ns); | ||
870 | skb_tstamp_tx(skb, &shhwtstamps); | 859 | skb_tstamp_tx(skb, &shhwtstamps); |
871 | |||
872 | bfin_dump_hwtamp("TX", &shhwtstamps.hwtstamp, &shhwtstamps.syststamp, &lp->compare); | ||
873 | } | 860 | } |
874 | } | 861 | } |
875 | } | 862 | } |
@@ -892,51 +879,25 @@ static void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) | |||
892 | 879 | ||
893 | regval = bfin_read_EMAC_PTP_RXSNAPLO(); | 880 | regval = bfin_read_EMAC_PTP_RXSNAPLO(); |
894 | regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32; | 881 | regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32; |
895 | ns = timecounter_cyc2time(&lp->clock, regval); | 882 | ns = regval << lp->shift; |
896 | timecompare_update(&lp->compare, ns); | ||
897 | memset(shhwtstamps, 0, sizeof(*shhwtstamps)); | 883 | memset(shhwtstamps, 0, sizeof(*shhwtstamps)); |
898 | shhwtstamps->hwtstamp = ns_to_ktime(ns); | 884 | shhwtstamps->hwtstamp = ns_to_ktime(ns); |
899 | shhwtstamps->syststamp = timecompare_transform(&lp->compare, ns); | ||
900 | |||
901 | bfin_dump_hwtamp("RX", &shhwtstamps->hwtstamp, &shhwtstamps->syststamp, &lp->compare); | ||
902 | } | ||
903 | |||
904 | /* | ||
905 | * bfin_read_clock - read raw cycle counter (to be used by time counter) | ||
906 | */ | ||
907 | static cycle_t bfin_read_clock(const struct cyclecounter *tc) | ||
908 | { | ||
909 | u64 stamp; | ||
910 | |||
911 | stamp = bfin_read_EMAC_PTP_TIMELO(); | ||
912 | stamp |= (u64)bfin_read_EMAC_PTP_TIMEHI() << 32ULL; | ||
913 | |||
914 | return stamp; | ||
915 | } | 885 | } |
916 | 886 | ||
917 | #define PTP_CLK 25000000 | ||
918 | |||
919 | static void bfin_mac_hwtstamp_init(struct net_device *netdev) | 887 | static void bfin_mac_hwtstamp_init(struct net_device *netdev) |
920 | { | 888 | { |
921 | struct bfin_mac_local *lp = netdev_priv(netdev); | 889 | struct bfin_mac_local *lp = netdev_priv(netdev); |
922 | u64 append; | 890 | u64 addend; |
891 | u32 input_clk, phc_clk; | ||
923 | 892 | ||
924 | /* Initialize hardware timer */ | 893 | /* Initialize hardware timer */ |
925 | append = PTP_CLK * (1ULL << 32); | 894 | input_clk = get_sclk(); |
926 | do_div(append, get_sclk()); | 895 | phc_clk = bfin_select_phc_clock(input_clk, &lp->shift); |
927 | bfin_write_EMAC_PTP_ADDEND((u32)append); | 896 | addend = phc_clk * (1ULL << 32); |
928 | 897 | do_div(addend, input_clk); | |
929 | memset(&lp->cycles, 0, sizeof(lp->cycles)); | 898 | bfin_write_EMAC_PTP_ADDEND((u32)addend); |
930 | lp->cycles.read = bfin_read_clock; | 899 | |
931 | lp->cycles.mask = CLOCKSOURCE_MASK(64); | 900 | lp->addend = addend; |
932 | lp->cycles.mult = 1000000000 / PTP_CLK; | ||
933 | lp->cycles.shift = 0; | ||
934 | |||
935 | /* Synchronize our NIC clock against system wall clock */ | ||
936 | memset(&lp->compare, 0, sizeof(lp->compare)); | ||
937 | lp->compare.source = &lp->clock; | ||
938 | lp->compare.target = ktime_get_real; | ||
939 | lp->compare.num_samples = 10; | ||
940 | 901 | ||
941 | /* Initialize hwstamp config */ | 902 | /* Initialize hwstamp config */ |
942 | lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE; | 903 | lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE; |
diff --git a/drivers/net/ethernet/adi/bfin_mac.h b/drivers/net/ethernet/adi/bfin_mac.h index 960905c08223..57f042c3111c 100644 --- a/drivers/net/ethernet/adi/bfin_mac.h +++ b/drivers/net/ethernet/adi/bfin_mac.h | |||
@@ -11,8 +11,6 @@ | |||
11 | #define _BFIN_MAC_H_ | 11 | #define _BFIN_MAC_H_ |
12 | 12 | ||
13 | #include <linux/net_tstamp.h> | 13 | #include <linux/net_tstamp.h> |
14 | #include <linux/clocksource.h> | ||
15 | #include <linux/timecompare.h> | ||
16 | #include <linux/timer.h> | 14 | #include <linux/timer.h> |
17 | #include <linux/etherdevice.h> | 15 | #include <linux/etherdevice.h> |
18 | #include <linux/bfin_mac.h> | 16 | #include <linux/bfin_mac.h> |
@@ -94,9 +92,8 @@ struct bfin_mac_local { | |||
94 | struct mii_bus *mii_bus; | 92 | struct mii_bus *mii_bus; |
95 | 93 | ||
96 | #if defined(CONFIG_BFIN_MAC_USE_HWSTAMP) | 94 | #if defined(CONFIG_BFIN_MAC_USE_HWSTAMP) |
97 | struct cyclecounter cycles; | 95 | u32 addend; |
98 | struct timecounter clock; | 96 | unsigned int shift; |
99 | struct timecompare compare; | ||
100 | struct hwtstamp_config stamp_cfg; | 97 | struct hwtstamp_config stamp_cfg; |
101 | #endif | 98 | #endif |
102 | }; | 99 | }; |