DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH] drivers: add external clock support for cnxk timer
@ 2021-07-28 15:24 Shijith Thotton
  2021-09-15 16:03 ` [dpdk-dev] [PATCH v2] " Shijith Thotton
  0 siblings, 1 reply; 11+ messages in thread
From: Shijith Thotton @ 2021-07-28 15:24 UTC (permalink / raw)
  To: dev
  Cc: Shijith Thotton, thomas, jerinj, pbhagavatula, Nithin Dabilpuram,
	Kiran Kumar K, Sunil Kumar Kori, Satha Rao

To configure tim with external clock, requested resolution should be
adjusted based on core and external clock frequency for accuracy.

tim_ext_clk is the devarg used to pass external clock frequency.

E.g. -a 0002:0e:00.0,tim_ext_clk=122880000

Signed-off-by: Shijith Thotton <sthotton@marvell.com>
Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com>
---
Depends-on: series-18039 ("eal: add macro to swap two numbers")

 doc/guides/eventdevs/cnxk.rst       |   9 ++
 drivers/common/cnxk/roc_platform.h  |   1 +
 drivers/event/cnxk/cnxk_tim_evdev.c | 124 ++++++++++++++++++++++++++--
 drivers/event/cnxk/cnxk_tim_evdev.h |   6 +-
 4 files changed, 131 insertions(+), 9 deletions(-)

diff --git a/doc/guides/eventdevs/cnxk.rst b/doc/guides/eventdevs/cnxk.rst
index 53560d3830..238b71f81f 100644
--- a/doc/guides/eventdevs/cnxk.rst
+++ b/doc/guides/eventdevs/cnxk.rst
@@ -164,6 +164,15 @@ Runtime Config Options
 
     -a 0002:0e:00.0,tim_ring_ctl=[2-1023-1-0]
 
+- ``TIM external clock frequency``
+
+  The ``tim_ext_clk`` devagrs can be used to pass external clock frequency when
+  external clock source is selected.
+
+  For Example::
+
+    -a 0002:0e:00.0,tim_ext_clk=122880000
+
 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/cnxk_tim_evdev.c b/drivers/event/cnxk/cnxk_tim_evdev.c
index 9d40e336d7..702686e68e 100644
--- a/drivers/event/cnxk/cnxk_tim_evdev.c
+++ b/drivers/event/cnxk/cnxk_tim_evdev.c
@@ -2,6 +2,8 @@
  * Copyright(C) 2021 Marvell.
  */
 
+#include <math.h>
+
 #include "cnxk_eventdev.h"
 #include "cnxk_tim_evdev.h"
 
@@ -115,12 +117,88 @@ 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] % cnxk_tim_min_resolution_ns(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)
+{
+#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];
+	uint64_t m_tck = cnxk_tim_min_tmo_ticks(cnxk_tim_cntfrq());
+	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)
 {
 	struct rte_event_timer_adapter_conf *rcfg = &adptr->data->conf;
 	struct cnxk_tim_evdev *dev = cnxk_tim_priv_get();
 	struct cnxk_tim_ring *tim_ring;
+	uint64_t interval;
 	int i, rc;
 
 	if (dev == NULL)
@@ -153,11 +231,35 @@ cnxk_tim_ring_create(struct rte_event_timer_adapter *adptr)
 			goto tim_hw_free;
 		}
 	}
+
 	tim_ring->ring_id = adptr->data->id;
 	tim_ring->clk_src = (int)rcfg->clk_src;
-	tim_ring->tck_nsec = RTE_ALIGN_MUL_CEIL(
-		rcfg->timer_tick_ns,
-		cnxk_tim_min_resolution_ns(cnxk_tim_cntfrq()));
+	if (rcfg->clk_src == RTE_EVENT_TIMER_ADAPTER_CPU_CLK) {
+		rcfg->timer_tick_ns = RTE_ALIGN_MUL_CEIL(
+			rcfg->timer_tick_ns,
+			cnxk_tim_min_resolution_ns(cnxk_tim_cntfrq()));
+	} else { /* External clock */
+		uint64_t req_ns, req_tck;
+		double tck_ns;
+
+		if (dev->ext_clk_frq == 0) {
+			rc = -ENODEV;
+			goto tim_hw_free;
+		}
+
+		req_ns = rcfg->timer_tick_ns;
+		tck_ns = NSECPERSEC / dev->ext_clk_frq;
+		req_tck = round(rcfg->timer_tick_ns / tck_ns);
+		tim_adjust_resolution(&req_ns, &req_tck, tck_ns,
+				      cnxk_tim_cntfrq(), rcfg->max_tmo_ns);
+		if ((rcfg->timer_tick_ns != req_ns) &&
+		    !(rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES)) {
+			rc = -ERANGE;
+			goto tim_hw_free;
+		}
+		rcfg->timer_tick_ns = ceil(req_tck * tck_ns);
+	}
+	tim_ring->tck_nsec = rcfg->timer_tick_ns;
 	tim_ring->max_tout = rcfg->max_tmo_ns;
 	tim_ring->nb_bkts = (tim_ring->max_tout / tim_ring->tck_nsec);
 	tim_ring->nb_timers = rcfg->nb_timers;
@@ -201,11 +303,15 @@ cnxk_tim_ring_create(struct rte_event_timer_adapter *adptr)
 	if (rc < 0)
 		goto tim_bkt_free;
 
-	rc = roc_tim_lf_config(
-		&dev->tim, tim_ring->ring_id,
-		cnxk_tim_convert_clk_src(tim_ring->clk_src), 0, 0,
-		tim_ring->nb_bkts, tim_ring->chunk_sz,
-		NSEC2TICK(tim_ring->tck_nsec, cnxk_tim_cntfrq()));
+	if (rcfg->clk_src == RTE_EVENT_TIMER_ADAPTER_CPU_CLK)
+		interval = NSEC2TICK(tim_ring->tck_nsec, cnxk_tim_cntfrq());
+	else
+		interval = NSEC2TICK(tim_ring->tck_nsec, dev->ext_clk_frq);
+
+	rc = roc_tim_lf_config(&dev->tim, tim_ring->ring_id,
+			       cnxk_tim_convert_clk_src(tim_ring->clk_src), 0,
+			       0, tim_ring->nb_bkts, tim_ring->chunk_sz,
+			       interval);
 	if (rc < 0) {
 		plt_err("Failed to configure timer ring");
 		goto tim_chnk_free;
@@ -480,6 +586,8 @@ cnxk_tim_parse_devargs(struct rte_devargs *devargs, struct cnxk_tim_evdev *dev)
 			   &dev->enable_stats);
 	rte_kvargs_process(kvlist, CNXK_TIM_RINGS_LMT, &parse_kvargs_value,
 			   &dev->min_ring_cnt);
+	rte_kvargs_process(kvlist, CNXK_TIM_EXT_CLK, &parse_kvargs_value,
+			   &dev->ext_clk_frq);
 	rte_kvargs_process(kvlist, CNXK_TIM_RING_CTL,
 			   &cnxk_tim_parse_kvargs_dict, &dev);
 
diff --git a/drivers/event/cnxk/cnxk_tim_evdev.h b/drivers/event/cnxk/cnxk_tim_evdev.h
index c369f6f472..b6e975dd50 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_ext_clk"
 
 #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_frq;
 	struct cnxk_tim_ctl *ring_ctl_data;
 };
 
@@ -187,7 +189,9 @@ cnxk_tim_convert_clk_src(enum cnxk_tim_clk_src clk_src)
 	switch (clk_src) {
 	case RTE_EVENT_TIMER_ADAPTER_CPU_CLK:
 		return roc_model_runtime_is_cn9k() ? ROC_TIM_CLK_SRC_10NS :
-							   ROC_TIM_CLK_SRC_GTI;
+						     ROC_TIM_CLK_SRC_GTI;
+	case RTE_EVENT_TIMER_ADAPTER_EXT_CLK0:
+		return ROC_TIM_CLK_SRC_GPIO;
 	default:
 		return ROC_TIM_CLK_SRC_INVALID;
 	}
-- 
2.25.1


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

end of thread, other threads:[~2022-01-25  9:54 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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     ` [dpdk-dev] [PATCH v3 2/2] event/cnxk: add external clock support for timer pbhagavatula
2021-10-09  8:04     ` [dpdk-dev] [PATCH v4 1/2] event/cnxk: update min interval calculation 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

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).