All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] ptp: add PTP_PEROUT_REVERSE_POLARITY flag
@ 2021-12-20 12:08 Radu Pirea (NXP OSS)
  2021-12-20 12:08 ` [PATCH 2/3] phy: nxp-c45-tja11xx: add extts and perout support Radu Pirea (NXP OSS)
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Radu Pirea (NXP OSS) @ 2021-12-20 12:08 UTC (permalink / raw)
  To: netdev, linux-kernel
  Cc: christian.herber, andrew, hkallweit1, linux, davem, kuba,
	Radu Pirea (NXP OSS)

Some ptp controllers may be able to reverse the polarity of the periodic
output signal. Using the PTP_PEROUT_REVERSE_POLARITY flag we can tell the
drivers to reverse the polarity of the signal.

Signed-off-by: Radu Pirea (NXP OSS) <radu-nicolae.pirea@oss.nxp.com>
---
 include/uapi/linux/ptp_clock.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/ptp_clock.h b/include/uapi/linux/ptp_clock.h
index 1d108d597f66..34bc4ff89341 100644
--- a/include/uapi/linux/ptp_clock.h
+++ b/include/uapi/linux/ptp_clock.h
@@ -56,13 +56,15 @@
 #define PTP_PEROUT_ONE_SHOT		(1<<0)
 #define PTP_PEROUT_DUTY_CYCLE		(1<<1)
 #define PTP_PEROUT_PHASE		(1<<2)
+#define PTP_PEROUT_REVERSE_POLARITY	(1<<3)
 
 /*
  * flag fields valid for the new PTP_PEROUT_REQUEST2 ioctl.
  */
 #define PTP_PEROUT_VALID_FLAGS		(PTP_PEROUT_ONE_SHOT | \
 					 PTP_PEROUT_DUTY_CYCLE | \
-					 PTP_PEROUT_PHASE)
+					 PTP_PEROUT_PHASE | \
+					 PTP_PEROUT_REVERSE_POLARITY)
 
 /*
  * No flags are valid for the original PTP_PEROUT_REQUEST ioctl
-- 
2.34.1


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

* [PATCH 2/3] phy: nxp-c45-tja11xx: add extts and perout support
  2021-12-20 12:08 [PATCH 1/3] ptp: add PTP_PEROUT_REVERSE_POLARITY flag Radu Pirea (NXP OSS)
@ 2021-12-20 12:08 ` Radu Pirea (NXP OSS)
  2021-12-20 12:08 ` [PATCH 3/3] phy: nxp-c45-tja11xx: read the tx timestamp without lock Radu Pirea (NXP OSS)
  2021-12-20 15:04 ` [PATCH 1/3] ptp: add PTP_PEROUT_REVERSE_POLARITY flag Andrew Lunn
  2 siblings, 0 replies; 6+ messages in thread
From: Radu Pirea (NXP OSS) @ 2021-12-20 12:08 UTC (permalink / raw)
  To: netdev, linux-kernel
  Cc: christian.herber, andrew, hkallweit1, linux, davem, kuba,
	Radu Pirea (NXP OSS)

Add support for external timestamp and periodic signal output.
TJA1103 have one periodic signal and one external time stamp signal that
can be multiplexed on all 11 gpio pins.

The periodic signal can be only enabled or disabled. Have no start time
and if is enabled will be generated with a period of one second in sync
with the LTC seconds counter.

The external timestamp signal has no interrupt and no valid bit and
that's why the timestamps are handled by polling in .do_aux_work.

Signed-off-by: Radu Pirea (NXP OSS) <radu-nicolae.pirea@oss.nxp.com>
---
 drivers/net/phy/nxp-c45-tja11xx.c | 202 ++++++++++++++++++++++++++++++
 1 file changed, 202 insertions(+)

diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
index 91a327f67a42..74de66c90f24 100644
--- a/drivers/net/phy/nxp-c45-tja11xx.c
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
@@ -97,6 +97,11 @@
 #define VEND1_TX_IPG_LENGTH		0xAFD1
 #define COUNTER_EN			BIT(15)
 
+#define VEND1_PTP_CONFIG		0x1102
+#define EXT_TRG_EDGE			BIT(1)
+#define PPS_OUT_POL			BIT(2)
+#define PPS_OUT_EN			BIT(3)
+
 #define VEND1_LTC_LOAD_CTRL		0x1105
 #define READ_LTC			BIT(2)
 #define LOAD_LTC			BIT(0)
