Title: [7427] trunk: initial check-in for BF518 IEEE 1588 PTP module driver
Revision
7427
Author
bhsong
Date
2009-09-23 05:53:54 -0400 (Wed, 23 Sep 2009)

Log Message

initial check-in for BF518 IEEE 1588 PTP module driver

Modified Paths


Diff

Modified: trunk/arch/blackfin/mach-bf518/include/mach/cdefBF518.h (7426 => 7427)


--- trunk/arch/blackfin/mach-bf518/include/mach/cdefBF518.h	2009-09-23 09:39:39 UTC (rev 7426)
+++ trunk/arch/blackfin/mach-bf518/include/mach/cdefBF518.h	2009-09-23 09:53:54 UTC (rev 7427)
@@ -211,46 +211,46 @@
 #define bfin_read_EMAC_TXC_ABORT()		bfin_read32(EMAC_TXC_ABORT)
 #define bfin_write_EMAC_TXC_ABORT(val)		bfin_write32(EMAC_TXC_ABORT, val)
 
-#define bfin_read_EMAC_PTP_CTL()                bfin_read32(EMAC_PTP_CTL)
-#define bfin_write_EMAC_PTP_CTL(val)            bfin_write32(EMAC_PTP_CTL, val)
-#define bfin_read_EMAC_PTP_IE()                 bfin_read32(EMAC_PTP_IE)
-#define bfin_write_EMAC_PTP_IE()                bfin_write32(EMAC_PTP_IE, val)
-#define bfin_read_EMAC_PTP_ISTAT()              bfin_read32(EMAC_PTP_ISTAT)
-#define bfin_write_EMAC_PTP_ISTAT()             bfin_write32(EMAC_PTP_ISTAT, val)
+#define bfin_read_EMAC_PTP_CTL()                bfin_read16(EMAC_PTP_CTL)
+#define bfin_write_EMAC_PTP_CTL(val)            bfin_write16(EMAC_PTP_CTL, val)
+#define bfin_read_EMAC_PTP_IE()                 bfin_read16(EMAC_PTP_IE)
+#define bfin_write_EMAC_PTP_IE(val)             bfin_write16(EMAC_PTP_IE, val)
+#define bfin_read_EMAC_PTP_ISTAT()              bfin_read16(EMAC_PTP_ISTAT)
+#define bfin_write_EMAC_PTP_ISTAT(val)          bfin_write16(EMAC_PTP_ISTAT, val)
 #define bfin_read_EMAC_PTP_FOFF()               bfin_read32(EMAC_PTP_FOFF)
-#define bfin_write_EMAC_PTP_FOFF()              bfin_write32(EMAC_PTP_FOFF, val)
+#define bfin_write_EMAC_PTP_FOFF(val)           bfin_write32(EMAC_PTP_FOFF, val)
 #define bfin_read_EMAC_PTP_FV1()                bfin_read32(EMAC_PTP_FV1)
-#define bfin_write_EMAC_PTP_FV1()               bfin_write32(EMAC_PTP_FV1, val)
+#define bfin_write_EMAC_PTP_FV1(val)            bfin_write32(EMAC_PTP_FV1, val)
 #define bfin_read_EMAC_PTP_FV2()                bfin_read32(EMAC_PTP_FV2)
-#define bfin_write_EMAC_PTP_FV2()               bfin_write32(EMAC_PTP_FV2, val)
+#define bfin_write_EMAC_PTP_FV2(val)            bfin_write32(EMAC_PTP_FV2, val)
 #define bfin_read_EMAC_PTP_FV3()                bfin_read32(EMAC_PTP_FV3)
-#define bfin_write_EMAC_PTP_FV3()               bfin_write32(EMAC_PTP_FV3, val)
+#define bfin_write_EMAC_PTP_FV3(val)            bfin_write32(EMAC_PTP_FV3, val)
 #define bfin_read_EMAC_PTP_ADDEND()             bfin_read32(EMAC_PTP_ADDEND)
-#define bfin_write_EMAC_PTP_ADDEND()            bfin_write32(EMAC_PTP_ADDEND, val)
+#define bfin_write_EMAC_PTP_ADDEND(val)         bfin_write32(EMAC_PTP_ADDEND, val)
 #define bfin_read_EMAC_PTP_ACCR()               bfin_read32(EMAC_PTP_ACCR)
