feat: add support for lib based timer ops

Add timer functions based on POSIX clock_gettime().
Add option in CMake to use these functions.

Signed-off-by: Matthew Ellis <Matthew.Ellis@arm.com>
Change-Id: I8a08e1fc2f88bed823d802240d2846d546e817fe
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a89f4f3..718e785 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,6 +41,9 @@
 set(DEBUG_BACKEND_HEADER "log_backend_printf.h" CACHE STRING "Path to debug backend header")
 add_compile_definitions(DEBUG_BACKEND_HEADER="${DEBUG_BACKEND_HEADER}")
 
+set (LIB_TIMER "NONE" CACHE STRING "Option to use library timer, rather than explicitly pass one")
+set_property (CACHE LIB_TIMER PROPERTY STRINGS "NONE" "POSIX")
+
 
 SET(TARGET_GROUP release CACHE STRING "Specify the Build Target [\"release\" by default]")
 
@@ -68,6 +71,15 @@
    message(FATAL_ERROR "Unknown transport interface selected")
 endif()
 
+if (${LIB_TIMER} STREQUAL "POSIX")
+   target_sources (tpm2
+       PRIVATE
+          ${PROJECT_SOURCE_DIR}/src/timer/posix_timer_ops.c
+   )
+   add_compile_definitions (HAS_LIB_TIMER=1)
+endif()
+
+
 target_include_directories(tpm2
     PUBLIC
         $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
diff --git a/include/tpm2_private.h b/include/tpm2_private.h
index d5461da..17e925c 100644
--- a/include/tpm2_private.h
+++ b/include/tpm2_private.h
@@ -116,4 +116,12 @@
 
 int tpm2_fifo_read_chunk(uint16_t tpm_reg, uint8_t len, void *val);
 
+/* HAS_LIB_TIMER is set if a standard library (e.g. POSIX) timer supplies
+ * the timeout functions, rather than being passed explicitly to the TPM
+ * library.
+ */
+#ifdef HAS_LIB_TIMER
+extern const struct tpm_timeout_ops tpm_lib_timeout_ops;
+#endif
+
 #endif /* TPM2_PRIVATE_H */
diff --git a/src/timer/posix_timer_ops.c b/src/timer/posix_timer_ops.c
new file mode 100644
index 0000000..96f7d0d
--- /dev/null
+++ b/src/timer/posix_timer_ops.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "tpm2.h"
+
+/**
+ * @brief Gets the current time in microseconds using CLOCK_MONOTONIC.
+ *
+ * @return Time in microseconds since system boot (or an unspecified starting point).
+ */
+static uint64_t get_time_us(void)
+{
+	struct timespec ts;
+	clock_gettime(CLOCK_MONOTONIC, &ts);
+	return (uint64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
+}
+
+/**
+ * @brief Retrieves the current timer value as the lower 32 bits of microseconds.
+ *
+ * @return 32-bit timer value.
+ */
+static uint32_t get_timer_value_impl(void)
+{
+	return (uint32_t)(get_time_us() & 0xFFFFFFFF);
+}
+
+/**
+ * @brief Initializes a timeout by returning the expiration timestamp.
+ *
+ * @param usec Timeout duration in microseconds.
+ * @return Expiration timestamp in microseconds.
+ */
+static uint64_t timeout_init_us_impl(uint32_t usec)
+{
+	return get_time_us() + (uint64_t)usec;
+}
+
+/**
+ * @brief Determines if the specified timeout has elapsed.
+ *
+ * @param expiry_time_us The expiration time from timeout_init_us().
+ * @return true if the timeout has expired, false otherwise.
+ */
+static bool timeout_elapsed_impl(uint64_t expiry_time_us)
+{
+	return get_time_us() >= expiry_time_us;
+}
+
+/**
+ * @brief Global instance of the POSIX-based timer implementation.
+ *
+ */
+const struct tpm_timeout_ops tpm_lib_timeout_ops = {
+	.timeout_init_us = timeout_init_us_impl,
+	.timeout_elapsed = timeout_elapsed_impl
+};
diff --git a/src/tpm2_cmds.c b/src/tpm2_cmds.c
index 5fc7dc4..56fbc55 100644
--- a/src/tpm2_cmds.c
+++ b/src/tpm2_cmds.c
@@ -47,9 +47,16 @@
 	int err;
 	tpm_spidev = transport;
 	if (timeout_ops == NULL) {
+#ifdef HAS_LIB_TIMER
+		tpm_timeout_ops = tpm_lib_timeout_ops;
+#else
+		ERROR("%s: delay_ops required\n", __func__);
 		return TPM_INVALID_PARAM;
+#endif
 	}
-	tpm_timeout_ops = *timeout_ops;
+	else {
+		tpm_timeout_ops = *timeout_ops;
+	}
 	interface = tpm_interface_getops(chip_data, locality);
 
 	err = interface->request_access(chip_data, locality);