[sw, dif_aon_timer] Introduce DIF AON Timer library
This change introduces public API for the AON Timer peripheral. It
also adds register definitions generation and blank implementation
to make this library compile.
Signed-off-by: Silvestrs Timofejevs <silvestrst@lowrisc.org>
diff --git a/hw/ip/aon_timer/data/aon_timer.prj.hjson b/hw/ip/aon_timer/data/aon_timer.prj.hjson
index 116f51c..0028b5f 100644
--- a/hw/ip/aon_timer/data/aon_timer.prj.hjson
+++ b/hw/ip/aon_timer/data/aon_timer.prj.hjson
@@ -7,8 +7,10 @@
design_spec: "hw/ip/aon_timer/doc",
dv_doc: "",
hw_checklist: "",
+ sw_checklist: "sw/device/lib/dif/dif_aon_timer",
version: "0.1",
life_stage: "L0",
design_stage: "D0",
verification_stage: "V0",
+ dif_stage: "S0",
}
diff --git a/meson.build b/meson.build
index 9a6fd3e..2b12355 100644
--- a/meson.build
+++ b/meson.build
@@ -180,6 +180,7 @@
# TODO: Considering moving these into hw/ip directories.
hw_ip_aes_reg_h = gen_hw_hdr.process('hw/ip/aes/data/aes.hjson')
hw_ip_alert_handler_reg_h = gen_hw_hdr.process('hw/ip/alert_handler/data/alert_handler.hjson')
+hw_ip_aon_timer_reg_h = gen_hw_hdr.process('hw/ip/aon_timer/data/aon_timer.hjson')
hw_ip_clkgmr_reg_h = gen_hw_hdr.process('hw/top_earlgrey/ip/clkmgr/data/autogen/clkmgr.hjson')
hw_ip_flash_ctrl_reg_h = gen_hw_hdr.process('hw/top_earlgrey/ip/flash_ctrl/data/autogen/flash_ctrl.hjson')
hw_ip_gpio_reg_h = gen_hw_hdr.process('hw/ip/gpio/data/gpio.hjson')
diff --git a/sw/device/lib/dif/dif_aon_timer.c b/sw/device/lib/dif/dif_aon_timer.c
new file mode 100644
index 0000000..55168f6
--- /dev/null
+++ b/sw/device/lib/dif/dif_aon_timer.c
@@ -0,0 +1,10 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "sw/device/lib/dif/dif_aon_timer.h"
+
+#include "aon_timer_regs.h" // Generated.
+
+// This just exists to check that the header compiles for now. The actual
+// implementation is work in progress.
diff --git a/sw/device/lib/dif/dif_aon_timer.h b/sw/device/lib/dif/dif_aon_timer.h
new file mode 100644
index 0000000..d6b652f
--- /dev/null
+++ b/sw/device/lib/dif/dif_aon_timer.h
@@ -0,0 +1,294 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_AON_TIMER_H_
+#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_AON_TIMER_H_
+
+/**
+ * @file
+ * @brief <a href="/hw/ip/aon_timer/doc/">Always-On Timer</a> Device Interface
+ * Functions
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_warn_unused_result.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * Hardware instantiation parameters for Always-On Timer.
+ *
+ * This struct describes information about the underlying hardware that is
+ * not determined until the hardware design is used as part of a top-level
+ * design.
+ */
+typedef struct dif_aon_timer_params {
+ /**
+ * The base address for the Always-On Timer hardware registers.
+ */
+ mmio_region_t base_addr;
+} dif_aon_timer_params_t;
+
+/**
+ * A handle to Always-On Timer.
+ *
+ * This type should be treated as opaque by users.
+ */
+typedef struct dif_aon_timer {
+ dif_aon_timer_params_t params;
+} dif_aon_timer_t;
+
+/**
+ * The result of a Always-On Timer operation.
+ */
+typedef enum dif_aon_timer_result {
+ /**
+ * Indicates that the operation succeeded.
+ */
+ kDifAonTimerOk = 0,
+ /**
+ * Indicates some unspecified failure.
+ */
+ kDifAonTimerError = 1,
+ /**
+ * Indicates that some parameter passed into a function failed a
+ * precondition.
+ *
+ * When this value is returned, no hardware operations occurred.
+ */
+ kDifAonTimerBadArg = 2,
+} dif_aon_timer_result_t;
+
+/**
+ * The result of a Always-On Timer (watchdog timer) operation.
+ */
+typedef enum dif_aon_timer_watchdog_result {
+ /**
+ * Indicates that the operation succeeded.
+ */
+ kDifAonTimerWatchdogOk = kDifAonTimerOk,
+ /**
+ * Indicates some unspecified failure.
+ */
+ kDifAonTimerWatchdogError = kDifAonTimerError,
+ /**
+ * Indicates that some parameter passed into a function failed a
+ * precondition.
+ *
+ * When this value is returned, no hardware operations occurred.
+ */
+ kDifAonTimerWatchdogBadArg = kDifAonTimerBadArg,
+ /**
+ * Indicates that this operation has been locked out, and can never
+ * succeed until hardware reset.
+ */
+ kDifAonTimerWatchdogLocked = 3,
+} dif_aon_timer_watchdog_result_t;
+
+/**
+ * An Always-On Timer interrupt request type.
+ */
+typedef enum dif_aon_timer_irq {
+ /**
+ * Wake-up timer has expired.
+ */
+ kDifAonTimerIrqWakeupThreshold = 0,
+ /**
+ * Watchdog timer "Bark" threshold has expired.
+ */
+ kDifAonTimerIrqWatchdogBarkThreshold,
+} dif_aon_timer_irq_t;
+
+/**
+ * Creates a new handle for Always-On Timer.
+ *
+ * This function does not actuate the hardware.
+ *
+ * @param params Hardware instantiation parameters.
+ * @param[out] aon Out param for the initialised handle.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_result_t dif_aon_timer_init(dif_aon_timer_params_t params,
+ dif_aon_timer_t *aon);
+
+/** Starts Always-On Timer (wake-up timer).
+ *
+ * @param aon An Always-On Timer handle.
+ * @param threshold Threshold in ticks.
+ * @param prescaler 12 bit pre-scaler to enable very long timeouts (one tick
+ * every N + 1 clock cycles, where N is the pre-scaler value).
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_result_t dif_aon_timer_wakeup_start(const dif_aon_timer_t *aon,
+ uint32_t threshold,
+ uint32_t prescaler);
+
+/** Stops Always-On Timer (wake-up timer).
+ *
+ * Stops the timer. Configuration is not touched, and can be restarted via
+ * `dif_aon_timer_wakeup_restart`.
+ *
+ * @param aon An Always-On Timer handle.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_result_t dif_aon_timer_wakeup_stop(const dif_aon_timer_t *aon);
+
+/** Restarts Always-On Timer (wake-up timer).
+ *
+ * Clears the counter and restarts the timer using the existing configuration.
+ *
+ * @param aon An Always-On Timer handle.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_result_t dif_aon_timer_wakeup_restart(const dif_aon_timer_t *aon);
+
+/** Retrieves Always-On Timer (wake-up timer) tick count.
+ *
+ * @param aon An Always-On Timer handle.
+ * @param[out] count Current timer tick count.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_result_t dif_aon_timer_wakeup_get_count(
+ const dif_aon_timer_t *aon, uint32_t *count);
+
+/** Starts Always-On Timer (watchdog timer).
+ *
+ * @param aon An Always-On Timer handle.
+ * @param bark_threshold "Bark" threshold in ticks.
+ * @param bite_threshold "Bite" threshold in ticks.
+ * @param pause_in_sleep Watchdog is paused when device is in one of the low
+ * power modes.
+ * @param lock Lock access to watchdog configuration registers.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_watchdog_result_t dif_aon_timer_watchdog_start(
+ const dif_aon_timer_t *aon, uint32_t bark_threshold,
+ uint32_t bite_threshold, bool pause_in_sleep, bool lock);
+
+/** Stops Always-On Timer (watchdog timer).
+ *
+ * Stops the timer. Configuration is not touched, and can be restarted via
+ * `dif_aon_timer_watchdog_restart`.
+ *
+ * @param aon An Always-On Timer handle.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_watchdog_result_t dif_aon_timer_watchdog_stop(
+ const dif_aon_timer_t *aon);
+
+/** Restarts Always-On Timer (watchdog timer).
+ *
+ * Clears the counter and restarts the timer using the existing configuration.
+ *
+ * @param aon An Always-On Timer handle.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_watchdog_result_t dif_aon_timer_watchdog_restart(
+ const dif_aon_timer_t *aon);
+
+/** Retrieves Always-On Timer (watchdog timer) tick count.
+ *
+ * @param aon An Always-On Timer handle.
+ * @param[out] count Current timer tick count.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_result_t dif_aon_timer_watchdog_get_count(
+ const dif_aon_timer_t *aon, uint32_t *count);
+
+/** Clears Always-On Timer (watchdog timer).
+ *
+ * This function must be called periodically to satisfy "Bite" and "Bark"
+ * thresholds. The semantics of this function are similar to
+ * `dif_aon_timer_watchdog_restart`, however it does not write to the control
+ * register, and is guaranteed to succeed even when the watchdog is locked.
+ *
+ * @param aon An Always-On Timer handle.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_result_t dif_aon_timer_watchdog_pet(const dif_aon_timer_t *aon);
+
+/**
+ * Locks Always-On Timer (watchdog timer).
+ *
+ * The watchdog configuration will be locked until the next reset. This means
+ * that this timer cannot be stopped, restarted or reconfigured, however the
+ * count can be cleared via `dif_aon_timer_watchdog_pet`.
+ *
+ * @param aon An Always-On Timer handle.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_watchdog_result_t dif_aon_timer_watchdog_lock(
+ const dif_aon_timer_t *aon);
+
+/**
+ * Checks whether this Always-On Timer (watchdog timer) is locked.
+ *
+ * @param aon An Always-On Timer handle.
+ * @param[out] is_locked Out-param for the locked state.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_watchdog_result_t dif_aon_timer_watchdog_is_locked(
+ const dif_aon_timer_t *aon, bool *is_locked);
+
+/**
+ * Returns whether a particular interrupt is currently pending.
+ *
+ * @param aon An Always-On Timer handle.
+ * @param irq An interrupt type.
+ * @param[out] is_pending Out-param for whether the interrupt is pending.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_result_t dif_aon_timer_irq_is_pending(const dif_aon_timer_t *aon,
+ dif_aon_timer_irq_t irq,
+ bool *is_pending);
+
+/**
+ * Acknowledges a particular interrupt.
+ *
+ * This operation indicates to the hardware that the interrupt has been
+ * successfully serviced.
+ *
+ * @param aon An Always-On Timer handle.
+ * @param irq An interrupt type.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_result_t dif_aon_timer_irq_acknowledge(const dif_aon_timer_t *aon,
+ dif_aon_timer_irq_t irq);
+
+/**
+ * Forces a particular interrupt, causing it to be serviced as if hardware had
+ * asserted it.
+ *
+ * @param aon An Always-On Timer handle.
+ * @param irq An interrupt type.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_aon_timer_result_t dif_aon_timer_irq_force(const dif_aon_timer_t *aon,
+ dif_aon_timer_irq_t irq);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_AON_TIMER_H_
diff --git a/sw/device/lib/dif/dif_aon_timer.md b/sw/device/lib/dif/dif_aon_timer.md
new file mode 100644
index 0000000..2343a3a
--- /dev/null
+++ b/sw/device/lib/dif/dif_aon_timer.md
@@ -0,0 +1,63 @@
+---
+title: "Always-On Timer DIF Checklist"
+---
+
+This checklist is for [Development Stage]({{< relref "/doc/project/development_stages.md" >}}) transitions for the [Always-On Timer DIF]({{< relref "hw/ip/aon_timer/doc" >}}).
+All checklist items refer to the content in the [Checklist]({{< relref "/doc/project/checklist.md" >}}).
+
+
+
+Type | Item | Resolution | Note/Collaterals
+---------------|----------------------|-------------|------------------
+Implementation | [DIF_EXISTS][] | Started |
+Implementation | [DIF_USED_IN_TREE][] | Not Started |
+Tests | [DIF_TEST_UNIT][] | Not Started |
+Tests | [DIF_TEST_SMOKE][] | Not Started |
+
+[DIF_EXISTS]: {{< relref "/doc/project/checklist.md#dif_exists" >}}
+[DIF_USED_IN_TREE]: {{< relref "/doc/project/checklist.md#dif_used_in_tree" >}}
+[DIF_TEST_UNIT]: {{< relref "/doc/project/checklist.md#dif_test_unit" >}}
+[DIF_TEST_SMOKE]: {{< relref "/doc/project/checklist.md#dif_test_smoke" >}}
+
+
+Type | Item | Resolution | Note/Collaterals
+---------------|-----------------------------|-------------|------------------
+Implementation | [DIF_FEATURES][] | Not Started |
+Coordination | [DIF_HW_USAGE_REVIEWED][] | Not Started |
+Coordination | [DIF_HW_FEATURE_COMPLETE][] | Not Started | [HW Dashboard]({{< relref "hw" >}})
+Implementation | [DIF_HW_PARAMS][] | Not Started |
+Documentation | [DIF_DOC_HW][] | Not Started |
+Documentation | [DIF_DOC_API][] | Not Started |
+Code Quality | [DIF_CODE_STYLE][] | Not Started |
+Coordination | [DIF_DV_TESTS][] | Not Started |
+Implementation | [DIF_USED_TOCK][] | Not Started |
+Review | HW IP Usage Reviewer(s) | Not Started |
+
+[DIF_FEATURES]: {{< relref "/doc/project/checklist.md#dif_features" >}}
+[DIF_HW_USAGE_REVIEWED]: {{< relref "/doc/project/checklist.md#dif_hw_usage_reviewed" >}}
+[DIF_HW_FEATURE_COMPLETE]: {{< relref "/doc/project/checklist.md#dif_hw_feature_complete" >}}
+[DIF_HW_PARAMS]: {{< relref "/doc/project/checklist.md#dif_hw_params" >}}
+[DIF_DOC_HW]: {{< relref "/doc/project/checklist.md#dif_doc_hw" >}}
+[DIF_DOC_API]: {{< relref "/doc/project/checklist.md#dif_doc_api" >}}
+[DIF_CODE_STYLE]: {{< relref "/doc/project/checklist.md#dif_code_style" >}}
+[DIF_DV_TESTS]: {{< relref "/doc/project/checklist.md#dif_dv_tests" >}}
+[DIF_USED_TOCK]: {{< relref "/doc/project/checklist.md#dif_used_tock" >}}
+
+
+Type | Item | Resolution | Note/Collaterals
+---------------|----------------------------------|-------------|------------------
+Coordination | [DIF_HW_DESIGN_COMPLETE][] | Not Started |
+Coordination | [DIF_HW_VERIFICATION_COMPLETE][] | Not Started |
+Review | [DIF_REVIEW_C_STABLE][] | Not Started |
+Tests | [DIF_TEST_UNIT_COMPLETE][] | Not Started |
+Review | [DIF_TODO_COMPLETE][] | Not Started |
+Review | [DIF_REVIEW_TOCK_STABLE][] | Not Started |
+Review | Reviewer(s) | Not Started |
+Review | Signoff date | Not Started |
+
+[DIF_HW_DESIGN_COMPLETE]: {{< relref "/doc/project/checklist.md#dif_hw_design_complete" >}}
+[DIF_HW_VERIFICATION_COMPLETE]: {{< relref "/doc/project/checklist.md#dif_hw_verification_complete" >}}
+[DIF_REVIEW_C_STABLE]: {{< relref "/doc/project/checklist.md#dif_review_c_stable" >}}
+[DIF_TEST_UNIT_COMPLETE]: {{< relref "/doc/project/checklist.md#dif_test_unit_complete" >}}
+[DIF_TODO_COMPLETE]: {{< relref "/doc/project/checklist.md#dif_todo_complete" >}}
+[DIF_REVIEW_TOCK_STABLE]: {{< relref "/doc/project/checklist.md#dif_review_tock_stable" >}}
diff --git a/sw/device/lib/dif/meson.build b/sw/device/lib/dif/meson.build
index ff6a5f4..b748e7a 100644
--- a/sw/device/lib/dif/meson.build
+++ b/sw/device/lib/dif/meson.build
@@ -217,3 +217,18 @@
],
)
)
+
+# Always-On Timer library
+sw_lib_dif_aon_timer = declare_dependency(
+ link_with: static_library(
+ 'sw_lib_dif_aon_timer',
+ sources: [
+ hw_ip_aon_timer_reg_h,
+ 'dif_aon_timer.c',
+ ],
+ dependencies: [
+ sw_lib_mmio,
+ sw_lib_bitfield,
+ ],
+ )
+)