All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/8] net: mscc: PTP offloading support
@ 2019-01-17 10:02 Antoine Tenart
  2019-01-17 10:02 ` [PATCH net-next 1/8] Documentation/bindings: net: ocelot: document the VCAP and PTP banks Antoine Tenart
                   ` (9 more replies)
  0 siblings, 10 replies; 16+ messages in thread
From: Antoine Tenart @ 2019-01-17 10:02 UTC (permalink / raw)
  To: davem, alexandre.belloni, UNGLinuxDriver, ralf, paul.burton, jhogan
  Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
	quentin.schulz, allan.nielsen

Hi all,

This series adds support for the PTP offloading support in the Mscc
Ocelot Ethernet switch driver. Both PTP 1-step and 2-step modes are
supported.

In order to make use of the PTP offloading support, two new register
banks were described in the Ocelot device tree. The use of those
registers by the Mscc Ocelot Ethernet switch driver is made optional for
dt compatibility reasons. For the same reason a new interrupt is
described, and its use is also made optinal for compatibility reasons.
All of this is done ine patches 1-5.

The PTP offloading support itself is added in patch 8.

While doing this support, a few reworks were done in the Ocelot switch
driver, in patches 6-7.

Patches 2 and 4 should probably go through the MIPS tree.

Thanks!
Antoine

Antoine Tenart (8):
  Documentation/bindings: net: ocelot: document the VCAP and PTP banks
  MIPS: dts: mscc: describe VCAP and PTP register ranges
  Documentation/bindings: net: ocelot: document the PTP ready IRQ
  MIPS: dts: mscc: describe the PTP ready interrupt
  net: mscc: describe the VCAP and PTP register ranges
  net: mscc: improve the frame header parsing readability
  net: mscc: remove the frame_info cpuq member
  net: mscc: PTP offloading support

 .../devicetree/bindings/net/mscc-ocelot.txt   |  22 +-
 arch/mips/boot/dts/mscc/ocelot.dtsi           |  14 +-
 drivers/net/ethernet/mscc/ocelot.c            | 509 +++++++++++++++++-
 drivers/net/ethernet/mscc/ocelot.h            |  55 +-
 drivers/net/ethernet/mscc/ocelot_board.c      | 150 +++++-
 drivers/net/ethernet/mscc/ocelot_ptp.h        |  41 ++
 drivers/net/ethernet/mscc/ocelot_regs.c       |  22 +
 drivers/net/ethernet/mscc/ocelot_vcap.h       | 104 ++++
 8 files changed, 877 insertions(+), 40 deletions(-)
 create mode 100644 drivers/net/ethernet/mscc/ocelot_ptp.h
 create mode 100644 drivers/net/ethernet/mscc/ocelot_vcap.h

-- 
2.20.1


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

* [PATCH net-next 1/8] Documentation/bindings: net: ocelot: document the VCAP and PTP banks
  2019-01-17 10:02 [PATCH net-next 0/8] net: mscc: PTP offloading support Antoine Tenart
@ 2019-01-17 10:02 ` Antoine Tenart
  2019-01-17 10:02 ` [PATCH net-next 2/8] MIPS: dts: mscc: describe VCAP and PTP register ranges Antoine Tenart
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Antoine Tenart @ 2019-01-17 10:02 UTC (permalink / raw)
  To: davem, alexandre.belloni, UNGLinuxDriver, ralf, paul.burton, jhogan
  Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
	quentin.schulz, allan.nielsen

Two additional register ranges needs to be described within the Ocelot
device tree node: the VCAP and the PTP ones. This patch documents the
binding needed to do so.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 Documentation/devicetree/bindings/net/mscc-ocelot.txt | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/mscc-ocelot.txt b/Documentation/devicetree/bindings/net/mscc-ocelot.txt
index 9e5c17d426ce..08bc8d7f0c99 100644
--- a/Documentation/devicetree/bindings/net/mscc-ocelot.txt
+++ b/Documentation/devicetree/bindings/net/mscc-ocelot.txt
@@ -11,7 +11,9 @@ Required properties:
 - reg-names: Must include the following entries:
   - "sys"
   - "rew"
+  - "vcap"
   - "qs"
+  - "ptp"
   - "qsys"
   - "ana"
   - "portX" with X from 0 to the number of last port index available on that
@@ -43,7 +45,9 @@ Example:
 		compatible = "mscc,vsc7514-switch";
 		reg = <0x1010000 0x10000>,
 		      <0x1030000 0x10000>,
+		      <0x1060000 0x10000>,
 		      <0x1080000 0x100>,
+		      <0x10e0000 0x10000>,
 		      <0x11e0000 0x100>,
 		      <0x11f0000 0x100>,
 		      <0x1200000 0x100>,
@@ -57,9 +61,10 @@ Example:
 		      <0x1280000 0x100>,
 		      <0x1800000 0x80000>,
 		      <0x1880000 0x10000>;
-		reg-names = "sys", "rew", "qs", "port0", "port1", "port2",
-			    "port3", "port4", "port5", "port6", "port7",
-			    "port8", "port9", "port10", "qsys", "ana";
+		reg-names = "sys", "rew", "vcap", "qs", "ptp", "port0",
+			    "port1", "port2", "port3", "port4", "port5",
+			    "port6", "port7", "port8", "port9", "port10",
+			    "qsys", "ana";
 		interrupts = <21 22>;
 		interrupt-names = "xtr", "inj";
 
-- 
2.20.1


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