-#define bfin_write_EMAC_PTP_ACCR()              bfin_write32(EMAC_PTP_ACCR, val)
+#define bfin_write_EMAC_PTP_ACCR(val)           bfin_write32(EMAC_PTP_ACCR, val)
 #define bfin_read_EMAC_PTP_OFFSET()             bfin_read32(EMAC_PTP_OFFSET)
-#define bfin_write_EMAC_PTP_OFFSET()            bfin_write32(EMAC_PTP_OFFSET, val)
+#define bfin_write_EMAC_PTP_OFFSET(val)         bfin_write32(EMAC_PTP_OFFSET, val)
 #define bfin_read_EMAC_PTP_TIMELO()             bfin_read32(EMAC_PTP_TIMELO)
-#define bfin_write_EMAC_PTP_TIMELO()            bfin_write32(EMAC_PTP_TIMELO, val)
+#define bfin_write_EMAC_PTP_TIMELO(val)         bfin_write32(EMAC_PTP_TIMELO, val)
 #define bfin_read_EMAC_PTP_TIMEHI()             bfin_read32(EMAC_PTP_TIMEHI)
-#define bfin_write_EMAC_PTP_TIMEHI()            bfin_write32(EMAC_PTP_TIMEHI, val)
+#define bfin_write_EMAC_PTP_TIMEHI(val)         bfin_write32(EMAC_PTP_TIMEHI, val)
 #define bfin_read_EMAC_PTP_RXSNAPLO()           bfin_read32(EMAC_PTP_RXSNAPLO)
 #define bfin_read_EMAC_PTP_RXSNAPHI()           bfin_read32(EMAC_PTP_RXSNAPHI)
 #define bfin_read_EMAC_PTP_TXSNAPLO()           bfin_read32(EMAC_PTP_TXSNAPLO)
 #define bfin_read_EMAC_PTP_TXSNAPHI()           bfin_read32(EMAC_PTP_TXSNAPHI)
 #define bfin_read_EMAC_PTP_ALARMLO()            bfin_read32(EMAC_PTP_ALARMLO)
-#define bfin_write_EMAC_PTP_ALARMLO()           bfin_write32(EMAC_PTP_ALARMLO, val)
+#define bfin_write_EMAC_PTP_ALARMLO(val)        bfin_write32(EMAC_PTP_ALARMLO, val)
 #define bfin_read_EMAC_PTP_ALARMHI()            bfin_read32(EMAC_PTP_ALARMHI)
-#define bfin_write_EMAC_PTP_ALARMHI()           bfin_write32(EMAC_PTP_ALARMHI, val)
-#define bfin_read_EMAC_PTP_ID_OFF()             bfin_read32(EMAC_PTP_ID_OFF)
-#define bfin_write_EMAC_PTP_ID_OFF()            bfin_write32(EMAC_PTP_ID_OFF, val)
+#define bfin_write_EMAC_PTP_ALARMHI(val)        bfin_write32(EMAC_PTP_ALARMHI, val)
+#define bfin_read_EMAC_PTP_ID_OFF()             bfin_read16(EMAC_PTP_ID_OFF)
+#define bfin_write_EMAC_PTP_ID_OFF(val)         bfin_write16(EMAC_PTP_ID_OFF, val)
 #define bfin_read_EMAC_PTP_ID_SNAP()            bfin_read32(EMAC_PTP_ID_SNAP)
-#define bfin_write_EMAC_PTP_ID_SNAP()           bfin_write32(EMAC_PTP_ID_SNAP, val)
+#define bfin_write_EMAC_PTP_ID_SNAP(val)        bfin_write32(EMAC_PTP_ID_SNAP, val)
 #define bfin_read_EMAC_PTP_PPS_STARTHI()        bfin_read32(EMAC_PTP_PPS_STARTHI)
-#define bfin_write_EMAC_PTP_PPS_STARTHI()       bfin_write32(EMAC_PTP_PPS_STARTHI, val)
+#define bfin_write_EMAC_PTP_PPS_STARTHI(val)    bfin_write32(EMAC_PTP_PPS_STARTHI, val)
 #define bfin_read_EMAC_PTP_PPS_PERIOD()         bfin_read32(EMAC_PTP_PPS_PERIOD)
