DPDK patches and discussions
 help / color / mirror / Atom feed
From: <pbhagavatula@marvell.com>
To: <jerinj@marvell.com>, Pavan Nikhilesh <pbhagavatula@marvell.com>,
	"Shijith Thotton" <sthotton@marvell.com>,
	Nithin Dabilpuram <ndabilpuram@marvell.com>,
	Kiran Kumar K <kirankumark@marvell.com>,
	Sunil Kumar Kori <skori@marvell.com>,
	Satha Rao <skoteshwar@marvell.com>
Cc: <dev@dpdk.org>
Subject: [dpdk-dev] [PATCH v3 2/2] event/cnxk: add external clock support for timer
Date: Fri, 24 Sep 2021 03:00:46 +0530	[thread overview]
Message-ID: <20210923213046.3157-2-pbhagavatula@marvell.com> (raw)
In-Reply-To: <20210923213046.3157-1-pbhagavatula@marvell.com>

From: Pavan Nikhilesh <pbhagavatula@marvell.com>

Add external clock support for cnxk timer adapter.

External clock mapping is as follows:
RTE_EVENT_TIMER_ADAPTER_EXT_CLK0 = TIM_CLK_SRC_10NS,
RTE_EVENT_TIMER_ADAPTER_EXT_CLK1 = TIM_CLK_SRC_GPIO,
RTE_EVENT_TIMER_ADAPTER_EXT_CLK2 = TIM_CLK_SRC_PTP,
RTE_EVENT_TIMER_ADAPTER_EXT_CLK3 = TIM_CLK_SRC_SYNCE,

TIM supports clock input from external GPIO, PTP, SYNCE clocks.
Input resolution is adjusted based on CNTVCT frequency for better
estimation.

Since TIM is unaware of input clock frequency, application is
expected to pass the frequency.
Example:
	-a 0002:0e:00.0,tim_eclk_freq=122880000-0-0

The order of frequencies above is GPIO-PTP-SYNCE.

Signed-off-by: Shijith Thotton <sthotton@marvell.com>
Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com>
---
 doc/guides/eventdevs/cnxk.rst       |  18 ++++
 drivers/common/cnxk/roc_platform.h  |   1 +
 drivers/event/cnxk/cn10k_eventdev.c |   3 +-
 drivers/event/cnxk/cnxk_tim_evdev.c | 130 +++++++++++++++++++++++++++-
 drivers/event/cnxk/cnxk_tim_evdev.h |   4 +
 5 files changed, 154 insertions(+), 2 deletions(-)

diff --git a/doc/guides/eventdevs/cnxk.rst b/doc/guides/eventdevs/cnxk.rst
index 53560d3830..18540dc911 100644
--- a/doc/guides/eventdevs/cnxk.rst
+++ b/doc/guides/eventdevs/cnxk.rst
@@ -164,6 +164,24 @@ Runtime Config Options
 
     -a 0002:0e:00.0,tim_ring_ctl=[2-1023-1-0]
 
+- ``TIM external clock frequency``
+
+  The ``tim_eclk_freq`` devagrs can be used to pass external clock frequencies
+  when external clock source is selected.
+
+  External clock frequencies are mapped as follows::
+
+    RTE_EVENT_TIMER_ADAPTER_EXT_CLK0 = TIM_CLK_SRC_10NS,
+    RTE_EVENT_TIMER_ADAPTER_EXT_CLK1 = TIM_CLK_SRC_GPIO,
+    RTE_EVENT_TIMER_ADAPTER_EXT_CLK2 = TIM_CLK_SRC_PTP,
+    RTE_EVENT_TIMER_ADAPTER_EXT_CLK3 = TIM_CLK_SRC_SYNCE
+
+  The order of frequencies supplied to device args should be GPIO-PTP-SYNCE.
+
+  For Example::
+
+    -a 0002:0e:00.0,tim_eclk_freq=122880000-1000000000-0
+
 Debugging Options
 -----------------
 
diff --git a/drivers/common/cnxk/roc_platform.h b/drivers/common/cnxk/roc_platform.h
index 285b24b82d..7e73972b80 100644
--- a/drivers/common/cnxk/roc_platform.h
+++ b/drivers/common/cnxk/roc_platform.h
@@ -43,6 +43,7 @@
 #define PLT_MAX			 RTE_MAX
 #define PLT_DIM			 RTE_DIM
 #define PLT_SET_USED		 RTE_SET_USED