* [PATCH net-next 2/8] MIPS: dts: mscc: describe VCAP and PTP register ranges
  2019-01-17 10:02 [PATCH net-next 0/8] net: mscc: PTP offloading support Antoine Tenart
  2019-01-17 10:02 ` [PATCH net-next 1/8] Documentation/bindings: net: ocelot: document the VCAP and PTP banks Antoine Tenart
@ 2019-01-17 10:02 ` Antoine Tenart
  2019-01-17 10:02 ` [PATCH net-next 3/8] Documentation/bindings: net: ocelot: document the PTP ready IRQ Antoine Tenart
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Antoine Tenart @ 2019-01-17 10:02 UTC (permalink / raw)
  To: davem, alexandre.belloni, UNGLinuxDriver, ralf, paul.burton, jhogan
  Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
	quentin.schulz, allan.nielsen

This patch adds two register ranges within the mscc,vsc7514-switch node,
to describe the VCAP and PTP registers.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 arch/mips/boot/dts/mscc/ocelot.dtsi | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/mips/boot/dts/mscc/ocelot.dtsi b/arch/mips/boot/dts/mscc/ocelot.dtsi
index 90c60d42f571..bb81652bebe8 100644
--- a/arch/mips/boot/dts/mscc/ocelot.dtsi
+++ b/arch/mips/boot/dts/mscc/ocelot.dtsi
@@ -119,7 +119,9 @@
 			compatible = "mscc,vsc7514-switch";
 			reg = <0x1010000 0x10000>,
 			      <0x1030000 0x10000>,
+			      <0x1060000 0x10000>,
 			      <0x1080000 0x100>,
+			      <0x10e0000 0x10000>,
 			      <0x11e0000 0x100>,
 			      <0x11f0000 0x100>,
 			      <0x1200000 0x100>,
@@ -133,10 +135,10 @@
 			      <0x1280000 0x100>,
 			      <0x1800000 0x80000>,
 			      <0x1880000 0x10000>;
-			reg-names = "sys", "rew", "qs", "port0", "port1",
-				    "port2", "port3", "port4", "port5", "port6",
-				    "port7", "port8", "port9", "port10", "qsys",
-				    "ana";
+			reg-names = "sys", "rew", "vcap", "qs", "ptp", "port0",
+				    "port1", "port2", "port3", "port4", "port5",
+				    "port6", "port7", "port8", "port9",
+				    "port10", "qsys", "ana";
 			interrupts = <21 22>;
 			interrupt-names = "xtr", "inj";
 
-- 
2.20.1


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

* [PATCH net-next 3/8] Documentation/bindings: net: ocelot: document the PTP ready IRQ
  2019-01-17 10:02 [PATCH net-next 0/8] net: mscc: PTP offloading support Antoine Tenart
  2019-01-17 10:02 ` [PATCH net-next 1/8] Documentation/bindings: net: ocelot: document the VCAP and PTP banks Antoine Tenart
  2019-01-17 10:02 ` [PATCH net-next 2/8] MIPS: dts: mscc: describe VCAP and PTP register ranges Antoine Tenart
@ 2019-01-17 10:02 ` Antoine Tenart
  2019-01-17 10:02 ` [PATCH net-next 4/8] MIPS: dts: mscc: describe the PTP ready interrupt Antoine Tenart
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Antoine Tenart @ 2019-01-17 10:02 UTC (permalink / raw)
  To: davem, alexandre.belloni, UNGLinuxDriver, ralf, paul.burton, jhogan
  Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
	quentin.schulz, allan.nielsen

One additional interrupt needs to be described within the Ocelot device
tree node: the PTP ready one. This patch documents the binding needed to
do so.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 Documentation/devicetree/bindings/net/mscc-ocelot.txt | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/mscc-ocelot.txt b/Documentation/devicetree/bindings/net/mscc-ocelot.txt
index 08bc8d7f0c99..aa33066f3403 100644
--- a/Documentation/devicetree/bindings/net/mscc-ocelot.txt
+++ b/Documentation/devicetree/bindings/net/mscc-ocelot.txt
@@ -18,9 +18,10 @@ Required properties:
   - "ana"
   - "portX" with X from 0 to the number of last port index available on that
     switch
-- interrupts: Should contain the switch interrupts for frame extraction and
-  frame injection
-- interrupt-names: should contain the interrupt names: "xtr", "inj"
+- interrupts: Should contain the switch interrupts for frame extraction,
+  frame injection and PTP ready.
+- interrupt-names: should contain the interrupt names: "xtr", "inj" and
+  "ptp_rdy".
 - ethernet-ports: A container for child nodes representing switch ports.
 
 The ethernet-ports container has the following properties
@@ -65,8 +66,8 @@ Example:
 			    "port1", "port2", "port3", "port4", "port5",
 			    "port6", "port7", "port8", "port9", "port10",
 			    "qsys", "ana";
-		interrupts = <21 22>;
-		interrupt-names = "xtr", "inj";
+		interrupts = <18 21 22>;
+		interrupt-names = "ptp_rdy", "xtr", "inj";
 
 		ethernet-ports {
 			#address-cells = <1>;
-- 
2.20.1


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

* [PATCH net-next 4/8] MIPS: dts: mscc: describe the PTP ready interrupt
  2019-01-17 10:02 [PATCH net-next 0/8] net: mscc: PTP offloading support Antoine Tenart
                   ` (2 preceding siblings ...)
  2019-01-17 10:02 ` [PATCH net-next 3/8] Documentation/bindings: net: ocelot: document the PTP ready IRQ Antoine Tenart
@ 2019-01-17 10:02 ` Antoine Tenart
  2019-01-17 10:02 ` [PATCH net-next 5/8] net: mscc: describe the VCAP and PTP register ranges Antoine Tenart
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Antoine Tenart @ 2019-01-17 10:02 UTC (permalink / raw)
  To: davem, alexandre.belloni, UNGLinuxDriver, ralf, paul.burton, jhogan
  Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
	quentin.schulz, allan.nielsen

This patch adds a description of the PTP ready interrupt, which can be
triggered when a PTP timestamp is available on an hardware FIFO.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 arch/mips/boot/dts/mscc/ocelot.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/mips/boot/dts/mscc/ocelot.dtsi b/arch/mips/boot/dts/mscc/ocelot.dtsi
index bb81652bebe8..0bf5fa11c4e7 100644
--- a/arch/mips/boot/dts/mscc/ocelot.dtsi
+++ b/arch/mips/boot/dts/mscc/ocelot.dtsi
@@ -139,8 +139,8 @@
 				    "port1", "port2", "port3", "port4", "port5",
 				    "port6", "port7", "port8", "port9",
 				    "port10", "qsys", "ana";
-			interrupts = <21 22>;
-			interrupt-names = "xtr", "inj";
+			interrupts = <18 21 22>;
+			interrupt-names = "ptp_rdy", "xtr", "inj";
 
 			ethernet-ports {
 				#address-cells = <1>;
-- 
2.20.1


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

* [PATCH net-next 5/8] net: mscc: describe the VCAP and PTP register ranges
  2019-01-17 10:02 [PATCH net-next 0/8] net: mscc: PTP offloading support Antoine Tenart
                   ` (3 preceding siblings ...)
  2019-01-17 10:02 ` [PATCH net-next 4/8] MIPS: dts: mscc: describe the PTP ready interrupt Antoine Tenart
@ 2019-01-17 10:02 ` Antoine Tenart
  2019-01-17 10:02 ` [PATCH net-next 6/8] net: mscc: improve the frame header parsing readability Antoine Tenart
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Antoine Tenart @ 2019-01-17 10:02 UTC (permalink / raw)
  To: davem, alexandre.belloni, UNGLinuxDriver, ralf, paul.burton, jhogan
  Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
	quentin.schulz, allan.nielsen

This patch adds support for using the VCAP and PTP register ranges, and
adds a description of their registers. Those banks are used when
configuring PTP.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 drivers/net/ethernet/mscc/ocelot.h       |  18 ++++
 drivers/net/ethernet/mscc/ocelot_board.c |  21 +++--
 drivers/net/ethernet/mscc/ocelot_ptp.h   |  41 +++++++++
 drivers/net/ethernet/mscc/ocelot_regs.c  |  22 +++++
 drivers/net/ethernet/mscc/ocelot_vcap.h  | 104 +++++++++++++++++++++++
 5 files changed, 200 insertions(+), 6 deletions(-)
 create mode 100644 drivers/net/ethernet/mscc/ocelot_ptp.h
 create mode 100644 drivers/net/ethernet/mscc/ocelot_vcap.h

diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index 086775f7b52f..4b1b180884ad 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -22,6 +22,8 @@
 #include "ocelot_rew.h"
 #include "ocelot_sys.h"
 #include "ocelot_qs.h"
+#include "ocelot_ptp.h"
+#include "ocelot_vcap.h"
 
 #define PGID_AGGR    64
 #define PGID_SRC     80
@@ -69,6 +71,8 @@ enum ocelot_target {
 	REW,
 	SYS,
 	HSIO,
+	PTP,
+	VCAP,
 	TARGET_MAX,
 };
 
@@ -334,6 +338,20 @@ enum ocelot_reg {
 	SYS_CM_DATA_RD,
 	SYS_CM_OP,
 	SYS_CM_DATA,
+	PTP_PIN_CFG = PTP << TARGET_OFFSET,
+	PTP_PIN_TOD_SEC_MSB,
+	PTP_PIN_TOD_SEC_LSB,
+	PTP_PIN_TOD_NSEC,
+	PTP_CFG_MISC,
+	PTP_CLK_CFG_ADJ_CFG,
+	PTP_CLK_CFG_ADJ_FREQ,
+	VCAP_UPDATE_CTRL = VCAP << TARGET_OFFSET,
+	VCAP_UPDATE_CTRL_MV_CFG,
+	VCAP_UPDATE_CTRL_ENTRY_DATA,
+	VCAP_UPDATE_CTRL_MASK_DATA,
+	VCAP_UPDATE_CTRL_ACTION_DATA,
+	VCAP_UPDATE_CTRL_COUNTER_DATA,
+	VCAP_CACHE_DATA_TYPE,
 };
 
 enum ocelot_regfield {
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index ca3ea2fbfcd0..ba7c93c4318a 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -182,12 +182,15 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 	struct {
 		enum ocelot_target id;
 		char *name;
+		u8 optional:1;
 	} res[] = {
-		{ SYS, "sys" },
-		{ REW, "rew" },
-		{ QSYS, "qsys" },
-		{ ANA, "ana" },
-		{ QS, "qs" },
+		{ SYS, "sys", 0 },
+		{ REW, "rew", 0 },
+		{ QSYS, "qsys", 0 },
+		{ ANA, "ana", 0 },
+		{ QS, "qs", 0 },
+		{ PTP, "ptp", 1 },
+		{ VCAP, "vcap", 1 },
 	};
 
 	if (!np && !pdev->dev.platform_data)
@@ -204,8 +207,14 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 		struct regmap *target;
 
 		target = ocelot_io_platform_init(ocelot, pdev, res[i].name);
-		if (IS_ERR(target))
+		if (IS_ERR(target)) {
+			if (res[i].optional) {
+				ocelot->targets[res[i].id] = NULL;
+				continue;
+			}
+
 			return PTR_ERR(target);
+		}
 
 		ocelot->targets[res[i].id] = target;
 	}
diff --git a/drivers/net/ethernet/mscc/ocelot_ptp.h b/drivers/net/ethernet/mscc/ocelot_ptp.h
new file mode 100644
index 000000000000..9ede14a12573
--- /dev/null
+++ b/drivers/net/ethernet/mscc/ocelot_ptp.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Microsemi Ocelot Switch driver
+ *
+ * License: Dual MIT/GPL
+ * Copyright (c) 2017 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_PTP_H_
+#define _MSCC_OCELOT_PTP_H_
+
+#define PTP_PIN_CFG_RSZ			0x20
+#define PTP_PIN_TOD_SEC_MSB_RSZ		PTP_PIN_CFG_RSZ
+#define PTP_PIN_TOD_SEC_LSB_RSZ		PTP_PIN_CFG_RSZ
+#define PTP_PIN_TOD_NSEC_RSZ		PTP_PIN_CFG_RSZ
+
+#define PTP_PIN_CFG_DOM			BIT(0)
+#define PTP_PIN_CFG_SYNC		BIT(2)
+#define PTP_PIN_CFG_ACTION(x)		((x) << 3)
+#define PTP_PIN_CFG_ACTION_MASK		PTP_PIN_CFG_ACTION(0x7)
+
+enum {
+	PTP_PIN_ACTION_IDLE = 0,
+	PTP_PIN_ACTION_LOAD,
+	PTP_PIN_ACTION_SAVE,
+	PTP_PIN_ACTION_CLOCK,
+	PTP_PIN_ACTION_DELTA,
+	PTP_PIN_ACTION_NOSYNC,
+	PTP_PIN_ACTION_SYNC,
+};
+
+#define PTP_CFG_MISC_PTP_EN		BIT(2)
+
+#define PSEC_PER_SEC			1000000000000LL
+
+#define PTP_CFG_CLK_ADJ_CFG_ENA		BIT(0)
+#define PTP_CFG_CLK_ADJ_CFG_DIR		BIT(1)
+
+#define PTP_CFG_CLK_ADJ_FREQ_NS		BIT(30)
+
+#endif
diff --git a/drivers/net/ethernet/mscc/ocelot_regs.c b/drivers/net/ethernet/mscc/ocelot_regs.c
index 9271af18b93b..bbba0f7a6962 100644
--- a/drivers/net/ethernet/mscc/ocelot_regs.c
+++ b/drivers/net/ethernet/mscc/ocelot_regs.c
@@ -224,12 +224,34 @@ static const u32 ocelot_sys_regmap[] = {
 	REG(SYS_PTP_CFG,                   0x0006c4),
 };
 
+static const u32 ocelot_ptp_regmap[] = {
+	REG(PTP_PIN_CFG,                   0x000000),
+	REG(PTP_PIN_TOD_SEC_MSB,           0x000004),
+	REG(PTP_PIN_TOD_SEC_LSB,           0x000008),
+	REG(PTP_PIN_TOD_NSEC,              0x00000c),
+	REG(PTP_CFG_MISC,                  0x0000a0),
+	REG(PTP_CLK_CFG_ADJ_CFG,           0x0000a4),
+	REG(PTP_CLK_CFG_ADJ_FREQ,          0x0000a8),
+};
+
+static const u32 ocelot_vcap_regmap[] = {
+	REG(VCAP_UPDATE_CTRL,              0x000000),
+	REG(VCAP_UPDATE_CTRL_MV_CFG,       0x000004),
+	REG(VCAP_UPDATE_CTRL_ENTRY_DATA,   0x000008),
+	REG(VCAP_UPDATE_CTRL_MASK_DATA,    0x000108),
+	REG(VCAP_UPDATE_CTRL_ACTION_DATA,  0x000208),
+	REG(VCAP_UPDATE_CTRL_COUNTER_DATA, 0x000308),
+	REG(VCAP_CACHE_DATA_TYPE,          0x000388),
+};
+
 static const u32 *ocelot_regmap[] = {
 	[ANA] = ocelot_ana_regmap,
 	[QS] = ocelot_qs_regmap,
 	[QSYS] = ocelot_qsys_regmap,
 	[REW] = ocelot_rew_regmap,
 	[SYS] = ocelot_sys_regmap,
+	[PTP] = ocelot_ptp_regmap,
+	[VCAP] = ocelot_vcap_regmap,
 };
 
 static const struct reg_field ocelot_regfields[] = {
diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.h b/drivers/net/ethernet/mscc/ocelot_vcap.h
new file mode 100644
index 000000000000..836bf0a96a73
--- /dev/null
+++ b/drivers/net/ethernet/mscc/ocelot_vcap.h
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Microsemi Ocelot Switch driver
+ *
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_VCAP_H_
+#define _MSCC_OCELOT_VCAP_H_
+
+/* Three PTP entries per port:
+ * - PTP ver Ethernet
+ * - PTP dst port 319
+ * - PTP dst port 320
+ */
+#define VCAP_IS2_N_PTP_ENTRIES			3
+
+/* VCAP */
+
+#define VCAP_UPDATE_CTRL_UPDATE_SHOT		BIT(2)
+#define VCAP_UPDATE_CTRL_UPDATE_ADDR(x)		(((x) & 0x3) << 16)
+#define VCAP_UPDATE_CTRL_UPDATE_COUNTER_DIS	BIT(19)
+#define VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS	BIT(20)
+#define VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS	BIT(21)
+#define VCAP_UPDATE_CTRL_UPDATE_CMD(x)		(((x) & 0x3) << 22)
+
+enum vcap_cmds {
+	VCAP_CMD_WRITE = 0,
+	VCAP_CMD_READ,
+	VCAP_CMD_MOVE_UP,
+	VCAP_CMD_MOVE_DOWN,
+	VCAP_CMD_INIT,
+};
+
+enum vcap_selector {
+	VCAP_SEL_COUNTER = BIT(0),
+	VCAP_SEL_ACTION  = BIT(1),
+	VCAP_SEL_ENTRY   = BIT(2),
+};
+
+struct vcap_data {
+	u32 entry[12];
+	u32 mask[12];
+	u32 action[4];
+	u32 counter;
+	u32 type_group;
+};
+
+/* VCAP IS2 lookup */
+
+#define VCAP_IS2_LKP_TYPE			0
+#define VCAP_IS2_LKP_INGRESS_PORT_MASK		13
+#define VCAP_IS2_LKP_MC				27
+#define VCAP_IS2_LKP_BC				28
+#define VCAP_IS2_LKP_VLAN			29
+#define VCAP_IS2_LKP_VID			30
+#define VCAP_IS2_LKP_IP4			46
+#define VCAP_IS2_LKP_DST_IP4			59
+#define VCAP_IS2_LKP_SRC_IP4			91
+#define VCAP_IS2_LKP_TCP			124
+#define VCAP_IS2_LKP_DPORT			125
+#define VCAP_IS2_LKP_SPORT			141
+#define VCAP_IS2_LKP_ETYPE			142
+
+/* Masks */
+#define VCAP_IS2_LKP_TYPE_M			0xf
+#define VCAP_IS2_LKP_INGRESS_PORT_MASK_M	0xfff
+#define VCAP_IS2_LKP_VID_M			0xfff
+#define VCAP_IS2_LKP_DST_IP4_M			0xffffffff
+#define VCAP_IS2_LKP_SRC_IP4_M			0xffffffff
+#define VCAP_IS2_LKP_DPORT_M			0xffff
+#define VCAP_IS2_LKP_SPORT_M			0xffff
+#define VCAP_IS2_LKP_ETYPE_M			0xffff
+
+/* IS2 lookup types */
+#define VCAP_IS2_LKP_TYPE_MAC_ETYPE		0
+#define VCAP_IS2_LKP_TYPE_TCP_UDP		4
+
+/* VCAP IS2 action */
+
+#define VCAP_IS2_ACT_MASK_MODE			5
+#define VCAP_IS2_ACT_PORT_MASK			20
+#define VCAP_IS2_ACT_REW_OP			31
+
+/* Masks */
+#define VCAP_IS2_ACT_PORT_MASK_M		0x7ff
+#define VCAP_IS2_ACT_REW_OP_M			0x1ff
+
+/* IS2 mask modes */
+#define VCAP_IS2_ACT_MASK_MODE_NOOP		0x0
+#define VCAP_IS2_ACT_MASK_MODE_FILTER		0x1
+
+/* IS2 REW OPS */
+#define VCAP_IS2_ACT_REW_OP_NOOP		0x0
+#define VCAP_IS2_ACT_REW_OP_PTP_ONE		0x2
+#define VCAP_IS2_ACT_REW_OP_PTP_TWO		0x3
+
+/* In addition to VCAP_IS2_REW_OP_PTP_ONE */
+#define VCAP_IS2_ACT_REW_OP_SUB_DELAY_1		(0x1 << 3)
+#define VCAP_IS2_ACT_REW_OP_SUB_DELAY_2		(0x2 << 3)
+#define VCAP_IS2_ACT_REW_OP_ADD_DELAY		(0x1 << 5)
+#define VCAP_IS2_ACT_REW_OP_ADD_SUB		(0x1 << 7)
+
+#endif
-- 
2.20.1


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

* [PATCH net-next 6/8] net: mscc: improve the frame header parsing readability
  2019-01-17 10:02 [PATCH net-next 0/8] net: mscc: PTP offloading support Antoine Tenart
                   ` (4 preceding siblings ...)
  2019-01-17 10:02 ` [PATCH net-next 5/8] net: mscc: describe the VCAP and PTP register ranges Antoine Tenart
@ 2019-01-17 10:02 ` Antoine Tenart
  2019-01-17 10:02 ` [PATCH net-next 7/8] net: mscc: remove the frame_info cpuq member Antoine Tenart
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Antoine Tenart @ 2019-01-17 10:02 UTC (permalink / raw)
  To: davem, alexandre.belloni, UNGLinuxDriver, ralf, paul.burton, jhogan
  Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
	quentin.schulz, allan.nielsen

This cosmetic patch improves the frame header parsing readability by
introducing a new macro to access and mask its fields.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 drivers/net/ethernet/mscc/ocelot_board.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index ba7c93c4318a..b85982e5717a 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -16,24 +16,26 @@
 
 #include "ocelot.h"
 
-static int ocelot_parse_ifh(u32 *ifh, struct frame_info *info)
+#define IFH_EXTRACT_BITFIELD64(x, o, w) (((x) >> (o)) & GENMASK_ULL((w) - 1, 0))
+
+static int ocelot_parse_ifh(u32 *_ifh, struct frame_info *info)
 {
-	int i;
 	u8 llen, wlen;
+	u64 ifh[2];
+
+	ifh[0] = be64_to_cpu(((__force __be64 *)_ifh)[0]);
+	ifh[1] = be64_to_cpu(((__force __be64 *)_ifh)[1]);
 
-	/* The IFH is in network order, switch to CPU order */
-	for (i = 0; i < IFH_LEN; i++)
-		ifh[i] = ntohl((__force __be32)ifh[i]);
+	wlen = IFH_EXTRACT_BITFIELD64(ifh[0], 7,  8);
+	llen = IFH_EXTRACT_BITFIELD64(ifh[0], 15,  6);
 
-	wlen = (ifh[1] >> 7) & 0xff;
-	llen = (ifh[1] >> 15) & 0x3f;
 	info->len = OCELOT_BUFFER_CELL_SZ * wlen + llen - 80;
 
-	info->port = (ifh[2] & GENMASK(14, 11)) >> 11;
+	info->port = IFH_EXTRACT_BITFIELD64(ifh[1], 43, 4);
 
-	info->cpuq = (ifh[3] & GENMASK(27, 20)) >> 20;
-	info->tag_type = (ifh[3] & BIT(16)) >> 16;
-	info->vid = ifh[3] & GENMASK(11, 0);
+	info->cpuq = IFH_EXTRACT_BITFIELD64(ifh[1], 20, 8);
+	info->tag_type = IFH_EXTRACT_BITFIELD64(ifh[1], 16,  1);
+	info->vid = IFH_EXTRACT_BITFIELD64(ifh[1], 0,  12);
 
 	return 0;
 }
-- 
2.20.1


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

* [PATCH net-next 7/8] net: mscc: remove the frame_info cpuq member
  2019-01-17 10:02 [PATCH net-next 0/8] net: mscc: PTP offloading support Antoine Tenart
                   ` (5 preceding siblings ...)
  2019-01-17 10:02 ` [PATCH net-next 6/8] net: mscc: improve the frame header parsing readability Antoine Tenart
@ 2019-01-17 10:02 ` Antoine Tenart
  2019-01-17 10:02 ` [PATCH net-next 8/8] net: mscc: PTP offloading support Antoine Tenart
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Antoine Tenart @ 2019-01-17 10:02 UTC (permalink / raw)
  To: davem, alexandre.belloni, UNGLinuxDriver, ralf, paul.burton, jhogan
  Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
	quentin.schulz, allan.nielsen

In struct frame_info, the cpuq member is never used. This cosmetic patch
removes it from the structure, and from the parsing of the frame header
as it's only set but never used.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 drivers/net/ethernet/mscc/ocelot.h       | 1 -
 drivers/net/ethernet/mscc/ocelot_board.c | 1 -
 2 files changed, 2 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index 4b1b180884ad..994ba953d60e 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -45,7 +45,6 @@ struct frame_info {
 	u32 len;
 	u16 port;
 	u16 vid;
-	u8 cpuq;
 	u8 tag_type;
 };
 
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index b85982e5717a..e0a3b6f70e8f 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -33,7 +33,6 @@ static int ocelot_parse_ifh(u32 *_ifh, struct frame_info *info)
 
 	info->port = IFH_EXTRACT_BITFIELD64(ifh[1], 43, 4);
 
-	info->cpuq = IFH_EXTRACT_BITFIELD64(ifh[1], 20, 8);
 	info->tag_type = IFH_EXTRACT_BITFIELD64(ifh[1], 16,  1);
 	info->vid = IFH_EXTRACT_BITFIELD64(ifh[1], 0,  12);
 
-- 
2.20.1


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

* [PATCH net-next 8/8] net: mscc: PTP offloading support
  2019-01-17 10:02 [PATCH net-next 0/8] net: mscc: PTP offloading support Antoine Tenart
                   ` (6 preceding siblings ...)
  2019-01-17 10:02 ` [PATCH net-next 7/8] net: mscc: remove the frame_info cpuq member Antoine Tenart
@ 2019-01-17 10:02 ` Antoine Tenart
  2019-01-18  2:23   ` Richard Cochran
  2019-01-18  2:13 ` [PATCH net-next 0/8] " Richard Cochran
  2019-01-18  5:07 ` Florian Fainelli
  9 siblings, 1 reply; 16+ messages in thread
From: Antoine Tenart @ 2019-01-17 10:02 UTC (permalink / raw)
  To: davem, alexandre.belloni, UNGLinuxDriver, ralf, paul.burton, jhogan
  Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
	quentin.schulz, allan.nielsen

This patch adds support for offloading PTP timestamping to the Ocelot
switch for both 1-step and 2-step modes.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 drivers/net/ethernet/mscc/ocelot.c       | 509 ++++++++++++++++++++++-
 drivers/net/ethernet/mscc/ocelot.h       |  36 ++
 drivers/net/ethernet/mscc/ocelot_board.c | 106 ++++-
 3 files changed, 643 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 215a45374d7b..ed84c18adcfe 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/phy.h>
+#include <linux/ptp_clock_kernel.h>
 #include <linux/skbuff.h>
 #include <linux/iopoll.h>
 #include <net/arp.h>
@@ -530,7 +531,7 @@ static int ocelot_port_stop(struct net_device *dev)
  */
 static int ocelot_gen_ifh(u32 *ifh, struct frame_info *info)
 {
-	ifh[0] = IFH_INJ_BYPASS;
+	ifh[0] = IFH_INJ_BYPASS | ((0x1ff & info->rew_op) << 21);
 	ifh[1] = (0xf00 & info->port) >> 8;
 	ifh[2] = (0xff & info->port) << 24;
 	ifh[3] = (info->tag_type << 16) | info->vid;
@@ -542,6 +543,7 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ocelot_port *port = netdev_priv(dev);
 	struct ocelot *ocelot = port->ocelot;
+	struct skb_shared_info *shinfo = skb_shinfo(skb);
 	u32 val, ifh[IFH_LEN];
 	struct frame_info info = {};
 	u8 grp = 0; /* Send everything on CPU group 0 */
@@ -558,6 +560,14 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
 	info.port = BIT(port->chip_port);
 	info.tag_type = IFH_TAG_TYPE_C;
 	info.vid = skb_vlan_tag_get(skb);
+
+	/* Check if timestamping is needed */
+	if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP) {
+		info.rew_op = port->ptp_cmd;
+		if (port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP)
+			info.rew_op |= (port->ts_id  % 4) << 3;
+	}
+
 	ocelot_gen_ifh(ifh, &info);
 
 	for (i = 0; i < IFH_LEN; i++)
@@ -588,11 +598,44 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
-	dev_kfree_skb_any(skb);
+
+	if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP &&
+	    port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
+		struct ocelot_skb *oskb =
+			devm_kzalloc(ocelot->dev, sizeof(struct ocelot_skb),
+				     GFP_KERNEL);
+
+		oskb->skb = skb;
+		oskb->id = port->ts_id % 4;
+		port->ts_id++;
+
+		list_add_tail(&oskb->head, &port->skbs);
+	} else {
+		dev_kfree_skb_any(skb);
+	}
 
 	return NETDEV_TX_OK;
 }
 
+void ocelot_get_hwtimestamp(struct ocelot *ocelot, struct timespec64 *ts)
+{
+	/* Read current PTP time to get seconds */
+	u32 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+
+	val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+	val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
+	ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+	ts->tv_sec = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
+
+	/* Read packet HW timestamp from FIFO */
+	val = ocelot_read(ocelot, SYS_PTP_TXSTAMP);
+	ts->tv_nsec = SYS_PTP_TXSTAMP_PTP_TXSTAMP(val);
+
+	/* Sec has incremented since the ts was registered */
+	if ((ts->tv_sec & 0x1) != !!(val & SYS_PTP_TXSTAMP_PTP_TXSTAMP_SEC))
+		ts->tv_sec--;
+}
+
 static void ocelot_mact_mc_reset(struct ocelot_port *port)
 {
 	struct ocelot *ocelot = port->ocelot;
@@ -915,6 +958,262 @@ static int ocelot_set_features(struct net_device *dev,
 	return 0;
 }
 
+static void ocelot_vcap_is2_cmd(struct ocelot *ocelot, u8 addr,
+				enum vcap_cmds cmd, enum vcap_selector sel)
+{
+	u32 val = VCAP_UPDATE_CTRL_UPDATE_CMD(cmd) |
+		  VCAP_UPDATE_CTRL_UPDATE_ADDR(addr) |
+		  VCAP_UPDATE_CTRL_UPDATE_SHOT;
+
+	/* Select the destination/origin */
+	if (!(sel & VCAP_SEL_COUNTER))
+		val |= VCAP_UPDATE_CTRL_UPDATE_COUNTER_DIS;
+	if (!(sel & VCAP_SEL_ACTION))
+		val |= VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS;
+	if (!(sel & VCAP_SEL_ENTRY))
+		val |= VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS;
+
+	ocelot_write(ocelot, val, VCAP_UPDATE_CTRL);
+
+	/* wait for the command to complete */
+	do {
+		val = ocelot_read(ocelot, VCAP_UPDATE_CTRL);
+	} while (val & VCAP_UPDATE_CTRL_UPDATE_SHOT);
+}
+
+static void ocelot_vcap_entry_to_cache(struct ocelot *ocelot,
+				       struct vcap_data *data)
+{
+	int i;
+
+	for (i = 0; i < 12; i++) {
+		ocelot_write(ocelot, data->entry[i],
+			     VCAP_UPDATE_CTRL_ENTRY_DATA + i * sizeof(u32));
+		ocelot_write(ocelot, ~data->mask[i],
+			     VCAP_UPDATE_CTRL_MASK_DATA + i * sizeof(u32));
+	}
+
+	ocelot_write(ocelot, data->type_group, VCAP_CACHE_DATA_TYPE);
+}
+
+static void ocelot_vcap_action_to_cache(struct ocelot *ocelot,
+					struct vcap_data *data)
+{
+	int i;
+
+	/* Encode the type */
+	data->action[0] &= ~BIT(0);
+
+	for (i = 0; i < 4; i++)
+		ocelot_write(ocelot, data->action[i],
+			     VCAP_UPDATE_CTRL_ACTION_DATA + i * sizeof(u32));
+
+	ocelot_write(ocelot, data->counter, VCAP_UPDATE_CTRL_COUNTER_DATA);
+}
+
+static void ocelot_vcap_is2_init(struct ocelot *ocelot)
+{
+	struct vcap_data data;
+	int port;
+
+	mutex_init(&ocelot->ptp_lock);
+
+	memset(&data, 0, sizeof(data));
+
+	/* Initialize entries */
+	ocelot_vcap_entry_to_cache(ocelot, &data);
+	ocelot_write(ocelot, 64 /* entry count */, VCAP_UPDATE_CTRL_MV_CFG);
+	ocelot_vcap_is2_cmd(ocelot, 0, VCAP_CMD_INIT, VCAP_SEL_ENTRY);
+
+	/* Initialize actions */
+	ocelot_vcap_action_to_cache(ocelot, &data);
+	ocelot_write(ocelot, 64 + ocelot->num_phys_ports + 2 /* action count */,
+		     VCAP_UPDATE_CTRL_MV_CFG);
+	ocelot_vcap_is2_cmd(ocelot, 0, VCAP_CMD_INIT,
+			    VCAP_SEL_ACTION | VCAP_SEL_COUNTER);
+
+	/* Enable the IS2 engine */
+	for (port = 0; port < ocelot->num_phys_ports; port++) {
+		ocelot_write_gix(ocelot, ANA_PORT_VCAP_S2_CFG_S2_ENA |
+					 ANA_PORT_VCAP_S2_CFG_S2_IP6_CFG(0xa),
+				 ANA_PORT_VCAP_S2_CFG, port);
+		ocelot_write_gix(ocelot, 0, ANA_PORT_PTP_CFG, port);
+	}
+}
+
+static void ocelot_vcap_is2_set(struct ocelot *ocelot, u8 addr,
+				struct vcap_data *data)
+{
+	ocelot_vcap_entry_to_cache(ocelot, data);
+	ocelot_vcap_action_to_cache(ocelot, data);
+	ocelot_vcap_is2_cmd(ocelot, addr, VCAP_CMD_WRITE,
+			    VCAP_SEL_ENTRY | VCAP_SEL_ACTION | VCAP_SEL_COUNTER);
+}
+
+static inline void ocelot_set_bits(u32 *data, u32 offset, u32 mask, u32 val)
+{
+	u32 word_off = offset / 32, bit_off = offset % 32;
+
+	data[word_off] &= ~(mask << bit_off);
+	data[word_off] |= val << bit_off;
+	if (get_bitmask_order(mask) > (32 - bit_off)) {
+		data[word_off + 1] &= ~(mask >> (32 - bit_off));
+		data[word_off + 1] |= val >> (32 - bit_off);
+	}
+}
+
+static void ocelot_vcap_is2_set_lookup(struct vcap_data *data, u32 offset,
+				       u32 mask, u32 val)
+{
+	ocelot_set_bits(data->entry, offset, mask, val);
+	ocelot_set_bits(data->mask, offset, mask, mask);
+}
+
+static void ocelot_vcap_is2_set_action(struct vcap_data *data, u32 offset,
+				       u32 mask, u32 val)
+{
+	ocelot_set_bits(data->action, offset, mask, val);
+}
+
+static int ocelot_hwstamp_get(struct ocelot_port *port, struct ifreq *ifr)
+{
+	struct ocelot *ocelot = port->ocelot;
+
+	return copy_to_user(ifr->ifr_data, &ocelot->hwtstamp_config,
+			    sizeof(ocelot->hwtstamp_config)) ? -EFAULT : 0;
+}
+
+static int ocelot_hwstamp_set(struct ocelot_port *port, struct ifreq *ifr)
+{
+	struct ocelot *ocelot = port->ocelot;
+	struct hwtstamp_config cfg;
+	struct vcap_data data;
+	int base = port->chip_port * VCAP_IS2_N_PTP_ENTRIES;
+	u32 ptp_op = VCAP_IS2_ACT_REW_OP_PTP_ONE;
+
+	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+		return -EFAULT;
+
+	/* reserved for future extensions */
+	if (cfg.flags)
+		return -EINVAL;
+
+	/* Tx type sanity check */
+	switch (cfg.tx_type) {
+	case HWTSTAMP_TX_ON:
+		port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
+		break;
+	case HWTSTAMP_TX_ONESTEP_SYNC:
+		/* IFH_REW_OP_ONE_STEP_PTP updates the correctional field, we
+		 * need to update the origin time.
+		 */
+		port->ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
+		break;
+	case HWTSTAMP_TX_OFF:
+		port->ptp_cmd = 0;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	mutex_lock(&ocelot->ptp_lock);
+
+	/* Prepare the VCAP PTP entry */
+	memset(&data, 0, sizeof(data));
+
+	switch (cfg.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		ptp_op = VCAP_IS2_ACT_REW_OP_NOOP;
+		break;
+	case HWTSTAMP_FILTER_ALL:
+	case HWTSTAMP_FILTER_SOME:
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_NTP_ALL:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+		break;
+	default:
+		mutex_unlock(&ocelot->ptp_lock);
+		return -ERANGE;
+	}
+
+	/* Set the PTP action */
+	ocelot_vcap_is2_set_action(&data, VCAP_IS2_ACT_REW_OP,
+				   VCAP_IS2_ACT_REW_OP_M, ptp_op);
+
+	data.type_group = 2;
+
+	/* Port mask */
+	ocelot_vcap_is2_set_lookup(&data, VCAP_IS2_LKP_INGRESS_PORT_MASK,
+				   VCAP_IS2_LKP_INGRESS_PORT_MASK_M, 0x7ff);
+
+	/* Commit the PTP VCAP entries:
+	 *
+	 * - One entry for PTP over Ethernet (etype 0x88f7).
+	 * - One entry for PTP over IPv4/v6 UDP dst port 319.
+	 * - One entry for PTP over IPv4/v6 UDP dst port 320.
+	 */
+
+	/* PTP over Ethernet */
+	ocelot_vcap_is2_set_lookup(&data, VCAP_IS2_LKP_TYPE,
+				   VCAP_IS2_LKP_TYPE_M,
+				   VCAP_IS2_LKP_TYPE_MAC_ETYPE);
+	ocelot_vcap_is2_set_lookup(&data, VCAP_IS2_LKP_ETYPE,
+				   VCAP_IS2_LKP_ETYPE_M, 0x88f7);
+	ocelot_vcap_is2_set(ocelot, base++, &data);
+
+	/* PTP over IPv4/v6 UDP dst port 319 */
+	ocelot_vcap_is2_set_lookup(&data, VCAP_IS2_LKP_TYPE,
+				   VCAP_IS2_LKP_TYPE_M,
+				   VCAP_IS2_LKP_TYPE_TCP_UDP);
+	ocelot_vcap_is2_set_lookup(&data, VCAP_IS2_LKP_DPORT,
+				   VCAP_IS2_LKP_DPORT_M, 319);
+	ocelot_vcap_is2_set(ocelot, base++, &data);
+
+	/* PTP over IPv4/v6 UDP dst port 320 */
+	ocelot_vcap_is2_set_lookup(&data, VCAP_IS2_LKP_TYPE,
+				   VCAP_IS2_LKP_TYPE_M,
+				   VCAP_IS2_LKP_TYPE_TCP_UDP);
+	ocelot_vcap_is2_set_lookup(&data, VCAP_IS2_LKP_DPORT,
+				   VCAP_IS2_LKP_DPORT_M, 320);
+	ocelot_vcap_is2_set(ocelot, base++, &data);
+
+	/* Commit back the result & save it */
+	memcpy(&ocelot->hwtstamp_config, &cfg, sizeof(cfg));
+	mutex_unlock(&ocelot->ptp_lock);
+
+	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
+
+static int ocelot_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	struct ocelot_port *port = netdev_priv(dev);
+	struct ocelot *ocelot = port->ocelot;
+
+	/* The function is only used for PTP operations for now */
+	if (!ocelot->ptp)
+		return -EOPNOTSUPP;
+
+	switch (cmd) {
+	case SIOCSHWTSTAMP:
+		return ocelot_hwstamp_set(port, ifr);
+	case SIOCGHWTSTAMP:
+		return ocelot_hwstamp_get(port, ifr);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static const struct net_device_ops ocelot_port_netdev_ops = {
 	.ndo_open			= ocelot_port_open,
 	.ndo_stop			= ocelot_port_stop,
@@ -929,6 +1228,7 @@ static const struct net_device_ops ocelot_port_netdev_ops = {
 	.ndo_vlan_rx_add_vid		= ocelot_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid		= ocelot_vlan_rx_kill_vid,
 	.ndo_set_features		= ocelot_set_features,
+	.ndo_do_ioctl			= ocelot_ioctl,
 };
 
 static void ocelot_get_strings(struct net_device *netdev, u32 sset, u8 *data)
@@ -1004,12 +1304,42 @@ static int ocelot_get_sset_count(struct net_device *dev, int sset)
 	return ocelot->num_stats;
 }
 
+static int ocelot_get_ts_info(struct net_device *dev,
+			      struct ethtool_ts_info *info)
+{
+	struct ocelot_port *ocelot_port = netdev_priv(dev);
+	struct ocelot *ocelot = ocelot_port->ocelot;
+	int ret;
+
+	if (!ocelot->ptp)
+		return -EOPNOTSUPP;
+
+	ret = ethtool_op_get_ts_info(dev, info);
+	if (ret)
+		return ret;
+
+	info->phc_index = ocelot->ptp_clock ?
+			  ptp_clock_index(ocelot->ptp_clock) : -1;
+	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;
+	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
+			 BIT(HWTSTAMP_TX_ONESTEP_SYNC);
+	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
+
+	return 0;
+}
+
 static const struct ethtool_ops ocelot_ethtool_ops = {
 	.get_strings		= ocelot_get_strings,
 	.get_ethtool_stats	= ocelot_get_ethtool_stats,
 	.get_sset_count		= ocelot_get_sset_count,
 	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
 	.set_link_ksettings	= phy_ethtool_set_link_ksettings,
+	.get_ts_info		= ocelot_get_ts_info,
 };
 
 static int ocelot_port_attr_get(struct net_device *dev,
@@ -1616,6 +1946,165 @@ struct notifier_block ocelot_switchdev_blocking_nb __read_mostly = {
 };
 EXPORT_SYMBOL(ocelot_switchdev_blocking_nb);
 
+int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
+{
+	struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
+	u32 val;
+	time64_t s;
+	s64 ns;
+
+	val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+	val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+	val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
+	ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+
+	s = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN);
+	s += ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
+	ns = ocelot_read_rix(ocelot, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
+
+	/* Deal with negative values */
+	if (ns >= 0x3ffffff0 && ns <= 0x3fffffff) {
+		s--;
+		ns &= 0xf;
+		ns += 999999984;
+	}
+
+	set_normalized_timespec64(ts, s, ns);
+	return 0;
+}
+
+static int ocelot_ptp_settime64(struct ptp_clock_info *ptp,
+				const struct timespec64 *ts)
+{
+	struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
+	u32 val;
+
+	val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+	val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+	val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
+
+	ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+
+	ocelot_write_rix(ocelot, lower_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_LSB,
+			 TOD_ACC_PIN);
+	ocelot_write_rix(ocelot, upper_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_MSB,
+			 TOD_ACC_PIN);
+	ocelot_write_rix(ocelot, ts->tv_nsec, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
+
+	val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+	val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+	val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_LOAD);
+
+	ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+
+	return 0;
+}
+
+static int ocelot_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	if (delta > -(NSEC_PER_SEC / 2) && delta < (NSEC_PER_SEC / 2)) {
+		struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
+		u32 val;
+
+		val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+		val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+		val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
+
+		ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+
+		ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
+		ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN);
+		ocelot_write_rix(ocelot, delta, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
+
+		val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+		val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+		val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_DELTA);
+
+		ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+	} else {
+		/* Fall back using ocelot_ptp_settime64 which is not exact. */
+		struct timespec64 ts;
+		u64 now;
+
+		ocelot_ptp_gettime64(ptp, &ts);
+
+		now = ktime_to_ns(timespec64_to_ktime(ts));
+		ts = ns_to_timespec64(now + delta);
+
+		ocelot_ptp_settime64(ptp, &ts);
+	}
+	return 0;
+}
+
+static int ocelot_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+	struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
+	u64 adj = 0;
+	u32 unit = 0, direction = 0;
+
+	if (!ppb)
+		goto disable_adj;
+
+	if (ppb < 0) {
+		direction = PTP_CFG_CLK_ADJ_CFG_DIR;
+		ppb = -ppb;
+	}
+
+	adj = PSEC_PER_SEC;
+	do_div(adj, ppb);
+
+	/* If the adjustment value is too large, use ns instead */
+	if (adj >= (1L << 30)) {
+		unit = PTP_CFG_CLK_ADJ_FREQ_NS;
+		do_div(adj, 1000);
+	}
+
+	/* Still too big */
+	if (adj >= (1L << 30))
+		goto disable_adj;
+
+	ocelot_write(ocelot, unit | adj, PTP_CLK_CFG_ADJ_FREQ);
+	ocelot_write(ocelot, PTP_CFG_CLK_ADJ_CFG_ENA | direction,
+		     PTP_CLK_CFG_ADJ_CFG);
+	return 0;
+
+disable_adj:
+	ocelot_write(ocelot, 0, PTP_CLK_CFG_ADJ_CFG);
+	return 0;
+}
+
+static struct ptp_clock_info ocelot_ptp_clock_info = {
+	.owner		= THIS_MODULE,
+	.name		= "ocelot ptp",
+	.max_adj	= 0x7fffffff,
+	.n_alarm	= 0,
+	.n_ext_ts	= 0,
+	.n_per_out	= 0,
+	.n_pins		= 0,
+	.pps		= 0,
+	.gettime64	= ocelot_ptp_gettime64,
+	.settime64	= ocelot_ptp_settime64,
+	.adjtime	= ocelot_ptp_adjtime,
+	.adjfreq	= ocelot_ptp_adjfreq,
+};
+
+static int ocelot_init_timestamp(struct ocelot *ocelot)
+{
+	ocelot->ptp_info = ocelot_ptp_clock_info;
+
+	ocelot->ptp_clock = ptp_clock_register(&ocelot->ptp_info, ocelot->dev);
+	if (IS_ERR(ocelot->ptp_clock))
+		return PTR_ERR(ocelot->ptp_clock);
+
+	ocelot_write(ocelot, SYS_PTP_CFG_PTP_STAMP_WID(30), SYS_PTP_CFG);
+	ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_LOW);
+	ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_HIGH);
+
+	ocelot_write(ocelot, PTP_CFG_MISC_PTP_EN, PTP_CFG_MISC);
+
+	return 0;
+}
+
 int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 		      void __iomem *regs,
 		      struct phy_device *phy)
@@ -1649,6 +2138,8 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 	ocelot_mact_learn(ocelot, PGID_CPU, dev->dev_addr, ocelot_port->pvid,
 			  ENTRYTYPE_LOCKED);
 
+	INIT_LIST_HEAD(&ocelot_port->skbs);
+
 	err = register_netdev(dev);
 	if (err) {
 		dev_err(ocelot->dev, "register_netdev failed\n");
@@ -1669,7 +2160,7 @@ EXPORT_SYMBOL(ocelot_probe_port);
 int ocelot_init(struct ocelot *ocelot)
 {
 	u32 port;
-	int i, cpu = ocelot->num_phys_ports;
+	int i, ret, cpu = ocelot->num_phys_ports;
 	char queue_name[32];
 
 	ocelot->lags = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
@@ -1796,6 +2287,18 @@ int ocelot_init(struct ocelot *ocelot)
 	INIT_DELAYED_WORK(&ocelot->stats_work, ocelot_check_stats);
 	queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
 			   OCELOT_STATS_CHECK_DELAY);
+
+	if (ocelot->ptp) {
+		ret = ocelot_init_timestamp(ocelot);
+		if (ret) {
+			dev_err(ocelot->dev,
+				"Timestamp initialization failed\n");
+			return ret;
+		}
+
+		ocelot_vcap_is2_init(ocelot);
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL(ocelot_init);
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index 994ba953d60e..ed1583037dc2 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -11,9 +11,11 @@
 #include <linux/bitops.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
+#include <linux/net_tstamp.h>
 #include <linux/phy.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
+#include <linux/ptp_clock_kernel.h>
 #include <linux/regmap.h>
 
 #include "ocelot_ana.h"
@@ -46,6 +48,8 @@ struct frame_info {
 	u16 port;
 	u16 vid;
 	u8 tag_type;
+	u16 rew_op;
+	u32 timestamp;	/* rew_val */
 };
 
 #define IFH_INJ_BYPASS	BIT(31)
@@ -54,6 +58,12 @@ struct frame_info {
 #define IFH_TAG_TYPE_C 0
 #define IFH_TAG_TYPE_S 1
 
+#define IFH_REW_OP_NOOP			0x0
+#define IFH_REW_OP_DSCP			0x1
+#define IFH_REW_OP_ONE_STEP_PTP		0x2
+#define IFH_REW_OP_TWO_STEP_PTP		0x3
+#define IFH_REW_OP_ORIGIN_PTP		0x5
+
 #define OCELOT_SPEED_2500 0
 #define OCELOT_SPEED_1000 1
 #define OCELOT_SPEED_100  2
@@ -401,6 +411,13 @@ enum ocelot_regfield {
 	REGFIELD_MAX
 };
 
+enum ocelot_clk_pins {
+	ALT_PPS_PIN	= 1,
+	EXT_CLK_PIN,
+	ALT_LDST_PIN,
+	TOD_ACC_PIN
+};
+
 struct ocelot_multicast {
 	struct list_head list;
 	unsigned char addr[ETH_ALEN];
@@ -450,6 +467,12 @@ struct ocelot {
 	u64 *stats;
 	struct delayed_work stats_work;
 	struct workqueue_struct *stats_queue;
+
+	u8 ptp:1;
+	struct ptp_clock *ptp_clock;
+	struct ptp_clock_info ptp_info;
+	struct hwtstamp_config hwtstamp_config;
+	struct mutex ptp_lock;
 };
 
 struct ocelot_port {
@@ -475,6 +498,16 @@ struct ocelot_port {
 
 	phy_interface_t phy_mode;
 	struct phy *serdes;
+
+	u8 ptp_cmd;
+	struct list_head skbs;
+	u8 ts_id;
+};
+
+struct ocelot_skb {
+	struct list_head head;
+	struct sk_buff *skb;
+	u8 id;
 };
 
 u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 offset);
@@ -518,4 +551,7 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 extern struct notifier_block ocelot_netdevice_nb;
 extern struct notifier_block ocelot_switchdev_blocking_nb;
 
+int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts);
+void ocelot_get_hwtimestamp(struct ocelot *ocelot, struct timespec64 *ts);
+
 #endif
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index e0a3b6f70e8f..d85920c05269 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -31,6 +31,8 @@ static int ocelot_parse_ifh(u32 *_ifh, struct frame_info *info)
 
 	info->len = OCELOT_BUFFER_CELL_SZ * wlen + llen - 80;
 
+	info->timestamp = IFH_EXTRACT_BITFIELD64(ifh[0], 21, 32);
+
 	info->port = IFH_EXTRACT_BITFIELD64(ifh[1], 43, 4);
 
 	info->tag_type = IFH_EXTRACT_BITFIELD64(ifh[1], 16,  1);
@@ -98,7 +100,11 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
 		int sz, len, buf_len;
 		u32 ifh[4];
 		u32 val;
-		struct frame_info info;
+		struct frame_info info = {};
+		struct timespec64 ts;
+		struct skb_shared_hwtstamps *shhwtstamps;
+		u64 tod_in_ns;
+		u64 full_ts_in_ns;
 
 		for (i = 0; i < IFH_LEN; i++) {
 			err = ocelot_rx_frame_word(ocelot, grp, true, &ifh[i]);
@@ -145,6 +151,22 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
 			break;
 		}
 
+		if (ocelot->ptp) {
+			ocelot_ptp_gettime64(&ocelot->ptp_info, &ts);
+
+			tod_in_ns = ktime_set(ts.tv_sec, ts.tv_nsec);
+			if ((tod_in_ns & 0xffffffff) < info.timestamp)
+				full_ts_in_ns = (((tod_in_ns >> 32) - 1) << 32) |
+						info.timestamp;
+			else
+				full_ts_in_ns = (tod_in_ns & GENMASK_ULL(63, 32)) |
+						info.timestamp;
+
+			shhwtstamps = skb_hwtstamps(skb);
+			memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
+			shhwtstamps->hwtstamp = full_ts_in_ns;
+		}
+
 		/* Everything we see on an interface that is in the HW bridge
 		 * has already been forwarded.
 		 */
@@ -164,6 +186,65 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t ocelot_ptp_rdy_irq_handler(int irq, void *arg)
+{
+	struct ocelot *ocelot = arg;
+
+	do {
+		struct skb_shared_hwtstamps shhwtstamps;
+		struct list_head *pos, *tmp;
+		struct ocelot_skb *entry;
+		struct ocelot_port *port;
+		struct timespec64 ts;
+		struct sk_buff *skb = NULL;
+		u32 val, id, txport;
+
+		val = ocelot_read(ocelot, SYS_PTP_STATUS);
+
+		/* Check if a timestamp can be retrieved */
+		if (!(val & SYS_PTP_STATUS_PTP_MESS_VLD))
+			break;
+
+		WARN_ON(val & SYS_PTP_STATUS_PTP_OVFL);
+
+		/* Retrieve the ts ID and Tx port */
+		id = SYS_PTP_STATUS_PTP_MESS_ID_X(val);
+		txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val);
+
+		/* Retrieve its associated skb */
+		port = ocelot->ports[txport];
+
+		list_for_each_safe(pos, tmp, &port->skbs) {
+			entry = list_entry(pos, struct ocelot_skb, head);
+			if (entry->id != id)
+				continue;
+
+			skb = entry->skb;
+
+			list_del(pos);
+			devm_kfree(ocelot->dev, entry);
+		}
+
+		/* Next ts */
+		ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
+
+		if (unlikely(!skb))
+			continue;
+
+		/* Get the h/w timestamp */
+		ocelot_get_hwtimestamp(ocelot, &ts);
+
+		/* Set the timestamp into the skb */
+		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+		shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
+		skb_tstamp_tx(skb, &shhwtstamps);
+
+		dev_kfree_skb_any(skb);
+	} while (true);
+
+	return IRQ_HANDLED;
+}
+
 static const struct of_device_id mscc_ocelot_match[] = {
 	{ .compatible = "mscc,vsc7514-switch" },
 	{ }
@@ -172,8 +253,8 @@ MODULE_DEVICE_TABLE(of, mscc_ocelot_match);
 
 static int mscc_ocelot_probe(struct platform_device *pdev)
 {
-	int err, irq;
 	unsigned int i;
+	int err, irq_xtr, irq_ptp_rdy;
 	struct device_node *np = pdev->dev.of_node;
 	struct device_node *ports, *portnp;
 	struct ocelot *ocelot;
@@ -232,16 +313,31 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
-	irq = platform_get_irq_byname(pdev, "xtr");
-	if (irq < 0)
+	irq_xtr = platform_get_irq_byname(pdev, "xtr");
+	if (irq_xtr < 0)
 		return -ENODEV;
 
-	err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+	err = devm_request_threaded_irq(&pdev->dev, irq_xtr, NULL,
 					ocelot_xtr_irq_handler, IRQF_ONESHOT,
 					"frame extraction", ocelot);
 	if (err)
 		return err;
 
+
+	irq_ptp_rdy = platform_get_irq_byname(pdev, "ptp_rdy");
+	if (irq_ptp_rdy > 0) {
+		err = devm_request_threaded_irq(&pdev->dev, irq_ptp_rdy, NULL,
+						ocelot_ptp_rdy_irq_handler,
+						IRQF_ONESHOT, "ptp ready",
+						ocelot);
+		if (err)
+			return err;
+	}
+
+	/* Check if we can support PTP */
+	if (irq_ptp_rdy > 0 && ocelot->targets[PTP] && ocelot->targets[VCAP])
+		ocelot->ptp = 1;
+
 	regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
 	regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
 
-- 
2.20.1


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

* Re: [PATCH net-next 0/8] net: mscc: PTP offloading support
  2019-01-17 10:02 [PATCH net-next 0/8] net: mscc: PTP offloading support Antoine Tenart
                   ` (7 preceding siblings ...)
  2019-01-17 10:02 ` [PATCH net-next 8/8] net: mscc: PTP offloading support Antoine Tenart
@ 2019-01-18  2:13 ` Richard Cochran
  2019-01-18  9:09   ` Antoine Tenart
  2019-01-18  5:07 ` Florian Fainelli
  9 siblings, 1 reply; 16+ messages in thread
