From d98cabbf54ac579c1dd85a1cc34bf5af2baee3f9 Mon Sep 17 00:00:00 2001
From: schneider <schneider@blinkenlichts.net>
Date: Mon, 9 Sep 2019 02:35:04 +0200
Subject: [PATCH] feat(sleep): Implement "deep" sleep

Also modifies the PMIC UI code to be more intuitive
---
 epicardium/modules/hardware.c                 |   7 +
 epicardium/modules/meson.build                |   1 +
 epicardium/modules/modules.h                  |   3 +
 epicardium/modules/pmic.c                     | 145 +++++++++----
 epicardium/modules/sleep.c                    | 202 ++++++++++++++++++
 lib/card10/card10.c                           |   6 +
 lib/card10/pmic.c                             |   5 +-
 .../Maxim/MAX32665/Source/system_max32665.c   |   3 +-
 8 files changed, 329 insertions(+), 43 deletions(-)
 create mode 100644 epicardium/modules/sleep.c

diff --git a/epicardium/modules/hardware.c b/epicardium/modules/hardware.c
index 370f9afb..aeb77c3a 100644
--- a/epicardium/modules/hardware.c
+++ b/epicardium/modules/hardware.c
@@ -54,6 +54,13 @@ int hardware_early_init(void)
 	 */
 	GPIO_Init();
 
+	/* Set the power hold pin, so the PMIC does not turn off again */
+	const gpio_cfg_t pwr_hold_pin = {
+		PORT_0, PIN_30, GPIO_FUNC_OUT, GPIO_PAD_NONE
+	};
+	GPIO_Config(&pwr_hold_pin);
+	GPIO_OutSet(&pwr_hold_pin);
+
 	/*
 	 * PMIC (MAX77650)
 	 */