@@ -132,6 +137,13 @@
 #define VEND1_EGR_RING_DATA_3		0x1151
 #define VEND1_EGR_RING_CTRL		0x1154
 
+#define VEND1_EXT_TRG_TS_DATA_0		0x1121
+#define VEND1_EXT_TRG_TS_DATA_1		0x1122
+#define VEND1_EXT_TRG_TS_DATA_2		0x1123
+#define VEND1_EXT_TRG_TS_DATA_3		0x1124
+#define VEND1_EXT_TRG_TS_DATA_4		0x1125
+#define VEND1_EXT_TRG_TS_CTRL		0x1126
+
 #define RING_DATA_0_DOMAIN_NUMBER	GENMASK(7, 0)
 #define RING_DATA_0_MSG_TYPE		GENMASK(11, 8)
 #define RING_DATA_0_SEC_4_2		GENMASK(14, 2)
@@ -162,6 +174,17 @@
 #define VEND1_RX_PIPE_DLY_NS		0x114B
 #define VEND1_RX_PIPEDLY_SUBNS		0x114C
 
+#define VEND1_GPIO_FUNC_CONFIG_BASE	0x2C40
+#define GPIO_FUNC_EN			BIT(15)
+#define GPIO_FUNC_PTP			BIT(6)
+#define GPIO_SIGNAL_PTP_TRIGGER		0x01
+#define GPIO_SIGNAL_PPS_OUT		0x12
+#define GPIO_DISABLE			0
+#define GPIO_PPS_OUT_CFG		(GPIO_FUNC_EN | GPIO_FUNC_PTP | \
+	GPIO_SIGNAL_PPS_OUT)
+#define GPIO_EXTTS_OUT_CFG		(GPIO_FUNC_EN | GPIO_FUNC_PTP | \
+	GPIO_SIGNAL_PTP_TRIGGER)
+
 #define RGMII_PERIOD_PS			8000U
 #define PS_PER_DEGREE			div_u64(RGMII_PERIOD_PS, 360)
 #define MIN_ID_PS			1644U
@@ -199,6 +222,9 @@ struct nxp_c45_phy {
 	int hwts_rx;
 	u32 tx_delay;
 	u32 rx_delay;
+	struct timespec64 extts_ts;
+	int extts_index;
+	bool extts;
 };
 
 struct nxp_c45_phy_stats {
@@ -339,6 +365,16 @@ static bool nxp_c45_match_ts(struct ptp_header *header,
 	       header->domain_number  == hwts->domain_number;
 }
 
+static void nxp_c45_get_extts(struct nxp_c45_phy *priv,
+			      struct timespec64 *extts)
+{
+	extts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EXT_TRG_TS_DATA_0);
+	extts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EXT_TRG_TS_DATA_1) << 16;
+	extts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EXT_TRG_TS_DATA_2);
+	extts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EXT_TRG_TS_DATA_3) << 16;
+	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EXT_TRG_TS_CTRL, RING_DONE);
+}
+
 static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv,
 			       struct nxp_c45_hwts *hwts)
 {
@@ -366,6 +402,7 @@ static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv,
 
 nxp_c45_get_hwtxts_out:
 	mutex_unlock(&priv->ptp_lock);
+
 	return valid;
 }
 
@@ -409,6 +446,7 @@ static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp)
 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
 	bool poll_txts = nxp_c45_poll_txts(priv->phydev);
 	struct skb_shared_hwtstamps *shhwtstamps_rx;
+	struct ptp_clock_event event;
 	struct nxp_c45_hwts hwts;
 	bool reschedule = false;
 	struct timespec64 ts;
@@ -439,9 +477,167 @@ static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp)
 		netif_rx_ni(skb);
 	}
 
+	if (priv->extts) {
+		nxp_c45_get_extts(priv, &ts);
+		if (timespec64_compare(&ts, &priv->extts_ts) > 0) {
+			priv->extts_ts = ts;
+			event.index = priv->extts_index;
+			event.type = PTP_CLOCK_EXTTS;
+			event.timestamp = ns_to_ktime(timespec64_to_ns(&ts));
+			ptp_clock_event(priv->ptp_clock, &event);
+		}
+		reschedule = true;
+	}
+
 	return reschedule ? 1 : -1;
 }
 