+#define PLT_SWAP		 RTE_SWAP
 #define PLT_STATIC_ASSERT(s)	 _Static_assert(s, #s)
 #define PLT_ALIGN		 RTE_ALIGN
 #define PLT_ALIGN_MUL_CEIL	 RTE_ALIGN_MUL_CEIL
diff --git a/drivers/event/cnxk/cn10k_eventdev.c b/drivers/event/cnxk/cn10k_eventdev.c
index 8af273a01b..cf0a7d2325 100644
--- a/drivers/event/cnxk/cn10k_eventdev.c
+++ b/drivers/event/cnxk/cn10k_eventdev.c
@@ -976,4 +976,5 @@ RTE_PMD_REGISTER_PARAM_STRING(event_cn10k, CNXK_SSO_XAE_CNT "=<int>"
 			      CNXK_TIM_DISABLE_NPA "=1"
 			      CNXK_TIM_CHNK_SLOTS "=<int>"
 			      CNXK_TIM_RINGS_LMT "=<int>"
-			      CNXK_TIM_STATS_ENA "=1");
+			      CNXK_TIM_STATS_ENA "=1"
+			      CNXK_TIM_EXT_CLK "=<string>");
diff --git a/drivers/event/cnxk/cnxk_tim_evdev.c b/drivers/event/cnxk/cnxk_tim_evdev.c
index 369f198444..21071c2d27 100644
--- a/drivers/event/cnxk/cnxk_tim_evdev.c
+++ b/drivers/event/cnxk/cnxk_tim_evdev.c
@@ -117,6 +117,80 @@ cnxk_tim_ring_info_get(const struct rte_event_timer_adapter *adptr,
 		   sizeof(struct rte_event_timer_adapter_conf));
 }
 
+static inline void
+sort_multi_array(double ref_arr[], uint64_t arr1[], uint64_t arr2[],
+		 uint64_t arr3[], uint8_t sz)
+{
+	int x;
+
+	for (x = 0; x < sz - 1; x++) {
+		if (ref_arr[x] > ref_arr[x + 1]) {
+			PLT_SWAP(ref_arr[x], ref_arr[x + 1]);
+			PLT_SWAP(arr1[x], arr1[x + 1]);
+			PLT_SWAP(arr2[x], arr2[x + 1]);
+			PLT_SWAP(arr3[x], arr3[x + 1]);
+			x = -1;
+		}
+	}
+}
+
+static inline void
+populate_sample(uint64_t tck[], uint64_t ns[], double diff[], uint64_t dst[],
+		uint64_t req_tck, uint64_t clk_freq, double tck_ns, uint8_t sz,
+		bool mov_fwd)
+{
+	int i;
+
+	for (i = 0; i < sz; i++) {
+		tck[i] = i ? tck[i - 1] : req_tck;
+		do {
+			mov_fwd ? tck[i]++ : tck[i]--;
+			ns[i] = round((double)tck[i] * tck_ns);
+			if (round((double)tck[i] * tck_ns) >
+			    ((double)tck[i] * tck_ns))
+				continue;
+		} while (ns[i] % (uint64_t)cnxk_tim_ns_per_tck(clk_freq));
+		diff[i] = PLT_MAX((double)ns[i], (double)tck[i] * tck_ns) -
+			  PLT_MIN((double)ns[i], (double)tck[i] * tck_ns);
+		dst[i] = mov_fwd ? tck[i] - req_tck : req_tck - tck[i];
+	}
+}
+
+static void
+tim_adjust_resolution(uint64_t *req_ns, uint64_t *req_tck, double tck_ns,
+		      uint64_t clk_freq, uint64_t max_tmo, uint64_t m_tck)
+{
+#define MAX_SAMPLES 5
+	double rmax_diff[MAX_SAMPLES], rmin_diff[MAX_SAMPLES];
+	uint64_t min_tck[MAX_SAMPLES], max_tck[MAX_SAMPLES];
+	uint64_t min_dst[MAX_SAMPLES], max_dst[MAX_SAMPLES];
+	uint64_t min_ns[MAX_SAMPLES], max_ns[MAX_SAMPLES];
+	int i;
+
+	populate_sample(max_tck, max_ns, rmax_diff, max_dst, *req_tck, clk_freq,
+			tck_ns, MAX_SAMPLES, true);
+	sort_multi_array(rmax_diff, max_dst, max_tck, max_ns, MAX_SAMPLES);
+
+	populate_sample(min_tck, min_ns, rmin_diff, min_dst, *req_tck, clk_freq,
+			tck_ns, MAX_SAMPLES, false);
+	sort_multi_array(rmin_diff, min_dst, min_tck, min_ns, MAX_SAMPLES);
+
+	for (i = 0; i < MAX_SAMPLES; i++) {
+		if (min_dst[i] < max_dst[i] && min_tck[i] > m_tck &&
+		    (max_tmo / min_ns[i]) <=
+			    (TIM_MAX_BUCKET_SIZE - TIM_MIN_BUCKET_SIZE)) {
+			*req_tck = min_tck[i];
+			*req_ns = min_ns[i];
+			break;
+		} else if ((max_tmo / max_ns[i]) <
+			   (TIM_MAX_BUCKET_SIZE - TIM_MIN_BUCKET_SIZE)) {
+			*req_tck = max_tck[i];
+			*req_ns = max_ns[i];
+			break;
+		}
+	}
+}
+
 static int
 cnxk_tim_ring_create(struct rte_event_timer_adapter *adptr)
 {
@@ -178,10 +252,25 @@ cnxk_tim_ring_create(struct rte_event_timer_adapter *adptr)
 		goto tim_hw_free;
 	}
 
