aboutsummaryrefslogtreecommitdiff
path: root/module/timer
diff options
context:
space:
mode:
authorElieva Pignat <Elieva.Pignat@arm.com>2018-06-14 17:45:50 +0100
committerdavidcunado-arm <david.cunado@arm.com>2018-07-25 11:35:23 +0100
commit9be0a173bade11b78fad74fd8181623eeeb096ce (patch)
tree345d88004d122276c64ccd8ebb609e14aeafb8f3 /module/timer
parenta8114e3b5b55688d362d2ea862253bc8caa0ab16 (diff)
timer: add function to get the remaining ticks of next alarm
Change-Id: I339715bf64ba38b6c1b0473419e55eed4e330e68 Signed-off-by: Elieva Pignat <Elieva.Pignat@arm.com>
Diffstat (limited to 'module/timer')
-rw-r--r--module/timer/include/mod_timer.h21
-rw-r--r--module/timer/src/mod_timer.c70
2 files changed, 84 insertions, 7 deletions
diff --git a/module/timer/include/mod_timer.h b/module/timer/include/mod_timer.h
index 3ba4a525..1caca802 100644
--- a/module/timer/include/mod_timer.h
+++ b/module/timer/include/mod_timer.h
@@ -223,6 +223,27 @@ struct mod_timer_api {
int (*remaining)(fwk_id_t dev_id,
uint64_t timestamp,
uint64_t *remaining_ticks);
+
+ /*!
+ * \brief Get the number of ticks before the next alarm trigger of a given
+ * timer.
+ *
+ * \warning If the timer has no active alarm, \p remaining_ticks is not
+ * initialized.
+ *
+ * \param dev_id Element identifier that identifies the timer device.
+ * \param [out] has_alarm \c true if the timer has an active alarm,
+ * otherwise \c false.
+ * \param [out] remaining_ticks Number of ticks between now and the next
+ * alarm trigger of the timer identified by \p dev_id.
+ *
+ * \retval FWK_SUCCESS Operation succeeded.
+ * \retval FWK_E_PARAM One of the parameters is invalid.
+ * \return One of the other specific error codes described by the framework.
+ */
+ int (*get_next_alarm_remaining)(fwk_id_t dev_id,
+ bool *has_alarm,
+ uint64_t *remaining_ticks);
};
/*!
diff --git a/module/timer/src/mod_timer.c b/module/timer/src/mod_timer.c
index 2b61cd26..a80e4901 100644
--- a/module/timer/src/mod_timer.c
+++ b/module/timer/src/mod_timer.c
@@ -11,6 +11,7 @@
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
+#include <fwk_assert.h>
#include <fwk_element.h>
#include <fwk_errno.h>
#include <fwk_event.h>
@@ -119,6 +120,29 @@ static int _timestamp_from_now(struct dev_ctx *ctx,
return FWK_SUCCESS;
}
+static int _remaining(const struct dev_ctx *ctx,
+ uint64_t timestamp,
+ uint64_t *remaining_ticks)
+{
+ int status;
+ uint64_t counter;
+
+ fwk_assert(ctx != NULL);
+ fwk_assert(remaining_ticks != NULL);
+
+ status = ctx->driver->get_counter(ctx->driver_dev_id, &counter);
+ if (!fwk_expect(status == FWK_SUCCESS))
+ return status;
+
+ /* If timestamp is in the past, remaining_ticks is set to zero. */
+ if (timestamp < counter)
+ *remaining_ticks = 0;
+ else
+ *remaining_ticks = timestamp - counter;
+
+ return FWK_SUCCESS;
+}
+
static void _configure_timer_with_next_alarm(struct dev_ctx *ctx)
{
struct alarm_ctx *alarm_head;
@@ -309,7 +333,6 @@ static int remaining(fwk_id_t dev_id,
{
struct dev_ctx *ctx;
int status;
- uint64_t counter;
status = fwk_module_check_call(dev_id);
if (status != FWK_SUCCESS)
@@ -320,16 +343,48 @@ static int remaining(fwk_id_t dev_id,
if (remaining_ticks == NULL)
return FWK_E_PARAM;
- status = ctx->driver->get_counter(ctx->driver_dev_id, &counter);
+ return _remaining(ctx, timestamp, remaining_ticks);
+}
+
+static int get_next_alarm_remaining(fwk_id_t dev_id,
+ bool *has_alarm,
+ uint64_t *remaining_ticks)
+{
+ int status;
+ const struct dev_ctx *ctx;
+ const struct alarm_ctx *alarm_ctx;
+ const struct fwk_dlist_node *alarm_ctx_node;
+
+ status = fwk_module_check_call(dev_id);
if (status != FWK_SUCCESS)
return status;
- if (timestamp <= counter)
- *remaining_ticks = 0;
- else
- *remaining_ticks = timestamp - counter;
+ if (has_alarm == NULL)
+ return FWK_E_PARAM;
- return FWK_SUCCESS;
+ if (remaining_ticks == NULL)
+ return FWK_E_PARAM;
+
+ ctx = &ctx_table[fwk_id_get_element_idx(dev_id)];
+
+ /*
+ * The timer interrupt is disabled to ensure that the alarm list is not
+ * modified while we are trying to read it below.
+ */
+ ctx->driver->disable(ctx->driver_dev_id);
+
+ *has_alarm = !fwk_list_is_empty(&ctx->alarms_active);
+
+ if (*has_alarm) {
+ alarm_ctx_node = fwk_list_head(&ctx->alarms_active);
+ alarm_ctx = FWK_LIST_GET(alarm_ctx_node, struct alarm_ctx, node);
+
+ status = _remaining(ctx, alarm_ctx->timestamp, remaining_ticks);
+ }
+
+ ctx->driver->enable(ctx->driver_dev_id);
+
+ return status;
}
static const struct mod_timer_api timer_api = {
@@ -339,6 +394,7 @@ static const struct mod_timer_api timer_api = {
.delay = delay,
.wait = wait,
.remaining = remaining,
+ .get_next_alarm_remaining = get_next_alarm_remaining,
};
/*