[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,
+    ],
+  )
+)