From: Richard Cochran @ 2019-01-18  2:13 UTC (permalink / raw)
  To: Antoine Tenart
  Cc: davem, alexandre.belloni, UNGLinuxDriver, ralf, paul.burton,
	jhogan, netdev, linux-mips, thomas.petazzoni, quentin.schulz,
	allan.nielsen

On Thu, Jan 17, 2019 at 11:02:04AM +0100, Antoine Tenart wrote:
> This series adds support for the PTP offloading support in the Mscc
> Ocelot Ethernet switch driver. Both PTP 1-step and 2-step modes are
> supported.
> 
> In order to make use of the PTP offloading support, two new register
> banks were described in the Ocelot device tree. The use of those
> registers by the Mscc Ocelot Ethernet switch driver is made optional for
> dt compatibility reasons. For the same reason a new interrupt is
> described, and its use is also made optinal for compatibility reasons.
> All of this is done ine patches 1-5.
> 
> The PTP offloading support itself is added in patch 8.

The subject lines and this description are misleading.  You are not
offloading the Precision Time Protocol.  Instead, this series
implements a normal PHC driver.

Please change the text to avoid the phrase, "PTP offloading".

Thanks,
Richard


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

* Re: [PATCH net-next 8/8] net: mscc: PTP offloading support
  2019-01-17 10:02 ` [PATCH net-next 8/8] net: mscc: PTP offloading support Antoine Tenart
@ 2019-01-18  2:23   ` Richard Cochran
  2019-01-18  9:08     ` Antoine Tenart
  0 siblings, 1 reply; 16+ messages in thread
From: Richard Cochran @ 2019-01-18  2:23 UTC (permalink / raw)
  To: Antoine Tenart
  Cc: davem, alexandre.belloni, UNGLinuxDriver, ralf, paul.burton,
	jhogan, netdev, linux-mips, thomas.petazzoni, quentin.schulz,
	allan.nielsen

On Thu, Jan 17, 2019 at 11:02:12AM +0100, Antoine Tenart wrote:
> This patch adds support for offloading PTP timestamping to the Ocelot
> switch for both 1-step and 2-step modes.

For PTP Hardware Clock drivers, please add the PTP maintainer onto CC.

> +int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
> +{
> +	struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
> +	u32 val;
> +	time64_t s;
> +	s64 ns;
> +
> +	val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
> +	val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
> +	val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
> +	ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
> +
> +	s = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN);
> +	s += ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
> +	ns = ocelot_read_rix(ocelot, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
> +
> +	/* Deal with negative values */
> +	if (ns >= 0x3ffffff0 && ns <= 0x3fffffff) {
> +		s--;
> +		ns &= 0xf;
> +		ns += 999999984;
> +	}
> +
> +	set_normalized_timespec64(ts, s, ns);
> +	return 0;
> +}
> +
> +static int ocelot_ptp_settime64(struct ptp_clock_info *ptp,
> +				const struct timespec64 *ts)
> +{
> +	struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
> +	u32 val;
> +
> +	val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
> +	val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
> +	val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
> +
> +	ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
> +
> +	ocelot_write_rix(ocelot, lower_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_LSB,
> +			 TOD_ACC_PIN);
> +	ocelot_write_rix(ocelot, upper_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_MSB,
> +			 TOD_ACC_PIN);
> +	ocelot_write_rix(ocelot, ts->tv_nsec, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
> +
> +	val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
> +	val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
> +	val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_LOAD);
> +
> +	ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);

You are writing multiple registers.  This code is not safe when called
concurrently.

Ditto for gettime, adjtime, and adjfreq.

> +	return 0;
> +}
> +
> +static int ocelot_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
> +{
> +	if (delta > -(NSEC_PER_SEC / 2) && delta < (NSEC_PER_SEC / 2)) {
> +		struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
> +		u32 val;
> +
> +		val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
> +		val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
> +		val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
> +
> +		ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
> +
> +		ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
> +		ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN);
> +		ocelot_write_rix(ocelot, delta, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
> +
> +		val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
> +		val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
> +		val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_DELTA);
> +
> +		ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
> +	} else {
> +		/* Fall back using ocelot_ptp_settime64 which is not exact. */
> +		struct timespec64 ts;
> +		u64 now;
> +
> +		ocelot_ptp_gettime64(ptp, &ts);
> +
> +		now = ktime_to_ns(timespec64_to_ktime(ts));
> +		ts = ns_to_timespec64(now + delta);
> +
> +		ocelot_ptp_settime64(ptp, &ts);
> +	}
> +	return 0;
> +}
> +
> +static int ocelot_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
> +{

Please implement adjfine instead.

> +	struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
> +	u64 adj = 0;
> +	u32 unit = 0, direction = 0;
> +
> +	if (!ppb)
> +		goto disable_adj;
> +
> +	if (ppb < 0) {
> +		direction = PTP_CFG_CLK_ADJ_CFG_DIR;
> +		ppb = -ppb;
> +	}
> +
> +	adj = PSEC_PER_SEC;
> +	do_div(adj, ppb);
> +
> +	/* If the adjustment value is too large, use ns instead */
> +	if (adj >= (1L << 30)) {
> +		unit = PTP_CFG_CLK_ADJ_FREQ_NS;
> +		do_div(adj, 1000);
> +	}
> +
> +	/* Still too big */
> +	if (adj >= (1L << 30))
> +		goto disable_adj;
> +
> +	ocelot_write(ocelot, unit | adj, PTP_CLK_CFG_ADJ_FREQ);
> +	ocelot_write(ocelot, PTP_CFG_CLK_ADJ_CFG_ENA | direction,
> +		     PTP_CLK_CFG_ADJ_CFG);
> +	return 0;
> +
> +disable_adj:
> +	ocelot_write(ocelot, 0, PTP_CLK_CFG_ADJ_CFG);
> +	return 0;
> +}
> +
> +static struct ptp_clock_info ocelot_ptp_clock_info = {
> +	.owner		= THIS_MODULE,
> +	.name		= "ocelot ptp",
> +	.max_adj	= 0x7fffffff,
> +	.n_alarm	= 0,
> +	.n_ext_ts	= 0,
> +	.n_per_out	= 0,
> +	.n_pins		= 0,
> +	.pps		= 0,
> +	.gettime64	= ocelot_ptp_gettime64,
> +	.settime64	= ocelot_ptp_settime64,
> +	.adjtime	= ocelot_ptp_adjtime,
> +	.adjfreq	= ocelot_ptp_adjfreq,
> +};
> +
> +static int ocelot_init_timestamp(struct ocelot *ocelot)
> +{
> +	ocelot->ptp_info = ocelot_ptp_clock_info;
> +
> +	ocelot->ptp_clock = ptp_clock_register(&ocelot->ptp_info, ocelot->dev);
> +	if (IS_ERR(ocelot->ptp_clock))
> +		return PTR_ERR(ocelot->ptp_clock);
> +
> +	ocelot_write(ocelot, SYS_PTP_CFG_PTP_STAMP_WID(30), SYS_PTP_CFG);
> +	ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_LOW);
> +	ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_HIGH);
> +
> +	ocelot_write(ocelot, PTP_CFG_MISC_PTP_EN, PTP_CFG_MISC);
> +
> +	return 0;
> +}
> +
>  int ocelot_probe_port(struct ocelot *ocelot, u8 port,
>  		      void __iomem *regs,
>  		      struct phy_device *phy)
> @@ -1649,6 +2138,8 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
>  	ocelot_mact_learn(ocelot, PGID_CPU, dev->dev_addr, ocelot_port->pvid,
>  			  ENTRYTYPE_LOCKED);
>  
> +	INIT_LIST_HEAD(&ocelot_port->skbs);
> +
>  	err = register_netdev(dev);
>  	if (err) {
>  		dev_err(ocelot->dev, "register_netdev failed\n");
> @@ -1669,7 +2160,7 @@ EXPORT_SYMBOL(ocelot_probe_port);
>  int ocelot_init(struct ocelot *ocelot)
>  {
>  	u32 port;
> -	int i, cpu = ocelot->num_phys_ports;
> +	int i, ret, cpu = ocelot->num_phys_ports;
>  	char queue_name[32];
>  
>  	ocelot->lags = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
> @@ -1796,6 +2287,18 @@ int ocelot_init(struct ocelot *ocelot)
>  	INIT_DELAYED_WORK(&ocelot->stats_work, ocelot_check_stats);
>  	queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
>  			   OCELOT_STATS_CHECK_DELAY);
> +
> +	if (ocelot->ptp) {
> +		ret = ocelot_init_timestamp(ocelot);
> +		if (ret) {
> +			dev_err(ocelot->dev,
> +				"Timestamp initialization failed\n");
> +			return ret;
> +		}
> +
> +		ocelot_vcap_is2_init(ocelot);
> +	}
> +
>  	return 0;
>  }
>  EXPORT_SYMBOL(ocelot_init);
> diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
> index 994ba953d60e..ed1583037dc2 100644
> --- a/drivers/net/ethernet/mscc/ocelot.h
> +++ b/drivers/net/ethernet/mscc/ocelot.h
> @@ -11,9 +11,11 @@
>  #include <linux/bitops.h>
>  #include <linux/etherdevice.h>
>  #include <linux/if_vlan.h>
> +#include <linux/net_tstamp.h>
>  #include <linux/phy.h>
>  #include <linux/phy/phy.h>
>  #include <linux/platform_device.h>
> +#include <linux/ptp_clock_kernel.h>
>  #include <linux/regmap.h>
>  
>  #include "ocelot_ana.h"
> @@ -46,6 +48,8 @@ struct frame_info {
>  	u16 port;
>  	u16 vid;
>  	u8 tag_type;
> +	u16 rew_op;
> +	u32 timestamp;	/* rew_val */
>  };
>  
>  #define IFH_INJ_BYPASS	BIT(31)
> @@ -54,6 +58,12 @@ struct frame_info {
>  #define IFH_TAG_TYPE_C 0
>  #define IFH_TAG_TYPE_S 1
>  
> +#define IFH_REW_OP_NOOP			0x0
> +#define IFH_REW_OP_DSCP			0x1
> +#define IFH_REW_OP_ONE_STEP_PTP		0x2
> +#define IFH_REW_OP_TWO_STEP_PTP		0x3
> +#define IFH_REW_OP_ORIGIN_PTP		0x5
> +
>  #define OCELOT_SPEED_2500 0
>  #define OCELOT_SPEED_1000 1
>  #define OCELOT_SPEED_100  2
> @@ -401,6 +411,13 @@ enum ocelot_regfield {
>  	REGFIELD_MAX
>  };
>  
> +enum ocelot_clk_pins {
> +	ALT_PPS_PIN	= 1,
> +	EXT_CLK_PIN,
> +	ALT_LDST_PIN,
> +	TOD_ACC_PIN
> +};
> +
>  struct ocelot_multicast {
>  	struct list_head list;
>  	unsigned char addr[ETH_ALEN];
> @@ -450,6 +467,12 @@ struct ocelot {
>  	u64 *stats;
>  	struct delayed_work stats_work;
>  	struct workqueue_struct *stats_queue;
> +
> +	u8 ptp:1;
> +	struct ptp_clock *ptp_clock;
> +	struct ptp_clock_info ptp_info;
> +	struct hwtstamp_config hwtstamp_config;
> +	struct mutex ptp_lock;

Just what does this mutex protect?  Please add a comment.

Thanks,
Richard

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

* Re: [PATCH net-next 0/8] net: mscc: PTP offloading support
  2019-01-17 10:02 [PATCH net-next 0/8] net: mscc: PTP offloading support Antoine Tenart
                   ` (8 preceding siblings ...)
  2019-01-18  2:13 ` [PATCH net-next 0/8] " Richard Cochran
@ 2019-01-18  5:07 ` Florian Fainelli
  2019-01-18  8:58   ` Antoine Tenart
  9 siblings, 1 reply; 16+ messages in thread
From: Florian Fainelli @ 2019-01-18  5:07 UTC (permalink / raw)
  To: Antoine Tenart, davem, alexandre.belloni, UNGLinuxDriver, ralf,
	paul.burton, jhogan
  Cc: netdev, linux-mips, thomas.petazzoni, quentin.schulz, allan.nielsen



On 1/17/2019 2:02 AM, Antoine Tenart wrote:
> Hi all,
> 
> This series adds support for the PTP offloading support in the Mscc
> Ocelot Ethernet switch driver. Both PTP 1-step and 2-step modes are
> supported.
> 
> In order to make use of the PTP offloading support, two new register
> banks were described in the Ocelot device tree. The use of those
> registers by the Mscc Ocelot Ethernet switch driver is made optional for
> dt compatibility reasons. For the same reason a new interrupt is
> described, and its use is also made optinal for compatibility reasons.
> All of this is done ine patches 1-5.
> 
> The PTP offloading support itself is added in patch 8.
> 
> While doing this support, a few reworks were done in the Ocelot switch
> driver, in patches 6-7.
> 
> Patches 2 and 4 should probably go through the MIPS tree.

Looks like you missed copying netdev on this patch series, do you mind
re-sending there as well?

> 
> Thanks!
> Antoine
> 
> Antoine Tenart (8):
>   Documentation/bindings: net: ocelot: document the VCAP and PTP banks
>   MIPS: dts: mscc: describe VCAP and PTP register ranges
>   Documentation/bindings: net: ocelot: document the PTP ready IRQ
>   MIPS: dts: mscc: describe the PTP ready interrupt
>   net: mscc: describe the VCAP and PTP register ranges
>   net: mscc: improve the frame header parsing readability
>   net: mscc: remove the frame_info cpuq member
>   net: mscc: PTP offloading support
> 
>  .../devicetree/bindings/net/mscc-ocelot.txt   |  22 +-
>  arch/mips/boot/dts/mscc/ocelot.dtsi           |  14 +-
>  drivers/net/ethernet/mscc/ocelot.c            | 509 +++++++++++++++++-
>  drivers/net/ethernet/mscc/ocelot.h            |  55 +-
>  drivers/net/ethernet/mscc/ocelot_board.c      | 150 +++++-
>  drivers/net/ethernet/mscc/ocelot_ptp.h        |  41 ++
>  drivers/net/ethernet/mscc/ocelot_regs.c       |  22 +
>  drivers/net/ethernet/mscc/ocelot_vcap.h       | 104 ++++
>  8 files changed, 877 insertions(+), 40 deletions(-)
>  create mode 100644 drivers/net/ethernet/mscc/ocelot_ptp.h
>  create mode 100644 drivers/net/ethernet/mscc/ocelot_vcap.h
> 

-- 
Florian

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

* Re: [PATCH net-next 0/8] net: mscc: PTP offloading support
  2019-01-18  5:07 ` Florian Fainelli
