blob: 7185b64b3548e7aa4cf4a57cd100126c8ccbc159 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "sw/device/lib/dif/dif_pwrmgr.h"
#include <array>
#include "gtest/gtest.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/base/mock_mmio.h"
#include "sw/device/lib/dif/dif_base.h"
#include "sw/device/lib/dif/dif_test_base.h"
#include "pwrmgr_regs.h" // Generated
namespace dif_pwrmgr_unittest {
namespace {
/**
* Returns a `uint32_t` with a single zero bit.
*/
uint32_t AllOnesExcept(uint32_t index) { return ~(1u << index); }
/**
* Common constants used in tests.
*/
static constexpr std::array<dif_toggle_t, 2> kAllToggles = {
kDifToggleDisabled,
kDifToggleEnabled,
};
static constexpr std::array<bool, 2> kAllBools = {true, false};
static constexpr dif_toggle_t kBadToggle = static_cast<dif_toggle_t>(2);
static constexpr dif_pwrmgr_req_type_t kBadReqType =
static_cast<dif_pwrmgr_req_type_t>(kDifPwrmgrReqTypeReset + 1);
static constexpr dif_pwrmgr_domain_config_t kBadConfig =
std::numeric_limits<uint8_t>::max();
static constexpr dif_pwrmgr_request_sources_t kBadSources =
std::numeric_limits<uint32_t>::max();
// Base class for the rest of the tests in this file, provides a
// `dif_pwrmgr_t` instance.
class DifPwrmgrInitialized : public testing::Test, public mock_mmio::MmioTest {
protected:
/**
* Expectations for functions that need to sync data to slow clock domain.
*
* Sync is triggered by writing a 1 to the CFG_CDC_SYNC register, which is
* reset back to 0 by the hardware when the operation is complete.
*/
void ExpectSync() {
EXPECT_WRITE32(PWRMGR_CFG_CDC_SYNC_REG_OFFSET, 1);
// Insert a small random delay.
uint8_t rand_delay = dev().GarbageMemory<uint32_t>() & 0x7F;
for (uint8_t i = 0; i < rand_delay; ++i) {
EXPECT_READ32(PWRMGR_CFG_CDC_SYNC_REG_OFFSET, 1);
}
EXPECT_READ32(PWRMGR_CFG_CDC_SYNC_REG_OFFSET, 0);
}
/**
* Initialized `dif_pwrmgr_t` used in tests.
*/
const dif_pwrmgr_t pwrmgr_ = {.base_addr = dev().region()};
};
class LowPowerTest : public DifPwrmgrInitialized {};
TEST_F(LowPowerTest, SetBadArgs) {
EXPECT_DIF_BADARG(dif_pwrmgr_low_power_set_enabled(nullptr, kDifToggleEnabled,
kDifToggleEnabled));
EXPECT_DIF_BADARG(dif_pwrmgr_low_power_set_enabled(&pwrmgr_, kBadToggle,
kDifToggleEnabled));
EXPECT_DIF_BADARG(dif_pwrmgr_low_power_set_enabled(
&pwrmgr_, kDifToggleEnabled, kBadToggle));
EXPECT_DIF_BADARG(
dif_pwrmgr_low_power_set_enabled(nullptr, kBadToggle, kDifToggleEnabled));
EXPECT_DIF_BADARG(
dif_pwrmgr_low_power_set_enabled(nullptr, kDifToggleEnabled, kBadToggle));
EXPECT_DIF_BADARG(
dif_pwrmgr_low_power_set_enabled(&pwrmgr_, kBadToggle, kBadToggle));
EXPECT_DIF_BADARG(
dif_pwrmgr_low_power_set_enabled(nullptr, kBadToggle, kBadToggle));
}
TEST_F(LowPowerTest, SetLocked) {
for (auto new_toggle : kAllToggles) {
for (auto sync_toggle : kAllToggles) {
EXPECT_READ32(PWRMGR_CTRL_CFG_REGWEN_REG_OFFSET,
AllOnesExcept(PWRMGR_CTRL_CFG_REGWEN_EN_BIT));
EXPECT_EQ(
dif_pwrmgr_low_power_set_enabled(&pwrmgr_, new_toggle, sync_toggle),
kDifLocked);
}
}
}
TEST_F(LowPowerTest, Set) {
for (auto new_toggle : kAllToggles) {
for (auto sync_toggle : kAllToggles) {
EXPECT_READ32(PWRMGR_CTRL_CFG_REGWEN_REG_OFFSET,
{{
.offset = PWRMGR_CTRL_CFG_REGWEN_EN_BIT,
.value = 1,
}});
EXPECT_MASK32(PWRMGR_CONTROL_REG_OFFSET,
{{
.offset = PWRMGR_CONTROL_LOW_POWER_HINT_BIT,
.mask = 1,
.value = (new_toggle == kDifToggleEnabled),
}});
if (sync_toggle == kDifToggleEnabled)
ExpectSync();
EXPECT_DIF_OK(
dif_pwrmgr_low_power_set_enabled(&pwrmgr_, new_toggle, sync_toggle));
}
}
}
TEST_F(LowPowerTest, GetBadArgs) {
dif_toggle_t state;
EXPECT_DIF_BADARG(dif_pwrmgr_low_power_get_enabled(nullptr, &state));
EXPECT_DIF_BADARG(dif_pwrmgr_low_power_get_enabled(&pwrmgr_, nullptr));
EXPECT_DIF_BADARG(dif_pwrmgr_low_power_get_enabled(nullptr, nullptr));
}
TEST_F(LowPowerTest, Get) {
for (auto toggle : kAllToggles) {
dif_toggle_t state;
EXPECT_READ32(PWRMGR_CONTROL_REG_OFFSET,
{{
.offset = PWRMGR_CONTROL_LOW_POWER_HINT_BIT,
.value = (toggle == kDifToggleEnabled),
}});
EXPECT_DIF_OK(dif_pwrmgr_low_power_get_enabled(&pwrmgr_, &state));
EXPECT_EQ(state, toggle);
}
}
class DomainConfig : public DifPwrmgrInitialized {
protected:
/**
* Constants used in set and get tests.
*/
static constexpr bitfield_field32_t kConfigBitfield{
.mask = kDifPwrmgrDomainOptionCoreClockInLowPower |
kDifPwrmgrDomainOptionIoClockInLowPower |
kDifPwrmgrDomainOptionUsbClockInLowPower |
kDifPwrmgrDomainOptionUsbClockInActivePower |
kDifPwrmgrDomainOptionMainPowerInLowPower,
.index = PWRMGR_CONTROL_CORE_CLK_EN_BIT,
};
static constexpr std::array<dif_pwrmgr_domain_config_t, 4> kConfigs = {
// All disabled.
0,
// All enabled.
kDifPwrmgrDomainOptionCoreClockInLowPower |
kDifPwrmgrDomainOptionIoClockInLowPower |
kDifPwrmgrDomainOptionUsbClockInLowPower |
kDifPwrmgrDomainOptionUsbClockInActivePower |
kDifPwrmgrDomainOptionMainPowerInLowPower,
// Some enabled.
kDifPwrmgrDomainOptionCoreClockInLowPower |
kDifPwrmgrDomainOptionUsbClockInLowPower |
kDifPwrmgrDomainOptionMainPowerInLowPower,
// Some enabled.
kDifPwrmgrDomainOptionIoClockInLowPower |
kDifPwrmgrDomainOptionUsbClockInActivePower,
};
};
// We need this definition for the `for` loops.
constexpr std::array<dif_pwrmgr_domain_config_t, 4> DomainConfig::kConfigs;
TEST_F(DomainConfig, SetBadArgs) {
EXPECT_DIF_BADARG(
dif_pwrmgr_set_domain_config(nullptr, 0, kDifToggleEnabled));
EXPECT_DIF_BADARG(
dif_pwrmgr_set_domain_config(&pwrmgr_, kBadConfig, kDifToggleEnabled));
EXPECT_DIF_BADARG(dif_pwrmgr_set_domain_config(&pwrmgr_, 0, kBadToggle));
EXPECT_DIF_BADARG(
dif_pwrmgr_set_domain_config(nullptr, kBadConfig, kDifToggleEnabled));
EXPECT_DIF_BADARG(dif_pwrmgr_set_domain_config(nullptr, 0, kBadToggle));
EXPECT_DIF_BADARG(
dif_pwrmgr_set_domain_config(&pwrmgr_, kBadConfig, kBadToggle));
EXPECT_DIF_BADARG(
dif_pwrmgr_set_domain_config(nullptr, kBadConfig, kBadToggle));
}
TEST_F(DomainConfig, SetLocked) {
EXPECT_READ32(PWRMGR_CTRL_CFG_REGWEN_REG_OFFSET,
AllOnesExcept(PWRMGR_WAKEUP_EN_REGWEN_EN_BIT));
EXPECT_EQ(dif_pwrmgr_set_domain_config(&pwrmgr_, 0, kDifToggleEnabled),
kDifLocked);
}
TEST_F(DomainConfig, Set) {
for (auto config : kConfigs) {
for (auto toggle : kAllToggles) {
EXPECT_READ32(PWRMGR_CTRL_CFG_REGWEN_REG_OFFSET,
{{
.offset = PWRMGR_CTRL_CFG_REGWEN_EN_BIT,
.value = 1,
}});
EXPECT_MASK32(PWRMGR_CONTROL_REG_OFFSET,
{{
.offset = kConfigBitfield.index,
.mask = kConfigBitfield.mask,
.value = config,
}});
if (toggle == kDifToggleEnabled)
ExpectSync();
EXPECT_DIF_OK(dif_pwrmgr_set_domain_config(&pwrmgr_, config, toggle));
}
}
}
TEST_F(DomainConfig, GetBadArgs) {
dif_pwrmgr_domain_config_t config;
EXPECT_DIF_BADARG(dif_pwrmgr_get_domain_config(nullptr, &config));
EXPECT_DIF_BADARG(dif_pwrmgr_get_domain_config(&pwrmgr_, nullptr));
EXPECT_DIF_BADARG(dif_pwrmgr_get_domain_config(nullptr, nullptr));
}
TEST_F(DomainConfig, Get) {
for (auto exp_config : kConfigs) {
EXPECT_READ32(PWRMGR_CONTROL_REG_OFFSET,
{{
.offset = kConfigBitfield.index,
.value = exp_config,
}});
dif_pwrmgr_domain_config_t act_config;
EXPECT_DIF_OK(dif_pwrmgr_get_domain_config(&pwrmgr_, &act_config));
EXPECT_EQ(act_config, exp_config);
}
}
class RequestSources : public DifPwrmgrInitialized {
protected:
/**
* Constants used in set and get tests.
*/
static constexpr std::array<dif_pwrmgr_request_sources_t, 2> kWakeupSources =
{
// No sources.
0,
// All sources.
kDifPwrmgrWakeupRequestSourceOne,
};
static constexpr std::array<dif_pwrmgr_request_sources_t, 2> kResetSources = {
// No sources.
0,
// All sources.
kDifPwrmgrResetRequestSourceOne,
};
};
// We need these definitions for the `for` loops.
constexpr std::array<dif_pwrmgr_request_sources_t, 2>
RequestSources::kWakeupSources;
constexpr std::array<dif_pwrmgr_request_sources_t, 2>
RequestSources::kResetSources;
TEST_F(RequestSources, SetBadArgs) {
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(
nullptr, kDifPwrmgrReqTypeWakeup, kDifPwrmgrWakeupRequestSourceOne,
kDifToggleEnabled));
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(
&pwrmgr_, kBadReqType, kDifPwrmgrWakeupRequestSourceOne,
kDifToggleEnabled));
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(
&pwrmgr_, kDifPwrmgrReqTypeWakeup, kBadSources, kDifToggleEnabled));
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(
&pwrmgr_, kDifPwrmgrReqTypeWakeup, kDifPwrmgrWakeupRequestSourceOne,
kBadToggle));
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(
nullptr, kBadReqType, kDifPwrmgrWakeupRequestSourceOne,
kDifToggleEnabled));
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(
nullptr, kDifPwrmgrReqTypeWakeup, kBadSources, kDifToggleEnabled));
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(
nullptr, kDifPwrmgrReqTypeWakeup, kDifPwrmgrWakeupRequestSourceOne,
kBadToggle));
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(
&pwrmgr_, kBadReqType, kBadSources, kDifToggleEnabled));
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(
&pwrmgr_, kBadReqType, kDifPwrmgrWakeupRequestSourceOne, kBadToggle));
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(
&pwrmgr_, kDifPwrmgrReqTypeWakeup, kBadSources, kBadToggle));
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(
nullptr, kBadReqType, kBadSources, kDifToggleEnabled));
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(
nullptr, kBadReqType, kDifPwrmgrWakeupRequestSourceOne, kBadToggle));
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(
nullptr, kDifPwrmgrReqTypeWakeup, kBadSources, kBadToggle));
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(&pwrmgr_, kBadReqType,
kBadSources, kBadToggle));
EXPECT_DIF_BADARG(dif_pwrmgr_set_request_sources(nullptr, kBadReqType,
kBadSources, kBadToggle));
}
TEST_F(RequestSources, SetWakeupLocked) {
EXPECT_READ32(PWRMGR_WAKEUP_EN_REGWEN_REG_OFFSET,
AllOnesExcept(PWRMGR_WAKEUP_EN_REGWEN_EN_BIT));
EXPECT_EQ(dif_pwrmgr_set_request_sources(&pwrmgr_, kDifPwrmgrReqTypeWakeup,
kDifPwrmgrWakeupRequestSourceOne,
kDifToggleEnabled),
kDifLocked);
}
TEST_F(RequestSources, SetResetLocked) {
EXPECT_READ32(PWRMGR_RESET_EN_REGWEN_REG_OFFSET,
AllOnesExcept(PWRMGR_RESET_EN_REGWEN_EN_BIT));
EXPECT_EQ(dif_pwrmgr_set_request_sources(&pwrmgr_, kDifPwrmgrReqTypeReset,
kDifPwrmgrResetRequestSourceOne,
kDifToggleEnabled),
kDifLocked);
}
TEST_F(RequestSources, SetWakeup) {
for (auto toggle : kAllToggles) {
EXPECT_READ32(PWRMGR_WAKEUP_EN_REGWEN_REG_OFFSET,
{{
.offset = PWRMGR_WAKEUP_EN_REGWEN_EN_BIT,
.value = 1,
}});
EXPECT_WRITE32(PWRMGR_WAKEUP_EN_REG_OFFSET,
kDifPwrmgrWakeupRequestSourceOne);
if (toggle == kDifToggleEnabled)
ExpectSync();
EXPECT_DIF_OK(dif_pwrmgr_set_request_sources(
&pwrmgr_, kDifPwrmgrReqTypeWakeup, kDifPwrmgrWakeupRequestSourceOne,
toggle));
}
}
TEST_F(RequestSources, SetReset) {
for (auto toggle : kAllToggles) {
EXPECT_READ32(PWRMGR_RESET_EN_REGWEN_REG_OFFSET,
{{
.offset = PWRMGR_RESET_EN_REGWEN_EN_BIT,
.value = 1,
}});
EXPECT_WRITE32(PWRMGR_RESET_EN_REG_OFFSET, kDifPwrmgrResetRequestSourceOne);
if (toggle == kDifToggleEnabled)
ExpectSync();
EXPECT_DIF_OK(dif_pwrmgr_set_request_sources(
&pwrmgr_, kDifPwrmgrReqTypeReset, kDifPwrmgrResetRequestSourceOne,
toggle));
}
}
TEST_F(RequestSources, GetBadArgs) {
dif_pwrmgr_request_sources_t sources;
EXPECT_DIF_BADARG(dif_pwrmgr_get_request_sources(
nullptr, kDifPwrmgrReqTypeWakeup, &sources));
EXPECT_DIF_BADARG(
dif_pwrmgr_get_request_sources(&pwrmgr_, kBadReqType, &sources));
EXPECT_DIF_BADARG(dif_pwrmgr_get_request_sources(
&pwrmgr_, kDifPwrmgrReqTypeWakeup, nullptr));
EXPECT_DIF_BADARG(
dif_pwrmgr_get_request_sources(nullptr, kBadReqType, &sources));
EXPECT_DIF_BADARG(dif_pwrmgr_get_request_sources(
nullptr, kDifPwrmgrReqTypeWakeup, nullptr));
EXPECT_DIF_BADARG(
dif_pwrmgr_get_request_sources(&pwrmgr_, kBadReqType, nullptr));
EXPECT_DIF_BADARG(
dif_pwrmgr_get_request_sources(nullptr, kBadReqType, nullptr));
}
TEST_F(RequestSources, GetWakeup) {
for (auto exp_sources : kWakeupSources) {
EXPECT_READ32(PWRMGR_WAKEUP_EN_REG_OFFSET, exp_sources);
dif_pwrmgr_request_sources_t act_sources = 0;
EXPECT_DIF_OK(dif_pwrmgr_get_request_sources(
&pwrmgr_, kDifPwrmgrReqTypeWakeup, &act_sources));
EXPECT_EQ(act_sources, exp_sources);
}
}
TEST_F(RequestSources, GetReset) {
for (auto exp_sources : kResetSources) {
EXPECT_READ32(PWRMGR_RESET_EN_REG_OFFSET, exp_sources);
dif_pwrmgr_request_sources_t act_sources = 0;
EXPECT_DIF_OK(dif_pwrmgr_get_request_sources(
&pwrmgr_, kDifPwrmgrReqTypeReset, &act_sources));
EXPECT_EQ(act_sources, exp_sources);
}
}
TEST_F(RequestSources, GetCurrentBadArgs) {
dif_pwrmgr_request_sources_t sources;
EXPECT_DIF_BADARG(dif_pwrmgr_get_current_request_sources(
nullptr, kDifPwrmgrReqTypeWakeup, &sources));
EXPECT_DIF_BADARG(
dif_pwrmgr_get_current_request_sources(&pwrmgr_, kBadReqType, &sources));
EXPECT_DIF_BADARG(dif_pwrmgr_get_current_request_sources(
&pwrmgr_, kDifPwrmgrReqTypeWakeup, nullptr));
EXPECT_DIF_BADARG(
dif_pwrmgr_get_current_request_sources(nullptr, kBadReqType, &sources));
EXPECT_DIF_BADARG(dif_pwrmgr_get_current_request_sources(
nullptr, kDifPwrmgrReqTypeWakeup, nullptr));
EXPECT_DIF_BADARG(
dif_pwrmgr_get_current_request_sources(&pwrmgr_, kBadReqType, nullptr));
EXPECT_DIF_BADARG(
dif_pwrmgr_get_current_request_sources(nullptr, kBadReqType, nullptr));
}
TEST_F(RequestSources, GetCurrentWakeup) {
for (auto exp_sources : kWakeupSources) {
EXPECT_READ32(PWRMGR_WAKE_STATUS_REG_OFFSET, exp_sources);
dif_pwrmgr_request_sources_t act_sources = 0;
EXPECT_DIF_OK(dif_pwrmgr_get_current_request_sources(
&pwrmgr_, kDifPwrmgrReqTypeWakeup, &act_sources));
EXPECT_EQ(act_sources, exp_sources);
}
}
TEST_F(RequestSources, GetCurrentReset) {
for (auto exp_sources : kResetSources) {
EXPECT_READ32(PWRMGR_RESET_STATUS_REG_OFFSET, exp_sources);
dif_pwrmgr_request_sources_t act_sources = 0;
EXPECT_DIF_OK(dif_pwrmgr_get_current_request_sources(
&pwrmgr_, kDifPwrmgrReqTypeReset, &act_sources));
EXPECT_EQ(act_sources, exp_sources);
}
}
TEST_F(RequestSources, LockBadArgs) {
EXPECT_DIF_BADARG(
dif_pwrmgr_request_sources_lock(nullptr, kDifPwrmgrReqTypeWakeup));
EXPECT_DIF_BADARG(dif_pwrmgr_request_sources_lock(&pwrmgr_, kBadReqType));
EXPECT_DIF_BADARG(dif_pwrmgr_request_sources_lock(nullptr, kBadReqType));
}
TEST_F(RequestSources, LockWakeup) {
EXPECT_WRITE32(PWRMGR_WAKEUP_EN_REGWEN_REG_OFFSET, 0);
EXPECT_DIF_OK(
dif_pwrmgr_request_sources_lock(&pwrmgr_, kDifPwrmgrReqTypeWakeup));
}
TEST_F(RequestSources, LockReset) {
EXPECT_WRITE32(PWRMGR_RESET_EN_REGWEN_REG_OFFSET, 0);
EXPECT_DIF_OK(
dif_pwrmgr_request_sources_lock(&pwrmgr_, kDifPwrmgrReqTypeReset));
}
TEST_F(RequestSources, IsLockedBadArgs) {
bool is_locked;
EXPECT_DIF_BADARG(dif_pwrmgr_request_sources_is_locked(
nullptr, kDifPwrmgrReqTypeWakeup, &is_locked));
EXPECT_DIF_BADARG(
dif_pwrmgr_request_sources_is_locked(&pwrmgr_, kBadReqType, &is_locked));
EXPECT_DIF_BADARG(dif_pwrmgr_request_sources_is_locked(
&pwrmgr_, kDifPwrmgrReqTypeWakeup, nullptr));
EXPECT_DIF_BADARG(
dif_pwrmgr_request_sources_is_locked(nullptr, kBadReqType, &is_locked));
EXPECT_DIF_BADARG(dif_pwrmgr_request_sources_is_locked(
nullptr, kDifPwrmgrReqTypeWakeup, nullptr));
EXPECT_DIF_BADARG(
dif_pwrmgr_request_sources_is_locked(&pwrmgr_, kBadReqType, nullptr));
EXPECT_DIF_BADARG(
dif_pwrmgr_request_sources_is_locked(nullptr, kBadReqType, nullptr));
}
TEST_F(RequestSources, IsLockedWakeup) {
for (auto exp_val : kAllBools) {
EXPECT_READ32(PWRMGR_WAKEUP_EN_REGWEN_REG_OFFSET,
{{
.offset = PWRMGR_WAKEUP_EN_REGWEN_EN_BIT,
.value = !exp_val,
}});
bool is_locked = !exp_val;
EXPECT_DIF_OK(dif_pwrmgr_request_sources_is_locked(
&pwrmgr_, kDifPwrmgrReqTypeWakeup, &is_locked));
EXPECT_EQ(is_locked, exp_val);
}
}
TEST_F(RequestSources, IsLockedReset) {
for (auto exp_val : kAllBools) {
EXPECT_READ32(PWRMGR_RESET_EN_REGWEN_REG_OFFSET,
{{
.offset = PWRMGR_RESET_EN_REGWEN_EN_BIT,
.value = !exp_val,
}});
bool is_locked = !exp_val;
EXPECT_DIF_OK(dif_pwrmgr_request_sources_is_locked(
&pwrmgr_, kDifPwrmgrReqTypeReset, &is_locked));
EXPECT_EQ(is_locked, exp_val);
}
}
class WakeupRecording : public DifPwrmgrInitialized {};
TEST_F(WakeupRecording, SetEnabledBadArgs) {
EXPECT_DIF_BADARG(dif_pwrmgr_wakeup_request_recording_set_enabled(
nullptr, kDifToggleEnabled));
EXPECT_DIF_BADARG(
dif_pwrmgr_wakeup_request_recording_set_enabled(&pwrmgr_, kBadToggle));
EXPECT_DIF_BADARG(
dif_pwrmgr_wakeup_request_recording_set_enabled(nullptr, kBadToggle));
}
TEST_F(WakeupRecording, SetEnabled) {
for (auto new_state : kAllToggles) {
EXPECT_WRITE32(PWRMGR_WAKE_INFO_CAPTURE_DIS_REG_OFFSET,
{{
.offset = PWRMGR_WAKE_INFO_CAPTURE_DIS_VAL_BIT,
.value = (new_state == kDifToggleDisabled),
}});
EXPECT_DIF_OK(
dif_pwrmgr_wakeup_request_recording_set_enabled(&pwrmgr_, new_state));
}
}
TEST_F(WakeupRecording, GetEnabledBadArgs) {
dif_toggle_t is_enabled;
EXPECT_DIF_BADARG(
dif_pwrmgr_wakeup_request_recording_get_enabled(nullptr, &is_enabled));
EXPECT_DIF_BADARG(
dif_pwrmgr_wakeup_request_recording_get_enabled(&pwrmgr_, nullptr));
EXPECT_DIF_BADARG(
dif_pwrmgr_wakeup_request_recording_get_enabled(nullptr, nullptr));
}
TEST_F(WakeupRecording, GetEnabled) {
for (auto exp_val : kAllToggles) {
EXPECT_READ32(PWRMGR_WAKE_INFO_CAPTURE_DIS_REG_OFFSET,
{{
.offset = PWRMGR_WAKE_INFO_CAPTURE_DIS_VAL_BIT,
.value = (exp_val == kDifToggleDisabled),
}});
dif_toggle_t is_enabled =
(exp_val == kDifToggleEnabled) ? kDifToggleDisabled : kDifToggleEnabled;
EXPECT_DIF_OK(
dif_pwrmgr_wakeup_request_recording_get_enabled(&pwrmgr_, &is_enabled));
EXPECT_EQ(is_enabled, exp_val);
}
}
TEST_F(WakeupRecording, GetReasonBadArgs) {
dif_pwrmgr_wakeup_reason_t wakeup_reason;
EXPECT_DIF_BADARG(dif_pwrmgr_wakeup_reason_get(nullptr, &wakeup_reason));
EXPECT_DIF_BADARG(dif_pwrmgr_wakeup_reason_get(&pwrmgr_, nullptr));
EXPECT_DIF_BADARG(dif_pwrmgr_wakeup_reason_get(nullptr, nullptr));
}
/**
* Custom equality matcher for `dif_pwrmgr_wakeup_reason_t`s.
*/
testing::Matcher<dif_pwrmgr_wakeup_reason_t> Eq(
const dif_pwrmgr_wakeup_reason_t &rhs) {
return testing::AllOf(
testing::Field("types", &dif_pwrmgr_wakeup_reason_t::types, rhs.types),
testing::Field("request_sources",
&dif_pwrmgr_wakeup_reason_t::request_sources,
rhs.request_sources));
}
TEST_F(WakeupRecording, GetReason) {
struct TestCase {
/**
* Value that will be read from hardware.
*/
std::initializer_list<mock_mmio::BitField> read_val;
/**
* Expected output.
*/
dif_pwrmgr_wakeup_reason_t exp_output;
};
std::array<TestCase, 10> test_cases = {{
// No bits set.
{
.read_val = {{
.offset = 0,
.value = 0,
}},
.exp_output =
{
.types = 0,
.request_sources = 0,
},
},
// All bits set.
{
.read_val = {{
.offset = PWRMGR_WAKE_INFO_ABORT_BIT,
.value = 1,
},
{
.offset = PWRMGR_WAKE_INFO_FALL_THROUGH_BIT,
.value = 1,
},
{
.offset = PWRMGR_PARAM_SYSRST_CTRL_AON_WKUP_REQ_IDX,
.value = 1,
},
{
.offset = PWRMGR_PARAM_ADC_CTRL_AON_WKUP_REQ_IDX,
.value = 1,
},
{
.offset = PWRMGR_PARAM_PINMUX_AON_PIN_WKUP_REQ_IDX,
.value = 1,
},
{
.offset = PWRMGR_PARAM_PINMUX_AON_USB_WKUP_REQ_IDX,
.value = 1,
},
{
.offset = PWRMGR_PARAM_AON_TIMER_AON_WKUP_REQ_IDX,
.value = 1,
},
{
.offset = PWRMGR_PARAM_SENSOR_CTRL_WKUP_REQ_IDX,
.value = 1,
}},
.exp_output = {.types = kDifPwrmgrWakeupTypeAbort |
kDifPwrmgrWakeupTypeFallThrough |
kDifPwrmgrWakeupTypeRequest,
.request_sources = kDifPwrmgrWakeupRequestSourceOne |
kDifPwrmgrWakeupRequestSourceTwo |
kDifPwrmgrWakeupRequestSourceThree |
kDifPwrmgrWakeupRequestSourceFour |
kDifPwrmgrWakeupRequestSourceFive |
kDifPwrmgrWakeupRequestSourceSix},
},
// Only abort.
{
.read_val = {{
.offset = PWRMGR_WAKE_INFO_ABORT_BIT,
.value = 1,
}},
.exp_output =
{
.types = kDifPwrmgrWakeupTypeAbort,
.request_sources = 0,
},
},
// Only fall-through.
{
.read_val = {{
.offset = PWRMGR_WAKE_INFO_FALL_THROUGH_BIT,
.value = 1,
}},
.exp_output =
{
.types = kDifPwrmgrWakeupTypeFallThrough,
.request_sources = 0,
},
},
// Only requests from peripherals.
{
.read_val = {{
.offset = PWRMGR_PARAM_SYSRST_CTRL_AON_WKUP_REQ_IDX,
.value = 1,
}},
.exp_output =
{
.types = kDifPwrmgrWakeupTypeRequest,
.request_sources = kDifPwrmgrWakeupRequestSourceOne,
},
},
{
.read_val = {{
.offset = PWRMGR_PARAM_ADC_CTRL_AON_WKUP_REQ_IDX,
.value = 1,
}},
.exp_output =
{
.types = kDifPwrmgrWakeupTypeRequest,
.request_sources = kDifPwrmgrWakeupRequestSourceTwo,
},
},
{
.read_val = {{
.offset = PWRMGR_PARAM_PINMUX_AON_PIN_WKUP_REQ_IDX,
.value = 1,
}},
.exp_output =
{
.types = kDifPwrmgrWakeupTypeRequest,
.request_sources = kDifPwrmgrWakeupRequestSourceThree,
},
},
{
.read_val = {{
.offset = PWRMGR_PARAM_PINMUX_AON_USB_WKUP_REQ_IDX,
.value = 1,
}},
.exp_output =
{
.types = kDifPwrmgrWakeupTypeRequest,
.request_sources = kDifPwrmgrWakeupRequestSourceFour,
},
},
{
.read_val = {{
.offset = PWRMGR_PARAM_AON_TIMER_AON_WKUP_REQ_IDX,
.value = 1,
}},
.exp_output =
{
.types = kDifPwrmgrWakeupTypeRequest,
.request_sources = kDifPwrmgrWakeupRequestSourceFive,
},
},
{
.read_val = {{
.offset = PWRMGR_PARAM_SENSOR_CTRL_WKUP_REQ_IDX,
.value = 1,
}},
.exp_output =
{
.types = kDifPwrmgrWakeupTypeRequest,
.request_sources = kDifPwrmgrWakeupRequestSourceSix,
},
},
}};
for (const auto &test_case : test_cases) {
EXPECT_READ32(PWRMGR_WAKE_INFO_REG_OFFSET, test_case.read_val);
dif_pwrmgr_wakeup_reason_t wakeup_reason;
EXPECT_DIF_OK(dif_pwrmgr_wakeup_reason_get(&pwrmgr_, &wakeup_reason));
EXPECT_THAT(wakeup_reason, Eq(test_case.exp_output));
}
}
TEST_F(WakeupRecording, ClearReasonBadArgs) {
EXPECT_DIF_BADARG(dif_pwrmgr_wakeup_reason_clear(nullptr));
}
TEST_F(WakeupRecording, ClearReason) {
EXPECT_WRITE32(PWRMGR_WAKE_INFO_REG_OFFSET,
std::numeric_limits<uint32_t>::max());
EXPECT_DIF_OK(dif_pwrmgr_wakeup_reason_clear(&pwrmgr_));
}
class FatalErrorTest : public DifPwrmgrInitialized {};
TEST_F(FatalErrorTest, GetBadArgs) {
dif_pwrmgr_fatal_err_codes_t codes;
EXPECT_DIF_BADARG(dif_pwrmgr_fatal_err_code_get_codes(nullptr, nullptr));
EXPECT_DIF_BADARG(dif_pwrmgr_fatal_err_code_get_codes(nullptr, &codes));
EXPECT_DIF_BADARG(dif_pwrmgr_fatal_err_code_get_codes(&pwrmgr_, nullptr));
}
TEST_F(FatalErrorTest, GetCodes) {
dif_pwrmgr_fatal_err_codes_t codes;
EXPECT_READ32(PWRMGR_FAULT_STATUS_REG_OFFSET, 6);
EXPECT_DIF_OK(dif_pwrmgr_fatal_err_code_get_codes(&pwrmgr_, &codes));
EXPECT_EQ(codes, 6);
}
} // namespace
} // namespace dif_pwrmgr_unittest