mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-04-19 22:49:06 -04:00
170 lines
5.5 KiB
C++
170 lines
5.5 KiB
C++
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
|
|
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
|
|
|
|
#include <log.hpp>
|
|
|
|
#include "PowerManager.hpp"
|
|
|
|
namespace sys
|
|
{
|
|
PowerManager::PowerManager()
|
|
{
|
|
lowPowerControl = bsp::LowPowerMode::Create().value_or(nullptr);
|
|
driverSEMC = drivers::DriverSEMC::Create("ExternalRAM");
|
|
cpuGovernor = std::make_unique<CpuGovernor>();
|
|
}
|
|
|
|
PowerManager::~PowerManager()
|
|
{}
|
|
|
|
int32_t PowerManager::PowerOff()
|
|
{
|
|
return lowPowerControl->PowerOff();
|
|
}
|
|
|
|
int32_t PowerManager::Reboot()
|
|
{
|
|
return lowPowerControl->Reboot(bsp::LowPowerMode::RebootType::NormalRestart);
|
|
}
|
|
|
|
int32_t PowerManager::RebootToUpdate(UpdateReason reason)
|
|
{
|
|
switch (reason) {
|
|
case UpdateReason::FactoryReset:
|
|
return lowPowerControl->Reboot(bsp::LowPowerMode::RebootType::GoToUpdaterFactoryReset);
|
|
case UpdateReason::Recovery:
|
|
return lowPowerControl->Reboot(bsp::LowPowerMode::RebootType::GoToUpdaterRecovery);
|
|
case UpdateReason::Update:
|
|
return lowPowerControl->Reboot(bsp::LowPowerMode::RebootType::GoToUpdaterUpdate);
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
void PowerManager::UpdateCpuFrequency(uint32_t cpuLoad)
|
|
{
|
|
const auto currentCpuFreq = lowPowerControl->GetCurrentFrequencyLevel();
|
|
const auto minFrequencyRequested = cpuGovernor->GetMinimumFrequencyRequested();
|
|
|
|
if (cpuLoad > frequencyShiftUpperThreshold && currentCpuFreq < bsp::CpuFrequencyHz::Level_6) {
|
|
aboveThresholdCounter++;
|
|
belowThresholdCounter = 0;
|
|
}
|
|
else if (cpuLoad < frequencyShiftLowerThreshold && currentCpuFreq > bsp::CpuFrequencyHz::Level_1) {
|
|
belowThresholdCounter++;
|
|
aboveThresholdCounter = 0;
|
|
}
|
|
else {
|
|
ResetFrequencyShiftCounter();
|
|
}
|
|
|
|
if (aboveThresholdCounter >= maxAboveThresholdCount || minFrequencyRequested > currentCpuFreq) {
|
|
ResetFrequencyShiftCounter();
|
|
IncreaseCpuFrequency();
|
|
}
|
|
else {
|
|
if (belowThresholdCounter >= maxBelowThresholdCount && currentCpuFreq > minFrequencyRequested) {
|
|
ResetFrequencyShiftCounter();
|
|
DecreaseCpuFrequency();
|
|
}
|
|
}
|
|
}
|
|
|
|
void PowerManager::IncreaseCpuFrequency() const
|
|
{
|
|
const auto freq = lowPowerControl->GetCurrentFrequencyLevel();
|
|
|
|
if (freq == bsp::CpuFrequencyHz::Level_1) {
|
|
// Switch DCDC to full throttle during oscillator switch
|
|
lowPowerControl->SetHighestCoreVoltage();
|
|
// switch oscillator source
|
|
lowPowerControl->SwitchOscillatorSource(bsp::LowPowerMode::OscillatorSource::External);
|
|
// then switch external RAM clock source
|
|
if (driverSEMC) {
|
|
driverSEMC->SwitchToPLL2ClockSource();
|
|
}
|
|
// Add intermediate step in frequency
|
|
SetCpuFrequency(bsp::CpuFrequencyHz::Level_4);
|
|
}
|
|
|
|
// and increase frequency
|
|
if (freq < bsp::CpuFrequencyHz::Level_6) {
|
|
SetCpuFrequency(bsp::CpuFrequencyHz::Level_6);
|
|
}
|
|
}
|
|
|
|
void PowerManager::DecreaseCpuFrequency() const
|
|
{
|
|
const auto freq = lowPowerControl->GetCurrentFrequencyLevel();
|
|
auto level = bsp::CpuFrequencyHz::Level_1;
|
|
|
|
switch (freq) {
|
|
case bsp::CpuFrequencyHz::Level_6:
|
|
level = bsp::CpuFrequencyHz::Level_5;
|
|
break;
|
|
case bsp::CpuFrequencyHz::Level_5:
|
|
level = bsp::CpuFrequencyHz::Level_4;
|
|
break;
|
|
case bsp::CpuFrequencyHz::Level_4:
|
|
level = bsp::CpuFrequencyHz::Level_3;
|
|
break;
|
|
case bsp::CpuFrequencyHz::Level_3:
|
|
level = bsp::CpuFrequencyHz::Level_2;
|
|
break;
|
|
case bsp::CpuFrequencyHz::Level_2:
|
|
level = bsp::CpuFrequencyHz::Level_1;
|
|
break;
|
|
case bsp::CpuFrequencyHz::Level_1:
|
|
break;
|
|
}
|
|
|
|
// decrease frequency first
|
|
if (level != freq) {
|
|
SetCpuFrequency(level);
|
|
}
|
|
|
|
if (level == bsp::CpuFrequencyHz::Level_1) {
|
|
// then switch osc source
|
|
lowPowerControl->SwitchOscillatorSource(bsp::LowPowerMode::OscillatorSource::Internal);
|
|
|
|
// and switch external RAM clock source
|
|
if (driverSEMC) {
|
|
driverSEMC->SwitchToPeripheralClockSource();
|
|
}
|
|
}
|
|
}
|
|
|
|
void PowerManager::RegisterNewSentinel(std::shared_ptr<CpuSentinel> newSentinel) const
|
|
{
|
|
cpuGovernor->RegisterNewSentinel(newSentinel);
|
|
}
|
|
|
|
void PowerManager::SetCpuFrequencyRequest(std::string sentinelName, bsp::CpuFrequencyHz request)
|
|
{
|
|
cpuGovernor->SetCpuFrequencyRequest(std::move(sentinelName), request);
|
|
}
|
|
|
|
void PowerManager::ResetCpuFrequencyRequest(std::string sentinelName)
|
|
{
|
|
cpuGovernor->ResetCpuFrequencyRequest(std::move(sentinelName));
|
|
}
|
|
|
|
void PowerManager::SetCpuFrequency(bsp::CpuFrequencyHz freq) const
|
|
{
|
|
lowPowerControl->SetCpuFrequency(freq);
|
|
cpuGovernor->InformSentinelsAboutCpuFrequencyChange(freq);
|
|
}
|
|
|
|
void PowerManager::ResetFrequencyShiftCounter()
|
|
{
|
|
aboveThresholdCounter = 0;
|
|
belowThresholdCounter = 0;
|
|
}
|
|
|
|
[[nodiscard]] auto PowerManager::getExternalRamDevice() const noexcept -> std::shared_ptr<devices::Device>
|
|
{
|
|
return driverSEMC;
|
|
}
|
|
|
|
} // namespace sys
|