mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
acpica: execute suspend&resume ACPI methods
on 'system' ROM state changes. Issue #4669
This commit is contained in:
parent
58ff53ec52
commit
dee178aae5
@ -46,7 +46,7 @@ Excerpt of important parts of the acpica configuration
|
||||
!<start name="acpica">
|
||||
! <!-- <binary name="debug-acpica"/> -->
|
||||
! ...
|
||||
! <config reset="no" poweroff="no" report="yes" report_period_ms="2000"/>
|
||||
! <config reset="no" sleep="no" poweroff="no" report="yes" report_period_ms="2000"/>
|
||||
! <route>
|
||||
! <service name="ROM" label="system"> <child name="..."/> </service>
|
||||
! <service name="Report"> <child name="..."/> </service>
|
||||
|
@ -55,18 +55,70 @@ struct Acpica::Statechange
|
||||
Attached_rom_dataspace _system_state;
|
||||
bool _enable_reset;
|
||||
bool _enable_poweroff;
|
||||
bool _enable_sleep;
|
||||
|
||||
Statechange(Env &env, bool reset, bool poweroff)
|
||||
Statechange(Env &env, bool reset, bool poweroff, bool sleep)
|
||||
:
|
||||
_dispatcher(env.ep(), *this, &Statechange::state_changed),
|
||||
_system_state(env, "system"),
|
||||
_enable_reset(reset), _enable_poweroff(poweroff)
|
||||
_enable_reset(reset), _enable_poweroff(poweroff), _enable_sleep(sleep)
|
||||
{
|
||||
_system_state.sigh(_dispatcher);
|
||||
|
||||
state_changed();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void suspend_prepare_check(T const &state)
|
||||
{
|
||||
if (!_enable_sleep)
|
||||
return;
|
||||
|
||||
UINT8 sleep_state = 0;
|
||||
|
||||
if (state == "s0_prepare") { sleep_state = 0; } else
|
||||
if (state == "s1_prepare") { sleep_state = 1; } else
|
||||
if (state == "s2_prepare") { sleep_state = 2; } else
|
||||
if (state == "s3_prepare") { sleep_state = 3; } else
|
||||
if (state == "s4_prepare") { sleep_state = 4; } else
|
||||
if (state == "s5_prepare") { sleep_state = 5; } else
|
||||
return;
|
||||
|
||||
Genode::log("prepare suspend S", sleep_state);
|
||||
|
||||
ACPI_STATUS res = AcpiEnterSleepStatePrep(sleep_state);
|
||||
if (ACPI_FAILURE(res))
|
||||
Genode::error("AcpiEnterSleepStatePrep failed ",
|
||||
res, " ", AcpiFormatException(res));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void resume_check(T const &state)
|
||||
{
|
||||
if (!_enable_sleep)
|
||||
return;
|
||||
|
||||
UINT8 sleep_state = 0;
|
||||
|
||||
if (state == "s0_resume") { sleep_state = 0; } else
|
||||
if (state == "s1_resume") { sleep_state = 1; } else
|
||||
if (state == "s2_resume") { sleep_state = 2; } else
|
||||
if (state == "s3_resume") { sleep_state = 3; } else
|
||||
if (state == "s4_resume") { sleep_state = 4; } else
|
||||
if (state == "s5_resume") { sleep_state = 5; } else
|
||||
return;
|
||||
|
||||
ACPI_STATUS res = AcpiLeaveSleepStatePrep(sleep_state);
|
||||
if (ACPI_FAILURE(res))
|
||||
Genode::error("AcpiLeaveSleepStatePrep failed ",
|
||||
res, " ", AcpiFormatException(res));
|
||||
|
||||
res = AcpiLeaveSleepState(sleep_state);
|
||||
if (ACPI_FAILURE(res))
|
||||
Genode::error("AcpiLeaveSleepState failed ",
|
||||
res, " ", AcpiFormatException(res));
|
||||
}
|
||||
|
||||
void state_changed() {
|
||||
|
||||
_system_state.update();
|
||||
@ -98,6 +150,11 @@ struct Acpica::Statechange
|
||||
" spaceid=", Hex(AcpiGbl_FADT.ResetRegister.SpaceId),
|
||||
" addr=", Hex(space_addr));
|
||||
}
|
||||
|
||||
suspend_prepare_check(state);
|
||||
|
||||
resume_check(state);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@ -139,6 +196,7 @@ struct Acpica::Main
|
||||
sci_irq(env.ep(), *this, &Main::acpi_irq),
|
||||
unchanged_state_max(config.xml().attribute_value("update_unchanged", 10U))
|
||||
{
|
||||
bool const enable_sleep = config.xml().attribute_value("sleep", false);
|
||||
bool const enable_reset = config.xml().attribute_value("reset", false);
|
||||
bool const enable_poweroff = config.xml().attribute_value("poweroff", false);
|
||||
bool const enable_report = config.xml().attribute_value("report", false);
|
||||
@ -152,8 +210,9 @@ struct Acpica::Main
|
||||
if (enable_report)
|
||||
report->enable();
|
||||
|
||||
if (enable_reset || enable_poweroff)
|
||||
new (heap) Acpica::Statechange(env, enable_reset, enable_poweroff);
|
||||
if (enable_reset || enable_poweroff || enable_sleep)
|
||||
new (heap) Acpica::Statechange(env, enable_reset, enable_poweroff,
|
||||
enable_sleep);
|
||||
|
||||
/* setup IRQ */
|
||||
if (!irq_handler.handler) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user