Add muen scheduling info as timer source

This is a very low precision clock. We just take the start of the cur-
rent scheduling minor frame as the minimum, yet elapsed moment and the
end of the frame as the maximum, yet reached moment in time. As a
result, every timer based delay will wait at least for the next minor
frame.

For the build, `musinfo.ads` and `muschedinfo.ads` from the Muen
project are required. One should point the `muen-common-path` variable
to the `common` subdir of the Muen source distribution.

Change-Id: Ib139749214bf8d2ca293e31327b156de5198b65d
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: https://review.coreboot.org/18357
Tested-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Adrian-Ken Rueegsegger <ken@codelabs.ch>
diff --git a/ada/Makefile.inc b/ada/Makefile.inc
index e09f1a5..2233094 100644
--- a/ada/Makefile.inc
+++ b/ada/Makefile.inc
@@ -1,3 +1,7 @@
 hw-$(CONFIG_HWBASE_STATIC_MMIO) += static_mmio/hw-mmio_range.adb
 hw-$(CONFIG_HWBASE_DYNAMIC_MMIO) += dynamic_mmio/hw-mmio_range.adb
 hw-$(CONFIG_HWBASE_TIMER_CLOCK_GETTIME) += clock_gettime/hw-time-timer.adb
+
+hw-$(CONFIG_HWBASE_TIMER_MUTIME) += $(muen-common-path)/musinfo/musinfo.ads
+hw-$(CONFIG_HWBASE_TIMER_MUTIME) += $(muen-common-path)/muschedinfo/muschedinfo.ads
+hw-$(CONFIG_HWBASE_TIMER_MUTIME) += mutime/hw-time-timer.adb
diff --git a/ada/mutime/hw-time-timer.adb b/ada/mutime/hw-time-timer.adb
new file mode 100644
index 0000000..272289c
--- /dev/null
+++ b/ada/mutime/hw-time-timer.adb
@@ -0,0 +1,59 @@
+--
+-- Copyright (C) 2015-2016 secunet Security Networks AG
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; version 2 of the License.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+
+with System;
+
+with Musinfo;
+with Muschedinfo;
+
+package body HW.Time.Timer
+   with Refined_State => (Timer_State => null,
+                          Abstract_Time => (Sinfo, Sched_Info))
+is
+   Sinfo_Base_Address : constant := 16#000e_0000_0000#;
+   Sinfo_Page_Size    : constant
+     := ((Musinfo.Subject_Info_Type_Size + (16#1000# - 1))
+         / 16#1000#) * 16#1000#;
+
+   Sinfo : Musinfo.Subject_Info_Type
+   with
+      Address => System'To_Address (Sinfo_Base_Address);
+
+   Sched_Info : Muschedinfo.Scheduling_Info_Type
+   with
+      Volatile,
+      Async_Writers,
+      Address => System'To_Address (Sinfo_Base_Address + Sinfo_Page_Size);
+
+   function Raw_Value_Min return T
+   is
+      TSC_Schedule_Start : constant Interfaces.Unsigned_64
+         := Sched_Info.TSC_Schedule_Start;
+   begin
+      return T (TSC_Schedule_Start);
+   end Raw_Value_Min;
+
+   function Raw_Value_Max return T
+   is
+      TSC_Schedule_End : constant Interfaces.Unsigned_64
+         := Sched_Info.TSC_Schedule_End;
+   begin
+      return T (TSC_Schedule_End);
+   end Raw_Value_Max;
+
+   function Hz return T is
+   begin
+      return T (Sinfo.TSC_Khz) * 1000;
+   end Hz;
+
+end HW.Time.Timer;