@ 2019-01-18  8:58   ` Antoine Tenart
  2019-01-18 18:16     ` Florian Fainelli
  0 siblings, 1 reply; 16+ messages in thread
From: Antoine Tenart @ 2019-01-18  8:58 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Antoine Tenart, davem, alexandre.belloni, UNGLinuxDriver, ralf,
	paul.burton, jhogan, netdev, linux-mips, thomas.petazzoni,
	quentin.schulz, allan.nielsen

Hi Florian,

On Thu, Jan 17, 2019 at 09:07:05PM -0800, Florian Fainelli wrote:
> On 1/17/2019 2:02 AM, Antoine Tenart wrote:
> > 
> > This series adds support for the PTP offloading support in the Mscc
> > Ocelot Ethernet switch driver. Both PTP 1-step and 2-step modes are
> > supported.
> > 
> > In order to make use of the PTP offloading support, two new register
> > banks were described in the Ocelot device tree. The use of those
> > registers by the Mscc Ocelot Ethernet switch driver is made optional for
> > dt compatibility reasons. For the same reason a new interrupt is
> > described, and its use is also made optinal for compatibility reasons.
> > All of this is done ine patches 1-5.
> > 
> > The PTP offloading support itself is added in patch 8.
> > 
> > While doing this support, a few reworks were done in the Ocelot switch
> > driver, in patches 6-7.
> > 
> > Patches 2 and 4 should probably go through the MIPS tree.
> 
> Looks like you missed copying netdev on this patch series, do you mind
> re-sending there as well?