diff --git a/epicardium/modules/meson.build b/epicardium/modules/meson.build
index e943af4f..dd74e322 100644
--- a/epicardium/modules/meson.build
+++ b/epicardium/modules/meson.build
@@ -17,6 +17,7 @@ module_sources = files(
   'pmic.c',
   'rtc.c',
   'serial.c',
+  'sleep.c',
   'stream.c',
   'trng.c',
   'vibra.c',
diff --git a/epicardium/modules/modules.h b/epicardium/modules/modules.h
index 330f4f67..fb65a737 100644
--- a/epicardium/modules/modules.h
+++ b/epicardium/modules/modules.h
@@ -111,4 +111,7 @@ void max30001_mutex_init(void);
 #define MAX30001_MUTEX_WAIT_MS          50
 extern gpio_cfg_t gpio_configs[];
 
+
+/* ---------- Sleep -------------------------------------------------------- */
+void sleep_deepsleep(void);
 #endif /* MODULES_H */
diff --git a/epicardium/modules/pmic.c b/epicardium/modules/pmic.c
index f8760532..921923c9 100644
--- a/epicardium/modules/pmic.c
+++ b/epicardium/modules/pmic.c
@@ -136,37 +136,22 @@ done:
  * Read the interrupt flag register and handle all interrupts which the PMIC has
  * sent.  In most cases this will be the buttons.
  */
-static void
-pmic_poll_interrupts(TickType_t *button_start_tick, TickType_t duration)
+static uint8_t pmic_poll_interrupts(void)
 {
 	while (hwlock_acquire(HWLOCK_I2C, LOCK_WAIT) < 0) {
 		LOG_WARN("pmic", "Failed to acquire I2C. Retrying ...");
-		xTaskNotify(pmic_task_id, PMIC_NOTIFY_IRQ, eSetBits);
-		return;
+		vTaskDelay(pdMS_TO_TICKS(100));
 	}
 
 	uint8_t int_flag = MAX77650_getINT_GLBL();
 	hwlock_release(HWLOCK_I2C);
 
-	if (int_flag & MAX77650_INT_nEN_F) {
-		/* Button was pressed */
-		*button_start_tick = xTaskGetTickCount();
-	}
-	if (int_flag & MAX77650_INT_nEN_R) {
-		/* Button was released */
-		*button_start_tick = 0;
-		if (duration < pdMS_TO_TICKS(400)) {
-			return_to_menu();
-		} else {
-			LOG_WARN("pmic", "Resetting ...");
-			card10_reset();
-		}
-	}
-
 	/* TODO: Remove when all interrupts are handled */
 	if (int_flag & ~(MAX77650_INT_nEN_F | MAX77650_INT_nEN_R)) {
 		LOG_WARN("pmic", "Unhandled PMIC Interrupt: %x", int_flag);
 	}
+
+	return int_flag;
 }
 
 __attribute__((noreturn)) static void pmic_die(float u_batt)
@@ -192,11 +177,15 @@ __attribute__((noreturn)) static void pmic_die(float u_batt)
 	for (int i = 0; i < 50000000; i++)
 		__NOP();
 
-	LOG_WARN("pmic", "Poweroff");
-	MAX77650_setSFT_RST(0x2);
+	/* We have some of headroom to keep the RTC going.
+	 * The battery protection circuit will shut down
+	 * the system at 3.0 V */
 
+	/* TODO: Wake-up when USB is attached again */
+	sleep_deepsleep();
+	card10_reset();
 	while (1)
-		__WFI();
+		;
 }
 
 /*
@@ -291,7 +280,9 @@ static void vPmicTimerCb(TimerHandle_t xTimer)
 
 void vPmicTask(void *pvParameters)
 {
-	pmic_task_id = xTaskGetCurrentTaskHandle();
+	pmic_task_id       = xTaskGetCurrentTaskHandle();
+	uint8_t interrupts = 0;
+	uint32_t reason    = 0;
 
 	ADC_Init(0x9, NULL);
 	GPIO_Config(&gpio_cfg_adc0);
@@ -314,33 +305,107 @@ void vPmicTask(void *pvParameters)
 	}
 	xTimerStart(pmic_timer, 0);
 
-	/*
-	 * Poll once before going to sleep in case the PMIC had triggered an
-	 * interrupt already.  This can occur, for example, if the user presses
-	 * the power-button during the version splash-screen.
-	 */
-	pmic_poll_interrupts(&button_start_tick, 0);
+	/* Clear all pending interrupts. */
+	pmic_poll_interrupts();
 
 	while (1) {
-		uint32_t reason;
-		if (button_start_tick == 0) {
-			reason = ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
-		} else {
-			reason = ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(100));
+		interrupts |= pmic_poll_interrupts();
+		if (interrupts == 0) {
+			reason |= ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
 		}
 
-		TickType_t duration = xTaskGetTickCount() - button_start_tick;
+		/* New interrupts */
+		if (reason & PMIC_NOTIFY_IRQ) {
+			reason ^= PMIC_NOTIFY_IRQ;
+			interrupts |= pmic_poll_interrupts();
+		}
 
-		if (button_start_tick != 0 && duration > pdMS_TO_TICKS(1000)) {
-			LOG_WARN("pmic", "Poweroff");
-			MAX77650_setSFT_RST(0x2);
+		if (interrupts & MAX77650_INT_nEN_R) {
+			/* Ignored in this state */
+			/* This can happen if the button is pressed
+			 * during boot and released now. */
+			interrupts ^= MAX77650_INT_nEN_R; /* Mark as handled. */
 		}
 
-		if (reason & PMIC_NOTIFY_IRQ) {
-			pmic_poll_interrupts(&button_start_tick, duration);
+		if (interrupts & MAX77650_INT_nEN_F) {
+			/* Button was pressed */
+			interrupts ^= MAX77650_INT_nEN_F; /* Mark as handled. */
+
+			button_start_tick = xTaskGetTickCount();
+			while (true) {
+				TickType_t duration =
+					xTaskGetTickCount() - button_start_tick;
+
+				if (duration > 1000) {
+					disp_forcelock();
+					epic_disp_clear(0x0000);
+
+					char buf[20];
+					sprintf(buf,
+						"Off in %d",
+						7 - (int)(duration + 500) /
+								1000);
+					epic_disp_print(
+						0,
+						0,
+						"Sleep zZz..",
+						0xffff,
+						0x0000
+					);
+					epic_disp_print(
+						0, 25, buf, 0xf000, 0x0000
+					);
+					epic_disp_print(
+						0,
+						50,
+						"   Reset ->",
+						0xffff,
+						0x0000
+					);
+					epic_disp_update();
+				}
+
+				if (duration >= pdMS_TO_TICKS(1000)) {
+					if (epic_buttons_read(
+						    BUTTON_RIGHT_TOP)) {
+						LOG_WARN(
+							"pmic",
+							"Resetting ..."
+						);
+						card10_reset();
+					}
+				}
+
+				if (interrupts & MAX77650_INT_nEN_R) {
+					/* Button is released */
+					interrupts ^=
+						MAX77650_INT_nEN_R; /* Mark as handled. */
+
+					if (duration < pdMS_TO_TICKS(1000)) {
+						return_to_menu();
+					}
+
+					if (duration > pdMS_TO_TICKS(1000)) {
+						LOG_WARN("pmic", "Poweroff");
+						sleep_deepsleep();
+						card10_reset();
+					}
+					break;
+				}
+
+				reason |= ulTaskNotifyTake(
+					pdTRUE, pdMS_TO_TICKS(200)
+				);
+				if (reason & PMIC_NOTIFY_IRQ) {
+					/* New interrupts */
+					reason ^= PMIC_NOTIFY_IRQ;
+					interrupts |= pmic_poll_interrupts();
+				}
+			}
 		}
 
 		if (reason & PMIC_NOTIFY_MONITOR) {
+			reason ^= PMIC_NOTIFY_MONITOR;
 			pmic_check_battery();
 		}
 	}
diff --git a/epicardium/modules/sleep.c b/epicardium/modules/sleep.c
new file mode 100644
index 00000000..a87bcb0c
--- /dev/null
+++ b/epicardium/modules/sleep.c
@@ -0,0 +1,202 @@
+#include "epicardium.h"
+#include "modules/modules.h"
+#include "modules/log.h"
+
+#include "card10.h"
+#include "simo.h"
+#include "lp.h"
+#include "max86150.h"
+#include "MAX77650-Arduino-Library.h"
+
+#include "max32665.h"
+#include "mxc_sys.h"
+#include "mxc_pins.h"
+
+#include <stdint.h>
+
+/* Most code is taken and adapted rom EvKitExamples/LP/main.c */
+
+static uint32_t old_clkcn;
+static uint32_t old_perckcn0, old_perckcn1;
+
+void GPIOWAKE_IRQHandler(void)
+{
+	/* Nothing to do here */
+}
+
+static void switchToHIRC(void)
+{
+	MXC_GCR->clkcn &= ~(MXC_S_GCR_CLKCN_PSC_DIV128);
+	MXC_GCR->clkcn |= MXC_S_GCR_CLKCN_PSC_DIV4;
+	MXC_GCR->clkcn |= MXC_F_GCR_CLKCN_HIRC_EN;
+
+	MXC_SETFIELD(
+		MXC_GCR->clkcn,
+		MXC_F_GCR_CLKCN_CLKSEL,
+		MXC_S_GCR_CLKCN_CLKSEL_HIRC
+	);
+
+	while (!(MXC_GCR->clkcn & MXC_F_GCR_CLKCN_CKRDY))
+		; /* Wait for the clock switch to occur */
+
+	/* Disable the now unused 96 MHz clock */
+	MXC_GCR->clkcn &= ~(MXC_F_GCR_CLKCN_HIRC96M_EN);
+
+	SystemCoreClockUpdate();
+}
+
+static void deepsleep(void)
+{
+	SIMO_setVregO_B(810); /* Reduce VCOREB to 0.81 V */
+	LP_FastWakeupEnable();
+	LP_EnterDeepSleepMode();
+	SIMO_setVregO_B(1000); /* Restore VCOREB to 1 V */
+}
+
+static void turnOffClocks(void)
+{
+	old_perckcn0 = MXC_GCR->perckcn0;
+	old_perckcn1 = MXC_GCR->perckcn1;
+
+	/* Allow the USB Switch to be turned off in deepsleep and backup modes. */
+	/* TODO: should this be the default setting? */
+	LP_USBSWLPDisable();
+
+	/* Disable all peripheral clocks except GPIO0 (needed for interrupt wakeup) */
+	MXC_GCR->perckcn0 = 0xFFFFFFFE;
+	MXC_GCR->perckcn1 = 0xFFFFFFFF;
+}
+
+static void turnOnClocks(void)
+{
+	MXC_GCR->perckcn0 = old_perckcn0;
+	MXC_GCR->perckcn1 = old_perckcn1;
+}
+
+/*
+ * Move most GPIOs into a special low power state with the fact
+ * in mind that the external 3.3 V are switched off.
+ *
+ * E.g. this means that the SD card pins need to be pulled low
+ * to preven them from backfeeding into the 3.3 V rail via their
+ * external pull-up resistors.
+ *
+ * Pins needed to talk to the PMIC are left untouched.
+ * ECG AOUT and 32 kHz out as well.
+ */
+static void gpio_low_power(void)
+{
+	/* clang-format off */
+	const gpio_cfg_t pins_low_power[] = {
+		{ PORT_0, PIN_0, GPIO_FUNC_IN, GPIO_PAD_PULL_UP },      // FLash
+		{ PORT_0, PIN_1, GPIO_FUNC_IN, GPIO_PAD_PULL_UP },      // Flash
+		{ PORT_0, PIN_2, GPIO_FUNC_IN, GPIO_PAD_PULL_UP },      // Flash
+		{ PORT_0, PIN_3, GPIO_FUNC_IN, GPIO_PAD_PULL_UP },      // Flash
+		{ PORT_0, PIN_4, GPIO_FUNC_IN, GPIO_PAD_PULL_UP },      // Flash
+		{ PORT_0, PIN_5, GPIO_FUNC_IN, GPIO_PAD_PULL_UP },      // Flash
+		{ PORT_0, PIN_6, GPIO_FUNC_OUT, GPIO_PAD_NONE },        // I2C 3.3V
+		{ PORT_0, PIN_7, GPIO_FUNC_OUT, GPIO_PAD_NONE },        // I2C 3.3V
+		{ PORT_0, PIN_8, GPIO_FUNC_OUT, GPIO_PAD_NONE },        // Motor
+		{ PORT_0, PIN_9, GPIO_FUNC_IN, GPIO_PAD_PULL_UP },      // UART TX
+		{ PORT_0, PIN_10, GPIO_FUNC_IN, GPIO_PAD_PULL_UP },     // UART RX
+		{ PORT_0, PIN_11, GPIO_FUNC_IN, GPIO_PAD_PULL_DOWN },   // BMA400 interrupt
+		// 0, 12: PMIC IRQ
+		{ PORT_0, PIN_13, GPIO_FUNC_IN, GPIO_PAD_NONE },        // BHI160 interrupt, not sure if PP
+		// 0, 14: PMIC I2C
+		// 0, 15: PMIC I2C
+		{ PORT_0, PIN_16, GPIO_FUNC_IN, GPIO_PAD_PULL_UP },     // PMIC AMUX
+		{ PORT_0, PIN_17, GPIO_FUNC_IN, GPIO_PAD_PULL_DOWN },   // SOA GPIO
+		// 0, 18: ECG AOUT
+		// 0, 19: 32 kHz
+		{ PORT_0, PIN_20, GPIO_FUNC_IN, GPIO_PAD_PULL_DOWN },   // Wristband 1
+		{ PORT_0, PIN_21, GPIO_FUNC_IN, GPIO_PAD_PULL_DOWN },   // Wristband 2
+		{ PORT_0, PIN_22, GPIO_FUNC_IN, GPIO_PAD_PULL_DOWN },   // Wristband 3
+		{ PORT_0, PIN_23, GPIO_FUNC_OUT, GPIO_PAD_NONE },       // IR-LED
+		{ PORT_0, PIN_24, GPIO_FUNC_OUT, GPIO_PAD_NONE },       // display SS
+		{ PORT_0, PIN_25, GPIO_FUNC_OUT, GPIO_PAD_NONE },       // display MOSI
+		{ PORT_0, PIN_26, GPIO_FUNC_IN, GPIO_PAD_PULL_DOWN },   // SOA GPIO
+		{ PORT_0, PIN_27, GPIO_FUNC_OUT, GPIO_PAD_NONE },       // display SCK
+		{ PORT_0, PIN_28, GPIO_FUNC_OUT, GPIO_PAD_NONE },       // Backlight
+		{ PORT_0, PIN_29, GPIO_FUNC_IN, GPIO_PAD_PULL_DOWN },   // Wristband 4
+		// 0, 30: PMIC power hold
+		{ PORT_0, PIN_31, GPIO_FUNC_OUT, GPIO_PAD_NONE },   // ECG switch
+
+		{ PORT_1, PIN_0, GPIO_FUNC_OUT, GPIO_PAD_NONE },    // SDHC
+		{ PORT_1, PIN_1, GPIO_FUNC_OUT, GPIO_PAD_NONE },    // SDHC
+		{ PORT_1, PIN_2, GPIO_FUNC_OUT, GPIO_PAD_NONE },    // SDHC
+		{ PORT_1, PIN_3, GPIO_FUNC_OUT, GPIO_PAD_NONE },    // SDHC
+		{ PORT_1, PIN_4, GPIO_FUNC_OUT, GPIO_PAD_NONE },    // SDHC
+		{ PORT_1, PIN_5, GPIO_FUNC_OUT, GPIO_PAD_NONE },    // SDHC
+		{ PORT_1, PIN_6, GPIO_FUNC_OUT, GPIO_PAD_NONE },    // display RS
+		{ PORT_1, PIN_7, GPIO_FUNC_IN, GPIO_PAD_PULL_UP },  // Portexpander interrupt
+		{ PORT_1, PIN_8, GPIO_FUNC_IN, GPIO_PAD_PULL_UP },  // ECG CS TODO: better OUT high
+		{ PORT_1, PIN_9, GPIO_FUNC_OUT, GPIO_PAD_NONE },    // ECG SDI
+		{ PORT_1, PIN_10, GPIO_FUNC_IN, GPIO_PAD_PULL_UP }, // ECG SDO
+		{ PORT_1, PIN_11, GPIO_FUNC_IN, GPIO_PAD_PULL_UP }, // ECG SCK
+		{ PORT_1, PIN_11, GPIO_FUNC_IN, GPIO_PAD_PULL_UP }, // ECG INT
+		{ PORT_1, PIN_13, GPIO_FUNC_IN, GPIO_PAD_NONE },    // PPG Interrupt
+		{ PORT_1, PIN_14, GPIO_FUNC_OUT, GPIO_PAD_NONE },   // RGB LEDs
+		{ PORT_1, PIN_15, GPIO_FUNC_OUT, GPIO_PAD_NONE },   // RGB LEDs
+	};
+	/* clang-format on */
+
+	const unsigned int num_pins =
+		(sizeof(pins_low_power) / sizeof(gpio_cfg_t));
+	int i;
+	for (i = 0; i < num_pins; i++) {
+		GPIO_OutClr(&pins_low_power[i]);
+		GPIO_Config(&pins_low_power[i]);
+	}
+}
+
+/*
+ * Go to deepsleep, turning off peripherals.
+ *
+ * This functions returns after waking up again.
+ * Currently the only wakeup source is an interrupt
+ * from the PMIC.
+ *
+ * Some peripherals and GPIOs are moved into a low
+ * power state before going to sleep. There is no guarantee
+ * that all peripherals will be moved to a low power state
+ *
+ * TODO: Move BHI160, BMA400, BME680, MAX30001 into a low
+ * power state.
+ *
+ * The state of the GPIOs and generally all peripherials
+ * on board is not restored after a wakeup.
+ */
+void sleep_deepsleep(void)
+{
+	LOG_WARN("pmic", "Powersave");
+	epic_disp_backlight(0);
+	epic_leds_set_rocket(0, 0);
+	epic_leds_set_rocket(1, 0);
+	epic_leds_set_rocket(2, 0);
+#if 1
+	/* This will fail if there is no
+     * harmonic board attached */
+	max86150_begin();
+	max86150_getINT1();
+	max86150_getINT2();
+	max86150_shutDown();
+#endif
+	MAX77650_setEN_SBB2(0b100);
+	MAX77650_setSBIA_LPM(true);
+	core1_stop();
+	MAX77650_getINT_GLBL();
+	gpio_low_power();
+	turnOffClocks();
+	old_clkcn = MXC_GCR->clkcn;
+	switchToHIRC();
+	deepsleep();
+
+	/* Now wait for an interrupt to wake us up */
+
+	turnOnClocks();
+	MXC_GCR->clkcn = old_clkcn;
+	while (!(MXC_GCR->clkcn & MXC_F_GCR_CLKCN_CKRDY))
+		; /* Wait for the clock switch to occur */
+	SystemCoreClockUpdate();
+	MAX77650_setEN_SBB2(0b110);
+}
diff --git a/lib/card10/card10.c b/lib/card10/card10.c
index 306d9f4d..09cc44ff 100644
--- a/lib/card10/card10.c
+++ b/lib/card10/card10.c
@@ -29,6 +29,10 @@ const gpio_cfg_t bhi_interrupt_pin = {
 	PORT_0, PIN_13, GPIO_FUNC_IN, GPIO_PAD_PULL_UP
 };
 
+static const gpio_cfg_t pwr_hold_pin = {
+	PORT_0, PIN_30, GPIO_FUNC_OUT, GPIO_PAD_NONE
+};
+
 void card10_init(void)
 {
 	printf("card10 init...\n");
@@ -41,6 +45,8 @@ void card10_init(void)
 	I2C_Init(MXC_I2C1_BUS0, I2C_FAST_MODE, NULL);
 
 	GPIO_Init();
+	GPIO_Config(&pwr_hold_pin);
+	GPIO_OutSet(&pwr_hold_pin);
 
 	pmic_init();
 	pmic_set_led(0, 0);
diff --git a/lib/card10/pmic.c b/lib/card10/pmic.c
index e60cf81a..609efc1c 100644
--- a/lib/card10/pmic.c
+++ b/lib/card10/pmic.c
@@ -1,5 +1,6 @@
 #include "i2c.h"
 #include "pmic.h"
+#include "lp.h"
 #include "MAX77650-Arduino-Library.h"
 #include <stdint.h>
 #include <stdio.h>
@@ -45,7 +46,7 @@ void pmic_init(void)
 	//MAX77650_setTV_SBB2(0b110100); //Set output Voltage of SBB2 to 5.0V
 	MAX77650_setTV_SBB2(0b010010); //Set output Voltage of SBB2 to 3.3V
 #endif
-	MAX77650_setADE_SBB2(0b0); //Disable Active Discharge at SBB2 Output
+	MAX77650_setADE_SBB2(0b1); //Enable Active Discharge at SBB2 Output
 	MAX77650_setEN_SBB2(
 		0b110); //Enable SBB2 is on irrespective of FPS whenever the on/off controller is in its "On via Software" or "On via On/Off Controller" states
 
@@ -90,6 +91,8 @@ void pmic_init(void)
 	);
 	NVIC_EnableIRQ((IRQn_Type)MXC_GPIO_GET_IRQ(pmic_interrupt_pin.port));
 
+	/* Allow the PMIC to interrupt us in deepsleep */
+	LP_EnableGPIOWakeup((gpio_cfg_t *)&pmic_interrupt_pin);
 	/* Setup power button interrupt */
 	MAX77650_setINT_M_GLBL(~(MAX77650_INT_nEN_R | MAX77650_INT_nEN_F));
 	/* Clear existing interrupts */
diff --git a/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/Source/system_max32665.c b/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/Source/system_max32665.c
index 569913e2..90c4f0a0 100644
--- a/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/Source/system_max32665.c
+++ b/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/Source/system_max32665.c
@@ -169,7 +169,6 @@ __weak void SystemInit(void)
     MXC_GPIO0->vssel |= (1UL << 20) | (1UL << 21) | (1UL << 22) | (1UL << 29); // Wristband
     MXC_GPIO0->vssel |= (1UL << 17) | (1UL << 23) | (1UL << 28); // GPIO to TOP
     MXC_GPIO0->vssel |= (1UL << 24) | (1UL << 25) | (1UL << 26) | (1UL << 27); // SPI to TOP
-    MXC_GPIO0->vssel |= (1UL << 31); // ECG Switch
 
     MXC_GPIO0->ps |= 0xFFFFFFFF;
     MXC_GPIO0->pad_cfg1 |= 0xFFFFFFFF;
@@ -178,7 +177,7 @@ __weak void SystemInit(void)
     // All GPIO on port 1 to 1.8 V first
     MXC_GPIO1->vssel = 0;
     MXC_GPIO1->vssel |= (1UL << 0) | (1UL << 1) | (1UL << 2) | (1UL << 3) | (1UL << 4) | (1UL << 5); // SDHC
-    MXC_GPIO1->vssel |= (1 << 6) | (1 << 7); // GPIO to TOP
+    MXC_GPIO1->vssel |= (1 << 6); // GPIO to TOP
     MXC_GPIO1->vssel |= (1 << 14) | (1 << 15); // GPIO for RGB LEDs
 
 #if BOARD_EVKIT
-- 
GitLab