diff --git a/stratosphere/boot/source/boot_functions.hpp b/stratosphere/boot/source/boot_functions.hpp
index a7be01861..9c150c39a 100644
--- a/stratosphere/boot/source/boot_functions.hpp
+++ b/stratosphere/boot/source/boot_functions.hpp
@@ -84,4 +84,8 @@ class Boot {
static u16 GetCrc16(const void *data, size_t size);
static u32 GetBatteryVersion();
static u32 GetBatteryVendor();
+
+ /* Wake pin utiliies. */
+ static void SetWakeEventLevel(u32 index, u32 level);
+ static void SetWakeEventEnabled(u32 index, bool enabled);
};
diff --git a/stratosphere/boot/source/boot_registers_pmc.hpp b/stratosphere/boot/source/boot_registers_pmc.hpp
index 46cf89454..d543f360b 100644
--- a/stratosphere/boot/source/boot_registers_pmc.hpp
+++ b/stratosphere/boot/source/boot_registers_pmc.hpp
@@ -24,6 +24,8 @@ static constexpr uintptr_t PmcBase = 0x7000E400ul;
static constexpr size_t APBDEV_PMC_CNTRL = 0x0;
static constexpr u32 PMC_CNTRL_MAIN_RST = (1 << 4);
static constexpr size_t APBDEV_PMC_SEC_DISABLE = 0x4;
+static constexpr size_t APBDEV_PMC_WAKE_MASK = 0xC;
+static constexpr size_t APBDEV_PMC_WAKE_LVL = 0x10;
static constexpr size_t APBDEV_PMC_DPD_PADS_ORIDE = 0x1C;
static constexpr size_t APBDEV_PMC_PWRGATE_TOGGLE = 0x30;
static constexpr size_t APBDEV_PMC_PWRGATE_STATUS = 0x38;
@@ -32,6 +34,7 @@ static constexpr size_t APBDEV_PMC_NO_IOPOWER = 0x44;
static constexpr size_t APBDEV_PMC_SCRATCH0 = 0x50;
static constexpr size_t APBDEV_PMC_SCRATCH1 = 0x54;
static constexpr size_t APBDEV_PMC_SCRATCH20 = 0xA0;
+static constexpr size_t APBDEV_PMC_AUTO_WAKE_LVL_MASK = 0xDC;
static constexpr size_t APBDEV_PMC_PWR_DET_VAL = 0xE4;
static constexpr u32 PMC_PWR_DET_SDMMC1_IO_EN = (1 << 12);
static constexpr size_t APBDEV_PMC_DDR_PWR = 0xE8;
@@ -40,6 +43,9 @@ static constexpr u32 PMC_CRYPTO_OP_SE_ENABLE = 0;
static constexpr u32 PMC_CRYPTO_OP_SE_DISABLE = 1;
static constexpr size_t APBDEV_PMC_SCRATCH33 = 0x120;
static constexpr size_t APBDEV_PMC_SCRATCH40 = 0x13C;
+static constexpr size_t APBDEV_PMC_WAKE2_MASK = 0x164;
+static constexpr size_t APBDEV_PMC_WAKE2_LVL = 0x164;
+static constexpr size_t APBDEV_PMC_AUTO_WAKE2_LVL_MASK = 0x170;
static constexpr size_t APBDEV_PMC_OSC_EDPD_OVER = 0x1A4;
static constexpr size_t APBDEV_PMC_CLK_OUT_CNTRL = 0x1A8;
static constexpr size_t APBDEV_PMC_RST_STATUS = 0x1B4;
diff --git a/stratosphere/boot/source/boot_types.hpp b/stratosphere/boot/source/boot_types.hpp
index b62f22add..03e2ad4cc 100644
--- a/stratosphere/boot/source/boot_types.hpp
+++ b/stratosphere/boot/source/boot_types.hpp
@@ -35,4 +35,10 @@ struct PinmuxInitialConfig {
u32 name;
u32 val;
u32 mask;
+};
+
+struct WakePinConfig {
+ u32 index;
+ bool enabled;
+ u32 level;
};
\ No newline at end of file
diff --git a/stratosphere/boot/source/boot_wake_pin_configuration.hpp b/stratosphere/boot/source/boot_wake_pin_configuration.hpp
new file mode 100644
index 000000000..0ef5dd8ba
--- /dev/null
+++ b/stratosphere/boot/source/boot_wake_pin_configuration.hpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+#include
+
+#include "boot_types.hpp"
+
+static constexpr WakePinConfig WakePinConfigs[] = {
+ {0x00, false, 0x02},
+ {0x01, false, 0x02},
+ {0x02, false, 0x02},
+ {0x03, false, 0x02},
+ {0x04, true, 0x02},
+ {0x05, false, 0x02},
+ {0x06, true, 0x02},
+ {0x07, true, 0x02},
+ {0x08, false, 0x02},
+ {0x0A, true, 0x02},
+ {0x0B, false, 0x02},
+ {0x0C, false, 0x02},
+ {0x0D, false, 0x02},
+ {0x0E, true, 0x00},
+ {0x0F, false, 0x02},
+ {0x11, false, 0x02},
+ {0x12, false, 0x02},
+ {0x13, false, 0x02},
+ {0x14, false, 0x02},
+ {0x15, false, 0x02},
+ {0x16, false, 0x02},
+ {0x17, false, 0x02},
+ {0x18, false, 0x02},
+ {0x19, false, 0x02},
+ {0x1A, false, 0x02},
+ {0x1B, true, 0x00},
+ {0x1C, false, 0x02},
+ {0x21, false, 0x02},
+ {0x22, true, 0x00},
+ {0x23, true, 0x02},
+ {0x24, false, 0x02},
+ {0x2D, false, 0x02},
+ {0x2E, false, 0x02},
+ {0x2F, false, 0x02},
+ {0x30, true, 0x02},
+ {0x31, false, 0x02},
+ {0x32, false, 0x02},
+ {0x33, true, 0x00},
+ {0x34, true, 0x00},
+ {0x35, false, 0x02},
+ {0x36, false, 0x02},
+ {0x37, false, 0x02},
+ {0x38, false, 0x02},
+ {0x39, false, 0x02},
+ {0x3A, false, 0x02},
+ {0x3B, false, 0x02},
+ {0x3D, false, 0x02},
+ {0x3E, false, 0x02},
+ {0x3F, false, 0x02},
+};
+
+static constexpr size_t NumWakePinConfigs = sizeof(WakePinConfigs) / sizeof(WakePinConfigs[0]);
diff --git a/stratosphere/boot/source/boot_wake_pin_configuration_copper.hpp b/stratosphere/boot/source/boot_wake_pin_configuration_copper.hpp
new file mode 100644
index 000000000..e053988ec
--- /dev/null
+++ b/stratosphere/boot/source/boot_wake_pin_configuration_copper.hpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+#include
+
+#include "boot_types.hpp"
+
+static constexpr WakePinConfig WakePinConfigsCopper[] = {
+ {0x00, true, 0x02},
+ {0x01, false, 0x02},
+ {0x02, false, 0x02},
+ {0x03, true, 0x02},
+ {0x04, false, 0x02},
+ {0x05, true, 0x02},
+ {0x06, false, 0x02},
+ {0x07, false, 0x02},
+ {0x08, true, 0x02},
+ {0x0A, false, 0x02},
+ {0x0B, false, 0x02},
+ {0x0C, false, 0x02},
+ {0x0D, false, 0x02},
+ {0x0E, true, 0x00},
+ {0x0F, false, 0x02},
+ {0x11, false, 0x02},
+ {0x12, false, 0x02},
+ {0x13, false, 0x02},
+ {0x14, false, 0x02},
+ {0x15, false, 0x02},
+ {0x16, false, 0x02},
+ {0x17, false, 0x02},
+ {0x18, true, 0x02},
+ {0x19, false, 0x02},
+ {0x1A, false, 0x02},
+ {0x1B, false, 0x00},
+ {0x1C, false, 0x02},
+ {0x21, false, 0x02},
+ {0x22, false, 0x00},
+ {0x23, false, 0x02},
+ {0x24, false, 0x02},
+ {0x2D, false, 0x02},
+ {0x2E, false, 0x02},
+ {0x2F, true, 0x02},
+ {0x30, true, 0x02},
+ {0x31, false, 0x02},
+ {0x32, true, 0x02},
+ {0x33, true, 0x00},
+ {0x34, true, 0x00},
+ {0x35, false, 0x02},
+ {0x36, false, 0x02},
+ {0x37, false, 0x02},
+ {0x38, false, 0x02},
+ {0x39, false, 0x02},
+ {0x3A, false, 0x02},
+ {0x3B, false, 0x02},
+ {0x3D, false, 0x02},
+ {0x3E, false, 0x02},
+ {0x3F, false, 0x02},
+};
+
+static constexpr size_t NumWakePinConfigsCopper = sizeof(WakePinConfigsCopper) / sizeof(WakePinConfigsCopper[0]);
diff --git a/stratosphere/boot/source/boot_wake_pins.cpp b/stratosphere/boot/source/boot_wake_pins.cpp
index 667ad711e..21dc3cbb4 100644
--- a/stratosphere/boot/source/boot_wake_pins.cpp
+++ b/stratosphere/boot/source/boot_wake_pins.cpp
@@ -17,6 +17,8 @@
#include "boot_functions.hpp"
#include "boot_registers_pmc.hpp"
#include "boot_wake_control_configs.hpp"
+#include "boot_wake_pin_configuration.hpp"
+#include "boot_wake_pin_configuration_copper.hpp"
static void UpdatePmcControlBit(const u32 reg_offset, const u32 mask_val, const bool flag) {
Boot::WritePmcRegister(PmcBase + reg_offset, flag ? UINT32_MAX : 0, mask_val);
@@ -44,8 +46,43 @@ static void InitializePmcWakeConfiguration(const bool is_blink) {
UpdatePmcControlBit(APBDEV_PMC_DPD_PADS_ORIDE, 0x100000, is_blink);
}
+void Boot::SetWakeEventLevel(u32 index, u32 level) {
+ u32 pmc_wake_level_reg_offset = index <= 0x1F ? APBDEV_PMC_WAKE_LVL : APBDEV_PMC_WAKE2_LVL;
+ u32 pmc_wake_level_mask_reg_offset = index <= 0x1F ? APBDEV_PMC_AUTO_WAKE_LVL_MASK : APBDEV_PMC_AUTO_WAKE2_LVL_MASK;
+ if (level == 2) {
+ std::swap(pmc_wake_level_reg_offset, pmc_wake_level_mask_reg_offset);
+ }
+
+ const u32 mask_val = (1 << (index & 0x1F));
+
+ /* Clear level reg bit. */
+ UpdatePmcControlBit(pmc_wake_level_reg_offset, mask_val, false);
+
+ /* Set or clear mask reg bit. */
+ UpdatePmcControlBit(pmc_wake_level_mask_reg_offset, mask_val, level > 0);
+}
+
+void Boot::SetWakeEventEnabled(u32 index, bool enabled) {
+ /* Set or clear enabled bit. */
+ UpdatePmcControlBit(index <= 0x1F ? APBDEV_PMC_WAKE_MASK : APBDEV_PMC_WAKE2_MASK, (1 << (index & 0x1F)), enabled);
+}
+
void Boot::SetInitialWakePinConfiguration() {
InitializePmcWakeConfiguration(false);
- /* TODO: Wake event levels, wake event enables. */
+ /* Set wake event levels, wake event enables. */
+ const WakePinConfig *configs;
+ size_t num_configs;
+ if (Boot::GetHardwareType() == HardwareType_Copper) {
+ configs = WakePinConfigsCopper;
+ num_configs = NumWakePinConfigsCopper;
+ } else {
+ configs = WakePinConfigs;
+ num_configs = NumWakePinConfigs;
+ }
+
+ for (size_t i = 0; i < num_configs; i++) {
+ Boot::SetWakeEventLevel(configs[i].index, configs[i].level);
+ Boot::SetWakeEventEnabled(configs[i].index, configs[i].enabled);
+ }
}