roc_tim_lf_config(struct roc_tim *roc_tim, uint8_t ring_id,
enum roc_tim_clk_src clk_src, uint8_t ena_periodic,
uint8_t ena_dfb, uint32_t bucket_sz, uint32_t chunk_sz,
- uint32_t interval)
+ uint32_t interval, uint64_t intervalns, uint64_t clockfreq)
{
struct dev *dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev;
struct tim_config_req *req;
req->enableperiodic = ena_periodic;
req->enabledontfreebuffer = ena_dfb;
req->interval = interval;
+ req->intervalns = intervalns;
+ req->clockfreq = clockfreq;
req->gpioedge = TIM_GPIO_LTOH_TRANS;
rc = mbox_process(dev->mbox);
return 0;
}
+int
+roc_tim_lf_interval(struct roc_tim *roc_tim, enum roc_tim_clk_src clk_src,
+ uint64_t clockfreq, uint64_t *intervalns,
+ uint64_t *interval)
+{
+ struct dev *dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev;
+ struct tim_intvl_req *req;
+ struct tim_intvl_rsp *rsp;
+ int rc = -ENOSPC;
+
+ req = mbox_alloc_msg_tim_get_min_intvl(dev->mbox);
+ if (req == NULL)
+ return rc;
+
+ req->clockfreq = clockfreq;
+ req->clocksource = clk_src;
+ rc = mbox_process_msg(dev->mbox, (void **)&rsp);
+ if (rc < 0) {
+ tim_err_desc(rc);
+ return rc;
+ }
+
+ *intervalns = rsp->intvl_ns;
+ *interval = rsp->intvl_cyc;
+
+ return 0;
+}
+
int
roc_tim_lf_alloc(struct roc_tim *roc_tim, uint8_t ring_id, uint64_t *clk)
{
ROC_TIM_CLK_SRC_GPIO,
ROC_TIM_CLK_SRC_GTI,
ROC_TIM_CLK_SRC_PTP,
+ ROC_TIM_CLK_SRC_SYNCE,
+ ROC_TIM_CLK_SRC_BTS,
ROC_TIM_CLK_SRC_INVALID,
};
enum roc_tim_clk_src clk_src,
uint8_t ena_periodic, uint8_t ena_dfb,
uint32_t bucket_sz, uint32_t chunk_sz,
- uint32_t interval);
+ uint32_t interval, uint64_t intervalns,
+ uint64_t clockfreq);
+int __roc_api roc_tim_lf_interval(struct roc_tim *roc_tim,
+ enum roc_tim_clk_src clk_src,
+ uint64_t clockfreq, uint64_t *intervalns,
+ uint64_t *interval);
int __roc_api roc_tim_lf_alloc(struct roc_tim *roc_tim, uint8_t ring_id,
uint64_t *clk);
int __roc_api roc_tim_lf_free(struct roc_tim *roc_tim, uint8_t ring_id);
roc_tim_lf_disable;
roc_tim_lf_enable;
roc_tim_lf_free;
+ roc_tim_lf_interval;
roc_se_ctx_swap;
roc_ree_af_reg_read;
roc_ree_af_reg_write;
* Copyright(C) 2021 Marvell.
*/
+#include <math.h>
+
#include "cnxk_eventdev.h"
#include "cnxk_tim_evdev.h"
{
struct rte_event_timer_adapter_conf *rcfg = &adptr->data->conf;
struct cnxk_tim_evdev *dev = cnxk_tim_priv_get();
+ uint64_t min_intvl_ns, min_intvl_cyc;
struct cnxk_tim_ring *tim_ring;
+ enum roc_tim_clk_src clk_src;
+ uint64_t clk_freq = 0;
int i, rc;
if (dev == NULL)
goto tim_ring_free;
}
- if (NSEC2TICK(RTE_ALIGN_MUL_CEIL(
- rcfg->timer_tick_ns,
- cnxk_tim_min_resolution_ns(cnxk_tim_cntfrq())),
- cnxk_tim_cntfrq()) <
- cnxk_tim_min_tmo_ticks(cnxk_tim_cntfrq())) {
- if (rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES)
- rcfg->timer_tick_ns = TICK2NSEC(
- cnxk_tim_min_tmo_ticks(cnxk_tim_cntfrq()),
- cnxk_tim_cntfrq());
- else {
+ clk_src = cnxk_tim_convert_clk_src(rcfg->clk_src);
+ if (clk_src == ROC_TIM_CLK_SRC_INVALID) {
+ plt_err("Invalid clock source");
+ goto tim_hw_free;
+ }
+
+ rc = cnxk_tim_get_clk_freq(dev, clk_src, &clk_freq);
+ if (rc < 0) {
+ plt_err("Failed to get clock frequency");
+ goto tim_hw_free;
+ }
+
+ rc = roc_tim_lf_interval(&dev->tim, clk_src, clk_freq, &min_intvl_ns,
+ &min_intvl_cyc);
+ if (rc < 0) {
+ plt_err("Failed to get min interval details");
+ goto tim_hw_free;
+ }
+
+ if (rcfg->timer_tick_ns < min_intvl_ns) {
+ if (rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES) {
+ rcfg->timer_tick_ns = min_intvl_ns;
+ } else {
rc = -ERANGE;
goto tim_hw_free;
}
}
+
+ if (rcfg->timer_tick_ns > rcfg->max_tmo_ns) {
+ plt_err("Max timeout to too high");
+ rc = -ERANGE;
+ 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)));
+
+ tim_ring->tck_int = round((long double)tim_ring->tck_nsec /
+ cnxk_tim_ns_per_tck(clk_freq));
+ tim_ring->tck_nsec =
+ ceil(tim_ring->tck_int * cnxk_tim_ns_per_tck(clk_freq));
+
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()));
+ tim_ring->clk_src = clk_src;
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;
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()));
+ rc = roc_tim_lf_config(&dev->tim, tim_ring->ring_id, clk_src, 0, 0,
+ tim_ring->nb_bkts, tim_ring->chunk_sz,
+ tim_ring->tck_int, tim_ring->tck_nsec, clk_freq);
if (rc < 0) {
plt_err("Failed to configure timer ring");
goto tim_chnk_free;
if (rc < 0)
return rc;
- tim_ring->tck_int = NSEC2TICK(tim_ring->tck_nsec, cnxk_tim_cntfrq());
tim_ring->tot_int = tim_ring->tck_int * tim_ring->nb_bkts;
tim_ring->fast_div = rte_reciprocal_value_u64(tim_ring->tck_int);
tim_ring->fast_bkt = rte_reciprocal_value_u64(tim_ring->nb_bkts);
struct cnxk_tim_ctl *ring_ctl_data;
};
-enum cnxk_tim_clk_src {
- CNXK_TIM_CLK_SRC_10NS = RTE_EVENT_TIMER_ADAPTER_CPU_CLK,
- CNXK_TIM_CLK_SRC_GPIO = RTE_EVENT_TIMER_ADAPTER_EXT_CLK0,
- CNXK_TIM_CLK_SRC_GTI = RTE_EVENT_TIMER_ADAPTER_EXT_CLK1,
- CNXK_TIM_CLK_SRC_PTP = RTE_EVENT_TIMER_ADAPTER_EXT_CLK2,
-};
-
struct cnxk_tim_bkt {
uint64_t first_chunk;
union {
uint64_t max_tout;
uint64_t nb_chunks;
uint64_t chunk_sz;
- enum cnxk_tim_clk_src clk_src;
+ enum roc_tim_clk_src clk_src;
} __rte_cache_aligned;
struct cnxk_tim_ent {
return mz->addr;
}
-static inline uint64_t
-cnxk_tim_min_tmo_ticks(uint64_t freq)
+static inline long double
+cnxk_tim_ns_per_tck(uint64_t freq)
{
- if (roc_model_runtime_is_cn9k())
- return CN9K_TIM_MIN_TMO_TKS;
- else /* CN10K min tick is of 1us */
- return freq / USECPERSEC;
-}
-
-static inline uint64_t
-cnxk_tim_min_resolution_ns(uint64_t freq)
-{
- return NSECPERSEC / freq;
-}
-
-static inline enum roc_tim_clk_src
-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;
- default:
- return ROC_TIM_CLK_SRC_INVALID;
- }
+ return (long double)NSECPERSEC / freq;
}
#ifdef RTE_ARCH_ARM64
}
#endif
+static inline enum roc_tim_clk_src
+cnxk_tim_convert_clk_src(enum rte_event_timer_adapter_clk_src clk_src)
+{
+ switch (clk_src) {
+ case RTE_EVENT_TIMER_ADAPTER_CPU_CLK:
+ return ROC_TIM_CLK_SRC_GTI;
+ case RTE_EVENT_TIMER_ADAPTER_EXT_CLK0:
+ return ROC_TIM_CLK_SRC_10NS;
+ case RTE_EVENT_TIMER_ADAPTER_EXT_CLK1:
+ return ROC_TIM_CLK_SRC_GPIO;
+ case RTE_EVENT_TIMER_ADAPTER_EXT_CLK2:
+ return ROC_TIM_CLK_SRC_PTP;
+ case RTE_EVENT_TIMER_ADAPTER_EXT_CLK3:
+ return roc_model_constant_is_cn9k() ? ROC_TIM_CLK_SRC_INVALID :
+ ROC_TIM_CLK_SRC_SYNCE;
+ default:
+ return ROC_TIM_CLK_SRC_INVALID;
+ }
+}
+
+static inline int
+cnxk_tim_get_clk_freq(struct cnxk_tim_evdev *dev, enum roc_tim_clk_src clk_src,
+ uint64_t *freq)
+{
+ if (freq == NULL)
+ return -EINVAL;
+
+ PLT_SET_USED(dev);
+ switch (clk_src) {
+ case ROC_TIM_CLK_SRC_GTI:
+ *freq = cnxk_tim_cntfrq();
+ break;
+ case ROC_TIM_CLK_SRC_10NS:
+ *freq = 1E8;
+ break;
+ case ROC_TIM_CLK_SRC_GPIO:
+ case ROC_TIM_CLK_SRC_PTP:
+ case ROC_TIM_CLK_SRC_SYNCE:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
#define TIM_ARM_FASTPATH_MODES \
FP(sp, 0, 0, 0, CNXK_TIM_ENA_DFB | CNXK_TIM_SP) \
FP(mp, 0, 0, 1, CNXK_TIM_ENA_DFB | CNXK_TIM_MP) \