-	/* Round */
 	tim_ring->tck_nsec =
 		round(RTE_ALIGN_MUL_NEAR((long double)rcfg->timer_tick_ns,
 					 cnxk_tim_ns_per_tck(clk_freq)));
+	if (log10(clk_freq) - floor(log10(clk_freq)) != 0.0) {
+		uint64_t req_ns, req_tck;
+		double tck_ns;
+
+		req_ns = tim_ring->tck_nsec;
+		tck_ns = NSECPERSEC / clk_freq;
+		req_tck = round(rcfg->timer_tick_ns / tck_ns);
+		tim_adjust_resolution(&req_ns, &req_tck, tck_ns, clk_freq,
+				      rcfg->max_tmo_ns, min_intvl_cyc);
+		if ((tim_ring->tck_nsec != req_ns) &&
+		    !(rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES)) {
+			rc = -ERANGE;
+			goto tim_hw_free;
+		}
+		tim_ring->tck_nsec = ceil(req_tck * tck_ns);
+	}
 
 	tim_ring->tck_int = round((long double)tim_ring->tck_nsec /
 				  cnxk_tim_ns_per_tck(clk_freq));
@@ -489,6 +578,43 @@ cnxk_tim_parse_kvargs_dict(const char *key, const char *value, void *opaque)
 	return 0;
 }
 
+static void
+cnxk_tim_parse_clk_list(const char *value, void *opaque)
+{
+	enum roc_tim_clk_src src[] = {ROC_TIM_CLK_SRC_GPIO, ROC_TIM_CLK_SRC_PTP,
+				      ROC_TIM_CLK_SRC_SYNCE,
+				      ROC_TIM_CLK_SRC_INVALID};
+	struct cnxk_tim_evdev *dev = opaque;
+	char *str = strdup(value);
+	char *tok;
+	int i = 0;
+
+	if (!strlen(str))
+		return;
+
+	tok = strtok(str, "-");
+	while (tok != NULL && src[i] != ROC_TIM_CLK_SRC_INVALID) {
+		dev->ext_clk_freq[src[i]] = strtoull(tok, NULL, 10);
+		tok = strtok(NULL, "-");
+		i++;
+	}
+
+	free(str);
+}
+
+static int
+cnxk_tim_parse_kvargs_dsv(const char *key, const char *value, void *opaque)
+{
+	RTE_SET_USED(key);
+
+	/* DSV format GPIO-PTP-SYNCE-BTS use '-' as ','
+	 * isn't allowed. 0 represents default.
+	 */
+	cnxk_tim_parse_clk_list(value, opaque);
+
+	return 0;
+}
+
 static void
 cnxk_tim_parse_devargs(struct rte_devargs *devargs, struct cnxk_tim_evdev *dev)
 {
@@ -511,6 +637,8 @@ cnxk_tim_parse_devargs(struct rte_devargs *devargs, struct cnxk_tim_evdev *dev)
 			   &dev->min_ring_cnt);
 	rte_kvargs_process(kvlist, CNXK_TIM_RING_CTL,
 			   &cnxk_tim_parse_kvargs_dict, &dev);
