exo2: implement the first half of SmcCpuSuspend

This commit is contained in:
Michael Scire 2020-06-07 19:16:48 -07:00 committed by SciresM
parent e1835d9ba2
commit 0202a95832
11 changed files with 175 additions and 5 deletions

View file

@ -105,7 +105,7 @@ namespace ams::clkrst {
}
void EnableI2c5Clock() {
EnableClock(I2c1Clock);
EnableClock(I2c5Clock);
}
void DisableI2c1Clock() {

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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;
}
}