diff --git a/libexosphere/include/exosphere/clkrst.hpp b/libexosphere/include/exosphere/clkrst.hpp index e4b31740..2ee68149 100644 --- a/libexosphere/include/exosphere/clkrst.hpp +++ b/libexosphere/include/exosphere/clkrst.hpp @@ -27,6 +27,7 @@ namespace ams::clkrst { void EnableUartCClock(); void EnableActmonClock(); void EnableI2c1Clock(); + void EnableI2c5Clock(); void DisableI2c1Clock(); diff --git a/libexosphere/include/exosphere/flow.hpp b/libexosphere/include/exosphere/flow.hpp index 210ecced..b539a29f 100644 --- a/libexosphere/include/exosphere/flow.hpp +++ b/libexosphere/include/exosphere/flow.hpp @@ -25,5 +25,6 @@ namespace ams::flow { void SetCpuCsr(int core, u32 enable_ext); void SetHaltCpuEvents(int core, bool resume_on_irq); void SetCc4Ctrl(int core, u32 value); + void ClearL2FlushControl(); } diff --git a/libexosphere/include/exosphere/pmc.hpp b/libexosphere/include/exosphere/pmc.hpp index d1e2091b..207307eb 100644 --- a/libexosphere/include/exosphere/pmc.hpp +++ b/libexosphere/include/exosphere/pmc.hpp @@ -36,6 +36,8 @@ namespace ams::pmc { void SetRegisterAddress(uintptr_t address); void InitializeRandomScratch(); + void EnableWakeEventDetection(); + void ConfigureForSc7Entry(); void LockSecureRegister(SecureRegister reg); diff --git a/libexosphere/include/exosphere/pmic.hpp b/libexosphere/include/exosphere/pmic.hpp index 46b10372..1d01eb81 100644 --- a/libexosphere/include/exosphere/pmic.hpp +++ b/libexosphere/include/exosphere/pmic.hpp @@ -29,5 +29,7 @@ namespace ams::pmic { void EnableVddCpu(Regulator regulator); void DisableVddCpu(Regulator regulator); + void EnableSleep(); + bool IsAcOk(); } \ No newline at end of file diff --git a/libexosphere/include/exosphere/tegra/tegra_flow_ctlr.hpp b/libexosphere/include/exosphere/tegra/tegra_flow_ctlr.hpp index d9077a9a..8bc203ff 100644 --- a/libexosphere/include/exosphere/tegra/tegra_flow_ctlr.hpp +++ b/libexosphere/include/exosphere/tegra/tegra_flow_ctlr.hpp @@ -18,6 +18,7 @@ #define FLOW_CTLR_FLOW_DBG_QUAL (0x050) +#define FLOW_CTLR_L2FLUSH_CONTROL (0x094) #define FLOW_CTLR_BPMP_CLUSTER_CONTROL (0x098) #define FLOW_CTLR_CPU0_CSR (0x008) diff --git a/libexosphere/include/exosphere/tegra/tegra_pmc.hpp b/libexosphere/include/exosphere/tegra/tegra_pmc.hpp index 3f1d90ed..c6ede5f0 100644 --- a/libexosphere/include/exosphere/tegra/tegra_pmc.hpp +++ b/libexosphere/include/exosphere/tegra/tegra_pmc.hpp @@ -212,3 +212,5 @@ DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_XUSBB, 21, DISABLE, ENABLE); DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_XUSBC, 22, DISABLE, ENABLE); DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_VIC, 23, DISABLE, ENABLE); DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_IRAM, 24, DISABLE, ENABLE); + +DEFINE_PMC_REG_BIT_ENUM(CNTRL2_WAKE_DET_EN, 9, DISABLE, ENABLE); diff --git a/libexosphere/source/clkrst/clkrst_api.cpp b/libexosphere/source/clkrst/clkrst_api.cpp index c9ac4f98..c0ae50b2 100644 --- a/libexosphere/source/clkrst/clkrst_api.cpp +++ b/libexosphere/source/clkrst/clkrst_api.cpp @@ -105,7 +105,7 @@ namespace ams::clkrst { } void EnableI2c5Clock() { - EnableClock(I2c1Clock); + EnableClock(I2c5Clock); } void DisableI2c1Clock() { diff --git a/libexosphere/source/flow/flow_api.cpp b/libexosphere/source/flow/flow_api.cpp index 82a19943..62d00640 100644 --- a/libexosphere/source/flow/flow_api.cpp +++ b/libexosphere/source/flow/flow_api.cpp @@ -76,4 +76,8 @@ namespace ams::flow { reg::Write(g_register_address + FlowControllerRegisterOffsets[core].cc4_core_ctrl, value); } + void ClearL2FlushControl() { + reg::Write(g_register_address + FLOW_CTLR_L2FLUSH_CONTROL, 0); + } + } diff --git a/libexosphere/source/pmc/pmc_api.cpp b/libexosphere/source/pmc/pmc_api.cpp index 67739e58..3de6b17a 100644 --- a/libexosphere/source/pmc/pmc_api.cpp +++ b/libexosphere/source/pmc/pmc_api.cpp @@ -224,6 +224,32 @@ namespace ams::pmc { LockSecureRegister(SecureRegister_Srk); } + void EnableWakeEventDetection() { + /* Get the address. */ + const uintptr_t address = g_register_address; + + /* Wait 75us, then enable event detection, then wait another 75us. */ + util::WaitMicroSeconds(75); + reg::ReadWrite(address + APBDEV_PMC_CNTRL2, PMC_REG_BITS_ENUM(CNTRL2_WAKE_DET_EN, ENABLE)); + util::WaitMicroSeconds(75); + + /* Enable all wake events. */ + reg::Write(address + APBDEV_PMC_WAKE_STATUS, 0xFFFFFFFFu); + reg::Write(address + APBDEV_PMC_WAKE2_STATUS, 0xFFFFFFFFu); + util::WaitMicroSeconds(75); + } + + void ConfigureForSc7Entry() { + /* Get the address. */ + const uintptr_t address = g_register_address; + + /* Configure the bootrom to perform a warmboot. */ + reg::Write(address + APBDEV_PMC_SCRATCH0, 0x1); + + /* Enable the TSC multiplier. */ + reg::ReadWrite(address + APBDEV_PMC_DPD_ENABLE, PMC_REG_BITS_ENUM(DPD_ENABLE_TSC_MULT_EN, ENABLE)); + } + void LockSecureRegister(SecureRegister reg) { /* Get the address. */ const uintptr_t address = g_register_address; diff --git a/libexosphere/source/pmic/pmic_api.cpp b/libexosphere/source/pmic/pmic_api.cpp index e50723dc..96847f89 100644 --- a/libexosphere/source/pmic/pmic_api.cpp +++ b/libexosphere/source/pmic/pmic_api.cpp @@ -25,13 +25,17 @@ namespace ams::pmic { constexpr inline int I2cAddressMarikoMax77812_A = 0x31; constexpr inline int I2cAddressMarikoMax77812_B = 0x33; + constexpr inline int I2cAddressMax77620Pmic = 0x3C; + /* https://github.com/Atmosphere-NX/Atmosphere/blob/master/emummc/source/power/max77620.h */ /* https://github.com/Atmosphere-NX/Atmosphere/blob/master/emummc/source/power/max7762x.h */ /* TODO: Find datasheet, link to it instead. */ /* NOTE: Tentatively, Max77620 "mostly" matches https://datasheets.maximintegrated.com/en/ds/MAX77863.pdf. */ /* This does not contain Max77621 documentation, though. */ - constexpr inline int Max77620RegisterGpio0 = 0x36; - constexpr inline int Max77620RegisterAmeGpio = 0x40; + constexpr inline int Max77620RegisterOnOffStat = 0x15; + constexpr inline int Max77620RegisterGpio0 = 0x36; + constexpr inline int Max77620RegisterAmeGpio = 0x40; + constexpr inline int Max77620RegisterOnOffCnfg1 = 0x41; constexpr inline int Max77621RegisterVOut = 0x00; constexpr inline int Max77621RegisterVOutDvc = 0x01; @@ -108,6 +112,10 @@ namespace ams::pmic { } } + u8 GetPmicOnOffStat() { + return i2c::QueryByte(i2c::Port_5, I2cAddressMax77620Pmic, Max77620RegisterOnOffStat); + } + } void EnableVddCpu(Regulator regulator) { @@ -132,4 +140,19 @@ namespace ams::pmic { } } + void EnableSleep() { + /* Get the current onoff cfg. */ + u8 cnfg = i2c::QueryByte(i2c::Port_5, I2cAddressMax77620Pmic, Max77620RegisterOnOffCnfg1); + + /* Set SlpEn. */ + cnfg |= (1 << 2); + + /* Write the new cfg. */ + i2c::SendByte(i2c::Port_5, I2cAddressMax77620Pmic, Max77620RegisterOnOffCnfg1, cnfg); + } + + bool IsAcOk() { + return (GetPmicOnOffStat() & (1 << 1)) != 0; + } + }