All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 net-next 0/9] lan743x: Add features to lan743x driver
@ 2018-07-12 19:04 Bryan Whitehead
  2018-07-12 19:04 ` [PATCH v2 net-next 1/9] lan743x: Add support for ethtool get_drvinfo Bryan Whitehead
                   ` (8 more replies)
  0 siblings, 9 replies; 23+ messages in thread
From: Bryan Whitehead @ 2018-07-12 19:04 UTC (permalink / raw)
  To: davem; +Cc: netdev, UNGLinuxDriver, richardcochran

This patch series adds extra features to the lan743x driver.

Updates for V2:
Patch 3/9 - Used ARRAY_SIZE macro in lan743x_ethtool_get_ethtool_stats.
Patch 5/9 - Used MAX_EEPROM_SIZE in lan743x_ethtool_set_eeprom.
Patch 6/9 - Removed unnecessary read of PMT_CTL.
	    Used CRC algorithm from lib.
	    Removed PHY interrupt settings from lan743x_pm_suspend
	    Change "#if CONFIG_PM" to "#ifdef CONFIG_PM"

Bryan Whitehead (9):
  lan743x: Add support for ethtool get_drvinfo
  lan743x: Add support for ethtool link settings
  lan743x: Add support for ethtool statistics
  lan743x: Add support for ethtool message level
  lan743x: Add support for ethtool eeprom access
  lan743x: Add power management support
  lan743x: Add EEE support
  lan743x: Add RSS support
  lan743x: Add PTP support

 drivers/net/ethernet/microchip/Makefile          |    2 +-
 drivers/net/ethernet/microchip/lan743x_ethtool.c |  729 +++++++++++++
 drivers/net/ethernet/microchip/lan743x_ethtool.h |   11 +
 drivers/net/ethernet/microchip/lan743x_main.c    |  293 +++++-
 drivers/net/ethernet/microchip/lan743x_main.h    |  229 ++++-
 drivers/net/ethernet/microchip/lan743x_ptp.c     | 1194 ++++++++++++++++++++++
 drivers/net/ethernet/microchip/lan743x_ptp.h     |   78 ++
 7 files changed, 2528 insertions(+), 8 deletions(-)
 create mode 100644 drivers/net/ethernet/microchip/lan743x_ethtool.c
 create mode 100644 drivers/net/ethernet/microchip/lan743x_ethtool.h
 create mode 100644 drivers/net/ethernet/microchip/lan743x_ptp.c
 create mode 100644 drivers/net/ethernet/microchip/lan743x_ptp.h

-- 
2.7.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 1/9] lan743x: Add support for ethtool get_drvinfo
  2018-07-12 19:04 [PATCH v2 net-next 0/9] lan743x: Add features to lan743x driver Bryan Whitehead
@ 2018-07-12 19:04 ` Bryan Whitehead
  2018-07-12 22:28   ` Andrew Lunn
  2018-07-12 19:04 ` [PATCH v2 net-next 2/9] lan743x: Add support for ethtool link settings Bryan Whitehead
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Bryan Whitehead @ 2018-07-12 19:04 UTC (permalink / raw)
  To: davem; +Cc: netdev, UNGLinuxDriver, richardcochran

Implement ethtool get_drvinfo

Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>
---
 drivers/net/ethernet/microchip/Makefile          |  2 +-
 drivers/net/ethernet/microchip/lan743x_ethtool.c | 21 +++++++++++++++++++++
 drivers/net/ethernet/microchip/lan743x_ethtool.h | 11 +++++++++++
 drivers/net/ethernet/microchip/lan743x_main.c    |  2 ++
 4 files changed, 35 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/microchip/lan743x_ethtool.c
 create mode 100644 drivers/net/ethernet/microchip/lan743x_ethtool.h

diff --git a/drivers/net/ethernet/microchip/Makefile b/drivers/net/ethernet/microchip/Makefile
index 2e982cc..43f47cb 100644
--- a/drivers/net/ethernet/microchip/Makefile
+++ b/drivers/net/ethernet/microchip/Makefile
@@ -6,4 +6,4 @@ obj-$(CONFIG_ENC28J60) += enc28j60.o
 obj-$(CONFIG_ENCX24J600) += encx24j600.o encx24j600-regmap.o
 obj-$(CONFIG_LAN743X) += lan743x.o
 
-lan743x-objs := lan743x_main.o
+lan743x-objs := lan743x_main.o lan743x_ethtool.o
diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
new file mode 100644
index 0000000..0e20758
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (C) 2018 Microchip Technology Inc. */
+
+#include <linux/netdevice.h>
+#include "lan743x_main.h"
+#include "lan743x_ethtool.h"
+#include <linux/pci.h>
+
+static void lan743x_ethtool_get_drvinfo(struct net_device *netdev,
+					struct ethtool_drvinfo *info)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+	strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
+	strlcpy(info->bus_info,
+		pci_name(adapter->pdev), sizeof(info->bus_info));
+}
+
+const struct ethtool_ops lan743x_ethtool_ops = {
+	.get_drvinfo = lan743x_ethtool_get_drvinfo,
+};
diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.h b/drivers/net/ethernet/microchip/lan743x_ethtool.h
new file mode 100644
index 0000000..d0d11a7
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (C) 2018 Microchip Technology Inc. */
+
+#ifndef _LAN743X_ETHTOOL_H
+#define _LAN743X_ETHTOOL_H
+
+#include "linux/ethtool.h"
+
+extern const struct ethtool_ops lan743x_ethtool_ops;
+
+#endif /* _LAN743X_ETHTOOL_H */
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index e1747a4..ade3b04 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -12,6 +12,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/iopoll.h>
 #include "lan743x_main.h"
+#include "lan743x_ethtool.h"
 
 static void lan743x_pci_cleanup(struct lan743x_adapter *adapter)
 {
@@ -2689,6 +2690,7 @@ static int lan743x_pcidev_probe(struct pci_dev *pdev,
 		goto cleanup_hardware;
 
 	adapter->netdev->netdev_ops = &lan743x_netdev_ops;
+	adapter->netdev->ethtool_ops = &lan743x_ethtool_ops;
 	adapter->netdev->features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_CSUM;
 	adapter->netdev->hw_features = adapter->netdev->features;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 2/9] lan743x: Add support for ethtool link settings
  2018-07-12 19:04 [PATCH v2 net-next 0/9] lan743x: Add features to lan743x driver Bryan Whitehead
  2018-07-12 19:04 ` [PATCH v2 net-next 1/9] lan743x: Add support for ethtool get_drvinfo Bryan Whitehead
@ 2018-07-12 19:04 ` Bryan Whitehead
  2018-07-12 22:29   ` Andrew Lunn
  2018-07-12 19:05 ` [PATCH v2 net-next 3/9] lan743x: Add support for ethtool statistics Bryan Whitehead
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Bryan Whitehead @ 2018-07-12 19:04 UTC (permalink / raw)
  To: davem; +Cc: netdev, UNGLinuxDriver, richardcochran

Use default link setting functions

Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>
---
 drivers/net/ethernet/microchip/lan743x_ethtool.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
index 0e20758..5c4582c 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -5,6 +5,7 @@
 #include "lan743x_main.h"
 #include "lan743x_ethtool.h"
 #include <linux/pci.h>
+#include <linux/phy.h>
 
 static void lan743x_ethtool_get_drvinfo(struct net_device *netdev,
 					struct ethtool_drvinfo *info)
@@ -18,4 +19,8 @@ static void lan743x_ethtool_get_drvinfo(struct net_device *netdev,
 
 const struct ethtool_ops lan743x_ethtool_ops = {
 	.get_drvinfo = lan743x_ethtool_get_drvinfo,
+	.get_link = ethtool_op_get_link,
+
+	.get_link_ksettings = phy_ethtool_get_link_ksettings,
+	.set_link_ksettings = phy_ethtool_set_link_ksettings,
 };
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 3/9] lan743x: Add support for ethtool statistics
  2018-07-12 19:04 [PATCH v2 net-next 0/9] lan743x: Add features to lan743x driver Bryan Whitehead
  2018-07-12 19:04 ` [PATCH v2 net-next 1/9] lan743x: Add support for ethtool get_drvinfo Bryan Whitehead
  2018-07-12 19:04 ` [PATCH v2 net-next 2/9] lan743x: Add support for ethtool link settings Bryan Whitehead
@ 2018-07-12 19:05 ` Bryan Whitehead
  2018-07-12 22:31   ` Andrew Lunn
  2018-07-12 19:05 ` [PATCH v2 net-next 4/9] lan743x: Add support for ethtool message level Bryan Whitehead
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Bryan Whitehead @ 2018-07-12 19:05 UTC (permalink / raw)
  To: davem; +Cc: netdev, UNGLinuxDriver, richardcochran

Implement ethtool statistics

Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>
---
 drivers/net/ethernet/microchip/lan743x_ethtool.c | 180 +++++++++++++++++++++++
 drivers/net/ethernet/microchip/lan743x_main.c    |   6 +-
 drivers/net/ethernet/microchip/lan743x_main.h    |  31 ++++
 3 files changed, 214 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
index 5c4582c..9ed9711 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -17,10 +17,190 @@ static void lan743x_ethtool_get_drvinfo(struct net_device *netdev,
 		pci_name(adapter->pdev), sizeof(info->bus_info));
 }
 