-#define bfin_write_EMAC_PTP_PPS_PERIOD()        bfin_write32(EMAC_PTP_PPS_PERIOD, val)
+#define bfin_write_EMAC_PTP_PPS_PERIOD(val)     bfin_write32(EMAC_PTP_PPS_PERIOD, val)
 
 /* Removable Storage Interface Registers */
 

Modified: trunk/drivers/net/Kconfig (7426 => 7427)


--- trunk/drivers/net/Kconfig	2009-09-23 09:39:39 UTC (rev 7426)
+++ trunk/drivers/net/Kconfig	2009-09-23 09:53:54 UTC (rev 7427)
@@ -875,6 +875,13 @@
 	help
 	  Use Reduced PHY MII Interface
 
+config BFIN_MAC_USE_HWSTAMP
+	bool "Use IEEE 1588 hwstamp"
+	depends on BFIN_MAC && BF518
+	default y
+	help
+	  To support IEEE 1588 Precision Time Protocol(PTP), selete y here
+
 config SMC9194
 	tristate "SMC 9194 support"
 	depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)

Modified: trunk/drivers/net/bfin_mac.c (7426 => 7427)


--- trunk/drivers/net/bfin_mac.c	2009-09-23 09:39:39 UTC (rev 7426)
+++ trunk/drivers/net/bfin_mac.c	2009-09-23 09:53:54 UTC (rev 7427)
@@ -561,6 +561,259 @@
 	return 0;
 }
 