+	rte_kvargs_process(kvlist, CNXK_TIM_EXT_CLK, &cnxk_tim_parse_kvargs_dsv,
+			   dev);
 
 	rte_kvargs_free(kvlist);
 }
diff --git a/drivers/event/cnxk/cnxk_tim_evdev.h b/drivers/event/cnxk/cnxk_tim_evdev.h
index 7d401fccbd..4ce22ed7a4 100644
--- a/drivers/event/cnxk/cnxk_tim_evdev.h
+++ b/drivers/event/cnxk/cnxk_tim_evdev.h
@@ -39,6 +39,7 @@
 #define CNXK_TIM_STATS_ENA   "tim_stats_ena"
 #define CNXK_TIM_RINGS_LMT   "tim_rings_lmt"
 #define CNXK_TIM_RING_CTL    "tim_ring_ctl"
+#define CNXK_TIM_EXT_CLK     "tim_eclk_freq"
 
 #define CNXK_TIM_SP	   0x1
 #define CNXK_TIM_MP	   0x2
@@ -94,6 +95,7 @@ struct cnxk_tim_evdev {
 	uint16_t min_ring_cnt;
 	uint8_t enable_stats;
 	uint16_t ring_ctl_cnt;
+	uint64_t ext_clk_freq[ROC_TIM_CLK_SRC_INVALID];
 	struct cnxk_tim_ctl *ring_ctl_data;
 };
 
@@ -237,6 +239,8 @@ cnxk_tim_get_clk_freq(struct cnxk_tim_evdev *dev, enum roc_tim_clk_src clk_src,
 	case ROC_TIM_CLK_SRC_GPIO:
 	case ROC_TIM_CLK_SRC_PTP:
 	case ROC_TIM_CLK_SRC_SYNCE:
+		*freq = dev->ext_clk_freq[clk_src];
+		break;
 	default:
 		return -EINVAL;
 	}
-- 
2.17.1


  reply	other threads:[~2021-09-23 21:31 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-28 15:24 [dpdk-dev] [PATCH] drivers: add external clock support for cnxk timer Shijith Thotton
2021-09-15 16:03 ` [dpdk-dev] [PATCH v2] " Shijith Thotton
2021-09-23 21:30   ` [dpdk-dev] [PATCH v3 1/2] event/cnxk: update min interval calculation pbhagavatula
2021-09-23 21:30     ` pbhagavatula [this message]
2021-10-09  8:04     ` [dpdk-dev] [PATCH v4 " pbhagavatula
2021-10-09  8:04       ` [dpdk-dev] [PATCH v4 2/2] event/cnxk: add external clock support for timer pbhagavatula
2021-10-14 11:51       ` [dpdk-dev] [PATCH v4 1/2] event/cnxk: update min interval calculation Jerin Jacob
2021-12-13 11:13       ` [PATCH v5 " pbhagavatula
2021-12-13 11:13         ` [PATCH v5 2/2] event/cnxk: add external clock support for timer pbhagavatula
2022-01-21 10:18         ` [PATCH v5 1/2] event/cnxk: update min interval calculation Jerin Jacob
2022-01-25  9:54         ` Ray Kinsella

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210923213046.3157-2-pbhagavatula@marvell.com \
    --to=pbhagavatula@marvell.com \
    --cc=dev@dpdk.org \
    --cc=jerinj@marvell.com \
    --cc=kirankumark@marvell.com \
    --cc=ndabilpuram@marvell.com \
    --cc=skori@marvell.com \
    --cc=skoteshwar@marvell.com \
    --cc=sthotton@marvell.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).