+static const char lan743x_set0_hw_cnt_strings[][ETH_GSTRING_LEN] = {
+	"RX FCS Errors",
+	"RX Alignment Errors",
+	"Rx Fragment Errors",
+	"RX Jabber Errors",
+	"RX Undersize Frame Errors",
+	"RX Oversize Frame Errors",
+	"RX Dropped Frames",
+	"RX Unicast Byte Count",
+	"RX Broadcast Byte Count",
+	"RX Multicast Byte Count",
+	"RX Unicast Frames",
+	"RX Broadcast Frames",
+	"RX Multicast Frames",
+	"RX Pause Frames",
+	"RX 64 Byte Frames",
+	"RX 65 - 127 Byte Frames",
+	"RX 128 - 255 Byte Frames",
+	"RX 256 - 511 Bytes Frames",
+	"RX 512 - 1023 Byte Frames",
+	"RX 1024 - 1518 Byte Frames",
+	"RX Greater 1518 Byte Frames",
+};
+
+static const char lan743x_set1_sw_cnt_strings[][ETH_GSTRING_LEN] = {
+	"RX Queue 0 Frames",
+	"RX Queue 1 Frames",
+	"RX Queue 2 Frames",
+	"RX Queue 3 Frames",
+};
+
+static const char lan743x_set2_hw_cnt_strings[][ETH_GSTRING_LEN] = {
+	"RX Total Frames",
+	"EEE RX LPI Transitions",
+	"EEE RX LPI Time",
+	"RX Counter Rollover Status",
+	"TX FCS Errors",
+	"TX Excess Deferral Errors",
+	"TX Carrier Errors",
+	"TX Bad Byte Count",
+	"TX Single Collisions",
+	"TX Multiple Collisions",
+	"TX Excessive Collision",
+	"TX Late Collisions",
+	"TX Unicast Byte Count",
+	"TX Broadcast Byte Count",
+	"TX Multicast Byte Count",
+	"TX Unicast Frames",
+	"TX Broadcast Frames",
+	"TX Multicast Frames",
+	"TX Pause Frames",
+	"TX 64 Byte Frames",
+	"TX 65 - 127 Byte Frames",
+	"TX 128 - 255 Byte Frames",
+	"TX 256 - 511 Bytes Frames",
+	"TX 512 - 1023 Byte Frames",
+	"TX 1024 - 1518 Byte Frames",
+	"TX Greater 1518 Byte Frames",
+	"TX Total Frames",
+	"EEE TX LPI Transitions",
+	"EEE TX LPI Time",
+	"TX Counter Rollover Status",
+};
+
+static const u32 lan743x_set0_hw_cnt_addr[] = {
+	STAT_RX_FCS_ERRORS,
+	STAT_RX_ALIGNMENT_ERRORS,
+	STAT_RX_FRAGMENT_ERRORS,
+	STAT_RX_JABBER_ERRORS,
+	STAT_RX_UNDERSIZE_FRAME_ERRORS,
+	STAT_RX_OVERSIZE_FRAME_ERRORS,
+	STAT_RX_DROPPED_FRAMES,
+	STAT_RX_UNICAST_BYTE_COUNT,
+	STAT_RX_BROADCAST_BYTE_COUNT,
+	STAT_RX_MULTICAST_BYTE_COUNT,
+	STAT_RX_UNICAST_FRAMES,
+	STAT_RX_BROADCAST_FRAMES,
+	STAT_RX_MULTICAST_FRAMES,
+	STAT_RX_PAUSE_FRAMES,
+	STAT_RX_64_BYTE_FRAMES,
+	STAT_RX_65_127_BYTE_FRAMES,
+	STAT_RX_128_255_BYTE_FRAMES,
+	STAT_RX_256_511_BYTES_FRAMES,
+	STAT_RX_512_1023_BYTE_FRAMES,
+	STAT_RX_1024_1518_BYTE_FRAMES,
+	STAT_RX_GREATER_1518_BYTE_FRAMES,
+};
+
+static const u32 lan743x_set2_hw_cnt_addr[] = {
+	STAT_RX_TOTAL_FRAMES,
+	STAT_EEE_RX_LPI_TRANSITIONS,
+	STAT_EEE_RX_LPI_TIME,
+	STAT_RX_COUNTER_ROLLOVER_STATUS,
+	STAT_TX_FCS_ERRORS,
+	STAT_TX_EXCESS_DEFERRAL_ERRORS,
+	STAT_TX_CARRIER_ERRORS,
+	STAT_TX_BAD_BYTE_COUNT,
+	STAT_TX_SINGLE_COLLISIONS,
+	STAT_TX_MULTIPLE_COLLISIONS,
+	STAT_TX_EXCESSIVE_COLLISION,
+	STAT_TX_LATE_COLLISIONS,
+	STAT_TX_UNICAST_BYTE_COUNT,
+	STAT_TX_BROADCAST_BYTE_COUNT,
+	STAT_TX_MULTICAST_BYTE_COUNT,
+	STAT_TX_UNICAST_FRAMES,
+	STAT_TX_BROADCAST_FRAMES,
+	STAT_TX_MULTICAST_FRAMES,
+	STAT_TX_PAUSE_FRAMES,
+	STAT_TX_64_BYTE_FRAMES,
+	STAT_TX_65_127_BYTE_FRAMES,
+	STAT_TX_128_255_BYTE_FRAMES,
+	STAT_TX_256_511_BYTES_FRAMES,
+	STAT_TX_512_1023_BYTE_FRAMES,
+	STAT_TX_1024_1518_BYTE_FRAMES,
+	STAT_TX_GREATER_1518_BYTE_FRAMES,
+	STAT_TX_TOTAL_FRAMES,
+	STAT_EEE_TX_LPI_TRANSITIONS,
+	STAT_EEE_TX_LPI_TIME,
+	STAT_TX_COUNTER_ROLLOVER_STATUS
+};
+
+static void lan743x_ethtool_get_strings(struct net_device *netdev,
+					u32 stringset, u8 *data)
+{
+	switch (stringset) {
+	case ETH_SS_STATS:
+		memcpy(data, lan743x_set0_hw_cnt_strings,
+		       sizeof(lan743x_set0_hw_cnt_strings));
+		memcpy(&data[sizeof(lan743x_set0_hw_cnt_strings)],
+		       lan743x_set1_sw_cnt_strings,
+		       sizeof(lan743x_set1_sw_cnt_strings));
+		memcpy(&data[sizeof(lan743x_set0_hw_cnt_strings) +
+		       sizeof(lan743x_set1_sw_cnt_strings)],
+		       lan743x_set2_hw_cnt_strings,
+		       sizeof(lan743x_set2_hw_cnt_strings));
+		break;
+	}
+}
+
+static void lan743x_ethtool_get_ethtool_stats(struct net_device *netdev,
+					      struct ethtool_stats *stats,
+					      u64 *data)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+	int data_index = 0;
+	u32 buf;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lan743x_set0_hw_cnt_addr); i++) {
+		buf = lan743x_csr_read(adapter, lan743x_set0_hw_cnt_addr[i]);
+		data[data_index++] = (u64)buf;
+	}
+	for (i = 0; i < ARRAY_SIZE(adapter->rx); i++)
+		data[data_index++] = (u64)(adapter->rx[i].frame_count);
+	for (i = 0; i < ARRAY_SIZE(lan743x_set2_hw_cnt_addr); i++) {
+		buf = lan743x_csr_read(adapter, lan743x_set2_hw_cnt_addr[i]);
+		data[data_index++] = (u64)buf;
+	}
+}
+
+static int lan743x_ethtool_get_sset_count(struct net_device *netdev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+	{
+		int ret;
+
+		ret = ARRAY_SIZE(lan743x_set0_hw_cnt_strings);
+		ret += ARRAY_SIZE(lan743x_set1_sw_cnt_strings);
+		ret += ARRAY_SIZE(lan743x_set2_hw_cnt_strings);
+		return ret;
+	}
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 const struct ethtool_ops lan743x_ethtool_ops = {
 	.get_drvinfo = lan743x_ethtool_get_drvinfo,
 	.get_link = ethtool_op_get_link,
 
+	.get_strings = lan743x_ethtool_get_strings,
+	.get_ethtool_stats = lan743x_ethtool_get_ethtool_stats,
+	.get_sset_count = lan743x_ethtool_get_sset_count,
 	.get_link_ksettings = phy_ethtool_get_link_ksettings,
 	.set_link_ksettings = phy_ethtool_set_link_ksettings,
 };
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index ade3b04..1e2f8c6 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -54,13 +54,13 @@ static int lan743x_pci_init(struct lan743x_adapter *adapter,
 	return ret;
 }
 
-static u32 lan743x_csr_read(struct lan743x_adapter *adapter, int offset)
+u32 lan743x_csr_read(struct lan743x_adapter *adapter, int offset)
 {
 	return ioread32(&adapter->csr.csr_address[offset]);
 }
 
-static void lan743x_csr_write(struct lan743x_adapter *adapter, int offset,
-			      u32 data)
+void lan743x_csr_write(struct lan743x_adapter *adapter, int offset,
+		       u32 data)
 {
 	iowrite32(data, &adapter->csr.csr_address[offset]);
 }
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index 73b463a..de4f2cc 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -291,6 +291,7 @@
 /* MAC statistics registers */
 #define STAT_RX_FCS_ERRORS			(0x1200)
 #define STAT_RX_ALIGNMENT_ERRORS		(0x1204)
+#define STAT_RX_FRAGMENT_ERRORS			(0x1208)
 #define STAT_RX_JABBER_ERRORS			(0x120C)
 #define STAT_RX_UNDERSIZE_FRAME_ERRORS		(0x1210)
 #define STAT_RX_OVERSIZE_FRAME_ERRORS		(0x1214)
@@ -298,12 +299,26 @@
 #define STAT_RX_UNICAST_BYTE_COUNT		(0x121C)
 #define STAT_RX_BROADCAST_BYTE_COUNT		(0x1220)
 #define STAT_RX_MULTICAST_BYTE_COUNT		(0x1224)
+#define STAT_RX_UNICAST_FRAMES			(0x1228)
+#define STAT_RX_BROADCAST_FRAMES		(0x122C)
 #define STAT_RX_MULTICAST_FRAMES		(0x1230)
+#define STAT_RX_PAUSE_FRAMES			(0x1234)
+#define STAT_RX_64_BYTE_FRAMES			(0x1238)
+#define STAT_RX_65_127_BYTE_FRAMES		(0x123C)
+#define STAT_RX_128_255_BYTE_FRAMES		(0x1240)
+#define STAT_RX_256_511_BYTES_FRAMES		(0x1244)
+#define STAT_RX_512_1023_BYTE_FRAMES		(0x1248)
+#define STAT_RX_1024_1518_BYTE_FRAMES		(0x124C)
+#define STAT_RX_GREATER_1518_BYTE_FRAMES	(0x1250)
 #define STAT_RX_TOTAL_FRAMES			(0x1254)
+#define STAT_EEE_RX_LPI_TRANSITIONS		(0x1258)
+#define STAT_EEE_RX_LPI_TIME			(0x125C)
+#define STAT_RX_COUNTER_ROLLOVER_STATUS		(0x127C)
 
 #define STAT_TX_FCS_ERRORS			(0x1280)
 #define STAT_TX_EXCESS_DEFERRAL_ERRORS		(0x1284)
 #define STAT_TX_CARRIER_ERRORS			(0x1288)
+#define STAT_TX_BAD_BYTE_COUNT			(0x128C)
 #define STAT_TX_SINGLE_COLLISIONS		(0x1290)
 #define STAT_TX_MULTIPLE_COLLISIONS		(0x1294)
 #define STAT_TX_EXCESSIVE_COLLISION		(0x1298)
@@ -311,8 +326,21 @@
 #define STAT_TX_UNICAST_BYTE_COUNT		(0x12A0)
 #define STAT_TX_BROADCAST_BYTE_COUNT		(0x12A4)
 #define STAT_TX_MULTICAST_BYTE_COUNT		(0x12A8)
+#define STAT_TX_UNICAST_FRAMES			(0x12AC)
+#define STAT_TX_BROADCAST_FRAMES		(0x12B0)
 #define STAT_TX_MULTICAST_FRAMES		(0x12B4)
+#define STAT_TX_PAUSE_FRAMES			(0x12B8)
+#define STAT_TX_64_BYTE_FRAMES			(0x12BC)
+#define STAT_TX_65_127_BYTE_FRAMES		(0x12C0)
+#define STAT_TX_128_255_BYTE_FRAMES		(0x12C4)
+#define STAT_TX_256_511_BYTES_FRAMES		(0x12C8)
+#define STAT_TX_512_1023_BYTE_FRAMES		(0x12CC)
+#define STAT_TX_1024_1518_BYTE_FRAMES		(0x12D0)
+#define STAT_TX_GREATER_1518_BYTE_FRAMES	(0x12D4)
 #define STAT_TX_TOTAL_FRAMES			(0x12D8)
+#define STAT_EEE_TX_LPI_TRANSITIONS		(0x12DC)
+#define STAT_EEE_TX_LPI_TIME			(0x12E0)
+#define STAT_TX_COUNTER_ROLLOVER_STATUS		(0x12FC)
 
 /* End of Register definitions */
 
@@ -594,4 +622,7 @@ struct lan743x_rx_buffer_info {
 #define RX_PROCESS_RESULT_PACKET_RECEIVED   (1)
 #define RX_PROCESS_RESULT_PACKET_DROPPED    (2)
 
+u32 lan743x_csr_read(struct lan743x_adapter *adapter, int offset);
+void lan743x_csr_write(struct lan743x_adapter *adapter, int offset, u32 data);
+
 #endif /* _LAN743X_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 4/9] lan743x: Add support for ethtool message level
  2018-07-12 19:04 [PATCH v2 net-next 0/9] lan743x: Add features to lan743x driver Bryan Whitehead
                   ` (2 preceding siblings ...)
  2018-07-12 19:05 ` [PATCH v2 net-next 3/9] lan743x: Add support for ethtool statistics Bryan Whitehead
@ 2018-07-12 19:05 ` Bryan Whitehead
  2018-07-12 22:31   ` Andrew Lunn
  2018-07-12 19:05 ` [PATCH v2 net-next 5/9] lan743x: Add support for ethtool eeprom access Bryan Whitehead
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Bryan Whitehead @ 2018-07-12 19:05 UTC (permalink / raw)
  To: davem; +Cc: netdev, UNGLinuxDriver, richardcochran

Implement ethtool message level

Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>
---
 drivers/net/ethernet/microchip/lan743x_ethtool.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
index 9ed9711..bab1344 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -17,6 +17,21 @@ static void lan743x_ethtool_get_drvinfo(struct net_device *netdev,
 		pci_name(adapter->pdev), sizeof(info->bus_info));
 }
 
+static u32 lan743x_ethtool_get_msglevel(struct net_device *netdev)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+	return adapter->msg_enable;
+}
+
+static void lan743x_ethtool_set_msglevel(struct net_device *netdev,
+					 u32 msglevel)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+	adapter->msg_enable = msglevel;
+}
+
 static const char lan743x_set0_hw_cnt_strings[][ETH_GSTRING_LEN] = {
 	"RX FCS Errors",
 	"RX Alignment Errors",
@@ -196,6 +211,8 @@ static int lan743x_ethtool_get_sset_count(struct net_device *netdev, int sset)
 
 const struct ethtool_ops lan743x_ethtool_ops = {
 	.get_drvinfo = lan743x_ethtool_get_drvinfo,
+	.get_msglevel = lan743x_ethtool_get_msglevel,
+	.set_msglevel = lan743x_ethtool_set_msglevel,
 	.get_link = ethtool_op_get_link,
 
 	.get_strings = lan743x_ethtool_get_strings,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 5/9] lan743x: Add support for ethtool eeprom access
  2018-07-12 19:04 [PATCH v2 net-next 0/9] lan743x: Add features to lan743x driver Bryan Whitehead
                   ` (3 preceding siblings ...)
  2018-07-12 19:05 ` [PATCH v2 net-next 4/9] lan743x: Add support for ethtool message level Bryan Whitehead
@ 2018-07-12 19:05 ` Bryan Whitehead
  2018-07-12 22:35   ` Andrew Lunn
  2018-07-12 19:05 ` [PATCH v2 net-next 6/9] lan743x: Add power management support Bryan Whitehead
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Bryan Whitehead @ 2018-07-12 19:05 UTC (permalink / raw)
  To: davem; +Cc: netdev, UNGLinuxDriver, richardcochran

Implement ethtool eeprom access
Also provides access to OTP (One Time Programming)

Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>
---
 drivers/net/ethernet/microchip/lan743x_ethtool.c | 209 +++++++++++++++++++++++
 drivers/net/ethernet/microchip/lan743x_main.h    |  33 ++++
 2 files changed, 242 insertions(+)

diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
index bab1344..f9ad237 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -7,6 +7,178 @@
 #include <linux/pci.h>
 #include <linux/phy.h>
 
+/* eeprom */
+#define LAN743X_EEPROM_MAGIC		    (0x74A5)
+#define LAN743X_OTP_MAGIC		    (0x74F3)
+#define EEPROM_INDICATOR_1		    (0xA5)
+#define EEPROM_INDICATOR_2		    (0xAA)
+#define EEPROM_MAC_OFFSET		    (0x01)
+#define MAX_EEPROM_SIZE			    512
+#define OTP_INDICATOR_1			    (0xF3)
+#define OTP_INDICATOR_2			    (0xF7)
+
+static int lan743x_otp_write(struct lan743x_adapter *adapter, u32 offset,
+			     u32 length, u8 *data)
+{
+	unsigned long timeout;
+	u32 buf;
+	int i;
+
+	buf = lan743x_csr_read(adapter, OTP_PWR_DN);
+
+	if (buf & OTP_PWR_DN_PWRDN_N_) {
+		/* clear it and wait to be cleared */
+		lan743x_csr_write(adapter, OTP_PWR_DN, 0);
+
+		timeout = jiffies + HZ;
+		do {
+			udelay(1);
+			buf = lan743x_csr_read(adapter, OTP_PWR_DN);
+			if (time_after(jiffies, timeout)) {
+				netif_warn(adapter, drv, adapter->netdev,
+					   "timeout on OTP_PWR_DN completion\n");
+				return -EIO;
+			}
+		} while (buf & OTP_PWR_DN_PWRDN_N_);
+	}
+
+	/* set to BYTE program mode */
+	lan743x_csr_write(adapter, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_);
+
+	for (i = 0; i < length; i++) {
+		lan743x_csr_write(adapter, OTP_ADDR1,
+				  ((offset + i) >> 8) &
+				  OTP_ADDR1_15_11_MASK_);
+		lan743x_csr_write(adapter, OTP_ADDR2,
+				  ((offset + i) &
+				  OTP_ADDR2_10_3_MASK_));
+		lan743x_csr_write(adapter, OTP_PRGM_DATA, data[i]);
+		lan743x_csr_write(adapter, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_);
+		lan743x_csr_write(adapter, OTP_CMD_GO, OTP_CMD_GO_GO_);
+
+		timeout = jiffies + HZ;
+		do {
+			udelay(1);
+			buf = lan743x_csr_read(adapter, OTP_STATUS);
+			if (time_after(jiffies, timeout)) {
+				netif_warn(adapter, drv, adapter->netdev,
+					   "Timeout on OTP_STATUS completion\n");
+				return -EIO;
+			}
+		} while (buf & OTP_STATUS_BUSY_);
+	}
+
+	return 0;
+}
+
+static int lan743x_eeprom_wait(struct lan743x_adapter *adapter)
+{
+	unsigned long start_time = jiffies;
+	u32 val;
+
+	do {
+		val = lan743x_csr_read(adapter, E2P_CMD);
+
+		if (!(val & E2P_CMD_EPC_BUSY_) ||
+		    (val & E2P_CMD_EPC_TIMEOUT_))
+			break;
+		usleep_range(40, 100);
+	} while (!time_after(jiffies, start_time + HZ));
+
+	if (val & (E2P_CMD_EPC_TIMEOUT_ | E2P_CMD_EPC_BUSY_)) {
+		netif_warn(adapter, drv, adapter->netdev,
+			   "EEPROM read operation timeout\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int lan743x_eeprom_confirm_not_busy(struct lan743x_adapter *adapter)
+{
+	unsigned long start_time = jiffies;
+	u32 val;
+
+	do {
+		val = lan743x_csr_read(adapter, E2P_CMD);
+
+		if (!(val & E2P_CMD_EPC_BUSY_))
+			return 0;
+
+		usleep_range(40, 100);
+	} while (!time_after(jiffies, start_time + HZ));
+
+	netif_warn(adapter, drv, adapter->netdev, "EEPROM is busy\n");
+	return -EIO;
+}
+
+static int lan743x_eeprom_read(struct lan743x_adapter *adapter,
+			       u32 offset, u32 length, u8 *data)
+{
+	int retval;
+	u32 val;
+	int i;
+
+	retval = lan743x_eeprom_confirm_not_busy(adapter);
+	if (retval)
+		return retval;
+
+	for (i = 0; i < length; i++) {
+		val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_READ_;
+		val |= (offset & E2P_CMD_EPC_ADDR_MASK_);
+		lan743x_csr_write(adapter, E2P_CMD, val);
+
+		retval = lan743x_eeprom_wait(adapter);
+		if (retval < 0)
+			return retval;
+
+		val = lan743x_csr_read(adapter, E2P_DATA);
+		data[i] = val & 0xFF;
+		offset++;
+	}
+
+	return 0;
+}
+
+static int lan743x_eeprom_write(struct lan743x_adapter *adapter,
+				u32 offset, u32 length, u8 *data)
+{
+	int retval;
+	u32 val;
+	int i;
+
+	retval = lan743x_eeprom_confirm_not_busy(adapter);
+	if (retval)
+		return retval;
+
+	/* Issue write/erase enable command */
+	val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_EWEN_;
+	lan743x_csr_write(adapter, E2P_CMD, val);
+
+	retval = lan743x_eeprom_wait(adapter);
+	if (retval < 0)
+		return retval;
+
+	for (i = 0; i < length; i++) {
+		/* Fill data register */
+		val = data[i];
+		lan743x_csr_write(adapter, E2P_DATA, val);
+
+		/* Send "write" command */
+		val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_WRITE_;
+		val |= (offset & E2P_CMD_EPC_ADDR_MASK_);
+		lan743x_csr_write(adapter, E2P_CMD, val);
+
+		retval = lan743x_eeprom_wait(adapter);
+		if (retval < 0)
+			return retval;
+
+		offset++;
+	}
+
+	return 0;
+}
+
 static void lan743x_ethtool_get_drvinfo(struct net_device *netdev,
 					struct ethtool_drvinfo *info)
 {
@@ -32,6 +204,40 @@ static void lan743x_ethtool_set_msglevel(struct net_device *netdev,
 	adapter->msg_enable = msglevel;
 }
 
+static int lan743x_ethtool_get_eeprom_len(struct net_device *netdev)
+{
+	return MAX_EEPROM_SIZE;
+}
+
+static int lan743x_ethtool_get_eeprom(struct net_device *netdev,
+				      struct ethtool_eeprom *ee, u8 *data)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+	return lan743x_eeprom_read(adapter, ee->offset, ee->len, data);
+}
+
+static int lan743x_ethtool_set_eeprom(struct net_device *netdev,
+				      struct ethtool_eeprom *ee, u8 *data)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+	int ret = -EINVAL;
+
+	if (ee->magic == LAN743X_EEPROM_MAGIC)
+		ret = lan743x_eeprom_write(adapter, ee->offset, ee->len,
+					   data);
+	/* Beware!  OTP is One Time Programming ONLY!
+	 * So do some strict condition check before messing up
+	 */
+	else if ((ee->magic == LAN743X_OTP_MAGIC) &&
+		 (ee->offset == 0) &&
+		 (ee->len == MAX_EEPROM_SIZE) &&
+		 (data[0] == OTP_INDICATOR_1))
+		ret = lan743x_otp_write(adapter, ee->offset, ee->len, data);
+
+	return ret;
+}
+
 static const char lan743x_set0_hw_cnt_strings[][ETH_GSTRING_LEN] = {
 	"RX FCS Errors",
 	"RX Alignment Errors",
@@ -215,6 +421,9 @@ const struct ethtool_ops lan743x_ethtool_ops = {
 	.set_msglevel = lan743x_ethtool_set_msglevel,
 	.get_link = ethtool_op_get_link,
 
+	.get_eeprom_len = lan743x_ethtool_get_eeprom_len,
+	.get_eeprom = lan743x_ethtool_get_eeprom,
+	.set_eeprom = lan743x_ethtool_set_eeprom,
 	.get_strings = lan743x_ethtool_get_strings,
 	.get_ethtool_stats = lan743x_ethtool_get_ethtool_stats,
 	.get_sset_count = lan743x_ethtool_get_sset_count,
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index de4f2cc..c026b8d 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -42,6 +42,16 @@
 
 #define DP_DATA_0			(0x030)
 
+#define E2P_CMD				(0x040)
+#define E2P_CMD_EPC_BUSY_		BIT(31)
+#define E2P_CMD_EPC_CMD_WRITE_		(0x30000000)
+#define E2P_CMD_EPC_CMD_EWEN_		(0x20000000)
+#define E2P_CMD_EPC_CMD_READ_		(0x00000000)
+#define E2P_CMD_EPC_TIMEOUT_		BIT(10)
+#define E2P_CMD_EPC_ADDR_MASK_		(0x000001FF)
+
+#define E2P_DATA			(0x044)
+
 #define FCT_RX_CTL			(0xAC)
 #define FCT_RX_CTL_EN_(channel)		BIT(28 + (channel))
 #define FCT_RX_CTL_DIS_(channel)	BIT(24 + (channel))
@@ -288,6 +298,29 @@
 #define TX_CFG_C_TX_DMA_INT_STS_AUTO_CLR_	BIT(3)
 #define TX_CFG_C_TX_INT_STS_R2C_MODE_MASK_	(0x00000007)
 
+#define OTP_PWR_DN				(0x1000)
+#define OTP_PWR_DN_PWRDN_N_			BIT(0)
+
+#define OTP_ADDR1				(0x1004)
+#define OTP_ADDR1_15_11_MASK_			(0x1F)
+
+#define OTP_ADDR2				(0x1008)
+#define OTP_ADDR2_10_3_MASK_			(0xFF)
+
+#define OTP_PRGM_DATA				(0x1010)
+
+#define OTP_PRGM_MODE				(0x1014)
+#define OTP_PRGM_MODE_BYTE_			BIT(0)
+
+#define OTP_TST_CMD				(0x1024)
+#define OTP_TST_CMD_PRGVRFY_			BIT(3)
+
+#define OTP_CMD_GO				(0x1028)
+#define OTP_CMD_GO_GO_				BIT(0)
+
+#define OTP_STATUS				(0x1030)
+#define OTP_STATUS_BUSY_			BIT(0)
+
 /* MAC statistics registers */
 #define STAT_RX_FCS_ERRORS			(0x1200)
 #define STAT_RX_ALIGNMENT_ERRORS		(0x1204)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 6/9] lan743x: Add power management support
  2018-07-12 19:04 [PATCH v2 net-next 0/9] lan743x: Add features to lan743x driver Bryan Whitehead
                   ` (4 preceding siblings ...)
  2018-07-12 19:05 ` [PATCH v2 net-next 5/9] lan743x: Add support for ethtool eeprom access Bryan Whitehead
@ 2018-07-12 19:05 ` Bryan Whitehead
  2018-07-12 22:42   ` Andrew Lunn
  2018-07-12 19:05 ` [PATCH v2 net-next 7/9] lan743x: Add EEE support Bryan Whitehead
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Bryan Whitehead @ 2018-07-12 19:05 UTC (permalink / raw)
  To: davem; +Cc: netdev, UNGLinuxDriver, richardcochran

Implement power management.
Supports suspend, resume, and Wake On LAN

Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>
---
 drivers/net/ethernet/microchip/lan743x_ethtool.c |  48 ++++++
 drivers/net/ethernet/microchip/lan743x_main.c    | 184 +++++++++++++++++++++++
 drivers/net/ethernet/microchip/lan743x_main.h    |  47 ++++++
 3 files changed, 279 insertions(+)

diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
index f9ad237..f9d875d 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -415,6 +415,50 @@ static int lan743x_ethtool_get_sset_count(struct net_device *netdev, int sset)
 	}
 }
 
+#ifdef CONFIG_PM
+static void lan743x_ethtool_get_wol(struct net_device *netdev,
+				    struct ethtool_wolinfo *wol)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+	wol->supported = WAKE_BCAST | WAKE_UCAST | WAKE_MCAST |
+		WAKE_MAGIC | WAKE_PHY | WAKE_ARP;
+
+	wol->wolopts = adapter->wolopts;
+}
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_PM
+static int lan743x_ethtool_set_wol(struct net_device *netdev,
+				   struct ethtool_wolinfo *wol)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+	if (wol->wolopts & WAKE_MAGICSECURE)
+		return -EOPNOTSUPP;
+
+	adapter->wolopts = 0;
+	if (wol->wolopts & WAKE_UCAST)
+		adapter->wolopts |= WAKE_UCAST;
+	if (wol->wolopts & WAKE_MCAST)
+		adapter->wolopts |= WAKE_MCAST;
+	if (wol->wolopts & WAKE_BCAST)
+		adapter->wolopts |= WAKE_BCAST;
+	if (wol->wolopts & WAKE_MAGIC)
+		adapter->wolopts |= WAKE_MAGIC;
+	if (wol->wolopts & WAKE_PHY)
+		adapter->wolopts |= WAKE_PHY;
+	if (wol->wolopts & WAKE_ARP)
+		adapter->wolopts |= WAKE_ARP;
+
+	device_set_wakeup_enable(&adapter->pdev->dev, (bool)wol->wolopts);
+
+	phy_ethtool_set_wol(netdev->phydev, wol);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
 const struct ethtool_ops lan743x_ethtool_ops = {
 	.get_drvinfo = lan743x_ethtool_get_drvinfo,
 	.get_msglevel = lan743x_ethtool_get_msglevel,
@@ -429,4 +473,8 @@ const struct ethtool_ops lan743x_ethtool_ops = {
 	.get_sset_count = lan743x_ethtool_get_sset_count,
 	.get_link_ksettings = phy_ethtool_get_link_ksettings,
 	.set_link_ksettings = phy_ethtool_set_link_ksettings,
+#ifdef CONFIG_PM
+	.get_wol = lan743x_ethtool_get_wol,
+	.set_wol = lan743x_ethtool_set_wol,
+#endif
 };
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index 1e2f8c6..8e9eff8 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -11,6 +11,7 @@
 #include <linux/phy.h>
 #include <linux/rtnetlink.h>
 #include <linux/iopoll.h>
+#include <linux/crc16.h>
 #include "lan743x_main.h"
 #include "lan743x_ethtool.h"
 
@@ -2749,10 +2750,190 @@ static void lan743x_pcidev_shutdown(struct pci_dev *pdev)
 		lan743x_netdev_close(netdev);
 	rtnl_unlock();
 
+#ifdef CONFIG_PM
+	pci_save_state(pdev);
+#endif
+
 	/* clean up lan743x portion */
 	lan743x_hardware_cleanup(adapter);
 }
 
+#ifdef CONFIG_PM
+static u16 lan743x_pm_wakeframe_crc16(const u8 *buf, int len)
+{
+	return bitrev16(crc16(0xFFFF, buf, len));
+}
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_PM
+static void lan743x_pm_set_wol(struct lan743x_adapter *adapter)
+{
+	const u8 ipv4_multicast[3] = { 0x01, 0x00, 0x5E };
+	const u8 ipv6_multicast[3] = { 0x33, 0x33 };
+	const u8 arp_type[2] = { 0x08, 0x06 };
+	int mask_index;
+	u32 pmtctl;
+	u32 wucsr;
+	u32 macrx;
+	u16 crc;
+
+	for (mask_index = 0; mask_index < MAC_NUM_OF_WUF_CFG; mask_index++)
+		lan743x_csr_write(adapter, MAC_WUF_CFG(mask_index), 0);
+
+	/* clear wake settings */
+	pmtctl = lan743x_csr_read(adapter, PMT_CTL);
+	pmtctl |= PMT_CTL_WUPS_MASK_;
+	pmtctl &= ~(PMT_CTL_GPIO_WAKEUP_EN_ | PMT_CTL_EEE_WAKEUP_EN_ |
+		PMT_CTL_WOL_EN_ | PMT_CTL_MAC_D3_RX_CLK_OVR_ |
+		PMT_CTL_RX_FCT_RFE_D3_CLK_OVR_ | PMT_CTL_ETH_PHY_WAKE_EN_);
+
+	macrx = lan743x_csr_read(adapter, MAC_RX);
+
+	wucsr = 0;
+	mask_index = 0;
+
+	pmtctl |= PMT_CTL_ETH_PHY_D3_COLD_OVR_ | PMT_CTL_ETH_PHY_D3_OVR_;
+
+	if (adapter->wolopts & WAKE_PHY) {
+		pmtctl |= PMT_CTL_ETH_PHY_EDPD_PLL_CTL_;
+		pmtctl |= PMT_CTL_ETH_PHY_WAKE_EN_;
+	}
+	if (adapter->wolopts & WAKE_MAGIC) {
+		wucsr |= MAC_WUCSR_MPEN_;
+		macrx |= MAC_RX_RXEN_;
+		pmtctl |= PMT_CTL_WOL_EN_ | PMT_CTL_MAC_D3_RX_CLK_OVR_;
+	}
+	if (adapter->wolopts & WAKE_UCAST) {
+		wucsr |= MAC_WUCSR_RFE_WAKE_EN_ | MAC_WUCSR_PFDA_EN_;
+		macrx |= MAC_RX_RXEN_;
+		pmtctl |= PMT_CTL_WOL_EN_ | PMT_CTL_MAC_D3_RX_CLK_OVR_;
+		pmtctl |= PMT_CTL_RX_FCT_RFE_D3_CLK_OVR_;
+	}
+	if (adapter->wolopts & WAKE_BCAST) {
+		wucsr |= MAC_WUCSR_RFE_WAKE_EN_ | MAC_WUCSR_BCST_EN_;
+		macrx |= MAC_RX_RXEN_;
+		pmtctl |= PMT_CTL_WOL_EN_ | PMT_CTL_MAC_D3_RX_CLK_OVR_;
+		pmtctl |= PMT_CTL_RX_FCT_RFE_D3_CLK_OVR_;
+	}
+	if (adapter->wolopts & WAKE_MCAST) {
+		/* IPv4 multicast */
+		crc = lan743x_pm_wakeframe_crc16(ipv4_multicast, 3);
+		lan743x_csr_write(adapter, MAC_WUF_CFG(mask_index),
+				  MAC_WUF_CFG_EN_ | MAC_WUF_CFG_TYPE_MCAST_ |
+				  (0 << MAC_WUF_CFG_OFFSET_SHIFT_) |
+				  (crc & MAC_WUF_CFG_CRC16_MASK_));
+		lan743x_csr_write(adapter, MAC_WUF_MASK0(mask_index), 7);
+		lan743x_csr_write(adapter, MAC_WUF_MASK1(mask_index), 0);
+		lan743x_csr_write(adapter, MAC_WUF_MASK2(mask_index), 0);
+		lan743x_csr_write(adapter, MAC_WUF_MASK3(mask_index), 0);
+		mask_index++;
+
+		/* IPv6 multicast */
+		crc = lan743x_pm_wakeframe_crc16(ipv6_multicast, 2);
+		lan743x_csr_write(adapter, MAC_WUF_CFG(mask_index),
+				  MAC_WUF_CFG_EN_ | MAC_WUF_CFG_TYPE_MCAST_ |
+				  (0 << MAC_WUF_CFG_OFFSET_SHIFT_) |
+				  (crc & MAC_WUF_CFG_CRC16_MASK_));
+		lan743x_csr_write(adapter, MAC_WUF_MASK0(mask_index), 3);
+		lan743x_csr_write(adapter, MAC_WUF_MASK1(mask_index), 0);
+		lan743x_csr_write(adapter, MAC_WUF_MASK2(mask_index), 0);
+		lan743x_csr_write(adapter, MAC_WUF_MASK3(mask_index), 0);
+		mask_index++;
+
+		wucsr |= MAC_WUCSR_RFE_WAKE_EN_ | MAC_WUCSR_WAKE_EN_;
+		macrx |= MAC_RX_RXEN_;
+		pmtctl |= PMT_CTL_WOL_EN_ | PMT_CTL_MAC_D3_RX_CLK_OVR_;
+		pmtctl |= PMT_CTL_RX_FCT_RFE_D3_CLK_OVR_;
+	}
+	if (adapter->wolopts & WAKE_ARP) {
+		/* set MAC_WUF_CFG & WUF_MASK
+		 * for packettype (offset 12,13) = ARP (0x0806)
+		 */
+		crc = lan743x_pm_wakeframe_crc16(arp_type, 2);
+		lan743x_csr_write(adapter, MAC_WUF_CFG(mask_index),
+				  MAC_WUF_CFG_EN_ | MAC_WUF_CFG_TYPE_ALL_ |
+				  (0 << MAC_WUF_CFG_OFFSET_SHIFT_) |
+				  (crc & MAC_WUF_CFG_CRC16_MASK_));
+		lan743x_csr_write(adapter, MAC_WUF_MASK0(mask_index), 0x3000);
+		lan743x_csr_write(adapter, MAC_WUF_MASK1(mask_index), 0);
+		lan743x_csr_write(adapter, MAC_WUF_MASK2(mask_index), 0);
+		lan743x_csr_write(adapter, MAC_WUF_MASK3(mask_index), 0);
+		mask_index++;
+
+		wucsr |= MAC_WUCSR_RFE_WAKE_EN_ | MAC_WUCSR_WAKE_EN_;
+		macrx |= MAC_RX_RXEN_;
+		pmtctl |= PMT_CTL_WOL_EN_ | PMT_CTL_MAC_D3_RX_CLK_OVR_;
+		pmtctl |= PMT_CTL_RX_FCT_RFE_D3_CLK_OVR_;
+	}
+
+	lan743x_csr_write(adapter, MAC_WUCSR, wucsr);
+	lan743x_csr_write(adapter, PMT_CTL, pmtctl);
+	lan743x_csr_write(adapter, MAC_RX, macrx);
+}
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_PM
+static int lan743x_pm_suspend(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+	int ret;
+
+	lan743x_pcidev_shutdown(pdev);
+
+	/* clear all wakes */
+	lan743x_csr_write(adapter, MAC_WUCSR, 0);
+	lan743x_csr_write(adapter, MAC_WUCSR2, 0);
+	lan743x_csr_write(adapter, MAC_WK_SRC, 0xFFFFFFFF);
+
+	if (adapter->wolopts)
+		lan743x_pm_set_wol(adapter);
+
+	/* Host sets PME_En, put D3hot */
+	ret = pci_prepare_to_sleep(pdev);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_PM
+static int lan743x_pm_resume(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+	int ret;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_save_state(pdev);
+
+	ret = lan743x_hardware_init(adapter, pdev);
+	if (ret) {
+		netif_err(adapter, probe, adapter->netdev,
+			  "lan743x_hardware_init returned %d\n", ret);
+	}
+
+	/* open netdev when netdev is at running state while resume.
+	 * For instance, it is true when system wakesup after pm-suspend
+	 * However, it is false when system wakes up after suspend GUI menu
+	 */
+	if (netif_running(netdev))
+		lan743x_netdev_open(netdev);
+
+	netif_device_attach(netdev);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_PM
+const struct dev_pm_ops lan743x_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(lan743x_pm_suspend, lan743x_pm_resume)
+};
+#endif /*CONFIG_PM */
+
 static const struct pci_device_id lan743x_pcidev_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SMSC, PCI_DEVICE_ID_SMSC_LAN7430) },
 	{ 0, }
@@ -2763,6 +2944,9 @@ static struct pci_driver lan743x_pcidev_driver = {
 	.id_table = lan743x_pcidev_tbl,
 	.probe    = lan743x_pcidev_probe,
 	.remove   = lan743x_pcidev_remove,
+#ifdef CONFIG_PM
+	.driver.pm = &lan743x_pm_ops,
+#endif
 	.shutdown = lan743x_pcidev_shutdown,
 };
 
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index c026b8d..72b9beb 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -24,8 +24,18 @@
 #define HW_CFG_LRST_				BIT(1)
 
 #define PMT_CTL					(0x014)
+#define PMT_CTL_ETH_PHY_D3_COLD_OVR_		BIT(27)
+#define PMT_CTL_MAC_D3_RX_CLK_OVR_		BIT(25)
+#define PMT_CTL_ETH_PHY_EDPD_PLL_CTL_		BIT(24)
+#define PMT_CTL_ETH_PHY_D3_OVR_			BIT(23)
+#define PMT_CTL_RX_FCT_RFE_D3_CLK_OVR_		BIT(18)
+#define PMT_CTL_GPIO_WAKEUP_EN_			BIT(15)
+#define PMT_CTL_EEE_WAKEUP_EN_			BIT(13)
 #define PMT_CTL_READY_				BIT(7)
 #define PMT_CTL_ETH_PHY_RST_			BIT(4)
+#define PMT_CTL_WOL_EN_				BIT(3)
+#define PMT_CTL_ETH_PHY_WAKE_EN_		BIT(2)
+#define PMT_CTL_WUPS_MASK_			(0x00000003)
 
 #define DP_SEL				(0x024)
 #define DP_SEL_DPRDY_			BIT(31)
@@ -107,6 +117,38 @@
 
 #define MAC_MII_DATA			(0x124)
 
+#define MAC_WUCSR				(0x140)
+#define MAC_WUCSR_RFE_WAKE_EN_			BIT(14)
+#define MAC_WUCSR_PFDA_EN_			BIT(3)
+#define MAC_WUCSR_WAKE_EN_			BIT(2)
+#define MAC_WUCSR_MPEN_				BIT(1)
+#define MAC_WUCSR_BCST_EN_			BIT(0)
+
+#define MAC_WK_SRC				(0x144)
+
+#define MAC_WUF_CFG0			(0x150)
+#define MAC_NUM_OF_WUF_CFG		(32)
+#define MAC_WUF_CFG_BEGIN		(MAC_WUF_CFG0)
+#define MAC_WUF_CFG(index)		(MAC_WUF_CFG_BEGIN + (4 * (index)))
+#define MAC_WUF_CFG_EN_			BIT(31)
+#define MAC_WUF_CFG_TYPE_MCAST_		(0x02000000)
+#define MAC_WUF_CFG_TYPE_ALL_		(0x01000000)
+#define MAC_WUF_CFG_OFFSET_SHIFT_	(16)
+#define MAC_WUF_CFG_CRC16_MASK_		(0x0000FFFF)
+
+#define MAC_WUF_MASK0_0			(0x200)
+#define MAC_WUF_MASK0_1			(0x204)
+#define MAC_WUF_MASK0_2			(0x208)
+#define MAC_WUF_MASK0_3			(0x20C)
+#define MAC_WUF_MASK0_BEGIN		(MAC_WUF_MASK0_0)
+#define MAC_WUF_MASK1_BEGIN		(MAC_WUF_MASK0_1)
+#define MAC_WUF_MASK2_BEGIN		(MAC_WUF_MASK0_2)
+#define MAC_WUF_MASK3_BEGIN		(MAC_WUF_MASK0_3)
+#define MAC_WUF_MASK0(index)		(MAC_WUF_MASK0_BEGIN + (0x10 * (index)))
+#define MAC_WUF_MASK1(index)		(MAC_WUF_MASK1_BEGIN + (0x10 * (index)))
+#define MAC_WUF_MASK2(index)		(MAC_WUF_MASK2_BEGIN + (0x10 * (index)))
+#define MAC_WUF_MASK3(index)		(MAC_WUF_MASK3_BEGIN + (0x10 * (index)))
+
 /* offset 0x400 - 0x500, x may range from 0 to 32, for a total of 33 entries */
 #define RFE_ADDR_FILT_HI(x)		(0x400 + (8 * (x)))
 #define RFE_ADDR_FILT_HI_VALID_		BIT(31)
@@ -121,6 +163,8 @@
 #define RFE_CTL_MCAST_HASH_		BIT(3)
 #define RFE_CTL_DA_PERFECT_		BIT(1)
 
+#define MAC_WUCSR2			(0x600)
+
 #define INT_STS				(0x780)
 #define INT_BIT_DMA_RX_(channel)	BIT(24 + (channel))
 #define INT_BIT_ALL_RX_			(0x0F000000)
@@ -534,6 +578,9 @@ struct lan743x_adapter {
 	struct net_device       *netdev;
 	struct mii_bus		*mdiobus;
 	int                     msg_enable;
+#ifdef CONFIG_PM
+	u32			wolopts;
+#endif
 	struct pci_dev		*pdev;
 	struct lan743x_csr      csr;
 	struct lan743x_intr     intr;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 7/9] lan743x: Add EEE support
  2018-07-12 19:04 [PATCH v2 net-next 0/9] lan743x: Add features to lan743x driver Bryan Whitehead
                   ` (5 preceding siblings ...)
  2018-07-12 19:05 ` [PATCH v2 net-next 6/9] lan743x: Add power management support Bryan Whitehead
@ 2018-07-12 19:05 ` Bryan Whitehead
  2018-07-12 22:49   ` Andrew Lunn
  2018-07-12 19:05 ` [PATCH v2 net-next 8/9] lan743x: Add RSS support Bryan Whitehead
  2018-07-12 19:05 ` [PATCH v2 net-next 9/9] lan743x: Add PTP support Bryan Whitehead
  8 siblings, 1 reply; 23+ messages in thread
From: Bryan Whitehead @ 2018-07-12 19:05 UTC (permalink / raw)
  To: davem; +Cc: netdev, UNGLinuxDriver, richardcochran

Implement EEE support

Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>
---
 drivers/net/ethernet/microchip/lan743x_ethtool.c | 89 ++++++++++++++++++++++++
 drivers/net/ethernet/microchip/lan743x_main.h    |  3 +
 2 files changed, 92 insertions(+)

diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
index f9d875d..3d95290 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -415,6 +415,93 @@ static int lan743x_ethtool_get_sset_count(struct net_device *netdev, int sset)
 	}
 }
 
+static int lan743x_ethtool_get_eee(struct net_device *netdev,
+				   struct ethtool_eee *eee)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+	struct phy_device *phydev = netdev->phydev;
+	u32 buf;
+	int ret;
+
+	if (!phydev)
+		return -EIO;
+	if (!phydev->drv) {
+		netif_err(adapter, drv, adapter->netdev,
+			  "Missing PHY Driver\n");
+		return -EIO;
+	}
+
+	ret = phy_ethtool_get_eee(phydev, eee);
+	if (ret < 0)
+		return ret;
+
+	buf = lan743x_csr_read(adapter, MAC_CR);
+	if (buf & MAC_CR_EEE_EN_) {
+		eee->eee_enabled = true;
+		eee->eee_active = !!(eee->advertised & eee->lp_advertised);
+		eee->tx_lpi_enabled = true;
+		/* EEE_TX_LPI_REQ_DLY & tx_lpi_timer are same uSec unit */
+		buf = lan743x_csr_read(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT);
+		eee->tx_lpi_timer = buf;
+	} else {
+		eee->eee_enabled = false;
+		eee->eee_active = false;
+		eee->tx_lpi_enabled = false;
+		eee->tx_lpi_timer = 0;
+	}
+
+	return 0;
+}
+
+static int lan743x_ethtool_set_eee(struct net_device *netdev,
+				   struct ethtool_eee *eee)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+	struct phy_device *phydev = NULL;
+	u32 buf = 0;
+	int ret = 0;
+
+	if (!netdev)
+		return -EINVAL;
+	adapter = netdev_priv(netdev);
+	if (!adapter)
+		return -EINVAL;
+	phydev = netdev->phydev;
+	if (!phydev)
+		return -EIO;
+	if (!phydev->drv) {
+		netif_err(adapter, drv, adapter->netdev,
+			  "Missing PHY Driver\n");
+		return -EIO;
+	}
+
+	if (eee->eee_enabled) {
+		ret = phy_init_eee(phydev, 0);
+		if (ret) {
+			netif_err(adapter, drv, adapter->netdev,
+				  "EEE initialization failed\n");
+			return ret;
+		}
+
+		buf = lan743x_csr_read(adapter, MAC_CR);
+		buf |= MAC_CR_EEE_EN_;
+		lan743x_csr_write(adapter, MAC_CR, buf);
+
+		phy_ethtool_set_eee(phydev, eee);
+
+		buf = (u32)eee->tx_lpi_timer;
+		lan743x_csr_write(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT, buf);
+		netif_info(adapter, drv, adapter->netdev, "Enabled EEE\n");
+	} else {
+		buf = lan743x_csr_read(adapter, MAC_CR);
+		buf &= ~MAC_CR_EEE_EN_;
+		lan743x_csr_write(adapter, MAC_CR, buf);
+		netif_info(adapter, drv, adapter->netdev, "Disabled EEE\n");
+	}
+
+	return 0;
+}
+
 #ifdef CONFIG_PM
 static void lan743x_ethtool_get_wol(struct net_device *netdev,
 				    struct ethtool_wolinfo *wol)
@@ -471,6 +558,8 @@ const struct ethtool_ops lan743x_ethtool_ops = {
 	.get_strings = lan743x_ethtool_get_strings,
 	.get_ethtool_stats = lan743x_ethtool_get_ethtool_stats,
 	.get_sset_count = lan743x_ethtool_get_sset_count,
+	.get_eee = lan743x_ethtool_get_eee,
+	.set_eee = lan743x_ethtool_set_eee,
 	.get_link_ksettings = phy_ethtool_get_link_ksettings,
 	.set_link_ksettings = phy_ethtool_set_link_ksettings,
 #ifdef CONFIG_PM
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index 72b9beb..93cb60a 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -82,6 +82,7 @@
 	((value << 0) & FCT_FLOW_CTL_ON_THRESHOLD_)
 
 #define MAC_CR				(0x100)
+#define MAC_CR_EEE_EN_			BIT(17)
 #define MAC_CR_ADD_			BIT(12)
 #define MAC_CR_ASD_			BIT(11)
 #define MAC_CR_CNTR_RST_		BIT(5)
@@ -117,6 +118,8 @@
 
 #define MAC_MII_DATA			(0x124)
 
+#define MAC_EEE_TX_LPI_REQ_DLY_CNT		(0x130)
+
 #define MAC_WUCSR				(0x140)
 #define MAC_WUCSR_RFE_WAKE_EN_			BIT(14)
 #define MAC_WUCSR_PFDA_EN_			BIT(3)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 8/9] lan743x: Add RSS support
  2018-07-12 19:04 [PATCH v2 net-next 0/9] lan743x: Add features to lan743x driver Bryan Whitehead
                   ` (6 preceding siblings ...)
  2018-07-12 19:05 ` [PATCH v2 net-next 7/9] lan743x: Add EEE support Bryan Whitehead
@ 2018-07-12 19:05 ` Bryan Whitehead
  2018-07-12 19:05 ` [PATCH v2 net-next 9/9] lan743x: Add PTP support Bryan Whitehead
  8 siblings, 0 replies; 23+ messages in thread
From: Bryan Whitehead @ 2018-07-12 19:05 UTC (permalink / raw)
  To: davem; +Cc: netdev, UNGLinuxDriver, richardcochran

Implement RSS support

Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>
---
 drivers/net/ethernet/microchip/lan743x_ethtool.c | 132 +++++++++++++++++++++++
 drivers/net/ethernet/microchip/lan743x_main.c    |  20 ++++
 drivers/net/ethernet/microchip/lan743x_main.h    |  19 ++++
 3 files changed, 171 insertions(+)

diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
index 3d95290..33d6c2d 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -415,6 +415,133 @@ static int lan743x_ethtool_get_sset_count(struct net_device *netdev, int sset)
 	}
 }
 
+static int lan743x_ethtool_get_rxnfc(struct net_device *netdev,
+				     struct ethtool_rxnfc *rxnfc,
+				     u32 *rule_locs)
+{
+	switch (rxnfc->cmd) {
+	case ETHTOOL_GRXFH:
+		rxnfc->data = 0;
+		switch (rxnfc->flow_type) {
+		case TCP_V4_FLOW:case UDP_V4_FLOW:
+		case TCP_V6_FLOW:case UDP_V6_FLOW:
+			rxnfc->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+			/* fall through */
+		case IPV4_FLOW: case IPV6_FLOW:
+			rxnfc->data |= RXH_IP_SRC | RXH_IP_DST;
+			return 0;
+		}
+		break;
+	case ETHTOOL_GRXRINGS:
+		rxnfc->data = LAN743X_USED_RX_CHANNELS;
+		return 0;
+	}
+	return -EOPNOTSUPP;
+}
+
+static u32 lan743x_ethtool_get_rxfh_key_size(struct net_device *netdev)
+{
+	return 40;
+}
+
+static u32 lan743x_ethtool_get_rxfh_indir_size(struct net_device *netdev)
+{
+	return 128;
+}
+
+static int lan743x_ethtool_get_rxfh(struct net_device *netdev,
+				    u32 *indir, u8 *key, u8 *hfunc)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+	if (indir) {
+		int dw_index;
+		int byte_index = 0;
+
+		for (dw_index = 0; dw_index < 32; dw_index++) {
+			u32 four_entries =
+				lan743x_csr_read(adapter, RFE_INDX(dw_index));
+
+			byte_index = dw_index << 2;
+			indir[byte_index + 0] =
+				((four_entries >> 0) & 0x000000FF);
+			indir[byte_index + 1] =
+				((four_entries >> 8) & 0x000000FF);
+			indir[byte_index + 2] =
+				((four_entries >> 16) & 0x000000FF);
+			indir[byte_index + 3] =
+				((four_entries >> 24) & 0x000000FF);
+		}
+	}
+	if (key) {
+		int dword_index;
+		int byte_index = 0;
+
+		for (dword_index = 0; dword_index < 10; dword_index++) {
+			u32 four_entries =
+				lan743x_csr_read(adapter,
+						 RFE_HASH_KEY(dword_index));
+
+			byte_index = dword_index << 2;
+			key[byte_index + 0] =
+				((four_entries >> 0) & 0x000000FF);
+			key[byte_index + 1] =
+				((four_entries >> 8) & 0x000000FF);
+			key[byte_index + 2] =
+				((four_entries >> 16) & 0x000000FF);
+			key[byte_index + 3] =
+				((four_entries >> 24) & 0x000000FF);
+		}
+	}
+	if (hfunc)
+		(*hfunc) = ETH_RSS_HASH_TOP;
+	return 0;
+}
+
+static int lan743x_ethtool_set_rxfh(struct net_device *netdev,
+				    const u32 *indir, const u8 *key,
+				    const u8 hfunc)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+	if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
+		return -EOPNOTSUPP;
+
+	if (indir) {
+		u32 indir_value = 0;
+		int dword_index = 0;
+		int byte_index = 0;
+
+		for (dword_index = 0; dword_index < 32; dword_index++) {
+			byte_index = dword_index << 2;
+			indir_value =
+				(((indir[byte_index + 0] & 0x000000FF) << 0) |
+				((indir[byte_index + 1] & 0x000000FF) << 8) |
+				((indir[byte_index + 2] & 0x000000FF) << 16) |
+				((indir[byte_index + 3] & 0x000000FF) << 24));
+			lan743x_csr_write(adapter, RFE_INDX(dword_index),
+					  indir_value);
+		}
+	}
+	if (key) {
+		int dword_index = 0;
+		int byte_index = 0;
+		u32 key_value = 0;
+
+		for (dword_index = 0; dword_index < 10; dword_index++) {
+			byte_index = dword_index << 2;
+			key_value =
+				((((u32)(key[byte_index + 0])) << 0) |
+				(((u32)(key[byte_index + 1])) << 8) |
+				(((u32)(key[byte_index + 2])) << 16) |
+				(((u32)(key[byte_index + 3])) << 24));
+			lan743x_csr_write(adapter, RFE_HASH_KEY(dword_index),
+					  key_value);
+		}
+	}
+	return 0;
+}
+
 static int lan743x_ethtool_get_eee(struct net_device *netdev,
 				   struct ethtool_eee *eee)
 {
@@ -558,6 +685,11 @@ const struct ethtool_ops lan743x_ethtool_ops = {
 	.get_strings = lan743x_ethtool_get_strings,
 	.get_ethtool_stats = lan743x_ethtool_get_ethtool_stats,
 	.get_sset_count = lan743x_ethtool_get_sset_count,
+	.get_rxnfc = lan743x_ethtool_get_rxnfc,
+	.get_rxfh_key_size = lan743x_ethtool_get_rxfh_key_size,
+	.get_rxfh_indir_size = lan743x_ethtool_get_rxfh_indir_size,
+	.get_rxfh = lan743x_ethtool_get_rxfh,
+	.set_rxfh = lan743x_ethtool_set_rxfh,
 	.get_eee = lan743x_ethtool_get_eee,
 	.set_eee = lan743x_ethtool_set_eee,
 	.get_link_ksettings = phy_ethtool_get_link_ksettings,
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index 8e9eff8..953b581 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -1025,6 +1025,24 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter)
 	return ret;
 }
 
+static void lan743x_rfe_open(struct lan743x_adapter *adapter)
+{
+	lan743x_csr_write(adapter, RFE_RSS_CFG,
+		RFE_RSS_CFG_UDP_IPV6_EX_ |
+		RFE_RSS_CFG_TCP_IPV6_EX_ |
+		RFE_RSS_CFG_IPV6_EX_ |
+		RFE_RSS_CFG_UDP_IPV6_ |
+		RFE_RSS_CFG_TCP_IPV6_ |
+		RFE_RSS_CFG_IPV6_ |
+		RFE_RSS_CFG_UDP_IPV4_ |
+		RFE_RSS_CFG_TCP_IPV4_ |
+		RFE_RSS_CFG_IPV4_ |
+		RFE_RSS_CFG_VALID_HASH_BITS_ |
+		RFE_RSS_CFG_RSS_QUEUE_ENABLE_ |
+		RFE_RSS_CFG_RSS_HASH_STORE_ |
+		RFE_RSS_CFG_RSS_ENABLE_);
+}
+
 static void lan743x_rfe_update_mac_address(struct lan743x_adapter *adapter)
 {
 	u8 *mac_addr;
@@ -2419,6 +2437,8 @@ static int lan743x_netdev_open(struct net_device *netdev)
 	if (ret)
 		goto close_mac;
 
+	lan743x_rfe_open(adapter);
+
 	for (index = 0; index < LAN743X_USED_RX_CHANNELS; index++) {
 		ret = lan743x_rx_open(&adapter->rx[index]);
 		if (ret)
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index 93cb60a..4fa7a5e 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -166,6 +166,25 @@
 #define RFE_CTL_MCAST_HASH_		BIT(3)
 #define RFE_CTL_DA_PERFECT_		BIT(1)
 
+#define RFE_RSS_CFG			(0x554)
+#define RFE_RSS_CFG_UDP_IPV6_EX_	BIT(16)
+#define RFE_RSS_CFG_TCP_IPV6_EX_	BIT(15)
+#define RFE_RSS_CFG_IPV6_EX_		BIT(14)
+#define RFE_RSS_CFG_UDP_IPV6_		BIT(13)
+#define RFE_RSS_CFG_TCP_IPV6_		BIT(12)
+#define RFE_RSS_CFG_IPV6_		BIT(11)
+#define RFE_RSS_CFG_UDP_IPV4_		BIT(10)
+#define RFE_RSS_CFG_TCP_IPV4_		BIT(9)
+#define RFE_RSS_CFG_IPV4_		BIT(8)
+#define RFE_RSS_CFG_VALID_HASH_BITS_	(0x000000E0)
+#define RFE_RSS_CFG_RSS_QUEUE_ENABLE_	BIT(2)
+#define RFE_RSS_CFG_RSS_HASH_STORE_	BIT(1)
+#define RFE_RSS_CFG_RSS_ENABLE_		BIT(0)
+
+#define RFE_HASH_KEY(index)		(0x558 + (index << 2))
+
+#define RFE_INDX(index)			(0x580 + (index << 2))
+
 #define MAC_WUCSR2			(0x600)
 
 #define INT_STS				(0x780)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 9/9] lan743x: Add PTP support
  2018-07-12 19:04 [PATCH v2 net-next 0/9] lan743x: Add features to lan743x driver Bryan Whitehead
                   ` (7 preceding siblings ...)
  2018-07-12 19:05 ` [PATCH v2 net-next 8/9] lan743x: Add RSS support Bryan Whitehead
@ 2018-07-12 19:05 ` Bryan Whitehead
  2018-07-13  3:31   ` Richard Cochran
  8 siblings, 1 reply; 23+ messages in thread
From: Bryan Whitehead @ 2018-07-12 19:05 UTC (permalink / raw)
  To: davem; +Cc: netdev, UNGLinuxDriver, richardcochran

PTP support includes:
    Ingress, and egress timestamping.
    PTP clock support
    Pulse per second output on GPIO

Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>
---
 drivers/net/ethernet/microchip/Makefile          |    2 +-
 drivers/net/ethernet/microchip/lan743x_ethtool.c |   28 +
 drivers/net/ethernet/microchip/lan743x_main.c    |   81 +-
 drivers/net/ethernet/microchip/lan743x_main.h    |   96 +-
 drivers/net/ethernet/microchip/lan743x_ptp.c     | 1194 ++++++++++++++++++++++
 drivers/net/ethernet/microchip/lan743x_ptp.h     |   78 ++
 6 files changed, 1474 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/ethernet/microchip/lan743x_ptp.c
 create mode 100644 drivers/net/ethernet/microchip/lan743x_ptp.h

diff --git a/drivers/net/ethernet/microchip/Makefile b/drivers/net/ethernet/microchip/Makefile
index 43f47cb..538926d 100644
--- a/drivers/net/ethernet/microchip/Makefile
+++ b/drivers/net/ethernet/microchip/Makefile
@@ -6,4 +6,4 @@ obj-$(CONFIG_ENC28J60) += enc28j60.o
 obj-$(CONFIG_ENCX24J600) += encx24j600.o encx24j600-regmap.o
 obj-$(CONFIG_LAN743X) += lan743x.o
 
-lan743x-objs := lan743x_main.o lan743x_ethtool.o
+lan743x-objs := lan743x_main.o lan743x_ethtool.o lan743x_ptp.o
diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
index 33d6c2d..8800716 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -4,6 +4,7 @@
 #include <linux/netdevice.h>
 #include "lan743x_main.h"
 #include "lan743x_ethtool.h"
+#include <linux/net_tstamp.h>
 #include <linux/pci.h>
 #include <linux/phy.h>
 
@@ -542,6 +543,32 @@ static int lan743x_ethtool_set_rxfh(struct net_device *netdev,
 	return 0;
 }
 
+static int lan743x_ethtool_get_ts_info(struct net_device *netdev,
+				       struct ethtool_ts_info *ts_info)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+	ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+				   SOF_TIMESTAMPING_RX_SOFTWARE |
+				   SOF_TIMESTAMPING_SOFTWARE |
+				   SOF_TIMESTAMPING_TX_HARDWARE |
+				   SOF_TIMESTAMPING_RX_HARDWARE |
+				   SOF_TIMESTAMPING_RAW_HARDWARE;
+#ifdef CONFIG_PTP_1588_CLOCK
+	if (adapter->ptp.ptp_clock)
+		ts_info->phc_index = ptp_clock_index(adapter->ptp.ptp_clock);
+	else
+		ts_info->phc_index = -1;
+#else
+	ts_info->phc_index = -1;
+#endif
+	ts_info->tx_types = BIT(HWTSTAMP_TX_OFF) |
+			    BIT(HWTSTAMP_TX_ON);
+	ts_info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
+			      BIT(HWTSTAMP_FILTER_ALL);
+	return 0;
+}
+
 static int lan743x_ethtool_get_eee(struct net_device *netdev,
 				   struct ethtool_eee *eee)
 {
@@ -690,6 +717,7 @@ const struct ethtool_ops lan743x_ethtool_ops = {
 	.get_rxfh_indir_size = lan743x_ethtool_get_rxfh_indir_size,
 	.get_rxfh = lan743x_ethtool_get_rxfh,
 	.set_rxfh = lan743x_ethtool_set_rxfh,
+	.get_ts_info = lan743x_ethtool_get_ts_info,
 	.get_eee = lan743x_ethtool_get_eee,
 	.set_eee = lan743x_ethtool_set_eee,
 	.get_link_ksettings = phy_ethtool_get_link_ksettings,
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index 953b581..ca9ae49 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -267,6 +267,10 @@ static void lan743x_intr_shared_isr(void *context, u32 int_sts, u32 flags)
 			lan743x_intr_software_isr(adapter);
 			int_sts &= ~INT_BIT_SW_GP_;
 		}
+		if (int_sts & INT_BIT_1588_) {
+			lan743x_ptp_isr(adapter);
+			int_sts &= ~INT_BIT_1588_;
+		}
 	}
 	if (int_sts)
 		lan743x_csr_write(adapter, INT_EN_CLR, int_sts);
@@ -976,6 +980,7 @@ static void lan743x_phy_link_status_change(struct net_device *netdev)
 					       ksettings.base.duplex,
 					       local_advertisement,
 					       remote_advertisement);
+		lan743x_ptp_update_latency(adapter, ksettings.base.speed);
 	}
 }
 
@@ -1256,11 +1261,29 @@ static void lan743x_tx_release_desc(struct lan743x_tx *tx,
 		buffer_info->dma_ptr = 0;
 		buffer_info->buffer_length = 0;
 	}
-	if (buffer_info->skb) {
+	if (!buffer_info->skb)
+		goto clear_active;
+
+	if (!(buffer_info->flags &
+		TX_BUFFER_INFO_FLAG_TIMESTAMP_REQUESTED)) {
 		dev_kfree_skb(buffer_info->skb);
-		buffer_info->skb = NULL;
+		goto clear_skb;
 	}
 
+	if (cleanup) {
+		lan743x_ptp_unrequest_tx_timestamp(tx->adapter);
+		dev_kfree_skb(buffer_info->skb);
+	} else {
+		lan743x_ptp_tx_timestamp_skb(tx->adapter,
+					     buffer_info->skb,
+					     (buffer_info->flags &
+					     TX_BUFFER_INFO_FLAG_IGNORE_SYNC)
+					     != 0);
+	}
+
+clear_skb:
+	buffer_info->skb = NULL;
+
 clear_active:
 	buffer_info->flags &= ~TX_BUFFER_INFO_FLAG_ACTIVE;
 
@@ -1321,10 +1344,25 @@ static int lan743x_tx_get_avail_desc(struct lan743x_tx *tx)
 		return last_head - last_tail - 1;
 }
 
+void lan743x_tx_set_timestamping_mode(struct lan743x_tx *tx,
+				      bool enable_timestamping,
+				      bool enable_onestep_sync)
+{
+	if (enable_timestamping)
+		tx->ts_flags |= TX_TS_FLAG_TIMESTAMPING_ENABLED;
+	else
+		tx->ts_flags &= ~TX_TS_FLAG_TIMESTAMPING_ENABLED;
+	if (enable_onestep_sync)
+		tx->ts_flags |= TX_TS_FLAG_ONE_STEP_SYNC;
+	else
+		tx->ts_flags &= ~TX_TS_FLAG_ONE_STEP_SYNC;
+}
+
 static int lan743x_tx_frame_start(struct lan743x_tx *tx,
 				  unsigned char *first_buffer,
 				  unsigned int first_buffer_length,
 				  unsigned int frame_length,
+				  bool time_stamp,
 				  bool check_sum)
 {
 	/* called only from within lan743x_tx_xmit_frame.
@@ -1362,6 +1400,8 @@ static int lan743x_tx_frame_start(struct lan743x_tx *tx,
 		TX_DESC_DATA0_DTYPE_DATA_ |
 		TX_DESC_DATA0_FS_ |
 		TX_DESC_DATA0_FCS_;
+	if (time_stamp)
+		tx->frame_data0 |= TX_DESC_DATA0_TSE_;
 
 	if (check_sum)
 		tx->frame_data0 |= TX_DESC_DATA0_ICE_ |
@@ -1475,6 +1515,7 @@ static int lan743x_tx_frame_add_fragment(struct lan743x_tx *tx,
 
 static void lan743x_tx_frame_end(struct lan743x_tx *tx,
 				 struct sk_buff *skb,
+				 bool time_stamp,
 				 bool ignore_sync)
 {
 	/* called only from within lan743x_tx_xmit_frame
@@ -1492,6 +1533,8 @@ static void lan743x_tx_frame_end(struct lan743x_tx *tx,
 	tx_descriptor = &tx->ring_cpu_ptr[tx->frame_tail];
 	buffer_info = &tx->buffer_info[tx->frame_tail];
 	buffer_info->skb = skb;
+	if (time_stamp)
+		buffer_info->flags |= TX_BUFFER_INFO_FLAG_TIMESTAMP_REQUESTED;
 	if (ignore_sync)
 		buffer_info->flags |= TX_BUFFER_INFO_FLAG_IGNORE_SYNC;
 
@@ -1520,6 +1563,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
 	unsigned int frame_length = 0;
 	unsigned int head_length = 0;
 	unsigned long irq_flags = 0;
+	bool do_timestamp = false;
 	bool ignore_sync = false;
 	int nr_frags = 0;
 	bool gso = false;
@@ -1541,6 +1585,16 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
 	}
 
 	/* space available, transmit skb  */
+	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
+		if (tx->ts_flags & TX_TS_FLAG_TIMESTAMPING_ENABLED) {
+			if (lan743x_ptp_request_tx_timestamp(tx->adapter)) {
+				skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+				do_timestamp = true;
+				if (tx->ts_flags & TX_TS_FLAG_ONE_STEP_SYNC)
+					ignore_sync = true;
+			}
+		}
+	}
 	head_length = skb_headlen(skb);
 	frame_length = skb_pagelen(skb);
 	nr_frags = skb_shinfo(skb)->nr_frags;
@@ -1554,6 +1608,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
 	if (lan743x_tx_frame_start(tx,
 				   skb->data, head_length,
 				   start_frame_length,
+				   do_timestamp,
 				   skb->ip_summed == CHECKSUM_PARTIAL)) {
 		dev_kfree_skb(skb);
 		goto unlock;
@@ -1581,7 +1636,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
 	}
 
 finish:
-	lan743x_tx_frame_end(tx, skb, ignore_sync);
+	lan743x_tx_frame_end(tx, skb, do_timestamp, ignore_sync);
 
 unlock:
 	spin_unlock_irqrestore(&tx->ring_lock, irq_flags);
@@ -2410,6 +2465,8 @@ static int lan743x_netdev_close(struct net_device *netdev)
 	for (index = 0; index < LAN743X_USED_RX_CHANNELS; index++)
 		lan743x_rx_close(&adapter->rx[index]);
 
+	lan743x_ptp_close(adapter);
+
 	lan743x_phy_close(adapter);
 
 	lan743x_mac_close(adapter);
@@ -2437,6 +2494,10 @@ static int lan743x_netdev_open(struct net_device *netdev)
 	if (ret)
 		goto close_mac;
 
+	ret = lan743x_ptp_open(adapter);
+	if (ret)
+		goto close_phy;
+
 	lan743x_rfe_open(adapter);
 
 	for (index = 0; index < LAN743X_USED_RX_CHANNELS; index++) {
@@ -2456,6 +2517,9 @@ static int lan743x_netdev_open(struct net_device *netdev)
 		if (adapter->rx[index].ring_cpu_ptr)
 			lan743x_rx_close(&adapter->rx[index]);
 	}
+	lan743x_ptp_close(adapter);
+
+close_phy:
 	lan743x_phy_close(adapter);
 
 close_mac:
@@ -2483,6 +2547,8 @@ static int lan743x_netdev_ioctl(struct net_device *netdev,
 {
 	if (!netif_running(netdev))
 		return -EINVAL;
+	if (cmd == SIOCSHWTSTAMP)
+		return lan743x_ptp_ioctl(netdev, ifr, cmd);
 	return phy_mii_ioctl(netdev->phydev, ifr, cmd);
 }
 
@@ -2607,6 +2673,11 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
 	adapter->intr.irq = adapter->pdev->irq;
 	lan743x_csr_write(adapter, INT_EN_CLR, 0xFFFFFFFF);
 	mutex_init(&adapter->dp_lock);
+
+	ret = lan743x_gpio_init(adapter);
+	if (ret)
+		return ret;
+
 	ret = lan743x_mac_init(adapter);
 	if (ret)
 		return ret;
@@ -2615,6 +2686,10 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
 	if (ret)
 		return ret;
 
+	ret = lan743x_ptp_init(adapter);
+	if (ret)
+		return ret;
+
 	lan743x_rfe_update_mac_address(adapter);
 
 	ret = lan743x_dmac_init(adapter);
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index 4fa7a5e..578a618 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -4,12 +4,17 @@
 #ifndef _LAN743X_H
 #define _LAN743X_H
 
+#include "lan743x_ptp.h"
+
 #define DRIVER_AUTHOR   "Bryan Whitehead <Bryan.Whitehead@microchip.com>"
 #define DRIVER_DESC "LAN743x PCIe Gigabit Ethernet Driver"
 #define DRIVER_NAME "lan743x"
 
 /* Register Definitions */
 #define ID_REV				(0x00)
+#define ID_REV_ID_MASK_			(0xFFFF0000)
+#define ID_REV_ID_LAN7430_		(0x74300000)
+#define ID_REV_ID_LAN7431_		(0x74310000)
 #define ID_REV_IS_VALID_CHIP_ID_(id_rev)	\
 	(((id_rev) & 0xFFF00000) == 0x74300000)
 #define ID_REV_CHIP_REV_MASK_		(0x0000FFFF)
@@ -62,6 +67,21 @@
 
 #define E2P_DATA			(0x044)
 
+#define GPIO_CFG0			(0x050)
+#define GPIO_CFG0_GPIO_DIR_BIT_(bit)	BIT(16 + (bit))
+#define GPIO_CFG0_GPIO_DATA_BIT_(bit)	BIT(0 + (bit))
+
+#define GPIO_CFG1			(0x054)
+#define GPIO_CFG1_GPIOEN_BIT_(bit)	BIT(16 + (bit))
+#define GPIO_CFG1_GPIOBUF_BIT_(bit)	BIT(0 + (bit))
+
+#define GPIO_CFG2			(0x058)
+#define GPIO_CFG2_1588_POL_BIT_(bit)	BIT(0 + (bit))
+
+#define GPIO_CFG3			(0x05C)
+#define GPIO_CFG3_1588_CH_SEL_BIT_(bit)	BIT(16 + (bit))
+#define GPIO_CFG3_1588_OE_BIT_(bit)	BIT(0 + (bit))
+
 #define FCT_RX_CTL			(0xAC)
 #define FCT_RX_CTL_EN_(channel)		BIT(28 + (channel))
 #define FCT_RX_CTL_DIS_(channel)	BIT(24 + (channel))
@@ -193,7 +213,8 @@
 #define INT_BIT_DMA_TX_(channel)	BIT(16 + (channel))
 #define INT_BIT_ALL_TX_			(0x000F0000)
 #define INT_BIT_SW_GP_			BIT(9)
-#define INT_BIT_ALL_OTHER_		(0x00000280)
+#define INT_BIT_1588_			BIT(7)
+#define INT_BIT_ALL_OTHER_		(INT_BIT_SW_GP_ | INT_BIT_1588_)
 #define INT_BIT_MAS_			BIT(0)
 
 #define INT_SET				(0x784)
@@ -234,6 +255,66 @@
 #define INT_MOD_CFG6			(0x7D8)
 #define INT_MOD_CFG7			(0x7DC)
 
+#define PTP_CMD_CTL					(0x0A00)
+#define PTP_CMD_CTL_PTP_CLK_STP_NSEC_			BIT(6)
+#define PTP_CMD_CTL_PTP_CLOCK_STEP_SEC_			BIT(5)
+#define PTP_CMD_CTL_PTP_CLOCK_LOAD_			BIT(4)
+#define PTP_CMD_CTL_PTP_CLOCK_READ_			BIT(3)
+#define PTP_CMD_CTL_PTP_ENABLE_				BIT(2)
+#define PTP_CMD_CTL_PTP_DISABLE_			BIT(1)
+#define PTP_CMD_CTL_PTP_RESET_				BIT(0)
+#define PTP_GENERAL_CONFIG				(0x0A04)
+#define PTP_GENERAL_CONFIG_CLOCK_EVENT_X_MASK_(channel) \
+	(0x7 << (1 + ((channel) << 2)))
+#define PTP_GENERAL_CONFIG_CLOCK_EVENT_100US_	(2)
+#define PTP_GENERAL_CONFIG_CLOCK_EVENT_X_SET_(channel, value) \
+	(((value) & 0x7) << (1 + ((channel) << 2)))
+#define PTP_GENERAL_CONFIG_RELOAD_ADD_X_(channel)	(BIT((channel) << 2))
+
+#define PTP_INT_STS				(0x0A08)
+#define PTP_INT_EN_SET				(0x0A0C)
+#define PTP_INT_EN_CLR				(0x0A10)
+#define PTP_INT_BIT_TX_SWTS_ERR_		BIT(13)
+#define PTP_INT_BIT_TX_TS_			BIT(12)
+#define PTP_INT_BIT_TIMER_B_			BIT(1)
+#define PTP_INT_BIT_TIMER_A_			BIT(0)
+
+#define PTP_CLOCK_SEC				(0x0A14)
+#define PTP_CLOCK_NS				(0x0A18)
+#define PTP_CLOCK_SUBNS				(0x0A1C)
+#define PTP_CLOCK_RATE_ADJ			(0x0A20)
+#define PTP_CLOCK_RATE_ADJ_DIR_			BIT(31)
+#define PTP_CLOCK_STEP_ADJ			(0x0A2C)
+#define PTP_CLOCK_STEP_ADJ_DIR_			BIT(31)
+#define PTP_CLOCK_STEP_ADJ_VALUE_MASK_		(0x3FFFFFFF)
+#define PTP_CLOCK_TARGET_SEC_X(channel)		(0x0A30 + ((channel) << 4))
+#define PTP_CLOCK_TARGET_NS_X(channel)		(0x0A34 + ((channel) << 4))
+#define PTP_CLOCK_TARGET_RELOAD_SEC_X(channel)	(0x0A38 + ((channel) << 4))
+#define PTP_CLOCK_TARGET_RELOAD_NS_X(channel)	(0x0A3C + ((channel) << 4))
+#define PTP_LATENCY				(0x0A5C)
+#define PTP_LATENCY_TX_SET_(tx_latency)		(((u32)(tx_latency)) << 16)
+#define PTP_LATENCY_RX_SET_(rx_latency)		\
+	(((u32)(rx_latency)) & 0x0000FFFF)
+#define PTP_CAP_INFO				(0x0A60)
+#define PTP_CAP_INFO_TX_TS_CNT_GET_(reg_val)	((reg_val & 0x00000070) >> 4)
+
+#define PTP_TX_MOD				(0x0AA4)
+#define PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_	(0x10000000)
+
+#define PTP_TX_MOD2				(0x0AA8)
+#define PTP_TX_MOD2_TX_PTP_CLR_UDPV4_CHKSUM_	(0x00000001)
+
+#define PTP_TX_EGRESS_SEC			(0x0AAC)
+#define PTP_TX_EGRESS_NS			(0x0AB0)
+#define PTP_TX_EGRESS_NS_CAPTURE_CAUSE_MASK_	(0xC0000000)
+#define PTP_TX_EGRESS_NS_CAPTURE_CAUSE_AUTO_	(0x00000000)
+#define PTP_TX_EGRESS_NS_CAPTURE_CAUSE_SW_	(0x40000000)
+#define PTP_TX_EGRESS_NS_TS_NS_MASK_		(0x3FFFFFFF)
+
+#define PTP_TX_MSG_HEADER			(0x0AB4)
+#define PTP_TX_MSG_HEADER_MSG_TYPE_		(0x000F0000)
+#define PTP_TX_MSG_HEADER_MSG_TYPE_SYNC_	(0x00000000)
+
 #define DMAC_CFG				(0xC00)
 #define DMAC_CFG_COAL_EN_			BIT(16)
 #define DMAC_CFG_CH_ARB_SEL_RX_HIGH_		(0x00000000)
@@ -542,8 +623,12 @@ struct lan743x_tx_buffer_info;
 
 #define TX_FRAME_FLAG_IN_PROGRESS	BIT(0)
 
+#define TX_TS_FLAG_TIMESTAMPING_ENABLED	BIT(0)
+#define TX_TS_FLAG_ONE_STEP_SYNC	BIT(1)
+
 struct lan743x_tx {
 	struct lan743x_adapter *adapter;
+	u32	ts_flags;
 	u32	vector_flags;
 	int	channel_number;
 
@@ -570,6 +655,10 @@ struct lan743x_tx {
 	struct sk_buff *overflow_skb;
 };
 
+void lan743x_tx_set_timestamping_mode(struct lan743x_tx *tx,
+				      bool enable_timestamping,
+				      bool enable_onestep_sync);
+
 /* RX */
 struct lan743x_rx_descriptor;
 struct lan743x_rx_buffer_info;
@@ -610,6 +699,9 @@ struct lan743x_adapter {
 	/* lock, used to prevent concurrent access to data port */
 	struct mutex		dp_lock;
 
+	struct lan743x_gpio	gpio;
+	struct lan743x_ptp	ptp;
+
 	u8			mac_address[ETH_ALEN];
 
 	struct lan743x_phy      phy;
@@ -660,6 +752,7 @@ struct lan743x_adapter {
 #define TX_DESC_DATA0_IPE_			(0x00200000)
 #define TX_DESC_DATA0_TPE_			(0x00100000)
 #define TX_DESC_DATA0_FCS_			(0x00020000)
+#define TX_DESC_DATA0_TSE_			(0x00010000)
 #define TX_DESC_DATA0_BUF_LENGTH_MASK_		(0x0000FFFF)
 #define TX_DESC_DATA0_EXT_LSO_			(0x00200000)
 #define TX_DESC_DATA0_EXT_PAY_LENGTH_MASK_	(0x000FFFFF)
@@ -673,6 +766,7 @@ struct lan743x_tx_descriptor {
 } __aligned(DEFAULT_DMA_DESCRIPTOR_SPACING);
 
 #define TX_BUFFER_INFO_FLAG_ACTIVE		BIT(0)
+#define TX_BUFFER_INFO_FLAG_TIMESTAMP_REQUESTED	BIT(1)
 #define TX_BUFFER_INFO_FLAG_IGNORE_SYNC		BIT(2)
 #define TX_BUFFER_INFO_FLAG_SKB_FRAGMENT	BIT(3)
 struct lan743x_tx_buffer_info {
diff --git a/drivers/net/ethernet/microchip/lan743x_ptp.c b/drivers/net/ethernet/microchip/lan743x_ptp.c
new file mode 100644
index 0000000..f14565b
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan743x_ptp.c
@@ -0,0 +1,1194 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (C) 2018 Microchip Technology Inc. */
+
+#include <linux/netdevice.h>
+#include "lan743x_main.h"
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/net_tstamp.h>
+
+#include "lan743x_ptp.h"
+
+/* GPIO */
+#define LAN743X_NUMBER_OF_GPIO          (12)
+
+int lan743x_gpio_init(struct lan743x_adapter *adapter)
+{
+	struct lan743x_gpio *gpio = &adapter->gpio;
+
+	spin_lock_init(&gpio->gpio_lock);
+
+	gpio->gpio_cfg0 = 0; /* set all direction to input, data = 0 */
+	gpio->gpio_cfg1 = 0x0FFF0000;/* disable all gpio, set to open drain */
+	gpio->gpio_cfg2 = 0;/* set all to 1588 low polarity level */
+	gpio->gpio_cfg3 = 0;/* disable all 1588 output */
+	lan743x_csr_write(adapter, GPIO_CFG0, gpio->gpio_cfg0);
+	lan743x_csr_write(adapter, GPIO_CFG1, gpio->gpio_cfg1);
+	lan743x_csr_write(adapter, GPIO_CFG2, gpio->gpio_cfg2);
+	lan743x_csr_write(adapter, GPIO_CFG3, gpio->gpio_cfg3);
+
+	return 0;
+}
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_gpio_reserve_ptp_output(struct lan743x_adapter *adapter,
+					   int bit, int ptp_channel)
+{
+	struct lan743x_gpio *gpio = &adapter->gpio;
+	unsigned long irq_flags = 0;
+	int bit_mask = BIT(bit);
+	int ret = -EBUSY;
+
+	spin_lock_irqsave(&gpio->gpio_lock, irq_flags);
+
+	if (!(gpio->used_bits & bit_mask)) {
+		gpio->used_bits |= bit_mask;
+		gpio->output_bits |= bit_mask;
+		gpio->ptp_bits |= bit_mask;
+
+		/* set as output, and zero initial value */
+		gpio->gpio_cfg0 |= GPIO_CFG0_GPIO_DIR_BIT_(bit);
+		gpio->gpio_cfg0 &= ~GPIO_CFG0_GPIO_DATA_BIT_(bit);
+		lan743x_csr_write(adapter, GPIO_CFG0, gpio->gpio_cfg0);
+
+		/* enable gpio , and set buffer type to push pull */
+		gpio->gpio_cfg1 &= ~GPIO_CFG1_GPIOEN_BIT_(bit);
+		gpio->gpio_cfg1 |= GPIO_CFG1_GPIOBUF_BIT_(bit);
+		lan743x_csr_write(adapter, GPIO_CFG1, gpio->gpio_cfg1);
+
+		/* set 1588 polarity to high */
+		gpio->gpio_cfg2 |= GPIO_CFG2_1588_POL_BIT_(bit);
+		lan743x_csr_write(adapter, GPIO_CFG2, gpio->gpio_cfg2);
+
+		if (!ptp_channel) {
+			/* use channel A */
+			gpio->gpio_cfg3 &= ~GPIO_CFG3_1588_CH_SEL_BIT_(bit);
+		} else {
+			/* use channel B */
+			gpio->gpio_cfg3 |= GPIO_CFG3_1588_CH_SEL_BIT_(bit);
+		}
+		gpio->gpio_cfg3 |= GPIO_CFG3_1588_OE_BIT_(bit);
+		lan743x_csr_write(adapter, GPIO_CFG3, gpio->gpio_cfg3);
+
+		ret = bit;
+	}
+	spin_unlock_irqrestore(&gpio->gpio_lock, irq_flags);
+	return ret;
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static void lan743x_gpio_release(struct lan743x_adapter *adapter, int bit)
+{
+	struct lan743x_gpio *gpio = &adapter->gpio;
+	unsigned long irq_flags = 0;
+	int bit_mask = BIT(bit);
+
+	spin_lock_irqsave(&gpio->gpio_lock, irq_flags);
+	if (gpio->used_bits & bit_mask) {
+		gpio->used_bits &= ~bit_mask;
+		if (gpio->output_bits & bit_mask) {
+			gpio->output_bits &= ~bit_mask;
+
+			if (gpio->ptp_bits & bit_mask) {
+				gpio->ptp_bits &= ~bit_mask;
+				/* disable ptp output */
+				gpio->gpio_cfg3 &= ~GPIO_CFG3_1588_OE_BIT_(bit);
+				lan743x_csr_write(adapter, GPIO_CFG3,
+						  gpio->gpio_cfg3);
+			}
+			/* release gpio output */
+
+			/* disable gpio */
+			gpio->gpio_cfg1 |= GPIO_CFG1_GPIOEN_BIT_(bit);
+			gpio->gpio_cfg1 &= ~GPIO_CFG1_GPIOBUF_BIT_(bit);
+			lan743x_csr_write(adapter, GPIO_CFG1, gpio->gpio_cfg1);
+
+			/* reset back to input */
+			gpio->gpio_cfg0 &= ~GPIO_CFG0_GPIO_DIR_BIT_(bit);
+			gpio->gpio_cfg0 &= ~GPIO_CFG0_GPIO_DATA_BIT_(bit);
+			lan743x_csr_write(adapter, GPIO_CFG0, gpio->gpio_cfg0);
+		}
+	}
+	spin_unlock_irqrestore(&gpio->gpio_lock, irq_flags);
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+/* PTP */
+#define LAN743X_PTP_MAX_FREQ_ADJ_IN_PPB (31249999)
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptp_reserve_event_ch(struct lan743x_adapter *adapter);
+static void lan743x_ptp_release_event_ch(struct lan743x_adapter *adapter,
+					 int event_channel);
+#endif
+
+static bool lan743x_ptp_is_enabled(struct lan743x_adapter *adapter);
+static void lan743x_ptp_enable(struct lan743x_adapter *adapter);
+static void lan743x_ptp_disable(struct lan743x_adapter *adapter);
+static void lan743x_ptp_reset(struct lan743x_adapter *adapter);
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static void lan743x_ptp_clock_get(struct lan743x_adapter *adapter,
+				  u32 *seconds, u32 *nano_seconds,
+				  u32 *sub_nano_seconds);
+static int lan743x_ptp_enable_pps(struct lan743x_adapter *adapter);
+static void lan743x_ptp_disable_pps(struct lan743x_adapter *adapter);
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static void lan743x_ptp_clock_step(struct lan743x_adapter *adapter,
+				   s64 time_step_ns);
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+static void lan743x_ptp_clock_set(struct lan743x_adapter *adapter,
+				  u32 seconds, u32 nano_seconds,
+				  u32 sub_nano_seconds);
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptpci_adjfreq(struct ptp_clock_info *ptpci, s32 delta_ppb)
+{
+	struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
+					       ptp_clock_info);
+	struct lan743x_adapter *adapter = container_of(ptp,
+						       struct lan743x_adapter,
+						       ptp);
+	u32 lan743x_rate_adj = 0;
+	bool positive = true;
+	u32 u32_delta = 0;
+	u64 u64_delta = 0;
+
+	if ((delta_ppb < (-LAN743X_PTP_MAX_FREQ_ADJ_IN_PPB)) ||
+	    delta_ppb > LAN743X_PTP_MAX_FREQ_ADJ_IN_PPB) {
+		return -EINVAL;
+	}
+	if (delta_ppb > 0) {
+		u32_delta = (u32)delta_ppb;
+		positive = true;
+	} else {
+		u32_delta = (u32)(-delta_ppb);
+		positive = false;
+	}
+	u64_delta = (((u64)u32_delta) * 0x800000000ULL);
+	lan743x_rate_adj = (u32)(u64_delta / 1000000000);
+
+	if (positive)
+		lan743x_rate_adj |= PTP_CLOCK_RATE_ADJ_DIR_;
+
+	lan743x_csr_write(adapter, PTP_CLOCK_RATE_ADJ,
+			  lan743x_rate_adj);
+
+	netif_info(adapter, drv, adapter->netdev,
+		   "adjfreq, delta_ppb = %d, lan743x_rate_adj = 0x%08X\n",
+		   delta_ppb, lan743x_rate_adj);
+	return 0;
+}
+#endif /*CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptpci_adjtime(struct ptp_clock_info *ptpci, s64 delta)
+{
+	struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
+					       ptp_clock_info);
+	struct lan743x_adapter *adapter = container_of(ptp,
+						       struct lan743x_adapter,
+						       ptp);
+	bool enable_pps = false;
+
+	if (ptp->pps_event_ch >= 0) {
+		lan743x_ptp_disable_pps(adapter);
+		enable_pps = true;
+	}
+
+	lan743x_ptp_clock_step(adapter, delta);
+	netif_info(adapter, drv, adapter->netdev,
+		   "adjtime, delta = %lld\n", delta);
+
+	if (enable_pps)
+		lan743x_ptp_enable_pps(adapter);
+
+	return 0;
+}
+#endif /*CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptpci_gettime64(struct ptp_clock_info *ptpci,
+				   struct timespec64 *ts)
+{
+	struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
+					       ptp_clock_info);
+	struct lan743x_adapter *adapter = container_of(ptp,
+						       struct lan743x_adapter,
+						       ptp);
+
+	if (ts) {
+		u32 seconds = 0;
+		u32 nano_seconds = 0;
+
+		lan743x_ptp_clock_get(adapter, &seconds, &nano_seconds, NULL);
+		ts->tv_sec = seconds;
+		ts->tv_nsec = nano_seconds;
+		netif_info(adapter, drv, adapter->netdev,
+			   "gettime = %u.%09u\n", seconds, nano_seconds);
+	} else {
+		netif_warn(adapter, drv, adapter->netdev, "ts == NULL\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+#endif /*CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptpci_settime64(struct ptp_clock_info *ptpci,
+				   const struct timespec64 *ts)
+{
+	struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
+					       ptp_clock_info);
+	struct lan743x_adapter *adapter = container_of(ptp,
+						       struct lan743x_adapter,
+						       ptp);
+	bool enable_pps = false;
+
+	if (ptp->pps_event_ch >= 0) {
+		lan743x_ptp_disable_pps(adapter);
+		enable_pps = true;
+	}
+
+	if (ts) {
+		u32 seconds = 0;
+		u32 nano_seconds = 0;
+
+		if (ts->tv_sec > 0xFFFFFFFFLL ||
+		    ts->tv_sec < 0) {
+			netif_warn(adapter, drv, adapter->netdev,
+				   "ts->tv_sec out of range, %lld\n",
+				   ts->tv_sec);
+			return -EINVAL;
+		}
+		if (ts->tv_nsec >= 1000000000L ||
+		    ts->tv_nsec < 0) {
+			netif_warn(adapter, drv, adapter->netdev,
+				   "ts->tv_nsec out of range, %ld\n",
+				   ts->tv_nsec);
+			return -EINVAL;
+		}
+		seconds = ts->tv_sec;
+		nano_seconds = ts->tv_nsec;
+		netif_info(adapter, drv, adapter->netdev,
+			   "settime = %u.%09u\n", seconds, nano_seconds);
+		lan743x_ptp_clock_set(adapter, seconds, nano_seconds, 0);
+	} else {
+		netif_warn(adapter, drv, adapter->netdev, "ts == NULL\n");
+		return -EINVAL;
+	}
+
+	if (enable_pps)
+		lan743x_ptp_enable_pps(adapter);
+
+	return 0;
+}
+#endif /*CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptp_enable_pps(struct lan743x_adapter *adapter)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+	u32 current_seconds = 0;
+	u32 target_seconds = 0;
+	u32 general_config = 0;
+	int result = -ENODEV;
+	int pps_bit = 0;
+
+	if (ptp->pps_event_ch >= 0) {
+		result = 0;
+		goto done;
+	}
+
+	ptp->pps_event_ch = lan743x_ptp_reserve_event_ch(adapter);
+	if (ptp->pps_event_ch < 0) {
+		netif_warn(adapter, drv, adapter->netdev,
+			   "Failed to reserve event channel for PPS\n");
+		goto done;
+	}
+
+	switch(adapter->csr.id_rev & ID_REV_ID_MASK_) {
+	case ID_REV_ID_LAN7430_:
+		pps_bit = 2;/* GPIO 2 is preferred on EVB LAN7430 */
+		break;
+	case ID_REV_ID_LAN7431_:
+		pps_bit = 4;/* GPIO 4 is preferred on EVB LAN7431 */
+		break;
+	}
+
+	ptp->pps_gpio_bit = lan743x_gpio_reserve_ptp_output(adapter, pps_bit,
+							    ptp->pps_event_ch);
+
+	if (ptp->pps_gpio_bit < 0) {
+		netif_warn(adapter, drv, adapter->netdev,
+			   "Failed to reserve gpio 0 for PPS\n");
+		goto done;
+	}
+
+	lan743x_ptp_clock_get(adapter, &current_seconds, NULL, NULL);
+
+	/* set the first target ahead by 2 seconds
+	 *	to make sure its not missed
+	 */
+	target_seconds = current_seconds + 2;
+
+	/* set the new target */
+	lan743x_csr_write(adapter,
+			  PTP_CLOCK_TARGET_SEC_X(ptp->pps_event_ch),
+			  0xFFFF0000);
+	lan743x_csr_write(adapter,
+			  PTP_CLOCK_TARGET_NS_X(ptp->pps_event_ch), 0);
+
+	general_config = lan743x_csr_read(adapter, PTP_GENERAL_CONFIG);
+
+	general_config &= ~(PTP_GENERAL_CONFIG_CLOCK_EVENT_X_MASK_
+			  (ptp->pps_event_ch));
+	general_config |= PTP_GENERAL_CONFIG_CLOCK_EVENT_X_SET_
+			  (ptp->pps_event_ch,
+			   PTP_GENERAL_CONFIG_CLOCK_EVENT_100US_);
+	general_config &= ~PTP_GENERAL_CONFIG_RELOAD_ADD_X_
+			  (ptp->pps_event_ch);
+	lan743x_csr_write(adapter, PTP_GENERAL_CONFIG, general_config);
+
+	/* set the reload to one second steps */
+	lan743x_csr_write(adapter,
+			  PTP_CLOCK_TARGET_RELOAD_SEC_X(ptp->pps_event_ch),
+			  1);
+	lan743x_csr_write(adapter,
+			  PTP_CLOCK_TARGET_RELOAD_NS_X(ptp->pps_event_ch),
+			  0);
+
+	/* set the new target */
+	lan743x_csr_write(adapter,
+			  PTP_CLOCK_TARGET_SEC_X(ptp->pps_event_ch),
+			  target_seconds);
+	lan743x_csr_write(adapter,
+			  PTP_CLOCK_TARGET_NS_X(ptp->pps_event_ch),
+			  0);
+	return 0;
+
+done:
+	if (ptp->pps_gpio_bit >= 0) {
+		lan743x_gpio_release(adapter, ptp->pps_gpio_bit);
+		ptp->pps_gpio_bit = -1;
+	}
+	if (ptp->pps_event_ch >= 0) {
+		lan743x_ptp_release_event_ch(adapter,
+					     ptp->pps_event_ch);
+		ptp->pps_event_ch = -1;
+	}
+	return result;
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static void lan743x_ptp_disable_pps(struct lan743x_adapter *adapter)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+
+	if (ptp->pps_gpio_bit >= 0) {
+		lan743x_gpio_release(adapter, ptp->pps_gpio_bit);
+		ptp->pps_gpio_bit = -1;
+	}
+
+	if (ptp->pps_event_ch >= 0) {
+		u32 general_config = 0;
+
+		/* set target to far in the future, effectively disabling it */
+		lan743x_csr_write(adapter,
+				  PTP_CLOCK_TARGET_SEC_X(ptp->pps_event_ch),
+				  0xFFFF0000);
+		lan743x_csr_write(adapter,
+				  PTP_CLOCK_TARGET_NS_X(ptp->pps_event_ch), 0);
+
+		general_config = lan743x_csr_read(adapter, PTP_GENERAL_CONFIG);
+		general_config |= PTP_GENERAL_CONFIG_RELOAD_ADD_X_
+				  (ptp->pps_event_ch);
+		lan743x_csr_write(adapter, PTP_GENERAL_CONFIG, general_config);
+		lan743x_ptp_release_event_ch(adapter, ptp->pps_event_ch);
+		ptp->pps_event_ch = -1;
+	}
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptpci_enable(struct ptp_clock_info *ptpci,
+				struct ptp_clock_request *request, int on)
+{
+	struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
+					       ptp_clock_info);
+	struct lan743x_adapter *adapter = container_of(ptp,
+						       struct lan743x_adapter,
+						       ptp);
+
+	if (request) {
+		switch (request->type) {
+		case PTP_CLK_REQ_EXTTS:
+			return -EINVAL;
+		case PTP_CLK_REQ_PEROUT:
+			return -EINVAL;
+		case PTP_CLK_REQ_PPS:
+			if (on) {
+				if (lan743x_ptp_enable_pps(adapter) >= 0)
+					netif_info(adapter, drv,
+						   adapter->netdev,
+						   "PPS is ON\n");
+				else
+					netif_warn(adapter, drv,
+						   adapter->netdev,
+						   "Error starting PPS\n");
+			} else {
+				lan743x_ptp_disable_pps(adapter);
+				netif_info(adapter, drv, adapter->netdev,
+					   "PPS is OFF\n");
+			}
+			break;
+		default:
+			netif_err(adapter, drv, adapter->netdev,
+				  "request->type == %d, Unknown\n",
+				  request->type);
+			break;
+		}
+	} else {
+		netif_err(adapter, drv, adapter->netdev, "request == NULL\n");
+	}
+	return 0;
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+void lan743x_ptp_isr(void *context)
+{
+	struct lan743x_adapter *adapter = (struct lan743x_adapter *)context;
+	struct lan743x_ptp *ptp = NULL;
+	int enable_flag = 1;
+	u32 ptp_int_sts = 0;
+
+	ptp = &adapter->ptp;
+
+	lan743x_csr_write(adapter, INT_EN_CLR, INT_BIT_1588_);
+
+	ptp_int_sts = lan743x_csr_read(adapter, PTP_INT_STS);
+	ptp_int_sts &= lan743x_csr_read(adapter, PTP_INT_EN_SET);
+
+	if (ptp_int_sts & PTP_INT_BIT_TX_TS_) {
+		tasklet_schedule(&ptp->ptp_isr_bottom_half);
+		enable_flag = 0;/* tasklet will re-enable later */
+	}
+	if (ptp_int_sts & PTP_INT_BIT_TX_SWTS_ERR_) {
+		netif_err(adapter, drv, adapter->netdev,
+			  "PTP TX Software Timestamp Error\n");
+		/* clear int status bit */
+		lan743x_csr_write(adapter, PTP_INT_STS,
+				  PTP_INT_BIT_TX_SWTS_ERR_);
+	}
+	if (ptp_int_sts & PTP_INT_BIT_TIMER_B_) {
+		netif_info(adapter, drv, adapter->netdev,
+			   "PTP TIMER B Interrupt\n");
+		/* clear int status bit */
+		lan743x_csr_write(adapter, PTP_INT_STS,
+				  PTP_INT_BIT_TIMER_B_);
+	}
+	if (ptp_int_sts & PTP_INT_BIT_TIMER_A_) {
+		netif_info(adapter, drv, adapter->netdev,
+			   "PTP TIMER A Interrupt\n");
+		/* clear int status bit */
+		lan743x_csr_write(adapter, PTP_INT_STS,
+				  PTP_INT_BIT_TIMER_A_);
+	}
+
+	if (enable_flag) {
+		/* re-enable isr */
+		lan743x_csr_write(adapter, INT_EN_SET, INT_BIT_1588_);
+	}
+}
+
+static void lan743x_ptp_tx_ts_complete(struct lan743x_adapter *adapter)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+	int i;
+	int c;
+
+	spin_lock_bh(&ptp->tx_ts_lock);
+	c = ptp->tx_ts_skb_queue_size;
+
+	if (c > ptp->tx_ts_queue_size)
+		c = ptp->tx_ts_queue_size;
+	if (c <= 0)
+		goto done;
+
+	for (i = 0; i < c; i++) {
+		bool ignore_sync = ((ptp->tx_ts_ignore_sync_queue &
+				    BIT(i)) != 0);
+		struct sk_buff *skb = ptp->tx_ts_skb_queue[i];
+		u32 nseconds = ptp->tx_ts_nseconds_queue[i];
+		u32 seconds = ptp->tx_ts_seconds_queue[i];
+		u32 header = ptp->tx_ts_header_queue[i];
+		struct skb_shared_hwtstamps tstamps;
+
+		memset(&tstamps, 0, sizeof(tstamps));
+		tstamps.hwtstamp = ktime_set(seconds, nseconds);
+		if (!ignore_sync ||
+		    ((header & PTP_TX_MSG_HEADER_MSG_TYPE_) !=
+		    PTP_TX_MSG_HEADER_MSG_TYPE_SYNC_))
+			skb_tstamp_tx(skb, &tstamps);
+
+		dev_kfree_skb(skb);
+
+		ptp->tx_ts_skb_queue[i] = NULL;
+		ptp->tx_ts_seconds_queue[i] = 0;
+		ptp->tx_ts_nseconds_queue[i] = 0;
+		ptp->tx_ts_header_queue[i] = 0;
+	}
+
+	/* shift queue */
+	ptp->tx_ts_ignore_sync_queue >>= c;
+	for (i = c; i < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS; i++) {
+		ptp->tx_ts_skb_queue[i - c] = ptp->tx_ts_skb_queue[i];
+		ptp->tx_ts_seconds_queue[i - c] = ptp->tx_ts_seconds_queue[i];
+		ptp->tx_ts_nseconds_queue[i - c] = ptp->tx_ts_nseconds_queue[i];
+		ptp->tx_ts_header_queue[i - c] = ptp->tx_ts_header_queue[i];
+
+		ptp->tx_ts_skb_queue[i] = NULL;
+		ptp->tx_ts_seconds_queue[i] = 0;
+		ptp->tx_ts_nseconds_queue[i] = 0;
+		ptp->tx_ts_header_queue[i] = 0;
+	}
+	ptp->tx_ts_skb_queue_size -= c;
+	ptp->tx_ts_queue_size -= c;
+done:
+	ptp->pending_tx_timestamps -= c;
+	spin_unlock_bh(&ptp->tx_ts_lock);
+}
+
+static void lan743x_ptp_tx_ts_enqueue_skb(struct lan743x_adapter *adapter,
+					  struct sk_buff *skb, bool ignore_sync)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+
+	spin_lock_bh(&ptp->tx_ts_lock);
+	if (ptp->tx_ts_skb_queue_size < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS) {
+		ptp->tx_ts_skb_queue[ptp->tx_ts_skb_queue_size] = skb;
+		if (ignore_sync)
+			ptp->tx_ts_ignore_sync_queue |=
+				BIT(ptp->tx_ts_skb_queue_size);
+		ptp->tx_ts_skb_queue_size++;
+	} else {
+		/* this should never happen, so long as the tx channel
+		 * calls and honors the result from
+		 * lan743x_ptp_request_tx_timestamp
+		 */
+		netif_err(adapter, drv, adapter->netdev,
+			  "tx ts skb queue overflow\n");
+		dev_kfree_skb(skb);
+	}
+	spin_unlock_bh(&ptp->tx_ts_lock);
+}
+
+static void lan743x_ptp_tx_ts_enqueue_ts(struct lan743x_adapter *adapter,
+					 u32 seconds, u32 nano_seconds,
+					 u32 header)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+
+	spin_lock_bh(&ptp->tx_ts_lock);
+	if (ptp->tx_ts_queue_size < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS) {
+		ptp->tx_ts_seconds_queue[ptp->tx_ts_queue_size] = seconds;
+		ptp->tx_ts_nseconds_queue[ptp->tx_ts_queue_size] = nano_seconds;
+		ptp->tx_ts_header_queue[ptp->tx_ts_queue_size] = header;
+		ptp->tx_ts_queue_size++;
+	} else {
+		netif_err(adapter, drv, adapter->netdev,
+			  "tx ts queue overflow\n");
+	}
+	spin_unlock_bh(&ptp->tx_ts_lock);
+}
+
+static void lan743x_ptp_isr_bottom_half(unsigned long param)
+{
+	struct lan743x_adapter *adapter = (struct lan743x_adapter *)param;
+	bool new_timestamp_available = false;
+
+	while (lan743x_csr_read(adapter, PTP_INT_STS) & PTP_INT_BIT_TX_TS_) {
+		u32 cap_info = lan743x_csr_read(adapter, PTP_CAP_INFO);
+
+		if (PTP_CAP_INFO_TX_TS_CNT_GET_(cap_info) > 0) {
+			u32 seconds = lan743x_csr_read(adapter,
+				PTP_TX_EGRESS_SEC);
+			u32 nsec = lan743x_csr_read(adapter, PTP_TX_EGRESS_NS);
+			u32 cause = (nsec &
+				     PTP_TX_EGRESS_NS_CAPTURE_CAUSE_MASK_);
+			u32 header = lan743x_csr_read(adapter,
+						      PTP_TX_MSG_HEADER);
+
+			if (cause == PTP_TX_EGRESS_NS_CAPTURE_CAUSE_SW_) {
+				nsec &= PTP_TX_EGRESS_NS_TS_NS_MASK_;
+				lan743x_ptp_tx_ts_enqueue_ts(adapter,
+							     seconds, nsec,
+							     header);
+				new_timestamp_available = true;
+			} else if (cause ==
+				PTP_TX_EGRESS_NS_CAPTURE_CAUSE_AUTO_) {
+				netif_err(adapter, drv, adapter->netdev,
+					  "Auto capture cause not supported\n");
+			} else {
+				netif_warn(adapter, drv, adapter->netdev,
+					   "unknown tx timestamp capture cause\n");
+			}
+		} else {
+			netif_warn(adapter, drv, adapter->netdev,
+				   "TX TS INT but no TX TS CNT\n");
+		}
+		lan743x_csr_write(adapter, PTP_INT_STS, PTP_INT_BIT_TX_TS_);
+	}
+
+	if (new_timestamp_available)
+		lan743x_ptp_tx_ts_complete(adapter);
+
+	lan743x_csr_write(adapter, INT_EN_SET, INT_BIT_1588_);
+}
+
+static void lan743x_ptp_sync_to_system_clock(struct lan743x_adapter *adapter)
+{
+	struct timeval tv;
+
+	memset(&tv, 0, sizeof(tv));
+	do_gettimeofday(&tv);
+	lan743x_ptp_clock_set(adapter, tv.tv_sec, tv.tv_usec * 1000, 0);
+}
+
+void lan743x_ptp_update_latency(struct lan743x_adapter *adapter,
+				u32 link_speed)
+{
+	switch (link_speed) {
+	case 10:
+		lan743x_csr_write(adapter, PTP_LATENCY,
+				  PTP_LATENCY_TX_SET_(0) |
+				  PTP_LATENCY_RX_SET_(0));
+		break;
+	case 100:
+		lan743x_csr_write(adapter, PTP_LATENCY,
+				  PTP_LATENCY_TX_SET_(181) |
+				  PTP_LATENCY_RX_SET_(594));
+		break;
+	case 1000:
+		lan743x_csr_write(adapter, PTP_LATENCY,
+				  PTP_LATENCY_TX_SET_(30) |
+				  PTP_LATENCY_RX_SET_(525));
+		break;
+	}
+}
+
+int lan743x_ptp_init(struct lan743x_adapter *adapter)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+
+	mutex_init(&ptp->command_lock);
+	spin_lock_init(&ptp->tx_ts_lock);
+	tasklet_init(&ptp->ptp_isr_bottom_half,
+		     lan743x_ptp_isr_bottom_half, (unsigned long)adapter);
+	tasklet_disable(&ptp->ptp_isr_bottom_half);
+	ptp->used_event_ch = 0;
+	ptp->pps_event_ch = -1;
+	ptp->pps_gpio_bit = -1;
+	return 0;
+}
+
+int lan743x_ptp_open(struct lan743x_adapter *adapter)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+	int ret = -ENODEV;
+	u32 temp;
+
+	lan743x_ptp_reset(adapter);
+	lan743x_ptp_sync_to_system_clock(adapter);
+	temp = lan743x_csr_read(adapter, PTP_TX_MOD2);
+	temp |= PTP_TX_MOD2_TX_PTP_CLR_UDPV4_CHKSUM_;
+	lan743x_csr_write(adapter, PTP_TX_MOD2, temp);
+	lan743x_ptp_enable(adapter);
+	tasklet_enable(&ptp->ptp_isr_bottom_half);
+	lan743x_csr_write(adapter, INT_EN_SET, INT_BIT_1588_);
+	lan743x_csr_write(adapter, PTP_INT_EN_SET,
+			  PTP_INT_BIT_TX_SWTS_ERR_ | PTP_INT_BIT_TX_TS_);
+	ptp->flags |= PTP_FLAG_ISR_ENABLED;
+
+#ifdef CONFIG_PTP_1588_CLOCK
+	snprintf(ptp->pin_config[0].name, 32, "lan743x_ptp_pin_0");
+	ptp->pin_config[0].index = 0;
+	ptp->pin_config[0].func = PTP_PF_PEROUT;
+	ptp->pin_config[0].chan = 0;
+
+	ptp->ptp_clock_info.owner = THIS_MODULE;
+	snprintf(ptp->ptp_clock_info.name, 16, "%pm",
+		 adapter->netdev->dev_addr);
+	ptp->ptp_clock_info.max_adj = LAN743X_PTP_MAX_FREQ_ADJ_IN_PPB;
+	ptp->ptp_clock_info.n_alarm = 0;
+	ptp->ptp_clock_info.n_ext_ts = 0;
+	ptp->ptp_clock_info.n_per_out = 0;
+	ptp->ptp_clock_info.n_pins = 0;
+	ptp->ptp_clock_info.pps = 1;
+	ptp->ptp_clock_info.pin_config = NULL;
+	ptp->ptp_clock_info.adjfreq = lan743x_ptpci_adjfreq;
+	ptp->ptp_clock_info.adjtime = lan743x_ptpci_adjtime;
+	ptp->ptp_clock_info.gettime64 = lan743x_ptpci_gettime64;
+	ptp->ptp_clock_info.getcrosststamp = NULL;
+	ptp->ptp_clock_info.settime64 = lan743x_ptpci_settime64;
+	ptp->ptp_clock_info.enable = lan743x_ptpci_enable;
+	ptp->ptp_clock_info.verify = NULL;
+
+	ptp->ptp_clock = ptp_clock_register(&ptp->ptp_clock_info,
+					    &adapter->pdev->dev);
+
+	if (IS_ERR(ptp->ptp_clock)) {
+		netif_err(adapter, ifup, adapter->netdev,
+			  "ptp_clock_register failed\n");
+		goto done;
+	}
+	ptp->flags |= PTP_FLAG_PTP_CLOCK_REGISTERED;
+	netif_info(adapter, ifup, adapter->netdev,
+		   "successfully registered ptp clock\n");
+#endif
+
+	return 0;
+
+#ifdef CONFIG_PTP_1588_CLOCK
+done:
+	lan743x_ptp_close(adapter);
+	return ret;
+#endif
+}
+
+void lan743x_ptp_close(struct lan743x_adapter *adapter)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+	int index;
+
+#ifdef CONFIG_PTP_1588_CLOCK
+	if (ptp->flags & PTP_FLAG_PTP_CLOCK_REGISTERED) {
+		ptp_clock_unregister(ptp->ptp_clock);
+		ptp->ptp_clock = NULL;
+		ptp->flags &= ~PTP_FLAG_PTP_CLOCK_REGISTERED;
+		netif_info(adapter, drv, adapter->netdev,
+			   "ptp clock unregister\n");
+	}
+#endif
+
+	if (ptp->flags & PTP_FLAG_ISR_ENABLED) {
+		lan743x_csr_write(adapter, PTP_INT_EN_CLR,
+				  PTP_INT_BIT_TX_SWTS_ERR_ |
+				  PTP_INT_BIT_TX_TS_);
+		lan743x_csr_write(adapter, INT_EN_CLR, INT_BIT_1588_);
+		tasklet_disable(&ptp->ptp_isr_bottom_half);
+		ptp->flags &= ~PTP_FLAG_ISR_ENABLED;
+	}
+
+	/* clean up pending timestamp requests */
+	lan743x_ptp_tx_ts_complete(adapter);
+	spin_lock_bh(&ptp->tx_ts_lock);
+	for (index = 0;
+		index < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS;
+		index++) {
+		struct sk_buff *skb = ptp->tx_ts_skb_queue[index];
+
+		if (skb)
+			dev_kfree_skb(skb);
+		ptp->tx_ts_skb_queue[index] = NULL;
+		ptp->tx_ts_seconds_queue[index] = 0;
+		ptp->tx_ts_nseconds_queue[index] = 0;
+	}
+	ptp->tx_ts_skb_queue_size = 0;
+	ptp->tx_ts_queue_size = 0;
+	ptp->pending_tx_timestamps = 0;
+	spin_unlock_bh(&ptp->tx_ts_lock);
+
+	lan743x_ptp_disable(adapter);
+}
+
+void lan743x_ptp_set_sync_ts_insert(struct lan743x_adapter *adapter,
+				    bool ts_insert_enable)
+{
+	u32 ptp_tx_mod = lan743x_csr_read(adapter, PTP_TX_MOD);
+
+	if (ts_insert_enable)
+		ptp_tx_mod |= PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_;
+	else
+		ptp_tx_mod &= ~PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_;
+
+	lan743x_csr_write(adapter, PTP_TX_MOD, ptp_tx_mod);
+}
+
+static bool lan743x_ptp_is_enabled(struct lan743x_adapter *adapter)
+{
+	if (lan743x_csr_read(adapter, PTP_CMD_CTL) & PTP_CMD_CTL_PTP_ENABLE_)
+		return true;
+	return false;
+}
+
+static void lan743x_ptp_wait_till_cmd_done(struct lan743x_adapter *adapter,
+					   u32 bit_mask)
+{
+	int timeout = 1000;
+	u32 data = 0;
+
+	while (timeout &&
+	       (data = (lan743x_csr_read(adapter, PTP_CMD_CTL) &
+	       bit_mask))) {
+		usleep_range(1000, 20000);
+		timeout--;
+	}
+	if (data) {
+		netif_err(adapter, drv, adapter->netdev,
+			  "timeout waiting for cmd to be done, cmd = 0x%08X\n",
+			  bit_mask);
+	}
+}
+
+static void lan743x_ptp_enable(struct lan743x_adapter *adapter)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+
+	mutex_lock(&ptp->command_lock);
+
+	if (lan743x_ptp_is_enabled(adapter)) {
+		netif_warn(adapter, drv, adapter->netdev,
+			   "PTP already enabled\n");
+		goto done;
+	}
+	lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_ENABLE_);
+done:
+	mutex_unlock(&ptp->command_lock);
+}
+
+static void lan743x_ptp_disable(struct lan743x_adapter *adapter)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+
+	mutex_lock(&ptp->command_lock);
+	if (!lan743x_ptp_is_enabled(adapter)) {
+		netif_warn(adapter, drv, adapter->netdev,
+			   "PTP already disabled\n");
+		goto done;
+	}
+	lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_DISABLE_);
+	lan743x_ptp_wait_till_cmd_done(adapter, PTP_CMD_CTL_PTP_ENABLE_);
+done:
+	mutex_unlock(&ptp->command_lock);
+}
+
+static void lan743x_ptp_reset(struct lan743x_adapter *adapter)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+
+	mutex_lock(&ptp->command_lock);
+
+	if (lan743x_ptp_is_enabled(adapter)) {
+		netif_err(adapter, drv, adapter->netdev,
+			  "Attempting reset while enabled\n");
+		goto done;
+	}
+
+	lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_RESET_);
+	lan743x_ptp_wait_till_cmd_done(adapter, PTP_CMD_CTL_PTP_RESET_);
+done:
+	mutex_unlock(&ptp->command_lock);
+}
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static int lan743x_ptp_reserve_event_ch(struct lan743x_adapter *adapter)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+	int result = -ENODEV;
+	int index = 0;
+
+	mutex_lock(&ptp->command_lock);
+	for (index = 0; index < LAN743X_PTP_NUMBER_OF_EVENT_CHANNELS; index++) {
+		if (!(test_bit(index, &ptp->used_event_ch))) {
+			ptp->used_event_ch |= BIT(index);
+			result = index;
+			break;
+		}
+	}
+	mutex_unlock(&ptp->command_lock);
+	return result;
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static void lan743x_ptp_release_event_ch(struct lan743x_adapter *adapter,
+					 int event_channel)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+
+	mutex_lock(&ptp->command_lock);
+	if (test_bit(event_channel, &ptp->used_event_ch)) {
+		ptp->used_event_ch &= ~BIT(event_channel);
+	} else {
+		netif_warn(adapter, drv, adapter->netdev,
+			   "attempted release on a not used event_channel = %d\n",
+			   event_channel);
+	}
+	mutex_unlock(&ptp->command_lock);
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static void lan743x_ptp_clock_get(struct lan743x_adapter *adapter,
+				  u32 *seconds, u32 *nano_seconds,
+				  u32 *sub_nano_seconds)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+
+	mutex_lock(&ptp->command_lock);
+
+	lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_CLOCK_READ_);
+	lan743x_ptp_wait_till_cmd_done(adapter, PTP_CMD_CTL_PTP_CLOCK_READ_);
+
+	if (seconds)
+		(*seconds) = lan743x_csr_read(adapter, PTP_CLOCK_SEC);
+
+	if (nano_seconds)
+		(*nano_seconds) = lan743x_csr_read(adapter, PTP_CLOCK_NS);
+
+	if (sub_nano_seconds)
+		(*sub_nano_seconds) =
+		lan743x_csr_read(adapter, PTP_CLOCK_SUBNS);
+
+	mutex_unlock(&ptp->command_lock);
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+static void lan743x_ptp_clock_set(struct lan743x_adapter *adapter,
+				  u32 seconds, u32 nano_seconds,
+				  u32 sub_nano_seconds)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+
+	mutex_lock(&ptp->command_lock);
+
+	lan743x_csr_write(adapter, PTP_CLOCK_SEC, seconds);
+	lan743x_csr_write(adapter, PTP_CLOCK_NS, nano_seconds);
+	lan743x_csr_write(adapter, PTP_CLOCK_SUBNS, sub_nano_seconds);
+
+	lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_CLOCK_LOAD_);
+	lan743x_ptp_wait_till_cmd_done(adapter, PTP_CMD_CTL_PTP_CLOCK_LOAD_);
+	mutex_unlock(&ptp->command_lock);
+}
+
+#ifdef CONFIG_PTP_1588_CLOCK
+static void lan743x_ptp_clock_step(struct lan743x_adapter *adapter,
+				   s64 time_step_ns)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+	u64 abs_time_step_ns = 0;
+	u32 nano_seconds = 0;
+	s32 seconds = 0;
+
+	if (time_step_ns >  15000000000LL) {
+		/* convert to clock set */
+		u32 nano_seconds = 0;
+		u32 seconds = 0;
+
+		lan743x_ptp_clock_get(adapter, &seconds, &nano_seconds, NULL);
+		seconds += (time_step_ns / 1000000000LL);
+		nano_seconds += (time_step_ns % 1000000000LL);
+		if (nano_seconds >= 1000000000) {
+			seconds++;
+			nano_seconds -= 1000000000;
+		}
+		lan743x_ptp_clock_set(adapter, seconds, nano_seconds, 0);
+		return;
+	} else if (time_step_ns < -15000000000LL) {
+		/* convert to clock set */
+		u32 nano_seconds_step = 0;
+		u32 nano_seconds = 0;
+		u32 seconds = 0;
+
+		time_step_ns = -time_step_ns;
+
+		lan743x_ptp_clock_get(adapter, &seconds, &nano_seconds, NULL);
+		seconds -= (time_step_ns / 1000000000LL);
+		nano_seconds_step = (time_step_ns % 1000000000LL);
+		if (nano_seconds < nano_seconds_step) {
+			seconds--;
+			nano_seconds += 1000000000;
+		}
+		nano_seconds -= nano_seconds_step;
+		lan743x_ptp_clock_set(adapter, seconds, nano_seconds, 0);
+		return;
+	}
+
+	/* do clock step */
+
+	if (time_step_ns >= 0) {
+		abs_time_step_ns = (u64)(time_step_ns);
+		seconds = (s32)(abs_time_step_ns / 1000000000);
+		nano_seconds = (u32)(abs_time_step_ns % 1000000000);
+	} else {
+		abs_time_step_ns = (u64)(-time_step_ns);
+		seconds = -((s32)(abs_time_step_ns / 1000000000));
+		nano_seconds = (u32)(abs_time_step_ns % 1000000000);
+		if (nano_seconds > 0) {
+			/* subtracting nano seconds is not allowed
+			 * convert to subtracting from seconds,
+			 * and adding to nanoseconds
+			 */
+			seconds--;
+			nano_seconds = (1000000000 - nano_seconds);
+		}
+	}
+
+	if (nano_seconds > 0) {
+		/* add 8 ns to cover the likely normal increment */
+		nano_seconds += 8;
+	}
+
+	if (nano_seconds >= 1000000000) {
+		/* carry into seconds */
+		seconds++;
+		nano_seconds -= 1000000000;
+	}
+
+	while (seconds) {
+		mutex_lock(&ptp->command_lock);
+		if (seconds > 0) {
+			u32 adjustment_value = (u32)seconds;
+
+			if (adjustment_value > 0xF)
+				adjustment_value = 0xF;
+			lan743x_csr_write(adapter, PTP_CLOCK_STEP_ADJ,
+					  PTP_CLOCK_STEP_ADJ_DIR_ |
+					  adjustment_value);
+			seconds -= ((s32)adjustment_value);
+		} else {
+			u32 adjustment_value = (u32)(-seconds);
+
+			if (adjustment_value > 0xF)
+				adjustment_value = 0xF;
+			lan743x_csr_write(adapter, PTP_CLOCK_STEP_ADJ,
+					  adjustment_value);
+			seconds += ((s32)adjustment_value);
+		}
+		lan743x_csr_write(adapter, PTP_CMD_CTL,
+				  PTP_CMD_CTL_PTP_CLOCK_STEP_SEC_);
+		lan743x_ptp_wait_till_cmd_done(adapter,
+					       PTP_CMD_CTL_PTP_CLOCK_STEP_SEC_);
+		mutex_unlock(&ptp->command_lock);
+	}
+	if (nano_seconds) {
+		mutex_lock(&ptp->command_lock);
+		lan743x_csr_write(adapter, PTP_CLOCK_STEP_ADJ,
+				  PTP_CLOCK_STEP_ADJ_DIR_ |
+				  (nano_seconds &
+				  PTP_CLOCK_STEP_ADJ_VALUE_MASK_));
+		lan743x_csr_write(adapter, PTP_CMD_CTL,
+				  PTP_CMD_CTL_PTP_CLK_STP_NSEC_);
+		lan743x_ptp_wait_till_cmd_done(adapter,
+					       PTP_CMD_CTL_PTP_CLK_STP_NSEC_);
+		mutex_unlock(&ptp->command_lock);
+	}
+}
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+bool lan743x_ptp_request_tx_timestamp(struct lan743x_adapter *adapter)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+	bool result = false;
+
+	spin_lock_bh(&ptp->tx_ts_lock);
+	if (ptp->pending_tx_timestamps < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS) {
+		ptp->pending_tx_timestamps++;
+		result = true;/* request granted */
+	}
+	spin_unlock_bh(&ptp->tx_ts_lock);
+	return result;
+}
+
+void lan743x_ptp_unrequest_tx_timestamp(struct lan743x_adapter *adapter)
+{
+	struct lan743x_ptp *ptp = &adapter->ptp;
+
+	spin_lock_bh(&ptp->tx_ts_lock);
+	if (ptp->pending_tx_timestamps > 0)
+		ptp->pending_tx_timestamps--;
+	else
+		netif_err(adapter, drv, adapter->netdev,
+			  "unrequest failed, pending_tx_timestamps==0\n");
+	spin_unlock_bh(&ptp->tx_ts_lock);
+}
+
+void lan743x_ptp_tx_timestamp_skb(struct lan743x_adapter *adapter,
+				  struct sk_buff *skb, bool ignore_sync)
+{
+	lan743x_ptp_tx_ts_enqueue_skb(adapter, skb, ignore_sync);
+
+	lan743x_ptp_tx_ts_complete(adapter);
+}
+
+int lan743x_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+	struct hwtstamp_config config;
+	int ret = 0;
+	int index;
+
+	if (!ifr) {
+		netif_err(adapter, drv, adapter->netdev,
+			  "SIOCSHWTSTAMP, ifr == NULL\n");
+		return -EINVAL;
+	}
+
+	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	if (config.flags) {
+		netif_warn(adapter, drv, adapter->netdev,
+			   "ignoring hwtstamp_config.flags == 0x%08X, expected 0\n",
+			   config.flags);
+	}
+
+	switch (config.tx_type) {
+	case HWTSTAMP_TX_OFF:
+		for (index = 0; index < LAN743X_MAX_TX_CHANNELS;
+			index++)
+			lan743x_tx_set_timestamping_mode(&adapter->tx[index],
+							 false, false);
+		lan743x_ptp_set_sync_ts_insert(adapter, false);
+		netif_info(adapter, drv, adapter->netdev,
+			   "  tx_type = HWTSTAMP_TX_OFF\n");
+		break;
+	case HWTSTAMP_TX_ON:
+		for (index = 0; index < LAN743X_MAX_TX_CHANNELS;
+			index++)
+			lan743x_tx_set_timestamping_mode(&adapter->tx[index],
+							 true, false);
+		lan743x_ptp_set_sync_ts_insert(adapter, false);
+		netif_info(adapter, drv, adapter->netdev,
+			   "  tx_type = HWTSTAMP_TX_ON\n");
+		break;
+	case HWTSTAMP_TX_ONESTEP_SYNC:
+		for (index = 0; index < LAN743X_MAX_TX_CHANNELS;
+			index++)
+			lan743x_tx_set_timestamping_mode(&adapter->tx[index],
+							 true, true);
+
+		lan743x_ptp_set_sync_ts_insert(adapter, true);
+		netif_info(adapter, drv, adapter->netdev,
+			   "  tx_type = HWTSTAMP_TX_ONESTEP_SYNC\n");
+		break;
+	default:
+		netif_info(adapter, drv, adapter->netdev,
+			   "  tx_type = %d, UNKNOWN\n", config.tx_type);
+		ret = -EINVAL;
+		break;
+	}
+
+	if (!ret)
+		return copy_to_user(ifr->ifr_data, &config,
+			sizeof(config)) ? -EFAULT : 0;
+	return ret;
+}
diff --git a/drivers/net/ethernet/microchip/lan743x_ptp.h b/drivers/net/ethernet/microchip/lan743x_ptp.h
new file mode 100644
index 0000000..979ffce
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan743x_ptp.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (C) 2018 Microchip Technology Inc. */
+
+#ifndef _LAN743X_PTP_H
+#define _LAN743X_PTP_H
+
+#include "linux/ptp_clock_kernel.h"
+#include "linux/netdevice.h"
+
+struct lan743x_adapter;
+
+/* GPIO */
+struct lan743x_gpio {
+	/* gpio_lock: used to prevent concurrent access to gpio settings */
+	spinlock_t gpio_lock;
+
+	int used_bits;
+	int output_bits;
+	int ptp_bits;
+	u32 gpio_cfg0;
+	u32 gpio_cfg1;
+	u32 gpio_cfg2;
+	u32 gpio_cfg3;
+};
+
+int lan743x_gpio_init(struct lan743x_adapter *adapter);
+
+void lan743x_ptp_isr(void *context);
+bool lan743x_ptp_request_tx_timestamp(struct lan743x_adapter *adapter);
+void lan743x_ptp_unrequest_tx_timestamp(struct lan743x_adapter *adapter);
+void lan743x_ptp_tx_timestamp_skb(struct lan743x_adapter *adapter,
+				  struct sk_buff *skb, bool ignore_sync);
+int lan743x_ptp_init(struct lan743x_adapter *adapter);
+int lan743x_ptp_open(struct lan743x_adapter *adapter);
+void lan743x_ptp_close(struct lan743x_adapter *adapter);
+void lan743x_ptp_update_latency(struct lan743x_adapter *adapter,
+				u32 link_speed);
+
+int lan743x_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
+
+#define LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS (4)
+
+#define PTP_FLAG_PTP_CLOCK_REGISTERED	BIT(1)
+#define PTP_FLAG_ISR_ENABLED			BIT(2)
+
+struct lan743x_ptp {
+	int flags;
+
+	/* command_lock: used to prevent concurrent ptp commands */
+	struct mutex	command_lock;
+
+#ifdef CONFIG_PTP_1588_CLOCK
+	struct ptp_clock *ptp_clock;
+	struct ptp_clock_info ptp_clock_info;
+	struct ptp_pin_desc pin_config[1];
+#endif /* CONFIG_PTP_1588_CLOCK */
+
+	struct tasklet_struct	ptp_isr_bottom_half;
+
+#define LAN743X_PTP_NUMBER_OF_EVENT_CHANNELS (2)
+	unsigned long used_event_ch;
+
+	int pps_event_ch;
+	int pps_gpio_bit;
+
+	/* tx_ts_lock: used to prevent concurrent access to timestamp arrays */
+	spinlock_t	tx_ts_lock;
+	int pending_tx_timestamps;
+	struct sk_buff *tx_ts_skb_queue[LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS];
+	unsigned int	tx_ts_ignore_sync_queue;
+	int tx_ts_skb_queue_size;
+	u32 tx_ts_seconds_queue[LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS];
+	u32 tx_ts_nseconds_queue[LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS];
+	u32 tx_ts_header_queue[LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS];
+	int tx_ts_queue_size;
+};
+
+#endif /* _LAN743X_PTP_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 1/9] lan743x: Add support for ethtool get_drvinfo
  2018-07-12 19:04 ` [PATCH v2 net-next 1/9] lan743x: Add support for ethtool get_drvinfo Bryan Whitehead
@ 2018-07-12 22:28   ` Andrew Lunn
  0 siblings, 0 replies; 23+ messages in thread
From: Andrew Lunn @ 2018-07-12 22:28 UTC (permalink / raw)
  To: Bryan Whitehead; +Cc: davem, netdev, UNGLinuxDriver, richardcochran

On Thu, Jul 12, 2018 at 03:04:58PM -0400, Bryan Whitehead wrote:
> Implement ethtool get_drvinfo
> 
> Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 2/9] lan743x: Add support for ethtool link settings
  2018-07-12 19:04 ` [PATCH v2 net-next 2/9] lan743x: Add support for ethtool link settings Bryan Whitehead
@ 2018-07-12 22:29   ` Andrew Lunn
  0 siblings, 0 replies; 23+ messages in thread
From: Andrew Lunn @ 2018-07-12 22:29 UTC (permalink / raw)
  To: Bryan Whitehead; +Cc: davem, netdev, UNGLinuxDriver, richardcochran

On Thu, Jul 12, 2018 at 03:04:59PM -0400, Bryan Whitehead wrote:
> Use default link setting functions
> 
> Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 3/9] lan743x: Add support for ethtool statistics
  2018-07-12 19:05 ` [PATCH v2 net-next 3/9] lan743x: Add support for ethtool statistics Bryan Whitehead
@ 2018-07-12 22:31   ` Andrew Lunn
  0 siblings, 0 replies; 23+ messages in thread
From: Andrew Lunn @ 2018-07-12 22:31 UTC (permalink / raw)
  To: Bryan Whitehead; +Cc: davem, netdev, UNGLinuxDriver, richardcochran

On Thu, Jul 12, 2018 at 03:05:00PM -0400, Bryan Whitehead wrote:
> Implement ethtool statistics
> 
> Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 4/9] lan743x: Add support for ethtool message level
  2018-07-12 19:05 ` [PATCH v2 net-next 4/9] lan743x: Add support for ethtool message level Bryan Whitehead
@ 2018-07-12 22:31   ` Andrew Lunn
  0 siblings, 0 replies; 23+ messages in thread
From: Andrew Lunn @ 2018-07-12 22:31 UTC (permalink / raw)
  To: Bryan Whitehead; +Cc: davem, netdev, UNGLinuxDriver, richardcochran

On Thu, Jul 12, 2018 at 03:05:01PM -0400, Bryan Whitehead wrote:
> Implement ethtool message level
> 
> Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 5/9] lan743x: Add support for ethtool eeprom access
  2018-07-12 19:05 ` [PATCH v2 net-next 5/9] lan743x: Add support for ethtool eeprom access Bryan Whitehead
@ 2018-07-12 22:35   ` Andrew Lunn
  0 siblings, 0 replies; 23+ messages in thread
From: Andrew Lunn @ 2018-07-12 22:35 UTC (permalink / raw)
  To: Bryan Whitehead; +Cc: davem, netdev, UNGLinuxDriver, richardcochran

On Thu, Jul 12, 2018 at 03:05:02PM -0400, Bryan Whitehead wrote:
> Implement ethtool eeprom access
> Also provides access to OTP (One Time Programming)
> 
> Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 6/9] lan743x: Add power management support
  2018-07-12 19:05 ` [PATCH v2 net-next 6/9] lan743x: Add power management support Bryan Whitehead
@ 2018-07-12 22:42   ` Andrew Lunn
  2018-07-18 20:05     ` Bryan.Whitehead
  0 siblings, 1 reply; 23+ messages in thread
From: Andrew Lunn @ 2018-07-12 22:42 UTC (permalink / raw)
  To: Bryan Whitehead; +Cc: davem, netdev, UNGLinuxDriver, richardcochran

> +#ifdef CONFIG_PM
> +static void lan743x_ethtool_get_wol(struct net_device *netdev,
> +				    struct ethtool_wolinfo *wol)
> +{
> +	struct lan743x_adapter *adapter = netdev_priv(netdev);
> +
> +	wol->supported = WAKE_BCAST | WAKE_UCAST | WAKE_MCAST |
> +		WAKE_MAGIC | WAKE_PHY | WAKE_ARP;
> +
> +	wol->wolopts = adapter->wolopts;
> +}
> +#endif /* CONFIG_PM */
> +
> +#ifdef CONFIG_PM
> +static int lan743x_ethtool_set_wol(struct net_device *netdev,
> +				   struct ethtool_wolinfo *wol)
> +{
> +	struct lan743x_adapter *adapter = netdev_priv(netdev);
> +
> +	if (wol->wolopts & WAKE_MAGICSECURE)
> +		return -EOPNOTSUPP;
> +
> +	adapter->wolopts = 0;
> +	if (wol->wolopts & WAKE_UCAST)
> +		adapter->wolopts |= WAKE_UCAST;
> +	if (wol->wolopts & WAKE_MCAST)
> +		adapter->wolopts |= WAKE_MCAST;
> +	if (wol->wolopts & WAKE_BCAST)
> +		adapter->wolopts |= WAKE_BCAST;
> +	if (wol->wolopts & WAKE_MAGIC)
> +		adapter->wolopts |= WAKE_MAGIC;
> +	if (wol->wolopts & WAKE_PHY)
> +		adapter->wolopts |= WAKE_PHY;
> +	if (wol->wolopts & WAKE_ARP)
> +		adapter->wolopts |= WAKE_ARP;
> +
> +	device_set_wakeup_enable(&adapter->pdev->dev, (bool)wol->wolopts);
> +
> +	phy_ethtool_set_wol(netdev->phydev, wol);

Hi Bryan

This seems asymmetric. set_wol you call into the phylib to enable wol
in the PHY. But get_wol does not call into phylib. So the phy has no
chance to set what it supports.

       Andrew

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 7/9] lan743x: Add EEE support
  2018-07-12 19:05 ` [PATCH v2 net-next 7/9] lan743x: Add EEE support Bryan Whitehead
@ 2018-07-12 22:49   ` Andrew Lunn
  2018-07-13 16:35     ` Bryan.Whitehead
  0 siblings, 1 reply; 23+ messages in thread
From: Andrew Lunn @ 2018-07-12 22:49 UTC (permalink / raw)
  To: Bryan Whitehead; +Cc: davem, netdev, UNGLinuxDriver, richardcochran

> +static int lan743x_ethtool_set_eee(struct net_device *netdev,
> +				   struct ethtool_eee *eee)
> +{
> +	struct lan743x_adapter *adapter = netdev_priv(netdev);
> +	struct phy_device *phydev = NULL;
> +	u32 buf = 0;
> +	int ret = 0;
> +
> +	if (!netdev)
> +		return -EINVAL;
> +	adapter = netdev_priv(netdev);
> +	if (!adapter)
> +		return -EINVAL;
> +	phydev = netdev->phydev;
> +	if (!phydev)
> +		return -EIO;
> +	if (!phydev->drv) {
> +		netif_err(adapter, drv, adapter->netdev,
> +			  "Missing PHY Driver\n");
> +		return -EIO;
> +	}
> +
> +	if (eee->eee_enabled) {
> +		ret = phy_init_eee(phydev, 0);
> +		if (ret) {
> +			netif_err(adapter, drv, adapter->netdev,
> +				  "EEE initialization failed\n");
> +			return ret;
> +		}
> +
> +		buf = lan743x_csr_read(adapter, MAC_CR);
> +		buf |= MAC_CR_EEE_EN_;
> +		lan743x_csr_write(adapter, MAC_CR, buf);
> +
> +		phy_ethtool_set_eee(phydev, eee);
> +
> +		buf = (u32)eee->tx_lpi_timer;
> +		lan743x_csr_write(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT, buf);
> +		netif_info(adapter, drv, adapter->netdev, "Enabled EEE\n");
> +	} else {
> +		buf = lan743x_csr_read(adapter, MAC_CR);
> +		buf &= ~MAC_CR_EEE_EN_;
> +		lan743x_csr_write(adapter, MAC_CR, buf);
> +		netif_info(adapter, drv, adapter->netdev, "Disabled EEE\n");
> +	}
> +

Hi Bryan

You should call phy_ethtool_set_eee() in both cases, so that it gets
disabled in the PHY as well. It needs to stop advertising it.

       Andrew

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 9/9] lan743x: Add PTP support
  2018-07-12 19:05 ` [PATCH v2 net-next 9/9] lan743x: Add PTP support Bryan Whitehead
@ 2018-07-13  3:31   ` Richard Cochran
  2018-07-18 20:04     ` Bryan.Whitehead
  0 siblings, 1 reply; 23+ messages in thread
From: Richard Cochran @ 2018-07-13  3:31 UTC (permalink / raw)
  To: Bryan Whitehead; +Cc: davem, netdev, UNGLinuxDriver

On Thu, Jul 12, 2018 at 03:05:06PM -0400, Bryan Whitehead wrote:
> +static int lan743x_ethtool_get_ts_info(struct net_device *netdev,
> +				       struct ethtool_ts_info *ts_info)
> +{
> +	struct lan743x_adapter *adapter = netdev_priv(netdev);
> +
> +	ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
> +				   SOF_TIMESTAMPING_RX_SOFTWARE |
> +				   SOF_TIMESTAMPING_SOFTWARE |
> +				   SOF_TIMESTAMPING_TX_HARDWARE |
> +				   SOF_TIMESTAMPING_RX_HARDWARE |
> +				   SOF_TIMESTAMPING_RAW_HARDWARE;
> +#ifdef CONFIG_PTP_1588_CLOCK

No need for this ifdeferry - ptp_clock_index() already returns -1 in
that case.

> +	if (adapter->ptp.ptp_clock)
> +		ts_info->phc_index = ptp_clock_index(adapter->ptp.ptp_clock);
> +	else
> +		ts_info->phc_index = -1;
> +#else
> +	ts_info->phc_index = -1;
> +#endif
> +	ts_info->tx_types = BIT(HWTSTAMP_TX_OFF) |
> +			    BIT(HWTSTAMP_TX_ON);
> +	ts_info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
> +			      BIT(HWTSTAMP_FILTER_ALL);
> +	return 0;
> +}
> +

> @@ -690,6 +717,7 @@ const struct ethtool_ops lan743x_ethtool_ops = {
>  	.get_rxfh_indir_size = lan743x_ethtool_get_rxfh_indir_size,
>  	.get_rxfh = lan743x_ethtool_get_rxfh,
>  	.set_rxfh = lan743x_ethtool_set_rxfh,
> +	.get_ts_info = lan743x_ethtool_get_ts_info,
>  	.get_eee = lan743x_ethtool_get_eee,
>  	.set_eee = lan743x_ethtool_set_eee,
>  	.get_link_ksettings = phy_ethtool_get_link_ksettings,
> diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
> index 953b581..ca9ae49 100644
> --- a/drivers/net/ethernet/microchip/lan743x_main.c
> +++ b/drivers/net/ethernet/microchip/lan743x_main.c
> @@ -267,6 +267,10 @@ static void lan743x_intr_shared_isr(void *context, u32 int_sts, u32 flags)
>  			lan743x_intr_software_isr(adapter);
>  			int_sts &= ~INT_BIT_SW_GP_;
>  		}
> +		if (int_sts & INT_BIT_1588_) {
> +			lan743x_ptp_isr(adapter);
> +			int_sts &= ~INT_BIT_1588_;
> +		}
>  	}
>  	if (int_sts)
>  		lan743x_csr_write(adapter, INT_EN_CLR, int_sts);
> @@ -976,6 +980,7 @@ static void lan743x_phy_link_status_change(struct net_device *netdev)
>  					       ksettings.base.duplex,
>  					       local_advertisement,
>  					       remote_advertisement);
> +		lan743x_ptp_update_latency(adapter, ksettings.base.speed);
>  	}
>  }
>  
> @@ -1256,11 +1261,29 @@ static void lan743x_tx_release_desc(struct lan743x_tx *tx,
>  		buffer_info->dma_ptr = 0;
>  		buffer_info->buffer_length = 0;
>  	}
> -	if (buffer_info->skb) {
> +	if (!buffer_info->skb)
> +		goto clear_active;
> +
> +	if (!(buffer_info->flags &
> +		TX_BUFFER_INFO_FLAG_TIMESTAMP_REQUESTED)) {

Bad line break.

>  		dev_kfree_skb(buffer_info->skb);
> -		buffer_info->skb = NULL;
> +		goto clear_skb;
>  	}
>  
> +	if (cleanup) {
> +		lan743x_ptp_unrequest_tx_timestamp(tx->adapter);
> +		dev_kfree_skb(buffer_info->skb);
> +	} else {
> +		lan743x_ptp_tx_timestamp_skb(tx->adapter,
> +					     buffer_info->skb,
> +					     (buffer_info->flags &
> +					     TX_BUFFER_INFO_FLAG_IGNORE_SYNC)
> +					     != 0);

This is poor coding style.  Please find a better way.

> +	}
> +
> +clear_skb:
> +	buffer_info->skb = NULL;
> +
>  clear_active:
>  	buffer_info->flags &= ~TX_BUFFER_INFO_FLAG_ACTIVE;
>  
> @@ -1321,10 +1344,25 @@ static int lan743x_tx_get_avail_desc(struct lan743x_tx *tx)
>  		return last_head - last_tail - 1;
>  }
>  
> +void lan743x_tx_set_timestamping_mode(struct lan743x_tx *tx,
> +				      bool enable_timestamping,
> +				      bool enable_onestep_sync)
> +{
> +	if (enable_timestamping)
> +		tx->ts_flags |= TX_TS_FLAG_TIMESTAMPING_ENABLED;
> +	else
> +		tx->ts_flags &= ~TX_TS_FLAG_TIMESTAMPING_ENABLED;
> +	if (enable_onestep_sync)
> +		tx->ts_flags |= TX_TS_FLAG_ONE_STEP_SYNC;
> +	else
> +		tx->ts_flags &= ~TX_TS_FLAG_ONE_STEP_SYNC;
> +}
> +
>  static int lan743x_tx_frame_start(struct lan743x_tx *tx,
>  				  unsigned char *first_buffer,
>  				  unsigned int first_buffer_length,
>  				  unsigned int frame_length,
> +				  bool time_stamp,
>  				  bool check_sum)
>  {
>  	/* called only from within lan743x_tx_xmit_frame.
> @@ -1362,6 +1400,8 @@ static int lan743x_tx_frame_start(struct lan743x_tx *tx,
>  		TX_DESC_DATA0_DTYPE_DATA_ |
>  		TX_DESC_DATA0_FS_ |
>  		TX_DESC_DATA0_FCS_;
> +	if (time_stamp)
> +		tx->frame_data0 |= TX_DESC_DATA0_TSE_;
>  
>  	if (check_sum)
>  		tx->frame_data0 |= TX_DESC_DATA0_ICE_ |
> @@ -1475,6 +1515,7 @@ static int lan743x_tx_frame_add_fragment(struct lan743x_tx *tx,
>  
>  static void lan743x_tx_frame_end(struct lan743x_tx *tx,
>  				 struct sk_buff *skb,
> +				 bool time_stamp,
>  				 bool ignore_sync)
>  {
>  	/* called only from within lan743x_tx_xmit_frame
> @@ -1492,6 +1533,8 @@ static void lan743x_tx_frame_end(struct lan743x_tx *tx,
>  	tx_descriptor = &tx->ring_cpu_ptr[tx->frame_tail];
>  	buffer_info = &tx->buffer_info[tx->frame_tail];
>  	buffer_info->skb = skb;
> +	if (time_stamp)
> +		buffer_info->flags |= TX_BUFFER_INFO_FLAG_TIMESTAMP_REQUESTED;
>  	if (ignore_sync)
>  		buffer_info->flags |= TX_BUFFER_INFO_FLAG_IGNORE_SYNC;
>  
> @@ -1520,6 +1563,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
>  	unsigned int frame_length = 0;
>  	unsigned int head_length = 0;
>  	unsigned long irq_flags = 0;
> +	bool do_timestamp = false;
>  	bool ignore_sync = false;
>  	int nr_frags = 0;
>  	bool gso = false;
> @@ -1541,6 +1585,16 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
>  	}
>  
>  	/* space available, transmit skb  */
> +	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
> +		if (tx->ts_flags & TX_TS_FLAG_TIMESTAMPING_ENABLED) {
> +			if (lan743x_ptp_request_tx_timestamp(tx->adapter)) {

Why not use && instead of three nested tests?

> +				skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
> +				do_timestamp = true;
> +				if (tx->ts_flags & TX_TS_FLAG_ONE_STEP_SYNC)
> +					ignore_sync = true;
> +			}
> +		}
> +	}
>  	head_length = skb_headlen(skb);
>  	frame_length = skb_pagelen(skb);
>  	nr_frags = skb_shinfo(skb)->nr_frags;
> @@ -1554,6 +1608,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
>  	if (lan743x_tx_frame_start(tx,
>  				   skb->data, head_length,
>  				   start_frame_length,
> +				   do_timestamp,
>  				   skb->ip_summed == CHECKSUM_PARTIAL)) {
>  		dev_kfree_skb(skb);
>  		goto unlock;
> @@ -1581,7 +1636,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx,
>  	}
>  
>  finish:
> -	lan743x_tx_frame_end(tx, skb, ignore_sync);
> +	lan743x_tx_frame_end(tx, skb, do_timestamp, ignore_sync);
>  
>  unlock:
>  	spin_unlock_irqrestore(&tx->ring_lock, irq_flags);
> @@ -2410,6 +2465,8 @@ static int lan743x_netdev_close(struct net_device *netdev)
>  	for (index = 0; index < LAN743X_USED_RX_CHANNELS; index++)
>  		lan743x_rx_close(&adapter->rx[index]);
>  
> +	lan743x_ptp_close(adapter);
> +
>  	lan743x_phy_close(adapter);
>  
>  	lan743x_mac_close(adapter);
> @@ -2437,6 +2494,10 @@ static int lan743x_netdev_open(struct net_device *netdev)
>  	if (ret)
>  		goto close_mac;
>  
> +	ret = lan743x_ptp_open(adapter);
> +	if (ret)
> +		goto close_phy;
> +
>  	lan743x_rfe_open(adapter);
>  
>  	for (index = 0; index < LAN743X_USED_RX_CHANNELS; index++) {
> @@ -2456,6 +2517,9 @@ static int lan743x_netdev_open(struct net_device *netdev)
>  		if (adapter->rx[index].ring_cpu_ptr)
>  			lan743x_rx_close(&adapter->rx[index]);
>  	}
> +	lan743x_ptp_close(adapter);
> +
> +close_phy:
>  	lan743x_phy_close(adapter);
>  
>  close_mac:
> @@ -2483,6 +2547,8 @@ static int lan743x_netdev_ioctl(struct net_device *netdev,
>  {
>  	if (!netif_running(netdev))
>  		return -EINVAL;
> +	if (cmd == SIOCSHWTSTAMP)
> +		return lan743x_ptp_ioctl(netdev, ifr, cmd);
>  	return phy_mii_ioctl(netdev->phydev, ifr, cmd);
>  }
>  
> @@ -2607,6 +2673,11 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
>  	adapter->intr.irq = adapter->pdev->irq;
>  	lan743x_csr_write(adapter, INT_EN_CLR, 0xFFFFFFFF);
>  	mutex_init(&adapter->dp_lock);
> +
> +	ret = lan743x_gpio_init(adapter);
> +	if (ret)
> +		return ret;
> +
>  	ret = lan743x_mac_init(adapter);
>  	if (ret)
>  		return ret;
> @@ -2615,6 +2686,10 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
>  	if (ret)
>  		return ret;
>  
> +	ret = lan743x_ptp_init(adapter);
> +	if (ret)
> +		return ret;
> +
>  	lan743x_rfe_update_mac_address(adapter);
>  
>  	ret = lan743x_dmac_init(adapter);

...

> diff --git a/drivers/net/ethernet/microchip/lan743x_ptp.c b/drivers/net/ethernet/microchip/lan743x_ptp.c
> new file mode 100644
> index 0000000..f14565b
> --- /dev/null
> +++ b/drivers/net/ethernet/microchip/lan743x_ptp.c
> @@ -0,0 +1,1194 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/* Copyright (C) 2018 Microchip Technology Inc. */
> +
> +#include <linux/netdevice.h>
> +#include "lan743x_main.h"
> +
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +#include <linux/netdevice.h>
> +#include <linux/net_tstamp.h>
> +
> +#include "lan743x_ptp.h"
> +
> +/* GPIO */
> +#define LAN743X_NUMBER_OF_GPIO          (12)
> +
> +int lan743x_gpio_init(struct lan743x_adapter *adapter)
> +{
> +	struct lan743x_gpio *gpio = &adapter->gpio;
> +
> +	spin_lock_init(&gpio->gpio_lock);
> +
> +	gpio->gpio_cfg0 = 0; /* set all direction to input, data = 0 */
> +	gpio->gpio_cfg1 = 0x0FFF0000;/* disable all gpio, set to open drain */
> +	gpio->gpio_cfg2 = 0;/* set all to 1588 low polarity level */
> +	gpio->gpio_cfg3 = 0;/* disable all 1588 output */
> +	lan743x_csr_write(adapter, GPIO_CFG0, gpio->gpio_cfg0);
> +	lan743x_csr_write(adapter, GPIO_CFG1, gpio->gpio_cfg1);
> +	lan743x_csr_write(adapter, GPIO_CFG2, gpio->gpio_cfg2);
> +	lan743x_csr_write(adapter, GPIO_CFG3, gpio->gpio_cfg3);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static int lan743x_gpio_reserve_ptp_output(struct lan743x_adapter *adapter,
> +					   int bit, int ptp_channel)
> +{
> +	struct lan743x_gpio *gpio = &adapter->gpio;
> +	unsigned long irq_flags = 0;
> +	int bit_mask = BIT(bit);
> +	int ret = -EBUSY;
> +
> +	spin_lock_irqsave(&gpio->gpio_lock, irq_flags);
> +
> +	if (!(gpio->used_bits & bit_mask)) {
> +		gpio->used_bits |= bit_mask;
> +		gpio->output_bits |= bit_mask;
> +		gpio->ptp_bits |= bit_mask;
> +
> +		/* set as output, and zero initial value */
> +		gpio->gpio_cfg0 |= GPIO_CFG0_GPIO_DIR_BIT_(bit);
> +		gpio->gpio_cfg0 &= ~GPIO_CFG0_GPIO_DATA_BIT_(bit);
> +		lan743x_csr_write(adapter, GPIO_CFG0, gpio->gpio_cfg0);
> +
> +		/* enable gpio , and set buffer type to push pull */
> +		gpio->gpio_cfg1 &= ~GPIO_CFG1_GPIOEN_BIT_(bit);
> +		gpio->gpio_cfg1 |= GPIO_CFG1_GPIOBUF_BIT_(bit);
> +		lan743x_csr_write(adapter, GPIO_CFG1, gpio->gpio_cfg1);
> +
> +		/* set 1588 polarity to high */
> +		gpio->gpio_cfg2 |= GPIO_CFG2_1588_POL_BIT_(bit);
> +		lan743x_csr_write(adapter, GPIO_CFG2, gpio->gpio_cfg2);
> +
> +		if (!ptp_channel) {
> +			/* use channel A */
> +			gpio->gpio_cfg3 &= ~GPIO_CFG3_1588_CH_SEL_BIT_(bit);
> +		} else {
> +			/* use channel B */
> +			gpio->gpio_cfg3 |= GPIO_CFG3_1588_CH_SEL_BIT_(bit);
> +		}
> +		gpio->gpio_cfg3 |= GPIO_CFG3_1588_OE_BIT_(bit);
> +		lan743x_csr_write(adapter, GPIO_CFG3, gpio->gpio_cfg3);
> +
> +		ret = bit;
> +	}
> +	spin_unlock_irqrestore(&gpio->gpio_lock, irq_flags);
> +	return ret;
> +}
> +#endif /* CONFIG_PTP_1588_CLOCK */
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static void lan743x_gpio_release(struct lan743x_adapter *adapter, int bit)
> +{
> +	struct lan743x_gpio *gpio = &adapter->gpio;
> +	unsigned long irq_flags = 0;
> +	int bit_mask = BIT(bit);
> +
> +	spin_lock_irqsave(&gpio->gpio_lock, irq_flags);
> +	if (gpio->used_bits & bit_mask) {
> +		gpio->used_bits &= ~bit_mask;
> +		if (gpio->output_bits & bit_mask) {
> +			gpio->output_bits &= ~bit_mask;
> +
> +			if (gpio->ptp_bits & bit_mask) {
> +				gpio->ptp_bits &= ~bit_mask;
> +				/* disable ptp output */
> +				gpio->gpio_cfg3 &= ~GPIO_CFG3_1588_OE_BIT_(bit);
> +				lan743x_csr_write(adapter, GPIO_CFG3,
> +						  gpio->gpio_cfg3);
> +			}
> +			/* release gpio output */
> +
> +			/* disable gpio */
> +			gpio->gpio_cfg1 |= GPIO_CFG1_GPIOEN_BIT_(bit);
> +			gpio->gpio_cfg1 &= ~GPIO_CFG1_GPIOBUF_BIT_(bit);
> +			lan743x_csr_write(adapter, GPIO_CFG1, gpio->gpio_cfg1);
> +
> +			/* reset back to input */
> +			gpio->gpio_cfg0 &= ~GPIO_CFG0_GPIO_DIR_BIT_(bit);
> +			gpio->gpio_cfg0 &= ~GPIO_CFG0_GPIO_DATA_BIT_(bit);
> +			lan743x_csr_write(adapter, GPIO_CFG0, gpio->gpio_cfg0);
> +		}
> +	}
> +	spin_unlock_irqrestore(&gpio->gpio_lock, irq_flags);
> +}
> +#endif /* CONFIG_PTP_1588_CLOCK */
> +
> +/* PTP */
> +#define LAN743X_PTP_MAX_FREQ_ADJ_IN_PPB (31249999)
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static int lan743x_ptp_reserve_event_ch(struct lan743x_adapter *adapter);
> +static void lan743x_ptp_release_event_ch(struct lan743x_adapter *adapter,
> +					 int event_channel);
> +#endif
> +
> +static bool lan743x_ptp_is_enabled(struct lan743x_adapter *adapter);
> +static void lan743x_ptp_enable(struct lan743x_adapter *adapter);
> +static void lan743x_ptp_disable(struct lan743x_adapter *adapter);
> +static void lan743x_ptp_reset(struct lan743x_adapter *adapter);
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static void lan743x_ptp_clock_get(struct lan743x_adapter *adapter,
> +				  u32 *seconds, u32 *nano_seconds,
> +				  u32 *sub_nano_seconds);
> +static int lan743x_ptp_enable_pps(struct lan743x_adapter *adapter);
> +static void lan743x_ptp_disable_pps(struct lan743x_adapter *adapter);
> +#endif /* CONFIG_PTP_1588_CLOCK */
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static void lan743x_ptp_clock_step(struct lan743x_adapter *adapter,
> +				   s64 time_step_ns);
> +#endif /* CONFIG_PTP_1588_CLOCK */

The constant ifdef CONFIG_PTP_1588_CLOCK is poor style and
unnecessary.  Just group this code together under one ifdef, or better
yet put it into its own file.

> +static void lan743x_ptp_clock_set(struct lan743x_adapter *adapter,
> +				  u32 seconds, u32 nano_seconds,
> +				  u32 sub_nano_seconds);
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static int lan743x_ptpci_adjfreq(struct ptp_clock_info *ptpci, s32 delta_ppb)

Please implement adjfine().

 * @adjfine:  Adjusts the frequency of the hardware clock.
 *            parameter scaled_ppm: Desired frequency offset from
 *            nominal frequency in parts per million, but with a
 *            16 bit binary fractional field.
 *
 * @adjfreq:  Adjusts the frequency of the hardware clock.
 *            This method is deprecated.  New drivers should implement
 *            the @adjfine method instead.
 *            parameter delta: Desired frequency offset from nominal frequency
 *            in parts per billion

> +{
> +	struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
> +					       ptp_clock_info);
> +	struct lan743x_adapter *adapter = container_of(ptp,
> +						       struct lan743x_adapter,
> +						       ptp);

Coding style:
	struct lan743x_adapter *adapter =
		container_of(ptp, struct lan743x_adapter, ptp);

> +	u32 lan743x_rate_adj = 0;
> +	bool positive = true;
> +	u32 u32_delta = 0;
> +	u64 u64_delta = 0;
> +
> +	if ((delta_ppb < (-LAN743X_PTP_MAX_FREQ_ADJ_IN_PPB)) ||
> +	    delta_ppb > LAN743X_PTP_MAX_FREQ_ADJ_IN_PPB) {
> +		return -EINVAL;
> +	}
> +	if (delta_ppb > 0) {
> +		u32_delta = (u32)delta_ppb;
> +		positive = true;
> +	} else {
> +		u32_delta = (u32)(-delta_ppb);
> +		positive = false;
> +	}
> +	u64_delta = (((u64)u32_delta) * 0x800000000ULL);
> +	lan743x_rate_adj = (u32)(u64_delta / 1000000000);

You need to use the div_u64() macro here.

> +
> +	if (positive)
> +		lan743x_rate_adj |= PTP_CLOCK_RATE_ADJ_DIR_;
> +
> +	lan743x_csr_write(adapter, PTP_CLOCK_RATE_ADJ,
> +			  lan743x_rate_adj);
> +
> +	netif_info(adapter, drv, adapter->netdev,
> +		   "adjfreq, delta_ppb = %d, lan743x_rate_adj = 0x%08X\n",
> +		   delta_ppb, lan743x_rate_adj);

This definitely should be at the debug level, or just delete it altogether.

> +	return 0;
> +}
> +#endif /*CONFIG_PTP_1588_CLOCK */
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static int lan743x_ptpci_adjtime(struct ptp_clock_info *ptpci, s64 delta)
> +{
> +	struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
> +					       ptp_clock_info);
> +	struct lan743x_adapter *adapter = container_of(ptp,
> +						       struct lan743x_adapter,
> +						       ptp);

Coding style.

> +	bool enable_pps = false;
> +
> +	if (ptp->pps_event_ch >= 0) {
> +		lan743x_ptp_disable_pps(adapter);
> +		enable_pps = true;
> +	}
> +
> +	lan743x_ptp_clock_step(adapter, delta);
> +	netif_info(adapter, drv, adapter->netdev,
> +		   "adjtime, delta = %lld\n", delta);

Again, debug or delete.

> +
> +	if (enable_pps)
> +		lan743x_ptp_enable_pps(adapter);
> +
> +	return 0;
> +}
> +#endif /*CONFIG_PTP_1588_CLOCK */
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static int lan743x_ptpci_gettime64(struct ptp_clock_info *ptpci,
> +				   struct timespec64 *ts)
> +{
> +	struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
> +					       ptp_clock_info);
> +	struct lan743x_adapter *adapter = container_of(ptp,
> +						       struct lan743x_adapter,
> +						       ptp);

Style.

> +
> +	if (ts) {
> +		u32 seconds = 0;
> +		u32 nano_seconds = 0;

Please declare stack variables at the top of the function.

> +
> +		lan743x_ptp_clock_get(adapter, &seconds, &nano_seconds, NULL);
> +		ts->tv_sec = seconds;
> +		ts->tv_nsec = nano_seconds;
> +		netif_info(adapter, drv, adapter->netdev,
> +			   "gettime = %u.%09u\n", seconds, nano_seconds);

Debug/delete

> +	} else {
> +		netif_warn(adapter, drv, adapter->netdev, "ts == NULL\n");
> +		return -EINVAL;

No need to test for 'ts'. The caller must supply a valid pointer.

> +	}
> +	return 0;
> +}
> +#endif /*CONFIG_PTP_1588_CLOCK */
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static int lan743x_ptpci_settime64(struct ptp_clock_info *ptpci,
> +				   const struct timespec64 *ts)
> +{
> +	struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
> +					       ptp_clock_info);
> +	struct lan743x_adapter *adapter = container_of(ptp,
> +						       struct lan743x_adapter,
> +						       ptp);
> +	bool enable_pps = false;
> +
> +	if (ptp->pps_event_ch >= 0) {
> +		lan743x_ptp_disable_pps(adapter);
> +		enable_pps = true;
> +	}
> +
> +	if (ts) {
> +		u32 seconds = 0;
> +		u32 nano_seconds = 0;
> +
> +		if (ts->tv_sec > 0xFFFFFFFFLL ||
> +		    ts->tv_sec < 0) {

Actually seconds will exceed four bytes sooner than you think.  If
your HW has a restriction, then simply keep the seconds offset in SW
in the driver, adding it in where needed (like when reading the clock
or providing time stamps).

> +			netif_warn(adapter, drv, adapter->netdev,
> +				   "ts->tv_sec out of range, %lld\n",
> +				   ts->tv_sec);
> +			return -EINVAL;
> +		}
> +		if (ts->tv_nsec >= 1000000000L ||
> +		    ts->tv_nsec < 0) {
> +			netif_warn(adapter, drv, adapter->netdev,
> +				   "ts->tv_nsec out of range, %ld\n",
> +				   ts->tv_nsec);
> +			return -EINVAL;
> +		}
> +		seconds = ts->tv_sec;
> +		nano_seconds = ts->tv_nsec;
> +		netif_info(adapter, drv, adapter->netdev,
> +			   "settime = %u.%09u\n", seconds, nano_seconds);
> +		lan743x_ptp_clock_set(adapter, seconds, nano_seconds, 0);
> +	} else {
> +		netif_warn(adapter, drv, adapter->netdev, "ts == NULL\n");
> +		return -EINVAL;
> +	}
> +
> +	if (enable_pps)
> +		lan743x_ptp_enable_pps(adapter);
> +
> +	return 0;
> +}
> +#endif /*CONFIG_PTP_1588_CLOCK */
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static int lan743x_ptp_enable_pps(struct lan743x_adapter *adapter)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +	u32 current_seconds = 0;
> +	u32 target_seconds = 0;
> +	u32 general_config = 0;
> +	int result = -ENODEV;
> +	int pps_bit = 0;

