diff --git a/epicardium/api/dispatcher.c b/epicardium/api/dispatcher.c
index 20d873f2c2f6458f79991660594d9eae8001e461..c7a01d9f1adbfe39a36817a6b82c07d3855a64ac 100644
--- a/epicardium/api/dispatcher.c
+++ b/epicardium/api/dispatcher.c
@@ -9,7 +9,7 @@
 /* This function is defined by the generated dispatcher code */
 void __api_dispatch_call(api_id_t id, void *buffer);
 
-static volatile bool event_ready = false;
+static volatile bool call_pending = false;
 
 int api_dispatcher_init()
 {
@@ -34,7 +34,7 @@ int api_dispatcher_init()
 
 bool api_dispatcher_poll_once()
 {
-	if (event_ready) {
+	if (call_pending) {
 		return false;
 	}
 
@@ -46,22 +46,27 @@ bool api_dispatcher_poll_once()
 		return false;
 	}
 
-	event_ready = true;
+	call_pending = true;
 	return true;
 }
 
 bool api_dispatcher_poll()
 {
-	if (event_ready) {
+	if (call_pending) {
 		return true;
 	}
 
 	return api_dispatcher_poll_once();
 }
 
+bool api_dispatcher_call_pending()
+{
+	return call_pending;
+}
+
 api_id_t api_dispatcher_exec()
 {
-	if (!event_ready) {
+	if (!call_pending) {
 		return 0;
 	}
 
@@ -69,7 +74,7 @@ api_id_t api_dispatcher_exec()
 	__api_dispatch_call(id, API_CALL_MEM->buffer);
 	API_CALL_MEM->call_flag = _API_FLAG_RETURNED;
 
-	event_ready = false;
+	call_pending = false;
 	SEMA_FreeSema(_API_SEMAPHORE);
 
 	/* Notify the caller that we returned */
diff --git a/epicardium/api/dispatcher.h b/epicardium/api/dispatcher.h
index 727fe5acd339e1ce2e882b6bf4a73b433daf09c3..9ec0f0484d5f490bccf05299b296b91b5c4c61f1 100644
--- a/epicardium/api/dispatcher.h
+++ b/epicardium/api/dispatcher.h
@@ -15,6 +15,12 @@ int api_dispatcher_init();
 bool api_dispatcher_poll_once();
 bool api_dispatcher_poll();
 
+/*
+ * Check if the other core requested a call or if we are already excuting it.
+ * Only returns a cached version, without acquiring any locks.
+ */
+bool api_dispatcher_call_pending();
+
 /*
  * Attempt to dispatch a call, if one had been polled using
  * api_dispatcher_poll().  Will return 0 if no call was dispatched or the ID of
diff --git a/epicardium/support.c b/epicardium/support.c
index cbb90f8ba16f342237a36434067246e191fbcbdb..238a59ed40b7bb4c57facbad27705c22e24cab68 100644
--- a/epicardium/support.c
+++ b/epicardium/support.c
@@ -8,6 +8,11 @@
 #include "api/dispatcher.h"
 #include "user_core/user_core.h"
 #include "os/core.h"
+#include "drivers/drivers.h"
+
+#include "usb.h"
+#include "mxc_sys.h"
+#include "wut.h"
 
 #include "card10.h"
 
@@ -16,7 +21,8 @@
  */
 void pre_idle_sleep(TickType_t xExpectedIdleTime)
 {
-	if (xExpectedIdleTime > 0) {
+	if (xExpectedIdleTime > 0 &&
+	    (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) == 0) {
 		/*
 		 * WFE because the other core should be able to notify
 		 * epicardium if it wants to issue an API call.
@@ -26,7 +32,57 @@ void pre_idle_sleep(TickType_t xExpectedIdleTime)
 		 * TODO: Ensure this is actually correct and does not have any
 		 * race conditions.
 		 */
-		if ((CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) == 0) {
+
+		/* If the other core is waiting for a call to return and we are able
+		 * to sleep, reduce the system clock to save energy. */
+		if (xExpectedIdleTime >= pdMS_TO_TICKS(10) &&
+		    api_dispatcher_call_pending()) {
+			uint32_t ms = xExpectedIdleTime - 1;
+			/* Initialize Wakeup timer */
+			WUT_Init(WUT_PRES_1);
+			wut_cfg_t wut_cfg;
+			wut_cfg.mode    = WUT_MODE_COMPARE;
+			wut_cfg.cmp_cnt = 0xFFFFFFFF;
+			WUT_Config(&wut_cfg);
+			WUT_Enable();
+
+			/* Enable WUT as a wakup source */
+			NVIC_EnableIRQ(WUT_IRQn);
+
+			uint32_t targetTick;
+			targetTick = WUT_GetCount();
+			targetTick += ((uint64_t)(ms)*SYS_WUT_GetFreq() / 1000);
+			WUT_SetCompare(targetTick);
+
+			/* Stop SysTick */
+			uint32_t val = SysTick->VAL;
+			SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk);
+
+			if (usb_get_status() & MAXUSB_STATUS_VBUS_ON) {
+				SYS_Clock_Select(SYS_CLOCK_HIRC, NULL);
+			} else {
+				MXC_GCR->clkcn |= MXC_S_GCR_CLKCN_PSC_DIV4;
+				SYS_Clock_Select(SYS_CLOCK_HIRC, NULL);
+				SYS_ClockSourceDisable(SYS_CLOCK_HIRC96);
+			}
+			disp_update_backlight_clock();
+			__asm volatile("dsb" ::: "memory");
+			__asm volatile("wfe");
+			__asm volatile("isb");
+			MXC_GCR->clkcn &= ~(MXC_S_GCR_CLKCN_PSC_DIV4);
+			SYS_Clock_Select(SYS_CLOCK_HIRC96, NULL);
+			disp_update_backlight_clock();
+			SYS_ClockSourceDisable(SYS_CLOCK_HIRC);
+			SysTick->LOAD = val;
+			SysTick->VAL  = 0;
+			SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
+
+			ms = (WUT_GetCount() * 1000) / SYS_WUT_GetFreq();
+			for (uint32_t t = 0; t < ms; t++) {
+				xTaskIncrementTick();
+			}
+
+		} else {
 			__asm volatile("dsb" ::: "memory");
 			__asm volatile("wfe");
 			__asm volatile("isb");