I just checked and netdev is Cc'ed. I'll prepare a v2 to take in account
the comments, so I'll sent it again anyway.

Thanks!
Antoine

-- 
Antoine Ténart, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

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

* Re: [PATCH net-next 8/8] net: mscc: PTP offloading support
  2019-01-18  2:23   ` Richard Cochran
@ 2019-01-18  9:08     ` Antoine Tenart
  0 siblings, 0 replies; 16+ messages in thread
From: Antoine Tenart @ 2019-01-18  9:08 UTC (permalink / raw)
  To: Richard Cochran
  Cc: Antoine Tenart, davem, alexandre.belloni, UNGLinuxDriver, ralf,
	paul.burton, jhogan, netdev, linux-mips, thomas.petazzoni,
	quentin.schulz, allan.nielsen

Hi Richard,

On Thu, Jan 17, 2019 at 06:23:43PM -0800, Richard Cochran wrote:
> On Thu, Jan 17, 2019 at 11:02:12AM +0100, Antoine Tenart wrote:
> > This patch adds support for offloading PTP timestamping to the Ocelot
> > switch for both 1-step and 2-step modes.
> 
> For PTP Hardware Clock drivers, please add the PTP maintainer onto CC.

Will do for the v2, sorry about that.

> > +static int ocelot_ptp_settime64(struct ptp_clock_info *ptp,
> > +				const struct timespec64 *ts)
> > +{
> > +	struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
> > +	u32 val;
> > +
> > +	val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
> > +	val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
> > +	val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
> > +
> > +	ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
> > +
> > +	ocelot_write_rix(ocelot, lower_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_LSB,
> > +			 TOD_ACC_PIN);
> > +	ocelot_write_rix(ocelot, upper_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_MSB,
> > +			 TOD_ACC_PIN);
> > +	ocelot_write_rix(ocelot, ts->tv_nsec, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
> > +
> > +	val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
> > +	val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
> > +	val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_LOAD);
> > +
> > +	ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
> 
> You are writing multiple registers.  This code is not safe when called
> concurrently.
> 
> Ditto for gettime, adjtime, and adjfreq.

Right, I'll fix that.

> > +static int ocelot_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
> > +{
> 
> Please implement adjfine instead.

OK, I'll look into it.

> > +	struct mutex ptp_lock;
> 
> Just what does this mutex protect?  Please add a comment.

OK.

Thanks!
Antoine

-- 
Antoine Ténart, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

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

* Re: [PATCH net-next 0/8] net: mscc: PTP offloading support
  2019-01-18  2:13 ` [PATCH net-next 0/8] " Richard Cochran
@ 2019-01-18  9:09   ` Antoine Tenart
  0 siblings, 0 replies; 16+ messages in thread
From: Antoine Tenart @ 2019-01-18  9:09 UTC (permalink / raw)
  To: Richard Cochran
  Cc: Antoine Tenart, davem, alexandre.belloni, UNGLinuxDriver, ralf,
	paul.burton, jhogan, netdev, linux-mips, thomas.petazzoni,
	quentin.schulz, allan.nielsen

Hi Richard,

On Thu, Jan 17, 2019 at 06:13:42PM -0800, Richard Cochran wrote:
> On Thu, Jan 17, 2019 at 11:02:04AM +0100, Antoine Tenart wrote:
> > This series adds support for the PTP offloading support in the Mscc
> > Ocelot Ethernet switch driver. Both PTP 1-step and 2-step modes are
> > supported.
> > 
> > In order to make use of the PTP offloading support, two new register
> > banks were described in the Ocelot device tree. The use of those
> > registers by the Mscc Ocelot Ethernet switch driver is made optional for
> > dt compatibility reasons. For the same reason a new interrupt is
> > described, and its use is also made optinal for compatibility reasons.
> > All of this is done ine patches 1-5.
> > 
> > The PTP offloading support itself is added in patch 8.
> 
> The subject lines and this description are misleading.  You are not
> offloading the Precision Time Protocol.  Instead, this series
> implements a normal PHC driver.
> 
> Please change the text to avoid the phrase, "PTP offloading".

Will do.

Thanks!
Antoine

-- 
Antoine Ténart, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

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

* Re: [PATCH net-next 0/8] net: mscc: PTP offloading support
  2019-01-18  8:58   ` Antoine Tenart
@ 2019-01-18 18:16     ` Florian Fainelli
  0 siblings, 0 replies; 16+ messages in thread
From: Florian Fainelli @ 2019-01-18 18:16 UTC (permalink / raw)
  To: Antoine Tenart
  Cc: davem, alexandre.belloni, UNGLinuxDriver, ralf, paul.burton,
	jhogan, netdev, linux-mips, thomas.petazzoni, quentin.schulz,
	allan.nielsen

On 1/18/19 12:58 AM, Antoine Tenart wrote:
> Hi Florian,
> 
> On Thu, Jan 17, 2019 at 09:07:05PM -0800, Florian Fainelli wrote:
>> On 1/17/2019 2:02 AM, Antoine Tenart wrote:
>>>
>>> This series adds support for the PTP offloading support in the Mscc
>>> Ocelot Ethernet switch driver. Both PTP 1-step and 2-step modes are
>>> supported.
>>>
>>> In order to make use of the PTP offloading support, two new register
>>> banks were described in the Ocelot device tree. The use of those
>>> registers by the Mscc Ocelot Ethernet switch driver is made optional for
>>> dt compatibility reasons. For the same reason a new interrupt is
>>> described, and its use is also made optinal for compatibility reasons.
>>> All of this is done ine patches 1-5.
>>>
>>> The PTP offloading support itself is added in patch 8.
>>>
>>> While doing this support, a few reworks were done in the Ocelot switch
>>> driver, in patches 6-7.
>>>
>>> Patches 2 and 4 should probably go through the MIPS tree.
>>
>> Looks like you missed copying netdev on this patch series, do you mind
>> re-sending there as well?
> 
> I just checked and netdev is Cc'ed. I'll prepare a v2 to take in account
> the comments, so I'll sent it again anyway.

Indeed, my bad.
-- 
Florian

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

end of thread, other threads:[~2019-01-18 18:16 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-17 10:02 [PATCH net-next 0/8] net: mscc: PTP offloading support Antoine Tenart
2019-01-17 10:02 ` [PATCH net-next 1/8] Documentation/bindings: net: ocelot: document the VCAP and PTP banks Antoine Tenart
2019-01-17 10:02 ` [PATCH net-next 2/8] MIPS: dts: mscc: describe VCAP and PTP register ranges Antoine Tenart
2019-01-17 10:02 ` [PATCH net-next 3/8] Documentation/bindings: net: ocelot: document the PTP ready IRQ Antoine Tenart
2019-01-17 10:02 ` [PATCH net-next 4/8] MIPS: dts: mscc: describe the PTP ready interrupt Antoine Tenart
2019-01-17 10:02 ` [PATCH net-next 5/8] net: mscc: describe the VCAP and PTP register ranges Antoine Tenart
2019-01-17 10:02 ` [PATCH net-next 6/8] net: mscc: improve the frame header parsing readability Antoine Tenart
2019-01-17 10:02 ` [PATCH net-next 7/8] net: mscc: remove the frame_info cpuq member Antoine Tenart
2019-01-17 10:02 ` [PATCH net-next 8/8] net: mscc: PTP offloading support Antoine Tenart
2019-01-18  2:23   ` Richard Cochran
2019-01-18  9:08     ` Antoine Tenart
2019-01-18  2:13 ` [PATCH net-next 0/8] " Richard Cochran
2019-01-18  9:09   ` Antoine Tenart
2019-01-18  5:07 ` Florian Fainelli
2019-01-18  8:58   ` Antoine Tenart
2019-01-18 18:16     ` Florian Fainelli

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.