So this function is really *not* implementing the PTP_CLK_REQ_PPS
feature but rather the PTP_CLK_REQ_PEROUT with a period of once per
second.

PTP_CLK_REQ_PPS means placing a PPS event into the kernel's "hardpps"
subsystem by calling ptp_clock_event().

I'm sorry this isn't really documented.  I should fix that.

If you HW can output arbitrary signals, then you should implement
PTP_CLK_REQ_PEROUT.  In any case, you shouldn't advertise the
ptp_clock_info.pps capability.

> +	if (ptp->pps_event_ch >= 0) {
> +		result = 0;
> +		goto done;
> +	}
> +
> +	ptp->pps_event_ch = lan743x_ptp_reserve_event_ch(adapter);
> +	if (ptp->pps_event_ch < 0) {
> +		netif_warn(adapter, drv, adapter->netdev,
> +			   "Failed to reserve event channel for PPS\n");
> +		goto done;
> +	}
> +
> +	switch(adapter->csr.id_rev & ID_REV_ID_MASK_) {
> +	case ID_REV_ID_LAN7430_:
> +		pps_bit = 2;/* GPIO 2 is preferred on EVB LAN7430 */
> +		break;
> +	case ID_REV_ID_LAN7431_:
> +		pps_bit = 4;/* GPIO 4 is preferred on EVB LAN7431 */
> +		break;
> +	}
> +
> +	ptp->pps_gpio_bit = lan743x_gpio_reserve_ptp_output(adapter, pps_bit,
> +							    ptp->pps_event_ch);
> +
> +	if (ptp->pps_gpio_bit < 0) {
> +		netif_warn(adapter, drv, adapter->netdev,
> +			   "Failed to reserve gpio 0 for PPS\n");
> +		goto done;
> +	}
> +
> +	lan743x_ptp_clock_get(adapter, &current_seconds, NULL, NULL);
> +
> +	/* set the first target ahead by 2 seconds
> +	 *	to make sure its not missed
> +	 */
> +	target_seconds = current_seconds + 2;
> +
> +	/* set the new target */
> +	lan743x_csr_write(adapter,
> +			  PTP_CLOCK_TARGET_SEC_X(ptp->pps_event_ch),
> +			  0xFFFF0000);
> +	lan743x_csr_write(adapter,
> +			  PTP_CLOCK_TARGET_NS_X(ptp->pps_event_ch), 0);
> +
> +	general_config = lan743x_csr_read(adapter, PTP_GENERAL_CONFIG);
> +
> +	general_config &= ~(PTP_GENERAL_CONFIG_CLOCK_EVENT_X_MASK_
> +			  (ptp->pps_event_ch));
> +	general_config |= PTP_GENERAL_CONFIG_CLOCK_EVENT_X_SET_
> +			  (ptp->pps_event_ch,
> +			   PTP_GENERAL_CONFIG_CLOCK_EVENT_100US_);
> +	general_config &= ~PTP_GENERAL_CONFIG_RELOAD_ADD_X_
> +			  (ptp->pps_event_ch);
> +	lan743x_csr_write(adapter, PTP_GENERAL_CONFIG, general_config);
> +
> +	/* set the reload to one second steps */
> +	lan743x_csr_write(adapter,
> +			  PTP_CLOCK_TARGET_RELOAD_SEC_X(ptp->pps_event_ch),
> +			  1);
> +	lan743x_csr_write(adapter,
> +			  PTP_CLOCK_TARGET_RELOAD_NS_X(ptp->pps_event_ch),
> +			  0);
> +
> +	/* set the new target */
> +	lan743x_csr_write(adapter,
> +			  PTP_CLOCK_TARGET_SEC_X(ptp->pps_event_ch),
> +			  target_seconds);
> +	lan743x_csr_write(adapter,
> +			  PTP_CLOCK_TARGET_NS_X(ptp->pps_event_ch),
> +			  0);
> +	return 0;
> +
> +done:
> +	if (ptp->pps_gpio_bit >= 0) {
> +		lan743x_gpio_release(adapter, ptp->pps_gpio_bit);
> +		ptp->pps_gpio_bit = -1;
> +	}
> +	if (ptp->pps_event_ch >= 0) {
> +		lan743x_ptp_release_event_ch(adapter,
> +					     ptp->pps_event_ch);
> +		ptp->pps_event_ch = -1;
> +	}
> +	return result;
> +}
> +#endif /* CONFIG_PTP_1588_CLOCK */
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static void lan743x_ptp_disable_pps(struct lan743x_adapter *adapter)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +
> +	if (ptp->pps_gpio_bit >= 0) {
> +		lan743x_gpio_release(adapter, ptp->pps_gpio_bit);
> +		ptp->pps_gpio_bit = -1;
> +	}
> +
> +	if (ptp->pps_event_ch >= 0) {
> +		u32 general_config = 0;
> +
> +		/* set target to far in the future, effectively disabling it */
> +		lan743x_csr_write(adapter,
> +				  PTP_CLOCK_TARGET_SEC_X(ptp->pps_event_ch),
> +				  0xFFFF0000);
> +		lan743x_csr_write(adapter,
> +				  PTP_CLOCK_TARGET_NS_X(ptp->pps_event_ch), 0);
> +
> +		general_config = lan743x_csr_read(adapter, PTP_GENERAL_CONFIG);
> +		general_config |= PTP_GENERAL_CONFIG_RELOAD_ADD_X_
> +				  (ptp->pps_event_ch);
> +		lan743x_csr_write(adapter, PTP_GENERAL_CONFIG, general_config);
> +		lan743x_ptp_release_event_ch(adapter, ptp->pps_event_ch);
> +		ptp->pps_event_ch = -1;
> +	}
> +}
> +#endif /* CONFIG_PTP_1588_CLOCK */
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static int lan743x_ptpci_enable(struct ptp_clock_info *ptpci,
> +				struct ptp_clock_request *request, int on)
> +{
> +	struct lan743x_ptp *ptp = container_of(ptpci, struct lan743x_ptp,
> +					       ptp_clock_info);
> +	struct lan743x_adapter *adapter = container_of(ptp,
> +						       struct lan743x_adapter,
> +						       ptp);
> +
> +	if (request) {
> +		switch (request->type) {
> +		case PTP_CLK_REQ_EXTTS:
> +			return -EINVAL;
> +		case PTP_CLK_REQ_PEROUT:
> +			return -EINVAL;
> +		case PTP_CLK_REQ_PPS:
> +			if (on) {
> +				if (lan743x_ptp_enable_pps(adapter) >= 0)
> +					netif_info(adapter, drv,
> +						   adapter->netdev,
> +						   "PPS is ON\n");
> +				else
> +					netif_warn(adapter, drv,
> +						   adapter->netdev,
> +						   "Error starting PPS\n");
> +			} else {
> +				lan743x_ptp_disable_pps(adapter);
> +				netif_info(adapter, drv, adapter->netdev,
> +					   "PPS is OFF\n");
> +			}
> +			break;
> +		default:
> +			netif_err(adapter, drv, adapter->netdev,
> +				  "request->type == %d, Unknown\n",
> +				  request->type);
> +			break;
> +		}
> +	} else {
> +		netif_err(adapter, drv, adapter->netdev, "request == NULL\n");
> +	}
> +	return 0;
> +}
> +#endif /* CONFIG_PTP_1588_CLOCK */
> +
> +void lan743x_ptp_isr(void *context)
> +{
> +	struct lan743x_adapter *adapter = (struct lan743x_adapter *)context;
> +	struct lan743x_ptp *ptp = NULL;
> +	int enable_flag = 1;
> +	u32 ptp_int_sts = 0;
> +
> +	ptp = &adapter->ptp;
> +
> +	lan743x_csr_write(adapter, INT_EN_CLR, INT_BIT_1588_);
> +
> +	ptp_int_sts = lan743x_csr_read(adapter, PTP_INT_STS);
> +	ptp_int_sts &= lan743x_csr_read(adapter, PTP_INT_EN_SET);
> +
> +	if (ptp_int_sts & PTP_INT_BIT_TX_TS_) {
> +		tasklet_schedule(&ptp->ptp_isr_bottom_half);

Please no new tasklets.  Instead use a work queue.  If you need lower
latency, consider using ptp_schedule_worker().

> +		enable_flag = 0;/* tasklet will re-enable later */
> +	}
> +	if (ptp_int_sts & PTP_INT_BIT_TX_SWTS_ERR_) {
> +		netif_err(adapter, drv, adapter->netdev,
> +			  "PTP TX Software Timestamp Error\n");
> +		/* clear int status bit */
> +		lan743x_csr_write(adapter, PTP_INT_STS,
> +				  PTP_INT_BIT_TX_SWTS_ERR_);
> +	}
> +	if (ptp_int_sts & PTP_INT_BIT_TIMER_B_) {
> +		netif_info(adapter, drv, adapter->netdev,
> +			   "PTP TIMER B Interrupt\n");

Don't print like this from an ISR.  Or is this an error, since you
don't enable this bit?

> +		/* clear int status bit */
> +		lan743x_csr_write(adapter, PTP_INT_STS,
> +				  PTP_INT_BIT_TIMER_B_);
> +	}
> +	if (ptp_int_sts & PTP_INT_BIT_TIMER_A_) {
> +		netif_info(adapter, drv, adapter->netdev,
> +			   "PTP TIMER A Interrupt\n");
> +		/* clear int status bit */
> +		lan743x_csr_write(adapter, PTP_INT_STS,
> +				  PTP_INT_BIT_TIMER_A_);
> +	}
> +
> +	if (enable_flag) {
> +		/* re-enable isr */
> +		lan743x_csr_write(adapter, INT_EN_SET, INT_BIT_1588_);
> +	}
> +}
> +
> +static void lan743x_ptp_tx_ts_complete(struct lan743x_adapter *adapter)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +	int i;
> +	int c;