+#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
+static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
+		struct ifreq *ifr, int cmd)
+{
+	struct hwtstamp_config config;
+	struct bfin_mac_local *lp = netdev_priv(netdev);
+	u16 ptpctl;
+	u32 ptpfv1, ptpfv2, ptpfv3, ptpfoff;
+
+	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	pr_debug("%s config flag:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
+			__func__, config.flags, config.tx_type, config.rx_filter);
+
+	/* reserved for future extensions */
+	if (config.flags)
+		return -EINVAL;
+
+	if ((config.tx_type != HWTSTAMP_TX_OFF) &&
+			(config.tx_type != HWTSTAMP_TX_ON))
+		return -ERANGE;
+
+	ptpctl = bfin_read_EMAC_PTP_CTL();
+
+	switch (config.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		/*
+		 * Dont allow any timestamping
+		 */
+		ptpfv3 = 0xFFFFFFFF;
+		bfin_write_EMAC_PTP_FV3(ptpfv3);
+		break;
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+		/*
+		 * Clear the five comparison mask bits (bits[12:8]) in EMAC_PTP_CTL)
+		 * to enable all the field matches.
+		 */
+		ptpctl &= ~0x1F00;
+		bfin_write_EMAC_PTP_CTL(ptpctl);
+		/*
+		 * Keep the default values of the EMAC_PTP_FOFF register.
+		 */
+		ptpfoff = 0x4A24170C;
+		bfin_write_EMAC_PTP_FOFF(ptpfoff);
+		/*
+		 * Keep the default values of the EMAC_PTP_FV1 and EMAC_PTP_FV2
+		 * registers.
+		 */
+		ptpfv1 = 0x11040800;
+		bfin_write_EMAC_PTP_FV1(ptpfv1);
+		ptpfv2 = 0x0140013F;
+		bfin_write_EMAC_PTP_FV2(ptpfv2);
+		/*
+		 * The default value (0xFFFC) allows the timestamping of both
+		 * received Sync messages and Delay_Req messages.
+		 */
+		ptpfv3 = 0xFFFFFFFC;
+		bfin_write_EMAC_PTP_FV3(ptpfv3);
+
+		config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
+		break;
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		/* Clear all five comparison mask bits (bits[12:8]) in the
+		 * EMAC_PTP_CTL register to enable all the field matches.
+		 */
+		ptpctl &= ~0x1F00;
+		bfin_write_EMAC_PTP_CTL(ptpctl);
+		/*
+		 * Keep the default values of the EMAC_PTP_FOFF register, except set
+		 * the PTPCOF field to 0x2A.
+		 */
+		ptpfoff = 0x2A24170C;
+		bfin_write_EMAC_PTP_FOFF(ptpfoff);
+		/*
+		 * Keep the default values of the EMAC_PTP_FV1 and EMAC_PTP_FV2
+		 * registers.
+		 */
+		ptpfv1 = 0x11040800;
+		bfin_write_EMAC_PTP_FV1(ptpfv1);
+		ptpfv2 = 0x0140013F;
+		bfin_write_EMAC_PTP_FV2(ptpfv2);
+		/*
+		 * To allow the timestamping of Pdelay_Req and Pdelay_Resp, set
+		 * the value to 0xFFF0.
+		 */
+		ptpfv3 = 0xFFFFFFF0;
+		bfin_write_EMAC_PTP_FV3(ptpfv3);
+
+		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
+		break;
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+		/*
+		 * Clear bits 8 and 12 of the EMAC_PTP_CTL register to enable only the
+		 * EFTM and PTPCM field comparison.
+		 */
+		ptpctl &= ~0x1100;
+		bfin_write_EMAC_PTP_CTL(ptpctl);
+		/*
+		 * Keep the default values of all the fields of the EMAC_PTP_FOFF
+		 * register, except set the PTPCOF field to 0x0E.
+		 */
+		ptpfoff = 0x0E24170C;
+		bfin_write_EMAC_PTP_FOFF(ptpfoff);
+		/*
+		 * Program bits [15:0] of the EMAC_PTP_FV1 register to 0x88F7, which
+		 * corresponds to PTP messages on the MAC layer.
+		 */
+		ptpfv1 = 0x110488F7;
+		bfin_write_EMAC_PTP_FV1(ptpfv1);
+		ptpfv2 = 0x0140013F;
+		bfin_write_EMAC_PTP_FV2(ptpfv2);
+		/*
+		 * To allow the timestamping of Pdelay_Req and Pdelay_Resp
+		 * messages, set the value to 0xFFF0.
+		 */
+		ptpfv3 = 0xFFFFFFF0;
+		bfin_write_EMAC_PTP_FV3(ptpfv3);
+
+		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	if ((config.tx_type == HWTSTAMP_TX_OFF) &&
+			(config.rx_filter == HWTSTAMP_FILTER_NONE))
+		ptpctl &= ~PTP_EN;
+	else
+		ptpctl |= PTP_EN;
+	bfin_write_EMAC_PTP_CTL(ptpctl);
+
+	SSYNC();
+
+	pr_debug("%s PTP setting ptpctl:%x ptpfv1:%x ptpfv2:%x ptpfv3:%x ptpfoff:%x\n",
+			__func__, ptpctl, ptpfv1, ptpfv2, ptpfv3, ptpfoff);
+
+	lp->stamp_cfg = config;
+	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+		-EFAULT : 0;
+}
+
+#ifdef DEBUG
+static void pr_dump_ptp_skb(char *str, struct sk_buff *skb)
+{
+	if ((skb->data[23] == 0x11) && (*(u16 *)(skb->data + 36) == 0x3F01)) {
+		pr_debug("%s dump\n", str);
+		pr_debug("MAC frame type:%02x%02x\n", skb->data[12], skb->data[13]);
+		pr_debug("IP version:%02x\n", skb->data[14]);
+		pr_debug("Layer 4 protocol:%02x\n", skb->data[23]);
+		pr_debug("UDP source port:%02x%02x\n", skb->data[34], skb->data[35]);
+		pr_debug("UDP destination port:%02x%02x\n", skb->data[36], skb->data[37]);
+		pr_debug("PTP control:%02x\n\n", skb->data[74]);
+	}
+}
+#else
+#define pr_dump_ptp_skb(p1, p2)
+#endif
+
+static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
+{
+	struct bfin_mac_local *lp = netdev_priv(netdev);
+	union skb_shared_tx *shtx = skb_tx(skb);
+
+	if (shtx->hardware) {
+		int timeout_cnt = MAX_TIMEOUT_CNT;
+
+		pr_dump_ptp_skb("tx packet", skb);
+
+		/* When doing time stamping, keep the connection to the socket
+		 * a while longer
+		 */
+		shtx->in_progress = 1;
+
+		/*
+		 * The timestamping is done at the EMAC module's MII/RMII interface
+		 * when the module sees the Start of Frame of an event message packet. This
+		 * interface is the closest possible place to the physical Ethernet transmission
+		 * medium, providing the best timing accuracy.
+		 */
+		while ((!(bfin_read_EMAC_PTP_ISTAT() & TXTL)) && (--timeout_cnt))
+			udelay(1);
+		if (timeout_cnt == 0)
+			printk(KERN_ERR DRV_NAME
+					": fails to timestamp the TX packet\n");
+		else {
+			struct skb_shared_hwtstamps shhwtstamps;
+			u64 ns;
+			u64 regval;
+
+			regval = bfin_read_EMAC_PTP_TXSNAPLO();
+			regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32;
+			memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+			ns = timecounter_cyc2time(&lp->clock,
+					regval);
+			timecompare_update(&lp->compare, ns);
+			shhwtstamps.hwtstamp = ns_to_ktime(ns);
+			shhwtstamps.syststamp =
+				timecompare_transform(&lp->compare, ns);
+			skb_tstamp_tx(skb, &shhwtstamps);
+
+			pr_debug("%s tx time counter:%016llx\n", __func__, regval);
+		}
+	}
+}
+
+static void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
+{
+	struct bfin_mac_local *lp = netdev_priv(netdev);
+
+	if (lp->stamp_cfg.rx_filter != HWTSTAMP_FILTER_NONE) {
+		u32 valid = bfin_read_EMAC_PTP_ISTAT() & RXEL;
+		if (valid) {
+			u64 regval;
+			u64 ns;
+			struct skb_shared_hwtstamps *shhwtstamps =
+				skb_hwtstamps(skb);
+
+			regval = bfin_read_EMAC_PTP_RXSNAPLO();
+			regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32;
+			ns = timecounter_cyc2time(&lp->clock, regval);
+			timecompare_update(&lp->compare, ns);
+			memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+			shhwtstamps->hwtstamp = ns_to_ktime(ns);
+			shhwtstamps->syststamp =
+				timecompare_transform(&lp->compare, ns);
+
+			pr_debug("%s rx time counter:%016llx\n", __func__, regval);
+		}
+	}
+}
+
+/*
+ * bfin_read_clock - read raw cycle counter (to be used by time counter)
+ */
+static cycle_t bfin_read_clock(const struct cyclecounter *tc)
+{
+	u64 stamp;
+
+	stamp =  bfin_read_EMAC_PTP_TIMELO();
+	stamp |= (u64)bfin_read_EMAC_PTP_TIMEHI() << 32ULL;
+
+	return stamp;
+}
+
+#endif
+
 static void adjust_tx_list(void)
 {
 	int timeout_cnt = MAX_TIMEOUT_CNT;
@@ -618,18 +871,32 @@
 {
 	u16 *data;
 	u32 data_align = (unsigned long)(skb->data) & 0x3;
+	union skb_shared_tx *shtx = skb_tx(skb);
+
 	current_tx_ptr->skb = skb;
 
 	if (data_align == 0x2) {
 		/* move skb->data to current_tx_ptr payload */
 		data = "" *)(skb->data) - 1;
-				*data = ""
+		*data = ""
+		/*
+		 * When transmitting an Ethernet packet, the PTP_TSYNC module requires
+		 * a DMA_Length_Word field associated with the packet. The lower 12 bits
+		 * of this field are the length of the packet payload in bytes and the higher
+		 * 4 bits are the timestamping enable field.
+		 */
+		if (shtx->hardware)
+			*data |= 0x1000;
+
 		current_tx_ptr->desc_a.start_addr = (u32)data;
 		/* this is important! */
 		blackfin_dcache_flush_range((u32)data,
 				(u32)((u8 *)data + skb->len + 4));
 	} else {
 		*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
+		/* enable timestamping for the sent packet */
+		if (shtx->hardware)
+			*((u16 *)(current_tx_ptr->packet)) |= 0x1000;
 		memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
 			skb->len);
 		current_tx_ptr->desc_a.start_addr =
@@ -663,20 +930,32 @@
 
 out:
 	adjust_tx_list();
+
+#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
+	bfin_tx_hwtstamp(dev, skb);
+#endif
+
 	current_tx_ptr = current_tx_ptr->next;
 	dev->trans_start = jiffies;
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += (skb->len);
-	return 0;
+	return NETDEV_TX_OK;
 }
 
 static void bfin_mac_rx(struct net_device *dev)
 {
 	struct sk_buff *skb, *new_skb;
 	unsigned short len;
+	struct bfin_mac_local *lp = netdev_priv(dev);
 
 	/* allocate a new skb for next time receive */
 	skb = current_rx_ptr->skb;
+
+#if defined(CONFIG_BFIN_MAC_USE_HWSTAMP)
+	if (lp->stamp_cfg.rx_filter != HWTSTAMP_FILTER_NONE)
+		pr_dump_ptp_skb("rx packet", skb);
+#endif
+
 	new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
 	if (!new_skb) {
 		printk(KERN_NOTICE DRV_NAME
@@ -701,6 +980,11 @@
 					 (unsigned long)skb->tail);
 
 	skb->protocol = eth_type_trans(skb, dev);
+
+#if defined(CONFIG_BFIN_MAC_USE_HWSTAMP)
+	bfin_rx_hwtstamp(dev, skb);
+#endif
+
 #if defined(BFIN_MAC_CSUM_OFFLOAD)
 	skb->csum = current_rx_ptr->status.ip_payload_csum;
 	skb->ip_summed = CHECKSUM_COMPLETE;
@@ -886,6 +1170,18 @@
 	}
 }
 
+static int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	switch (cmd) {
+#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
+	case SIOCSHWTSTAMP:
+		return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd);
+#endif
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 /*
  * this puts the device in an inactive state
  */
@@ -970,6 +1266,7 @@
 	.ndo_set_mac_address	= bfin_mac_set_mac_address,
 	.ndo_tx_timeout		= bfin_mac_timeout,
 	.ndo_set_multicast_list	= bfin_mac_set_multicast_list,
+	.ndo_do_ioctl           = bfin_mac_ioctl,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1061,6 +1358,36 @@
 		goto out_err_reg_ndev;
 	}
 
