blob: a192e8ccefd7ca075a407218ece64014d9bcd02e [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 "gtest/gtest.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/base/testing/mock_mmio.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_pwrmgr_toggle_t, 2> kAllToggles = {
kDifPwrmgrToggleEnabled, kDifPwrmgrToggleDisabled};
static constexpr std::array<bool, 2> kAllBools = {true, false};
static constexpr dif_pwrmgr_toggle_t kBadToggle =
static_cast<dif_pwrmgr_toggle_t>(kDifPwrmgrToggleDisabled + 1);
static constexpr dif_pwrmgr_irq_t kBadIrq =
static_cast<dif_pwrmgr_irq_t>(kDifPwrmgrIrqLast + 1);
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();
class DifPwrmgrTest : public testing::Test, public mock_mmio::MmioTest {
protected:
/**
* Parameters for initializing a `dif_pwrmgr_t`.
*/
const dif_pwrmgr_params_t params_ = {.base_addr = dev().region()};
};
class InitTest : public DifPwrmgrTest {};
TEST_F(InitTest, BadArgs) {
EXPECT_EQ(dif_pwrmgr_init(params_, nullptr), kDifPwrmgrBadArg);
}
TEST_F(InitTest, Init) {
dif_pwrmgr_t pwrmgr;
EXPECT_EQ(dif_pwrmgr_init(params_, &pwrmgr), kDifPwrmgrOk);
}
// Base class for the rest of the tests in this file, provides a
// `dif_pwrmgr_t` instance.
class DifPwrmgrInitialized : public DifPwrmgrTest {
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_ = {.params = params_};
};
class LowPowerTest : public DifPwrmgrInitialized {};
TEST_F(LowPowerTest, SetBadArgs) {
EXPECT_EQ(dif_pwrmgr_low_power_set_enabled(nullptr, kDifPwrmgrToggleEnabled),
kDifPwrmgrConfigBadArg);
EXPECT_EQ(dif_pwrmgr_low_power_set_enabled(&pwrmgr_, kBadToggle),
kDifPwrmgrConfigBadArg);
EXPECT_EQ(dif_pwrmgr_low_power_set_enabled(nullptr, kBadToggle),
kDifPwrmgrConfigBadArg);
}
TEST_F(LowPowerTest, SetLocked) {
for (auto 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_, toggle),
kDifPwrMgrConfigLocked);
}
}
TEST_F(LowPowerTest, Set) {
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 = PWRMGR_CONTROL_LOW_POWER_HINT_BIT,
.mask = 1,
.value = (toggle == kDifPwrmgrToggleEnabled),
}});
ExpectSync();
EXPECT_EQ(dif_pwrmgr_low_power_set_enabled(&pwrmgr_, toggle),
kDifPwrmgrConfigOk);
}
}
TEST_F(LowPowerTest, GetBadArgs) {
dif_pwrmgr_toggle_t state;
EXPECT_EQ(dif_pwrmgr_low_power_get_enabled(nullptr, &state),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_low_power_get_enabled(&pwrmgr_, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_low_power_get_enabled(nullptr, nullptr),
kDifPwrmgrBadArg);
}
TEST_F(LowPowerTest, Get) {
for (auto toggle : kAllToggles) {
dif_pwrmgr_toggle_t state;
EXPECT_READ32(PWRMGR_CONTROL_REG_OFFSET,
{{
.offset = PWRMGR_CONTROL_LOW_POWER_HINT_BIT,
.value = (toggle == kDifPwrmgrToggleEnabled),
}});
EXPECT_EQ(dif_pwrmgr_low_power_get_enabled(&pwrmgr_, &state), kDifPwrmgrOk);
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_EQ(dif_pwrmgr_set_domain_config(nullptr, 0), kDifPwrmgrConfigBadArg);
EXPECT_EQ(dif_pwrmgr_set_domain_config(&pwrmgr_, kBadConfig),
kDifPwrmgrConfigBadArg);
EXPECT_EQ(dif_pwrmgr_set_domain_config(nullptr, kBadConfig),
kDifPwrmgrConfigBadArg);
}
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), kDifPwrMgrConfigLocked);
}
TEST_F(DomainConfig, Set) {
for (auto config : kConfigs) {
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,
}});
ExpectSync();
EXPECT_EQ(dif_pwrmgr_set_domain_config(&pwrmgr_, config), kDifPwrmgrOk);
}
}
TEST_F(DomainConfig, GetBadArgs) {
dif_pwrmgr_domain_config_t config;
EXPECT_EQ(dif_pwrmgr_get_domain_config(nullptr, &config),
kDifPwrmgrConfigBadArg);
EXPECT_EQ(dif_pwrmgr_get_domain_config(&pwrmgr_, nullptr),
kDifPwrmgrConfigBadArg);
EXPECT_EQ(dif_pwrmgr_get_domain_config(nullptr, nullptr),
kDifPwrmgrConfigBadArg);
}
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_EQ(dif_pwrmgr_get_domain_config(&pwrmgr_, &act_config),
kDifPwrmgrOk);
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_EQ(dif_pwrmgr_set_request_sources(nullptr, kDifPwrmgrReqTypeWakeup,
kDifPwrmgrWakeupRequestSourceOne),
kDifPwrmgrConfigBadArg);
EXPECT_EQ(dif_pwrmgr_set_request_sources(&pwrmgr_, kBadReqType,
kDifPwrmgrWakeupRequestSourceOne),
kDifPwrmgrConfigBadArg);
EXPECT_EQ(dif_pwrmgr_set_request_sources(&pwrmgr_, kDifPwrmgrReqTypeWakeup,
kBadSources),
kDifPwrmgrConfigBadArg);
EXPECT_EQ(dif_pwrmgr_set_request_sources(nullptr, kBadReqType,
kDifPwrmgrWakeupRequestSourceOne),
kDifPwrmgrConfigBadArg);
EXPECT_EQ(dif_pwrmgr_set_request_sources(nullptr, kDifPwrmgrReqTypeWakeup,
kBadSources),
kDifPwrmgrConfigBadArg);
EXPECT_EQ(dif_pwrmgr_set_request_sources(&pwrmgr_, kBadReqType, kBadSources),
kDifPwrmgrConfigBadArg);
EXPECT_EQ(dif_pwrmgr_set_request_sources(nullptr, kBadReqType, kBadSources),
kDifPwrmgrConfigBadArg);
}
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),
kDifPwrMgrConfigLocked);
}
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),
kDifPwrMgrConfigLocked);
}
TEST_F(RequestSources, SetWakeup) {
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);
ExpectSync();
EXPECT_EQ(dif_pwrmgr_set_request_sources(&pwrmgr_, kDifPwrmgrReqTypeWakeup,
kDifPwrmgrWakeupRequestSourceOne),
kDifPwrmgrConfigOk);
}
TEST_F(RequestSources, SetReset) {
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);
ExpectSync();
EXPECT_EQ(dif_pwrmgr_set_request_sources(&pwrmgr_, kDifPwrmgrReqTypeReset,
kDifPwrmgrResetRequestSourceOne),
kDifPwrmgrConfigOk);
}
TEST_F(RequestSources, GetBadArgs) {
dif_pwrmgr_request_sources_t sources;
EXPECT_EQ(dif_pwrmgr_get_request_sources(nullptr, kDifPwrmgrReqTypeWakeup,
&sources),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_get_request_sources(&pwrmgr_, kBadReqType, &sources),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_get_request_sources(&pwrmgr_, kDifPwrmgrReqTypeWakeup,
nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_get_request_sources(nullptr, kBadReqType, &sources),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_get_request_sources(nullptr, kDifPwrmgrReqTypeWakeup, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_get_request_sources(&pwrmgr_, kBadReqType, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_get_request_sources(nullptr, kBadReqType, nullptr),
kDifPwrmgrBadArg);
}
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_EQ(dif_pwrmgr_get_request_sources(&pwrmgr_, kDifPwrmgrReqTypeWakeup,
&act_sources),
kDifPwrmgrOk);
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_EQ(dif_pwrmgr_get_request_sources(&pwrmgr_, kDifPwrmgrReqTypeReset,
&act_sources),
kDifPwrmgrOk);
EXPECT_EQ(act_sources, exp_sources);
}
}
TEST_F(RequestSources, GetCurrentBadArgs) {
dif_pwrmgr_request_sources_t sources;
EXPECT_EQ(dif_pwrmgr_get_current_request_sources(
nullptr, kDifPwrmgrReqTypeWakeup, &sources),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_get_current_request_sources(&pwrmgr_, kBadReqType, &sources),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_get_current_request_sources(
&pwrmgr_, kDifPwrmgrReqTypeWakeup, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_get_current_request_sources(nullptr, kBadReqType, &sources),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_get_current_request_sources(
nullptr, kDifPwrmgrReqTypeWakeup, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_get_current_request_sources(&pwrmgr_, kBadReqType, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_get_current_request_sources(nullptr, kBadReqType, nullptr),
kDifPwrmgrBadArg);
}
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_EQ(dif_pwrmgr_get_current_request_sources(
&pwrmgr_, kDifPwrmgrReqTypeWakeup, &act_sources),
kDifPwrmgrOk);
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_EQ(dif_pwrmgr_get_current_request_sources(
&pwrmgr_, kDifPwrmgrReqTypeReset, &act_sources),
kDifPwrmgrOk);
EXPECT_EQ(act_sources, exp_sources);
}
}
TEST_F(RequestSources, LockBadArgs) {
EXPECT_EQ(dif_pwrmgr_request_sources_lock(nullptr, kDifPwrmgrReqTypeWakeup),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_request_sources_lock(&pwrmgr_, kBadReqType),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_request_sources_lock(nullptr, kBadReqType),
kDifPwrmgrBadArg);
}
TEST_F(RequestSources, LockWakeup) {
EXPECT_WRITE32(PWRMGR_WAKEUP_EN_REGWEN_REG_OFFSET, 0);
EXPECT_EQ(dif_pwrmgr_request_sources_lock(&pwrmgr_, kDifPwrmgrReqTypeWakeup),
kDifPwrmgrOk);
}
TEST_F(RequestSources, LockReset) {
EXPECT_WRITE32(PWRMGR_RESET_EN_REGWEN_REG_OFFSET, 0);
EXPECT_EQ(dif_pwrmgr_request_sources_lock(&pwrmgr_, kDifPwrmgrReqTypeReset),
kDifPwrmgrOk);
}
TEST_F(RequestSources, IsLockedBadArgs) {
bool is_locked;
EXPECT_EQ(dif_pwrmgr_request_sources_is_locked(
nullptr, kDifPwrmgrReqTypeWakeup, &is_locked),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_request_sources_is_locked(&pwrmgr_, kBadReqType, &is_locked),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_request_sources_is_locked(
&pwrmgr_, kDifPwrmgrReqTypeWakeup, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_request_sources_is_locked(nullptr, kBadReqType, &is_locked),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_request_sources_is_locked(
nullptr, kDifPwrmgrReqTypeWakeup, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_request_sources_is_locked(&pwrmgr_, kBadReqType, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_request_sources_is_locked(nullptr, kBadReqType, nullptr),
kDifPwrmgrBadArg);
}
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_EQ(dif_pwrmgr_request_sources_is_locked(
&pwrmgr_, kDifPwrmgrReqTypeWakeup, &is_locked),
kDifPwrmgrOk);
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_EQ(dif_pwrmgr_request_sources_is_locked(
&pwrmgr_, kDifPwrmgrReqTypeReset, &is_locked),
kDifPwrmgrOk);
EXPECT_EQ(is_locked, exp_val);
}
}
class WakeupRecording : public DifPwrmgrInitialized {};
TEST_F(WakeupRecording, SetEnabledBadArgs) {
EXPECT_EQ(dif_pwrmgr_wakeup_request_recording_set_enabled(
nullptr, kDifPwrmgrToggleEnabled),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_wakeup_request_recording_set_enabled(&pwrmgr_, kBadToggle),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_wakeup_request_recording_set_enabled(nullptr, kBadToggle),
kDifPwrmgrBadArg);
}
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 == kDifPwrmgrToggleDisabled),
}});
EXPECT_EQ(
dif_pwrmgr_wakeup_request_recording_set_enabled(&pwrmgr_, new_state),
kDifPwrmgrOk);
}
}
TEST_F(WakeupRecording, GetEnabledBadArgs) {
dif_pwrmgr_toggle_t is_enabled;
EXPECT_EQ(
dif_pwrmgr_wakeup_request_recording_get_enabled(nullptr, &is_enabled),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_wakeup_request_recording_get_enabled(&pwrmgr_, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_wakeup_request_recording_get_enabled(nullptr, nullptr),
kDifPwrmgrBadArg);
}
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 == kDifPwrmgrToggleDisabled),
}});
dif_pwrmgr_toggle_t is_enabled = (exp_val == kDifPwrmgrToggleEnabled)
? kDifPwrmgrToggleDisabled
: kDifPwrmgrToggleEnabled;
EXPECT_EQ(
dif_pwrmgr_wakeup_request_recording_get_enabled(&pwrmgr_, &is_enabled),
kDifPwrmgrOk);
EXPECT_EQ(is_enabled, exp_val);
}
}
TEST_F(WakeupRecording, GetReasonBadArgs) {
dif_pwrmgr_wakeup_reason_t wakeup_reason;
EXPECT_EQ(dif_pwrmgr_wakeup_reason_get(nullptr, &wakeup_reason),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_wakeup_reason_get(&pwrmgr_, nullptr), kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_wakeup_reason_get(nullptr, nullptr), kDifPwrmgrBadArg);
}
/**
* 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, 5> 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_DEBUG_CABLE_WAKEUP_IDX,
.value = 1,
},
{
.offset = PWRMGR_PARAM_AON_WKUP_REQ_IDX,
.value = 1,
}},
.exp_output =
{
.types = kDifPwrmgrWakeupTypeAbort |
kDifPwrmgrWakeupTypeFallThrough |
kDifPwrmgrWakeupTypeRequest,
.request_sources = kDifPwrmgrWakeupRequestSourceTwo |
kDifPwrmgrWakeupRequestSourceThree,
},
},
// 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_DEBUG_CABLE_WAKEUP_IDX,
.value = 1,
}},
.exp_output =
{
.types = kDifPwrmgrWakeupTypeRequest,
.request_sources = kDifPwrmgrWakeupRequestSourceTwo,
},
},
}};
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_EQ(dif_pwrmgr_wakeup_reason_get(&pwrmgr_, &wakeup_reason),
kDifPwrmgrOk);
EXPECT_THAT(wakeup_reason, Eq(test_case.exp_output));
}
}
TEST_F(WakeupRecording, ClearReasonBadArgs) {
EXPECT_EQ(dif_pwrmgr_wakeup_reason_clear(nullptr), kDifPwrmgrBadArg);
}
TEST_F(WakeupRecording, ClearReason) {
EXPECT_WRITE32(PWRMGR_WAKE_INFO_REG_OFFSET,
std::numeric_limits<uint32_t>::max());
EXPECT_EQ(dif_pwrmgr_wakeup_reason_clear(&pwrmgr_), kDifPwrmgrOk);
}
class IrqTest : public DifPwrmgrInitialized {};
TEST_F(IrqTest, IsPendingBadArgs) {
bool is_pending;
EXPECT_EQ(
dif_pwrmgr_irq_is_pending(nullptr, kDifPwrmgrIrqWakeup, &is_pending),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_is_pending(&pwrmgr_, kBadIrq, &is_pending),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_is_pending(&pwrmgr_, kDifPwrmgrIrqWakeup, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_is_pending(nullptr, kBadIrq, &is_pending),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_is_pending(nullptr, kDifPwrmgrIrqWakeup, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_is_pending(&pwrmgr_, kBadIrq, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_is_pending(nullptr, kBadIrq, nullptr),
kDifPwrmgrBadArg);
}
TEST_F(IrqTest, IsPending) {
for (std::underlying_type<dif_pwrmgr_irq_t>::type irq = 0;
irq <= kDifPwrmgrIrqLast; ++irq) {
for (auto exp_val : kAllBools) {
EXPECT_READ32(PWRMGR_INTR_STATE_REG_OFFSET, {{
.offset = irq,
.value = exp_val,
}});
bool is_pending = !exp_val;
EXPECT_EQ(dif_pwrmgr_irq_is_pending(
&pwrmgr_, static_cast<dif_pwrmgr_irq_t>(irq), &is_pending),
kDifPwrmgrOk);
EXPECT_EQ(is_pending, exp_val);
}
}
}
TEST_F(IrqTest, AckBadArgs) {
EXPECT_EQ(dif_pwrmgr_irq_acknowledge(nullptr, kDifPwrmgrIrqWakeup),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_acknowledge(&pwrmgr_, kBadIrq), kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_acknowledge(nullptr, kBadIrq), kDifPwrmgrBadArg);
}
TEST_F(IrqTest, Ack) {
for (std::underlying_type<dif_pwrmgr_irq_t>::type irq = 0;
irq <= kDifPwrmgrIrqLast; ++irq) {
EXPECT_WRITE32(PWRMGR_INTR_STATE_REG_OFFSET, (1u << irq));
EXPECT_EQ(dif_pwrmgr_irq_acknowledge(&pwrmgr_,
static_cast<dif_pwrmgr_irq_t>(irq)),
kDifPwrmgrOk);
}
}
TEST_F(IrqTest, GetEnabledBadArgs) {
dif_pwrmgr_toggle_t is_enabled;
EXPECT_EQ(
dif_pwrmgr_irq_get_enabled(nullptr, kDifPwrmgrIrqWakeup, &is_enabled),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_get_enabled(&pwrmgr_, kBadIrq, &is_enabled),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_get_enabled(&pwrmgr_, kDifPwrmgrIrqWakeup, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_get_enabled(nullptr, kBadIrq, &is_enabled),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_get_enabled(nullptr, kDifPwrmgrIrqWakeup, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_get_enabled(&pwrmgr_, kBadIrq, nullptr),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_get_enabled(nullptr, kBadIrq, nullptr),
kDifPwrmgrBadArg);
}
TEST_F(IrqTest, GetEnabled) {
for (std::underlying_type<dif_pwrmgr_irq_t>::type irq = 0;
irq <= kDifPwrmgrIrqLast; ++irq) {
for (auto exp_val : kAllToggles) {
EXPECT_READ32(PWRMGR_INTR_ENABLE_REG_OFFSET,
{{
.offset = irq,
.value = (exp_val == kDifPwrmgrToggleEnabled),
}});
dif_pwrmgr_toggle_t is_enabled = (exp_val == kDifPwrmgrToggleEnabled)
? kDifPwrmgrToggleDisabled
: kDifPwrmgrToggleEnabled;
EXPECT_EQ(dif_pwrmgr_irq_get_enabled(
&pwrmgr_, static_cast<dif_pwrmgr_irq_t>(irq), &is_enabled),
kDifPwrmgrOk);
EXPECT_EQ(is_enabled, exp_val);
}
}
}
TEST_F(IrqTest, SetEnabledBadArgs) {
EXPECT_EQ(dif_pwrmgr_irq_set_enabled(nullptr, kDifPwrmgrIrqWakeup,
kDifPwrmgrToggleEnabled),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_irq_set_enabled(&pwrmgr_, kBadIrq, kDifPwrmgrToggleEnabled),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_irq_set_enabled(&pwrmgr_, kDifPwrmgrIrqWakeup, kBadToggle),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_irq_set_enabled(nullptr, kBadIrq, kDifPwrmgrToggleEnabled),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_irq_set_enabled(nullptr, kDifPwrmgrIrqWakeup, kBadToggle),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_set_enabled(&pwrmgr_, kBadIrq, kBadToggle),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_set_enabled(nullptr, kBadIrq, kBadToggle),
kDifPwrmgrBadArg);
}
TEST_F(IrqTest, SetEnabled) {
for (std::underlying_type<dif_pwrmgr_irq_t>::type irq = 0;
irq <= kDifPwrmgrIrqLast; ++irq) {
for (auto new_state : kAllToggles) {
EXPECT_MASK32(PWRMGR_INTR_ENABLE_REG_OFFSET,
{{
.offset = irq,
.mask = 1,
.value = (new_state == kDifPwrmgrToggleEnabled),
}});
EXPECT_EQ(dif_pwrmgr_irq_set_enabled(
&pwrmgr_, static_cast<dif_pwrmgr_irq_t>(irq), new_state),
kDifPwrmgrOk);
}
}
}
TEST_F(IrqTest, ForceBadArgs) {
EXPECT_EQ(dif_pwrmgr_irq_force(nullptr, kDifPwrmgrIrqWakeup),
kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_force(&pwrmgr_, kBadIrq), kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_force(nullptr, kBadIrq), kDifPwrmgrBadArg);
}
TEST_F(IrqTest, Force) {
for (std::underlying_type<dif_pwrmgr_irq_t>::type irq = 0;
irq <= kDifPwrmgrIrqLast; ++irq) {
EXPECT_WRITE32(PWRMGR_INTR_TEST_REG_OFFSET, {{
.offset = irq,
.value = 1,
}});
EXPECT_EQ(
dif_pwrmgr_irq_force(&pwrmgr_, static_cast<dif_pwrmgr_irq_t>(irq)),
kDifPwrmgrOk);
}
}
TEST_F(IrqTest, DisableAllBadArgs) {
dif_pwrmgr_irq_snapshot_t snapshot;
// `snapshot` is optional.
EXPECT_EQ(dif_pwrmgr_irq_disable_all(nullptr, &snapshot), kDifPwrmgrBadArg);
EXPECT_EQ(dif_pwrmgr_irq_disable_all(nullptr, nullptr), kDifPwrmgrBadArg);
}
TEST_F(IrqTest, DisableAll) {
uint32_t exp_snapshot = 0xA5A5A5A5;
// With `snapshot`.
EXPECT_READ32(PWRMGR_INTR_ENABLE_REG_OFFSET, exp_snapshot);
EXPECT_WRITE32(PWRMGR_INTR_ENABLE_REG_OFFSET, 0);
dif_pwrmgr_irq_snapshot_t act_snapshot = 0;
EXPECT_EQ(dif_pwrmgr_irq_disable_all(&pwrmgr_, &act_snapshot), kDifPwrmgrOk);
EXPECT_EQ(act_snapshot, exp_snapshot);
// Without `snapshot`.
EXPECT_WRITE32(PWRMGR_INTR_ENABLE_REG_OFFSET, 0);
EXPECT_EQ(dif_pwrmgr_irq_disable_all(&pwrmgr_, nullptr), kDifPwrmgrOk);
}
TEST_F(IrqTest, RestoreAllBadArgs) {
EXPECT_EQ(dif_pwrmgr_irq_restore_all(nullptr, 0), kDifPwrmgrBadArg);
}
TEST_F(IrqTest, RestoreAll) {
dif_pwrmgr_irq_snapshot_t snapshot = 0xA5A5A5A5;
EXPECT_WRITE32(PWRMGR_INTR_ENABLE_REG_OFFSET, snapshot);
EXPECT_EQ(dif_pwrmgr_irq_restore_all(&pwrmgr_, snapshot), kDifPwrmgrOk);
}
class AlertTest : public DifPwrmgrInitialized {};
TEST_F(AlertTest, ForceBadArgs) {
EXPECT_EQ(dif_pwrmgr_alert_force(nullptr, kDifPwrmgrAlertFatalFault),
kDifPwrmgrBadArg);
EXPECT_EQ(
dif_pwrmgr_alert_force(&pwrmgr_, static_cast<dif_pwrmgr_alert_t>(1)),
kDifPwrmgrBadArg);
}
TEST_F(AlertTest, Force) {
EXPECT_WRITE32(PWRMGR_ALERT_TEST_REG_OFFSET, {{0, true}});
EXPECT_EQ(dif_pwrmgr_alert_force(&pwrmgr_, kDifPwrmgrAlertFatalFault),
kDifPwrmgrOk);
}
} // namespace
} // namespace dif_pwrmgr_unittest