Put same types on one line:
	int c, i;

> +
> +	spin_lock_bh(&ptp->tx_ts_lock);
> +	c = ptp->tx_ts_skb_queue_size;
> +
> +	if (c > ptp->tx_ts_queue_size)
> +		c = ptp->tx_ts_queue_size;
> +	if (c <= 0)
> +		goto done;
> +
> +	for (i = 0; i < c; i++) {
> +		bool ignore_sync = ((ptp->tx_ts_ignore_sync_queue &
> +				    BIT(i)) != 0);
> +		struct sk_buff *skb = ptp->tx_ts_skb_queue[i];
> +		u32 nseconds = ptp->tx_ts_nseconds_queue[i];
> +		u32 seconds = ptp->tx_ts_seconds_queue[i];
> +		u32 header = ptp->tx_ts_header_queue[i];
> +		struct skb_shared_hwtstamps tstamps;

Locals to top of function please.

> +		memset(&tstamps, 0, sizeof(tstamps));
> +		tstamps.hwtstamp = ktime_set(seconds, nseconds);
> +		if (!ignore_sync ||
> +		    ((header & PTP_TX_MSG_HEADER_MSG_TYPE_) !=
> +		    PTP_TX_MSG_HEADER_MSG_TYPE_SYNC_))
> +			skb_tstamp_tx(skb, &tstamps);
> +
> +		dev_kfree_skb(skb);
> +
> +		ptp->tx_ts_skb_queue[i] = NULL;
> +		ptp->tx_ts_seconds_queue[i] = 0;
> +		ptp->tx_ts_nseconds_queue[i] = 0;
> +		ptp->tx_ts_header_queue[i] = 0;
> +	}
> +
> +	/* shift queue */
> +	ptp->tx_ts_ignore_sync_queue >>= c;
> +	for (i = c; i < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS; i++) {
> +		ptp->tx_ts_skb_queue[i - c] = ptp->tx_ts_skb_queue[i];
> +		ptp->tx_ts_seconds_queue[i - c] = ptp->tx_ts_seconds_queue[i];
> +		ptp->tx_ts_nseconds_queue[i - c] = ptp->tx_ts_nseconds_queue[i];
> +		ptp->tx_ts_header_queue[i - c] = ptp->tx_ts_header_queue[i];
> +
> +		ptp->tx_ts_skb_queue[i] = NULL;
> +		ptp->tx_ts_seconds_queue[i] = 0;
> +		ptp->tx_ts_nseconds_queue[i] = 0;
> +		ptp->tx_ts_header_queue[i] = 0;
> +	}
> +	ptp->tx_ts_skb_queue_size -= c;
> +	ptp->tx_ts_queue_size -= c;
> +done:
> +	ptp->pending_tx_timestamps -= c;
> +	spin_unlock_bh(&ptp->tx_ts_lock);
> +}
> +
> +static void lan743x_ptp_tx_ts_enqueue_skb(struct lan743x_adapter *adapter,
> +					  struct sk_buff *skb, bool ignore_sync)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +
> +	spin_lock_bh(&ptp->tx_ts_lock);
> +	if (ptp->tx_ts_skb_queue_size < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS) {
> +		ptp->tx_ts_skb_queue[ptp->tx_ts_skb_queue_size] = skb;
> +		if (ignore_sync)
> +			ptp->tx_ts_ignore_sync_queue |=
> +				BIT(ptp->tx_ts_skb_queue_size);
> +		ptp->tx_ts_skb_queue_size++;
> +	} else {
> +		/* this should never happen, so long as the tx channel
> +		 * calls and honors the result from
> +		 * lan743x_ptp_request_tx_timestamp
> +		 */
> +		netif_err(adapter, drv, adapter->netdev,
> +			  "tx ts skb queue overflow\n");
> +		dev_kfree_skb(skb);
> +	}
> +	spin_unlock_bh(&ptp->tx_ts_lock);
> +}
> +
> +static void lan743x_ptp_tx_ts_enqueue_ts(struct lan743x_adapter *adapter,
> +					 u32 seconds, u32 nano_seconds,
> +					 u32 header)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +
> +	spin_lock_bh(&ptp->tx_ts_lock);
> +	if (ptp->tx_ts_queue_size < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS) {
> +		ptp->tx_ts_seconds_queue[ptp->tx_ts_queue_size] = seconds;
> +		ptp->tx_ts_nseconds_queue[ptp->tx_ts_queue_size] = nano_seconds;
> +		ptp->tx_ts_header_queue[ptp->tx_ts_queue_size] = header;
> +		ptp->tx_ts_queue_size++;
> +	} else {
> +		netif_err(adapter, drv, adapter->netdev,
> +			  "tx ts queue overflow\n");
> +	}
> +	spin_unlock_bh(&ptp->tx_ts_lock);
> +}
> +
> +static void lan743x_ptp_isr_bottom_half(unsigned long param)
> +{
> +	struct lan743x_adapter *adapter = (struct lan743x_adapter *)param;
> +	bool new_timestamp_available = false;
> +
> +	while (lan743x_csr_read(adapter, PTP_INT_STS) & PTP_INT_BIT_TX_TS_) {

As a sanity check, you should break this loop using a counter.

> +		u32 cap_info = lan743x_csr_read(adapter, PTP_CAP_INFO);
> +
> +		if (PTP_CAP_INFO_TX_TS_CNT_GET_(cap_info) > 0) {
> +			u32 seconds = lan743x_csr_read(adapter,
> +				PTP_TX_EGRESS_SEC);
> +			u32 nsec = lan743x_csr_read(adapter, PTP_TX_EGRESS_NS);
> +			u32 cause = (nsec &
> +				     PTP_TX_EGRESS_NS_CAPTURE_CAUSE_MASK_);
> +			u32 header = lan743x_csr_read(adapter,
> +						      PTP_TX_MSG_HEADER);
> +
> +			if (cause == PTP_TX_EGRESS_NS_CAPTURE_CAUSE_SW_) {
> +				nsec &= PTP_TX_EGRESS_NS_TS_NS_MASK_;
> +				lan743x_ptp_tx_ts_enqueue_ts(adapter,
> +							     seconds, nsec,
> +							     header);
> +				new_timestamp_available = true;
> +			} else if (cause ==
> +				PTP_TX_EGRESS_NS_CAPTURE_CAUSE_AUTO_) {
> +				netif_err(adapter, drv, adapter->netdev,
> +					  "Auto capture cause not supported\n");
> +			} else {
> +				netif_warn(adapter, drv, adapter->netdev,
> +					   "unknown tx timestamp capture cause\n");
> +			}
> +		} else {
> +			netif_warn(adapter, drv, adapter->netdev,
> +				   "TX TS INT but no TX TS CNT\n");
> +		}
> +		lan743x_csr_write(adapter, PTP_INT_STS, PTP_INT_BIT_TX_TS_);
> +	}
> +
> +	if (new_timestamp_available)
> +		lan743x_ptp_tx_ts_complete(adapter);
> +
> +	lan743x_csr_write(adapter, INT_EN_SET, INT_BIT_1588_);
> +}
> +
> +static void lan743x_ptp_sync_to_system_clock(struct lan743x_adapter *adapter)
> +{
> +	struct timeval tv;
> +
> +	memset(&tv, 0, sizeof(tv));
> +	do_gettimeofday(&tv);

Use the TAI clock instead.

> +	lan743x_ptp_clock_set(adapter, tv.tv_sec, tv.tv_usec * 1000, 0);
> +}
> +
> +void lan743x_ptp_update_latency(struct lan743x_adapter *adapter,
> +				u32 link_speed)
> +{
> +	switch (link_speed) {
> +	case 10:
> +		lan743x_csr_write(adapter, PTP_LATENCY,
> +				  PTP_LATENCY_TX_SET_(0) |
> +				  PTP_LATENCY_RX_SET_(0));
> +		break;
> +	case 100:
> +		lan743x_csr_write(adapter, PTP_LATENCY,
> +				  PTP_LATENCY_TX_SET_(181) |
> +				  PTP_LATENCY_RX_SET_(594));
> +		break;
> +	case 1000:
> +		lan743x_csr_write(adapter, PTP_LATENCY,
> +				  PTP_LATENCY_TX_SET_(30) |
> +				  PTP_LATENCY_RX_SET_(525));
> +		break;
> +	}
> +}
> +
> +int lan743x_ptp_init(struct lan743x_adapter *adapter)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +
> +	mutex_init(&ptp->command_lock);
> +	spin_lock_init(&ptp->tx_ts_lock);
> +	tasklet_init(&ptp->ptp_isr_bottom_half,
> +		     lan743x_ptp_isr_bottom_half, (unsigned long)adapter);
> +	tasklet_disable(&ptp->ptp_isr_bottom_half);
> +	ptp->used_event_ch = 0;
> +	ptp->pps_event_ch = -1;
> +	ptp->pps_gpio_bit = -1;
> +	return 0;
> +}
> +
> +int lan743x_ptp_open(struct lan743x_adapter *adapter)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +	int ret = -ENODEV;
> +	u32 temp;
> +
> +	lan743x_ptp_reset(adapter);
> +	lan743x_ptp_sync_to_system_clock(adapter);
> +	temp = lan743x_csr_read(adapter, PTP_TX_MOD2);
> +	temp |= PTP_TX_MOD2_TX_PTP_CLR_UDPV4_CHKSUM_;
> +	lan743x_csr_write(adapter, PTP_TX_MOD2, temp);
> +	lan743x_ptp_enable(adapter);
> +	tasklet_enable(&ptp->ptp_isr_bottom_half);
> +	lan743x_csr_write(adapter, INT_EN_SET, INT_BIT_1588_);
> +	lan743x_csr_write(adapter, PTP_INT_EN_SET,
> +			  PTP_INT_BIT_TX_SWTS_ERR_ | PTP_INT_BIT_TX_TS_);
> +	ptp->flags |= PTP_FLAG_ISR_ENABLED;
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +	snprintf(ptp->pin_config[0].name, 32, "lan743x_ptp_pin_0");
> +	ptp->pin_config[0].index = 0;
> +	ptp->pin_config[0].func = PTP_PF_PEROUT;
> +	ptp->pin_config[0].chan = 0;
> +
> +	ptp->ptp_clock_info.owner = THIS_MODULE;
> +	snprintf(ptp->ptp_clock_info.name, 16, "%pm",
> +		 adapter->netdev->dev_addr);
> +	ptp->ptp_clock_info.max_adj = LAN743X_PTP_MAX_FREQ_ADJ_IN_PPB;
> +	ptp->ptp_clock_info.n_alarm = 0;
> +	ptp->ptp_clock_info.n_ext_ts = 0;
> +	ptp->ptp_clock_info.n_per_out = 0;
> +	ptp->ptp_clock_info.n_pins = 0;
> +	ptp->ptp_clock_info.pps = 1;
> +	ptp->ptp_clock_info.pin_config = NULL;
> +	ptp->ptp_clock_info.adjfreq = lan743x_ptpci_adjfreq;
> +	ptp->ptp_clock_info.adjtime = lan743x_ptpci_adjtime;
> +	ptp->ptp_clock_info.gettime64 = lan743x_ptpci_gettime64;
> +	ptp->ptp_clock_info.getcrosststamp = NULL;
> +	ptp->ptp_clock_info.settime64 = lan743x_ptpci_settime64;
> +	ptp->ptp_clock_info.enable = lan743x_ptpci_enable;
> +	ptp->ptp_clock_info.verify = NULL;
> +
> +	ptp->ptp_clock = ptp_clock_register(&ptp->ptp_clock_info,
> +					    &adapter->pdev->dev);
> +
> +	if (IS_ERR(ptp->ptp_clock)) {
> +		netif_err(adapter, ifup, adapter->netdev,
> +			  "ptp_clock_register failed\n");
> +		goto done;
> +	}
> +	ptp->flags |= PTP_FLAG_PTP_CLOCK_REGISTERED;
> +	netif_info(adapter, ifup, adapter->netdev,
> +		   "successfully registered ptp clock\n");
> +#endif
> +
> +	return 0;
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +done:
> +	lan743x_ptp_close(adapter);
> +	return ret;
> +#endif
> +}
> +
> +void lan743x_ptp_close(struct lan743x_adapter *adapter)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +	int index;
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +	if (ptp->flags & PTP_FLAG_PTP_CLOCK_REGISTERED) {
> +		ptp_clock_unregister(ptp->ptp_clock);
> +		ptp->ptp_clock = NULL;
> +		ptp->flags &= ~PTP_FLAG_PTP_CLOCK_REGISTERED;
> +		netif_info(adapter, drv, adapter->netdev,
> +			   "ptp clock unregister\n");
> +	}
> +#endif
> +
> +	if (ptp->flags & PTP_FLAG_ISR_ENABLED) {
> +		lan743x_csr_write(adapter, PTP_INT_EN_CLR,
> +				  PTP_INT_BIT_TX_SWTS_ERR_ |
> +				  PTP_INT_BIT_TX_TS_);
> +		lan743x_csr_write(adapter, INT_EN_CLR, INT_BIT_1588_);
> +		tasklet_disable(&ptp->ptp_isr_bottom_half);
> +		ptp->flags &= ~PTP_FLAG_ISR_ENABLED;
> +	}
> +
> +	/* clean up pending timestamp requests */
> +	lan743x_ptp_tx_ts_complete(adapter);
> +	spin_lock_bh(&ptp->tx_ts_lock);
> +	for (index = 0;
> +		index < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS;
> +		index++) {
> +		struct sk_buff *skb = ptp->tx_ts_skb_queue[index];
> +
> +		if (skb)
> +			dev_kfree_skb(skb);
> +		ptp->tx_ts_skb_queue[index] = NULL;
> +		ptp->tx_ts_seconds_queue[index] = 0;
> +		ptp->tx_ts_nseconds_queue[index] = 0;
> +	}
> +	ptp->tx_ts_skb_queue_size = 0;
> +	ptp->tx_ts_queue_size = 0;
> +	ptp->pending_tx_timestamps = 0;
> +	spin_unlock_bh(&ptp->tx_ts_lock);
> +
> +	lan743x_ptp_disable(adapter);
> +}
> +
> +void lan743x_ptp_set_sync_ts_insert(struct lan743x_adapter *adapter,
> +				    bool ts_insert_enable)
> +{
> +	u32 ptp_tx_mod = lan743x_csr_read(adapter, PTP_TX_MOD);
> +
> +	if (ts_insert_enable)
> +		ptp_tx_mod |= PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_;
> +	else
> +		ptp_tx_mod &= ~PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_;
> +
> +	lan743x_csr_write(adapter, PTP_TX_MOD, ptp_tx_mod);
> +}
> +
> +static bool lan743x_ptp_is_enabled(struct lan743x_adapter *adapter)
> +{
> +	if (lan743x_csr_read(adapter, PTP_CMD_CTL) & PTP_CMD_CTL_PTP_ENABLE_)
> +		return true;
> +	return false;
> +}
> +
> +static void lan743x_ptp_wait_till_cmd_done(struct lan743x_adapter *adapter,
> +					   u32 bit_mask)
> +{
> +	int timeout = 1000;
> +	u32 data = 0;
> +
> +	while (timeout &&
> +	       (data = (lan743x_csr_read(adapter, PTP_CMD_CTL) &
> +	       bit_mask))) {
> +		usleep_range(1000, 20000);
> +		timeout--;
> +	}
> +	if (data) {
> +		netif_err(adapter, drv, adapter->netdev,
> +			  "timeout waiting for cmd to be done, cmd = 0x%08X\n",
> +			  bit_mask);
> +	}
> +}
> +
> +static void lan743x_ptp_enable(struct lan743x_adapter *adapter)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +
> +	mutex_lock(&ptp->command_lock);
> +
> +	if (lan743x_ptp_is_enabled(adapter)) {
> +		netif_warn(adapter, drv, adapter->netdev,
> +			   "PTP already enabled\n");
> +		goto done;
> +	}
> +	lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_ENABLE_);
> +done:
> +	mutex_unlock(&ptp->command_lock);
> +}
> +
> +static void lan743x_ptp_disable(struct lan743x_adapter *adapter)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +
> +	mutex_lock(&ptp->command_lock);
> +	if (!lan743x_ptp_is_enabled(adapter)) {
> +		netif_warn(adapter, drv, adapter->netdev,
> +			   "PTP already disabled\n");
> +		goto done;
> +	}
> +	lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_DISABLE_);
> +	lan743x_ptp_wait_till_cmd_done(adapter, PTP_CMD_CTL_PTP_ENABLE_);
> +done:
> +	mutex_unlock(&ptp->command_lock);
> +}
> +
> +static void lan743x_ptp_reset(struct lan743x_adapter *adapter)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +
> +	mutex_lock(&ptp->command_lock);
> +
> +	if (lan743x_ptp_is_enabled(adapter)) {
> +		netif_err(adapter, drv, adapter->netdev,
> +			  "Attempting reset while enabled\n");
> +		goto done;
> +	}
> +
> +	lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_RESET_);
> +	lan743x_ptp_wait_till_cmd_done(adapter, PTP_CMD_CTL_PTP_RESET_);
> +done:
> +	mutex_unlock(&ptp->command_lock);
> +}
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static int lan743x_ptp_reserve_event_ch(struct lan743x_adapter *adapter)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +	int result = -ENODEV;
> +	int index = 0;
> +
> +	mutex_lock(&ptp->command_lock);
> +	for (index = 0; index < LAN743X_PTP_NUMBER_OF_EVENT_CHANNELS; index++) {
> +		if (!(test_bit(index, &ptp->used_event_ch))) {
> +			ptp->used_event_ch |= BIT(index);
> +			result = index;
> +			break;
> +		}
> +	}
> +	mutex_unlock(&ptp->command_lock);
> +	return result;
> +}
> +#endif /* CONFIG_PTP_1588_CLOCK */
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static void lan743x_ptp_release_event_ch(struct lan743x_adapter *adapter,
> +					 int event_channel)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +
> +	mutex_lock(&ptp->command_lock);
> +	if (test_bit(event_channel, &ptp->used_event_ch)) {
> +		ptp->used_event_ch &= ~BIT(event_channel);
> +	} else {
> +		netif_warn(adapter, drv, adapter->netdev,
> +			   "attempted release on a not used event_channel = %d\n",
> +			   event_channel);
> +	}
> +	mutex_unlock(&ptp->command_lock);
> +}
> +#endif /* CONFIG_PTP_1588_CLOCK */
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static void lan743x_ptp_clock_get(struct lan743x_adapter *adapter,
> +				  u32 *seconds, u32 *nano_seconds,
> +				  u32 *sub_nano_seconds)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +
> +	mutex_lock(&ptp->command_lock);
> +
> +	lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_CLOCK_READ_);
> +	lan743x_ptp_wait_till_cmd_done(adapter, PTP_CMD_CTL_PTP_CLOCK_READ_);
> +
> +	if (seconds)
> +		(*seconds) = lan743x_csr_read(adapter, PTP_CLOCK_SEC);
> +
> +	if (nano_seconds)
> +		(*nano_seconds) = lan743x_csr_read(adapter, PTP_CLOCK_NS);
> +
> +	if (sub_nano_seconds)
> +		(*sub_nano_seconds) =
> +		lan743x_csr_read(adapter, PTP_CLOCK_SUBNS);
> +
> +	mutex_unlock(&ptp->command_lock);
> +}
> +#endif /* CONFIG_PTP_1588_CLOCK */
> +
> +static void lan743x_ptp_clock_set(struct lan743x_adapter *adapter,
> +				  u32 seconds, u32 nano_seconds,
> +				  u32 sub_nano_seconds)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +
> +	mutex_lock(&ptp->command_lock);
> +
> +	lan743x_csr_write(adapter, PTP_CLOCK_SEC, seconds);
> +	lan743x_csr_write(adapter, PTP_CLOCK_NS, nano_seconds);
> +	lan743x_csr_write(adapter, PTP_CLOCK_SUBNS, sub_nano_seconds);
> +
> +	lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_CLOCK_LOAD_);
> +	lan743x_ptp_wait_till_cmd_done(adapter, PTP_CMD_CTL_PTP_CLOCK_LOAD_);
> +	mutex_unlock(&ptp->command_lock);
> +}
> +
> +#ifdef CONFIG_PTP_1588_CLOCK
> +static void lan743x_ptp_clock_step(struct lan743x_adapter *adapter,
> +				   s64 time_step_ns)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +	u64 abs_time_step_ns = 0;
> +	u32 nano_seconds = 0;
> +	s32 seconds = 0;
> +
> +	if (time_step_ns >  15000000000LL) {
> +		/* convert to clock set */
> +		u32 nano_seconds = 0;
> +		u32 seconds = 0;
> +
> +		lan743x_ptp_clock_get(adapter, &seconds, &nano_seconds, NULL);
> +		seconds += (time_step_ns / 1000000000LL);

Use the macro.

> +		nano_seconds += (time_step_ns % 1000000000LL);

Actually, use div_u64_rem() to avoid the % operator.

> +		if (nano_seconds >= 1000000000) {

How can this test be true?

> +			seconds++;
> +			nano_seconds -= 1000000000;
> +		}
> +		lan743x_ptp_clock_set(adapter, seconds, nano_seconds, 0);
> +		return;
> +	} else if (time_step_ns < -15000000000LL) {
> +		/* convert to clock set */
> +		u32 nano_seconds_step = 0;
> +		u32 nano_seconds = 0;
> +		u32 seconds = 0;

Ugh.  Now you have these defined twice.  Move them to the top, please.

> +		time_step_ns = -time_step_ns;
> +
> +		lan743x_ptp_clock_get(adapter, &seconds, &nano_seconds, NULL);
> +		seconds -= (time_step_ns / 1000000000LL);
> +		nano_seconds_step = (time_step_ns % 1000000000LL);

Use division macro for 64 bit.

> +		if (nano_seconds < nano_seconds_step) {
> +			seconds--;
> +			nano_seconds += 1000000000;
> +		}
> +		nano_seconds -= nano_seconds_step;
> +		lan743x_ptp_clock_set(adapter, seconds, nano_seconds, 0);
> +		return;
> +	}
> +
> +	/* do clock step */
> +
> +	if (time_step_ns >= 0) {
> +		abs_time_step_ns = (u64)(time_step_ns);
> +		seconds = (s32)(abs_time_step_ns / 1000000000);
> +		nano_seconds = (u32)(abs_time_step_ns % 1000000000);
> +	} else {
> +		abs_time_step_ns = (u64)(-time_step_ns);
> +		seconds = -((s32)(abs_time_step_ns / 1000000000));
> +		nano_seconds = (u32)(abs_time_step_ns % 1000000000);
> +		if (nano_seconds > 0) {
> +			/* subtracting nano seconds is not allowed
> +			 * convert to subtracting from seconds,
> +			 * and adding to nanoseconds
> +			 */
> +			seconds--;
> +			nano_seconds = (1000000000 - nano_seconds);
> +		}
> +	}
> +
> +	if (nano_seconds > 0) {
> +		/* add 8 ns to cover the likely normal increment */
> +		nano_seconds += 8;
> +	}
> +
> +	if (nano_seconds >= 1000000000) {
> +		/* carry into seconds */
> +		seconds++;
> +		nano_seconds -= 1000000000;
> +	}
> +
> +	while (seconds) {
> +		mutex_lock(&ptp->command_lock);
> +		if (seconds > 0) {
> +			u32 adjustment_value = (u32)seconds;
> +
> +			if (adjustment_value > 0xF)
> +				adjustment_value = 0xF;
> +			lan743x_csr_write(adapter, PTP_CLOCK_STEP_ADJ,
> +					  PTP_CLOCK_STEP_ADJ_DIR_ |
> +					  adjustment_value);
> +			seconds -= ((s32)adjustment_value);
> +		} else {
> +			u32 adjustment_value = (u32)(-seconds);
> +
> +			if (adjustment_value > 0xF)
> +				adjustment_value = 0xF;
> +			lan743x_csr_write(adapter, PTP_CLOCK_STEP_ADJ,
> +					  adjustment_value);
> +			seconds += ((s32)adjustment_value);
> +		}
> +		lan743x_csr_write(adapter, PTP_CMD_CTL,
> +				  PTP_CMD_CTL_PTP_CLOCK_STEP_SEC_);
> +		lan743x_ptp_wait_till_cmd_done(adapter,
> +					       PTP_CMD_CTL_PTP_CLOCK_STEP_SEC_);
> +		mutex_unlock(&ptp->command_lock);
> +	}
> +	if (nano_seconds) {
> +		mutex_lock(&ptp->command_lock);
> +		lan743x_csr_write(adapter, PTP_CLOCK_STEP_ADJ,
> +				  PTP_CLOCK_STEP_ADJ_DIR_ |
> +				  (nano_seconds &
> +				  PTP_CLOCK_STEP_ADJ_VALUE_MASK_));
> +		lan743x_csr_write(adapter, PTP_CMD_CTL,
> +				  PTP_CMD_CTL_PTP_CLK_STP_NSEC_);
> +		lan743x_ptp_wait_till_cmd_done(adapter,
> +					       PTP_CMD_CTL_PTP_CLK_STP_NSEC_);
> +		mutex_unlock(&ptp->command_lock);
> +	}
> +}
> +#endif /* CONFIG_PTP_1588_CLOCK */
> +
> +bool lan743x_ptp_request_tx_timestamp(struct lan743x_adapter *adapter)
> +{
> +	struct lan743x_ptp *ptp = &adapter->ptp;
> +	bool result = false;
> +
> +	spin_lock_bh(&ptp->tx_ts_lock);
> +	if (ptp->pending_tx_timestamps < LAN743X_PTP_NUMBER_OF_TX_TIMESTAMPS) {
> +		ptp->pending_tx_timestamps++;
> +		result = true;/* request granted */

Avoid tail comments please.

> +	}
> +	spin_unlock_bh(&ptp->tx_ts_lock);
> +	return result;
> +}