+static void nxp_c45_gpio_config(struct nxp_c45_phy *priv,
+				int pin, u16 pin_cfg)
+{
+	struct phy_device *phydev = priv->phydev;
+
+	phy_write_mmd(phydev, MDIO_MMD_VEND1,
+		      VEND1_GPIO_FUNC_CONFIG_BASE + pin, pin_cfg);
+}
+
+static int nxp_c45_perout_enable(struct nxp_c45_phy *priv,
+				 struct ptp_perout_request *perout, int on)
+{
+	bool rev_pol = false;
+	int pin;
+
+	if (perout->flags & ~PTP_PEROUT_REVERSE_POLARITY)
+		return -EOPNOTSUPP;
+
+	if (perout->flags & PTP_PEROUT_REVERSE_POLARITY)
+		rev_pol = true;
+
+	pin = ptp_find_pin(priv->ptp_clock, PTP_PF_PEROUT, perout->index);
+	if (pin < 0)
+		return pin;
+
+	if (!on) {
+		phy_clear_bits_mmd(priv->phydev, MDIO_MMD_VEND1,
+				   VEND1_PTP_CONFIG, PPS_OUT_EN);
+
+		nxp_c45_gpio_config(priv, pin, GPIO_DISABLE);
+
+		return 0;
+	}
+
+	if (perout->start.sec != 0 || perout->start.nsec != 0)
+		return -EINVAL;
+
+	if (perout->period.sec != 1 || perout->period.nsec != 0)
+		return -EINVAL;
+
+	nxp_c45_gpio_config(priv, pin, GPIO_PPS_OUT_CFG);
+
+	if (rev_pol)
+		phy_set_bits_mmd(priv->phydev, MDIO_MMD_VEND1,
+				 VEND1_PTP_CONFIG, PPS_OUT_POL);
+	else
+		phy_clear_bits_mmd(priv->phydev, MDIO_MMD_VEND1,
+				   VEND1_PTP_CONFIG, PPS_OUT_POL);
+
+	phy_set_bits_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_PTP_CONFIG,
+			 PPS_OUT_EN);
+
+	return 0;
+}
+
+static int nxp_c45_extts_enable(struct nxp_c45_phy *priv,
+				struct ptp_extts_request *extts, int on)
+{
+	int pin;
+
+	if (extts->flags & ~(PTP_ENABLE_FEATURE |
+			      PTP_RISING_EDGE |
+			      PTP_FALLING_EDGE |
+			      PTP_STRICT_FLAGS))
+		return -EOPNOTSUPP;
+
+	/* Sampling on both edges is not supported */
+	if ((extts->flags & PTP_RISING_EDGE) &&
+	    (extts->flags & PTP_FALLING_EDGE))
+		return -EOPNOTSUPP;
+
+	pin = ptp_find_pin(priv->ptp_clock, PTP_PF_EXTTS, extts->index);
+	if (pin < 0)
+		return pin;
+
+	if (!on) {
+		nxp_c45_gpio_config(priv, pin, GPIO_DISABLE);
+		priv->extts = false;
+
+		return 0;
+	}
+
+	if (extts->flags & PTP_RISING_EDGE)
+		phy_clear_bits_mmd(priv->phydev, MDIO_MMD_VEND1,
+				   VEND1_PTP_CONFIG, EXT_TRG_EDGE);
+
+	if (extts->flags & PTP_FALLING_EDGE)
+		phy_set_bits_mmd(priv->phydev, MDIO_MMD_VEND1,
+				 VEND1_PTP_CONFIG, EXT_TRG_EDGE);
+
+	nxp_c45_gpio_config(priv, pin, GPIO_EXTTS_OUT_CFG);
+	priv->extts = true;
+	priv->extts_index = extts->index;
+	ptp_schedule_worker(priv->ptp_clock, 0);
+
+	return 0;
+}
+
+static int nxp_c45_ptp_enable(struct ptp_clock_info *ptp,
+			      struct ptp_clock_request *req, int on)
+{
+	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
+
+	switch (req->type) {
+	case PTP_CLK_REQ_EXTTS:
+		return nxp_c45_extts_enable(priv, &req->extts, on);
+	case PTP_CLK_REQ_PEROUT:
+		return nxp_c45_perout_enable(priv, &req->perout, on);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static struct ptp_pin_desc nxp_c45_ptp_pins[] = {
+	{ "nxp_c45_gpio0", 0, PTP_PF_NONE},
+	{ "nxp_c45_gpio1", 1, PTP_PF_NONE},
+	{ "nxp_c45_gpio2", 2, PTP_PF_NONE},
+	{ "nxp_c45_gpio3", 3, PTP_PF_NONE},
+	{ "nxp_c45_gpio4", 4, PTP_PF_NONE},
+	{ "nxp_c45_gpio5", 5, PTP_PF_NONE},
+	{ "nxp_c45_gpio6", 6, PTP_PF_NONE},
+	{ "nxp_c45_gpio7", 7, PTP_PF_NONE},
+	{ "nxp_c45_gpio8", 8, PTP_PF_NONE},
+	{ "nxp_c45_gpio9", 9, PTP_PF_NONE},
+	{ "nxp_c45_gpio10", 10, PTP_PF_NONE},
+	{ "nxp_c45_gpio11", 11, PTP_PF_NONE},
+};
+
+static int nxp_c45_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
+				  enum ptp_pin_function func, unsigned int chan)
+{
+	if (pin >= ARRAY_SIZE(nxp_c45_ptp_pins))
+		return -EINVAL;
+
+	switch (func) {
+	case PTP_PF_NONE:
+	case PTP_PF_PEROUT:
+	case PTP_PF_EXTTS:
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
 static int nxp_c45_init_ptp_clock(struct nxp_c45_phy *priv)
 {
 	priv->caps = (struct ptp_clock_info) {
@@ -452,7 +648,13 @@ static int nxp_c45_init_ptp_clock(struct nxp_c45_phy *priv)
 		.adjtime	= nxp_c45_ptp_adjtime,
 		.gettimex64	= nxp_c45_ptp_gettimex64,
 		.settime64	= nxp_c45_ptp_settime64,
+		.enable		= nxp_c45_ptp_enable,
+		.verify		= nxp_c45_ptp_verify_pin,
 		.do_aux_work	= nxp_c45_do_aux_work,
+		.pin_config	= nxp_c45_ptp_pins,
+		.n_pins		= ARRAY_SIZE(nxp_c45_ptp_pins),
+		.n_ext_ts	= 1,
+		.n_per_out	= 1,
 	};
 
 	priv->ptp_clock = ptp_clock_register(&priv->caps,
-- 
2.34.1


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

* [PATCH 3/3] phy: nxp-c45-tja11xx: read the tx timestamp without lock
  2021-12-20 12:08 [PATCH 1/3] ptp: add PTP_PEROUT_REVERSE_POLARITY flag Radu Pirea (NXP OSS)
  2021-12-20 12:08 ` [PATCH 2/3] phy: nxp-c45-tja11xx: add extts and perout support Radu Pirea (NXP OSS)
@ 2021-12-20 12:08 ` Radu Pirea (NXP OSS)
  2021-12-20 15:10   ` Andrew Lunn
  2021-12-20 15:04 ` [PATCH 1/3] ptp: add PTP_PEROUT_REVERSE_POLARITY flag Andrew Lunn
  2 siblings, 1 reply; 6+ messages in thread
From: Radu Pirea (NXP OSS) @ 2021-12-20 12:08 UTC (permalink / raw)
  To: netdev, linux-kernel
  Cc: christian.herber, andrew, hkallweit1, linux, davem, kuba,
	Radu Pirea (NXP OSS)

The tx timestamps are read from only one place in interrupt or polling
mode. Locking the mutex is useless.

Signed-off-by: Radu Pirea (NXP OSS) <radu-nicolae.pirea@oss.nxp.com>
---
 drivers/net/phy/nxp-c45-tja11xx.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
index 74de66c90f24..5bd8c166d726 100644
--- a/drivers/net/phy/nxp-c45-tja11xx.c
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
@@ -381,7 +381,6 @@ static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv,
 	bool valid;
 	u16 reg;
 
-	mutex_lock(&priv->ptp_lock);
 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_CTRL,
 		      RING_DONE);
 	reg = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_DATA_0);
@@ -401,8 +400,6 @@ static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv,
 	hwts->sec |= (reg & RING_DATA_3_SEC_1_0) >> 14;
 
 nxp_c45_get_hwtxts_out:
-	mutex_unlock(&priv->ptp_lock);
-
 	return valid;
 }
 
-- 
2.34.1


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

* Re: [PATCH 1/3] ptp: add PTP_PEROUT_REVERSE_POLARITY flag
  2021-12-20 12:08 [PATCH 1/3] ptp: add PTP_PEROUT_REVERSE_POLARITY flag Radu Pirea (NXP OSS)
  2021-12-20 12:08 ` [PATCH 2/3] phy: nxp-c45-tja11xx: add extts and perout support Radu Pirea (NXP OSS)
  2021-12-20 12:08 ` [PATCH 3/3] phy: nxp-c45-tja11xx: read the tx timestamp without lock Radu Pirea (NXP OSS)
@ 2021-12-20 15:04 ` Andrew Lunn
  2 siblings, 0 replies; 6+ messages in thread
From: Andrew Lunn @ 2021-12-20 15:04 UTC (permalink / raw)
  To: Radu Pirea (NXP OSS)
  Cc: netdev, linux-kernel, christian.herber, hkallweit1, linux, davem, kuba

On Mon, Dec 20, 2021 at 02:08:57PM +0200, Radu Pirea (NXP OSS) wrote:
> Some ptp controllers may be able to reverse the polarity of the periodic
> output signal. Using the PTP_PEROUT_REVERSE_POLARITY flag we can tell the
> drivers to reverse the polarity of the signal.

Please always Cc: the PTP maintainer, Richard Cochran
<richardcochran@gmail.com>.

For a patch set, please also include a patch 0/X which explains what
the patches as a whole do.

    Andrew

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

* Re: [PATCH 3/3] phy: nxp-c45-tja11xx: read the tx timestamp without lock
  2021-12-20 12:08 ` [PATCH 3/3] phy: nxp-c45-tja11xx: read the tx timestamp without lock Radu Pirea (NXP OSS)
@ 2021-12-20 15:10   ` Andrew Lunn
  2021-12-22  8:19     ` Radu Nicolae Pirea (NXP OSS)
  0 siblings, 1 reply; 6+ messages in thread
From: Andrew Lunn @ 2021-12-20 15:10 UTC (permalink / raw)
  To: Radu Pirea (NXP OSS)
  Cc: netdev, linux-kernel, christian.herber, hkallweit1, linux, davem, kuba

On Mon, Dec 20, 2021 at 02:08:59PM +0200, Radu Pirea (NXP OSS) wrote:
> The tx timestamps are read from only one place in interrupt or polling
> mode. Locking the mutex is useless.

You cannot take a mutex in an interrupt handler. So your description
is probably not accurate.

Is it safe for other ptp operations to be performed in parallel with
reading the TX timestamp? _nxp_c45_ptp_settime64()?

	Andrew

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

* Re: [PATCH 3/3] phy: nxp-c45-tja11xx: read the tx timestamp without lock
  2021-12-20 15:10   ` Andrew Lunn
@ 2021-12-22  8:19     ` Radu Nicolae Pirea (NXP OSS)
  0 siblings, 0 replies; 6+ messages in thread
From: Radu Nicolae Pirea (NXP OSS) @ 2021-12-22  8:19 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: netdev, linux-kernel, christian.herber, hkallweit1, linux, davem, kuba

On Mon, 2021-12-20 at 16:10 +0100, Andrew Lunn wrote:
> On Mon, Dec 20, 2021 at 02:08:59PM +0200, Radu Pirea (NXP OSS) wrote:
> > The tx timestamps are read from only one place in interrupt or
> > polling
> > mode. Locking the mutex is useless.
> 
> You cannot take a mutex in an interrupt handler. So your description
> is probably not accurate.
Actually this is the second issue.
I will improve the description.
> 
> Is it safe for other ptp operations to be performed in parallel with
> reading the TX timestamp? _nxp_c45_ptp_settime64()?
Yes, it's safe. The purpose of the mutex is to protect the access to
LTC(PTP counter).
> 
>         Andrew


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

end of thread, other threads:[~2021-12-22  8:19 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-20 12:08 [PATCH 1/3] ptp: add PTP_PEROUT_REVERSE_POLARITY flag Radu Pirea (NXP OSS)
2021-12-20 12:08 ` [PATCH 2/3] phy: nxp-c45-tja11xx: add extts and perout support Radu Pirea (NXP OSS)
2021-12-20 12:08 ` [PATCH 3/3] phy: nxp-c45-tja11xx: read the tx timestamp without lock Radu Pirea (NXP OSS)
2021-12-20 15:10   ` Andrew Lunn
2021-12-22  8:19     ` Radu Nicolae Pirea (NXP OSS)
2021-12-20 15:04 ` [PATCH 1/3] ptp: add PTP_PEROUT_REVERSE_POLARITY flag Andrew Lunn

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.