diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index 102f11e..ba220c0 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -110,7 +110,6 @@ noinst_HEADERS = \
 		  ${srcdir}/include/odp_timer_internal.h \
 		  ${srcdir}/include/odp_timer_wheel_internal.h \
 		  ${srcdir}/include/odp_traffic_mngr_internal.h \
-		  ${srcdir}/include/odp_cpu_internal.h \
 		  ${srcdir}/Makefile.inc
 
 __LIB__libodp_la_SOURCES = \
diff --git a/platform/linux-generic/include/odp/plat/time_types.h b/platform/linux-generic/include/odp/plat/time_types.h
index 9ba1508..e5765ec 100644
--- a/platform/linux-generic/include/odp/plat/time_types.h
+++ b/platform/linux-generic/include/odp/plat/time_types.h
@@ -21,9 +21,11 @@ extern "C" {
  *  @{
  **/
 
-typedef uint64_t odp_time_t;
+typedef struct timespec odp_time_t;
 
-#define ODP_TIME_NULL ((odp_time_t)0)
+odp_time_t odp_time_null(void);
+
+#define ODP_TIME_NULL	odp_time_null()
 
 /**
  * @}
diff --git a/platform/linux-generic/include/odp_cpu_internal.h b/platform/linux-generic/include/odp_cpu_internal.h
deleted file mode 100644
index 664e2df..0000000
--- a/platform/linux-generic/include/odp_cpu_internal.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Copyright (c) 2015, Linaro Limited
- * All rights reserved.
- *
- * SPDX-License-Identifier:     BSD-3-Clause
- */
-
-#ifndef ODP_CPU_INTERNAL_H_
-#define ODP_CPU_INTERNAL_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <odp/cpu.h>
-
-static inline
-uint64_t _odp_cpu_cycles_diff(uint64_t c2, uint64_t c1)
-{
-	if (odp_likely(c2 >= c1))
-		return c2 - c1;
-
-	return c2 + (odp_cpu_cycles_max() - c1) + 1;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/platform/linux-generic/odp_cpu.c b/platform/linux-generic/odp_cpu.c
index 636f811..4bd6a9a 100644
--- a/platform/linux-generic/odp_cpu.c
+++ b/platform/linux-generic/odp_cpu.c
@@ -6,9 +6,11 @@
 
 #include <odp/cpu.h>
 #include <odp/hints.h>
-#include <odp_cpu_internal.h>
 
 uint64_t odp_cpu_cycles_diff(uint64_t c2, uint64_t c1)
 {
-	return _odp_cpu_cycles_diff(c2, c1);
+	if (odp_likely(c2 >= c1))
+		return c2 - c1;
+
+	return c2 + (odp_cpu_cycles_max() - c1) + 1;
 }
diff --git a/platform/linux-generic/odp_time.c b/platform/linux-generic/odp_time.c
index a2e4046..89bbf0c 100644
--- a/platform/linux-generic/odp_time.c
+++ b/platform/linux-generic/odp_time.c
@@ -6,81 +6,106 @@
 
 #define _POSIX_C_SOURCE 200809L
 
+#include <time.h>
 #include <odp/time.h>
 #include <odp/hints.h>
-#include <odp/system_info.h>
-#include <odp/cpu.h>
-#include <odp_cpu_internal.h>
+#include <odp_debug_internal.h>
 
-#define GIGA 1000000000
-
-static inline
-uint64_t time_to_tick(odp_time_t time)
+odp_time_t odp_time_local(void)
 {
-	return (uint64_t)time;
-}
+	int ret;
+	struct timespec time;
 
-static inline
-odp_time_t tick_to_time(uint64_t tick)
-{
-	return (odp_time_t)tick;
-}
+	ret = clock_gettime(CLOCK_MONOTONIC_RAW, &time);
+	if (odp_unlikely(ret != 0))
+		ODP_ABORT("clock_gettime failed\n");
 
-odp_time_t odp_time_local(void)
-{
-	return tick_to_time(odp_cpu_cycles());
+	return time;
 }
 
 odp_time_t odp_time_diff(odp_time_t t2, odp_time_t t1)
 {
-	return tick_to_time(_odp_cpu_cycles_diff(t2, t1));
+	uint64_t ns1, ns2;
+	struct timespec time;
+
+	ns1 = odp_time_to_ns(t1);
+	ns2 = odp_time_to_ns(t2);
+	if (ns2 < ns1)
+		return (struct timespec) {0, 1};
+
+	time.tv_sec = t2.tv_sec - t1.tv_sec;
+	time.tv_nsec = t2.tv_nsec - t1.tv_nsec;
+
+	if (time.tv_nsec < 0) {
+		time.tv_nsec += ODP_TIME_SEC_IN_NS;
+		--time.tv_sec;
+	}
+
+	return time;
 }
 
 uint64_t odp_time_to_ns(odp_time_t time)
 {
-	uint64_t hz = odp_cpu_hz_max();
-	uint64_t tick = time_to_tick(time);
+	uint64_t ns;
 
-	if (tick > (UINT64_MAX / GIGA))
-		return (tick / hz) * GIGA;
+	ns = time.tv_sec * ODP_TIME_SEC_IN_NS;
+	ns += time.tv_nsec;
 
-	return (tick * GIGA) / hz;
+	return ns;
 }
 
-
 odp_time_t odp_time_local_from_ns(uint64_t ns)
 {
-	uint64_t hz = odp_cpu_hz_max();
+	struct timespec time;
 
-	if (ns > (UINT64_MAX / hz))
-		return tick_to_time((ns / GIGA) * hz);
+	time.tv_sec = ns / ODP_TIME_SEC_IN_NS;
+	time.tv_nsec = ns % ODP_TIME_SEC_IN_NS;
 
-	return tick_to_time((ns * hz) / GIGA);
+	return time;
 }
 
 int odp_time_cmp(odp_time_t t2, odp_time_t t1)
 {
-	uint64_t tick1 = time_to_tick(t1);
-	uint64_t tick2 = time_to_tick(t2);
+	if (t2.tv_sec < t1.tv_sec)
+		return -1;
 
-	if (tick1 < tick2)
+	if (t2.tv_sec > t1.tv_sec)
 		return 1;
 
-	if (tick1 > tick2)
-		return -1;
-
-	return 0;
+	return t2.tv_nsec - t1.tv_nsec;
 }
 
 odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2)
 {
-	uint64_t tick1 = time_to_tick(t1);
-	uint64_t tick2 = time_to_tick(t2);
+	struct timespec time;
+
+	time.tv_sec = t2.tv_sec + t1.tv_sec;
+	time.tv_nsec = t2.tv_nsec + t1.tv_nsec;
+
+	if (time.tv_nsec >= (long)ODP_TIME_SEC_IN_NS) {
+		time.tv_nsec -= ODP_TIME_SEC_IN_NS;
+		++time.tv_sec;
+	}
+
+	return time;
+}
+
+uint64_t odp_time_to_u64(odp_time_t time)
+{
+	int ret;
+	struct timespec tres;
+	uint64_t resolution;
+
+	ret = clock_getres(CLOCK_MONOTONIC_RAW, &tres);
+	if (odp_unlikely(ret != 0))
+		ODP_ABORT("clock_getres failed\n");
+
+	resolution = (uint64_t)tres.tv_nsec;
 
-	return tick_to_time(tick1 + tick2);
+	return odp_time_to_ns(time) / resolution;
 }
 
-uint64_t odp_time_to_u64(odp_time_t hdl)
+odp_time_t odp_time_null(void)
 {
-	return time_to_tick(hdl);
+	return (struct timespec) {0, 0};
 }