Thanks,
Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [PATCH v2 net-next 7/9] lan743x: Add EEE support
  2018-07-12 22:49   ` Andrew Lunn
@ 2018-07-13 16:35     ` Bryan.Whitehead
  0 siblings, 0 replies; 23+ messages in thread
From: Bryan.Whitehead @ 2018-07-13 16:35 UTC (permalink / raw)
  To: andrew; +Cc: davem, netdev, UNGLinuxDriver, richardcochran

> > +static int lan743x_ethtool_set_eee(struct net_device *netdev,
> > +				   struct ethtool_eee *eee)
> > +{
<snip>
> 
> Hi Bryan
> 
> You should call phy_ethtool_set_eee() in both cases, so that it gets disabled
> in the PHY as well. It needs to stop advertising it.
> 
>        Andrew

OK, thanks Andrew, will do.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [PATCH v2 net-next 9/9] lan743x: Add PTP support
  2018-07-13  3:31   ` Richard Cochran
@ 2018-07-18 20:04     ` Bryan.Whitehead
  2018-07-18 20:55       ` Richard Cochran
  0 siblings, 1 reply; 23+ messages in thread
From: Bryan.Whitehead @ 2018-07-18 20:04 UTC (permalink / raw)
  To: richardcochran; +Cc: davem, netdev, UNGLinuxDriver

Hi Richard,

Thank you for your detailed feedback. I'm working on it now, but I feel it will take a little extra time to complete. Therefor I'm planning to remove PTP support from this patch series, and resubmit it in a new patch later.

I also have a few questions below.

> -----Original Message-----
> From: Richard Cochran [mailto:richardcochran@gmail.com]
> Sent: Thursday, July 12, 2018 11:32 PM
> To: Bryan Whitehead - C21958 <Bryan.Whitehead@microchip.com>
> Cc: davem@davemloft.net; netdev@vger.kernel.org; UNGLinuxDriver
> <UNGLinuxDriver@microchip.com>
> Subject: Re: [PATCH v2 net-next 9/9] lan743x: Add PTP support
> 
...
> > +	if (cleanup) {
> > +		lan743x_ptp_unrequest_tx_timestamp(tx->adapter);
> > +		dev_kfree_skb(buffer_info->skb);
> > +	} else {
> > +		lan743x_ptp_tx_timestamp_skb(tx->adapter,
> > +					     buffer_info->skb,
> > +					     (buffer_info->flags &
> > +
> TX_BUFFER_INFO_FLAG_IGNORE_SYNC)
> > +					     != 0);
> 
> This is poor coding style.  Please find a better way.

Can you clarify what is poor and what would be better?
For example, should I change "X != 0" to "X ? true : false".

> > +#ifdef CONFIG_PTP_1588_CLOCK
> > +static int lan743x_ptp_enable_pps(struct lan743x_adapter *adapter) {
> > +	struct lan743x_ptp *ptp = &adapter->ptp;
> > +	u32 current_seconds = 0;
> > +	u32 target_seconds = 0;
> > +	u32 general_config = 0;
> > +	int result = -ENODEV;
> > +	int pps_bit = 0;
> 
> So this function is really *not* implementing the PTP_CLK_REQ_PPS feature
> but rather the PTP_CLK_REQ_PEROUT with a period of once per second.
> 
> PTP_CLK_REQ_PPS means placing a PPS event into the kernel's "hardpps"
> subsystem by calling ptp_clock_event().
> 
> I'm sorry this isn't really documented.  I should fix that.
> 
> If you HW can output arbitrary signals, then you should implement
> PTP_CLK_REQ_PEROUT.  In any case, you shouldn't advertise the
> ptp_clock_info.pps capability.

So you mean PPS is not intended to generate a physical signal?
It is only intended to call ptp_clock_event?
I can configure the hardware to generate an interrupt each second and then call 
ptp_clock_event. Would that satisfy the pps requirements?

Regarding PTP_CLK_REQ_PEROUT. Is that intended for physical signals?

Thanks,
Bryan

^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [PATCH v2 net-next 6/9] lan743x: Add power management support
  2018-07-12 22:42   ` Andrew Lunn
@ 2018-07-18 20:05     ` Bryan.Whitehead
  0 siblings, 0 replies; 23+ messages in thread
From: Bryan.Whitehead @ 2018-07-18 20:05 UTC (permalink / raw)
  To: andrew; +Cc: davem, netdev, UNGLinuxDriver, richardcochran

Hi Andrew,

Thanks for your reviews, and corrections.
I will submit a new patch series soon.

Bryan

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 9/9] lan743x: Add PTP support
  2018-07-18 20:04     ` Bryan.Whitehead
@ 2018-07-18 20:55       ` Richard Cochran
  2018-07-18 21:05         ` Bryan.Whitehead
  0 siblings, 1 reply; 23+ messages in thread
From: Richard Cochran @ 2018-07-18 20:55 UTC (permalink / raw)
  To: Bryan.Whitehead; +Cc: davem, netdev, UNGLinuxDriver

On Wed, Jul 18, 2018 at 08:04:08PM +0000, Bryan.Whitehead@microchip.com wrote:
> Thank you for your detailed feedback. I'm working on it now, but I feel it will take a little extra time to complete. Therefor I'm planning to remove PTP support from this patch series, and resubmit it in a new patch later.

Ok.

> > > +	if (cleanup) {
> > > +		lan743x_ptp_unrequest_tx_timestamp(tx->adapter);
> > > +		dev_kfree_skb(buffer_info->skb);
> > > +	} else {
> > > +		lan743x_ptp_tx_timestamp_skb(tx->adapter,
> > > +					     buffer_info->skb,
> > > +					     (buffer_info->flags &
> > > +
> > TX_BUFFER_INFO_FLAG_IGNORE_SYNC)
> > > +					     != 0);
> > 
> > This is poor coding style.  Please find a better way.
> 
> Can you clarify what is poor and what would be better?
> For example, should I change "X != 0" to "X ? true : false".

Look at this:
		lan743x_ptp_tx_timestamp_skb(tx->adapter,
					     buffer_info->skb,
					     (buffer_info->flags &
					     TX_BUFFER_INFO_FLAG_IGNORE_SYNC)
					     != 0);

Can't you reduce

	(buffer_info->flags & TX_BUFFER_INFO_FLAG_IGNORE_SYNC) != 0

into a local variable:

		lan743x_ptp_tx_timestamp_skb(tx->adapter, buffer_info->skb, xyz);
?

> So you mean PPS is not intended to generate a physical signal?

Yes.

> It is only intended to call ptp_clock_event?

Yes.

> I can configure the hardware to generate an interrupt each second and then call 
> ptp_clock_event. Would that satisfy the pps requirements?

Yes.
 
> Regarding PTP_CLK_REQ_PEROUT. Is that intended for physical signals?

Yes.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [PATCH v2 net-next 9/9] lan743x: Add PTP support
  2018-07-18 20:55       ` Richard Cochran
@ 2018-07-18 21:05         ` Bryan.Whitehead
  0 siblings, 0 replies; 23+ messages in thread
From: Bryan.Whitehead @ 2018-07-18 21:05 UTC (permalink / raw)
  To: richardcochran; +Cc: davem, netdev, UNGLinuxDriver

> > Can you clarify what is poor and what would be better?
> > For example, should I change "X != 0" to "X ? true : false".
> 
> Look at this:
> 		lan743x_ptp_tx_timestamp_skb(tx->adapter,
> 					     buffer_info->skb,
> 					     (buffer_info->flags &
> 
> TX_BUFFER_INFO_FLAG_IGNORE_SYNC)
> 					     != 0);
> 
> Can't you reduce
> 
> 	(buffer_info->flags & TX_BUFFER_INFO_FLAG_IGNORE_SYNC) != 0
> 
> into a local variable:
> 
> 		lan743x_ptp_tx_timestamp_skb(tx->adapter, buffer_info-
> >skb, xyz); ?
> 
> > So you mean PPS is not intended to generate a physical signal?
> 
> Yes.
> 
> > It is only intended to call ptp_clock_event?
> 
> Yes.
> 
> > I can configure the hardware to generate an interrupt each second and
> > then call ptp_clock_event. Would that satisfy the pps requirements?
> 
> Yes.
> 
> > Regarding PTP_CLK_REQ_PEROUT. Is that intended for physical signals?
> 
> Yes.
> 
> Thanks,
> Richard

Richard,
Thank you for your quick answers.
Bryan

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2018-07-18 21:44 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-12 19:04 [PATCH v2 net-next 0/9] lan743x: Add features to lan743x driver Bryan Whitehead
2018-07-12 19:04 ` [PATCH v2 net-next 1/9] lan743x: Add support for ethtool get_drvinfo Bryan Whitehead
2018-07-12 22:28   ` Andrew Lunn
2018-07-12 19:04 ` [PATCH v2 net-next 2/9] lan743x: Add support for ethtool link settings Bryan Whitehead
2018-07-12 22:29   ` Andrew Lunn
2018-07-12 19:05 ` [PATCH v2 net-next 3/9] lan743x: Add support for ethtool statistics Bryan Whitehead
2018-07-12 22:31   ` Andrew Lunn
2018-07-12 19:05 ` [PATCH v2 net-next 4/9] lan743x: Add support for ethtool message level Bryan Whitehead
2018-07-12 22:31   ` Andrew Lunn
2018-07-12 19:05 ` [PATCH v2 net-next 5/9] lan743x: Add support for ethtool eeprom access Bryan Whitehead
2018-07-12 22:35   ` Andrew Lunn
2018-07-12 19:05 ` [PATCH v2 net-next 6/9] lan743x: Add power management support Bryan Whitehead
2018-07-12 22:42   ` Andrew Lunn
2018-07-18 20:05     ` Bryan.Whitehead
2018-07-12 19:05 ` [PATCH v2 net-next 7/9] lan743x: Add EEE support Bryan Whitehead
2018-07-12 22:49   ` Andrew Lunn
2018-07-13 16:35     ` Bryan.Whitehead
2018-07-12 19:05 ` [PATCH v2 net-next 8/9] lan743x: Add RSS support Bryan Whitehead
2018-07-12 19:05 ` [PATCH v2 net-next 9/9] lan743x: Add PTP support Bryan Whitehead
2018-07-13  3:31   ` Richard Cochran
2018-07-18 20:04     ` Bryan.Whitehead
2018-07-18 20:55       ` Richard Cochran
2018-07-18 21:05         ` Bryan.Whitehead

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.