+#if defined(CONFIG_BFIN_MAC_USE_HWSTAMP)
+	/*
+	 * Initialize hardware timer
+	 */
+	memset(&lp->cycles, 0, sizeof(lp->cycles));
+	lp->cycles.read = bfin_read_clock;
+	lp->cycles.mask = CLOCKSOURCE_MASK(64);
+	bfin_write_EMAC_PTP_ADDEND(0xA0000000); /* PTP freq = 50Mhz */
+	lp->cycles.mult = 20;
+	lp->cycles.shift = 0;
+	timecounter_init(&lp->clock,
+			&lp->cycles,
+			ktime_to_ns(ktime_get_real()));
+
+	/*
+	 * Synchronize our NIC clock against system wall clock
+	 */
+	memset(&lp->compare, 0, sizeof(lp->compare));
+	lp->compare.source = &lp->clock;
+	lp->compare.target = ktime_get_real;
+	lp->compare.num_samples = 10;
+	timecompare_update(&lp->compare, 0);
+
+	/*
+	 * Initialize hwstamp config
+	 */
+	lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
+	lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF;
+#endif
+
 	/* now, print out the card info, in a short format.. */
 	dev_info(&pdev->dev, "%s, Version %s\n", DRV_DESC, DRV_VERSION);
 

Modified: trunk/drivers/net/bfin_mac.h (7426 => 7427)


--- trunk/drivers/net/bfin_mac.h	2009-09-23 09:39:39 UTC (rev 7426)
+++ trunk/drivers/net/bfin_mac.h	2009-09-23 09:53:54 UTC (rev 7427)
@@ -7,7 +7,13 @@
  *
  * Licensed under the GPL-2 or later.
  */
+#ifndef _BFIN_MAC_H_
+#define _BFIN_MAC_H_
 
+#include <linux/net_tstamp.h>
+#include <linux/clocksource.h>
+#include <linux/timecompare.h>
+
 #define BFIN_MAC_CSUM_OFFLOAD
 
 struct dma_descriptor {
@@ -67,6 +73,15 @@
 
 	struct phy_device *phydev;
 	struct mii_bus *mii_bus;
+
+#if defined(CONFIG_BFIN_MAC_USE_HWSTAMP)
+	struct cyclecounter cycles;
+	struct timecounter clock;
+	struct timecompare compare;
+	struct hwtstamp_config stamp_cfg;
+#endif
 };
 
 extern void bfin_get_ether_addr(char *addr);
+
+#endif
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to