| // Copyright 2022 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/graphics/display/drivers/intel-i915/power-controller.h" |
| |
| #include <lib/mmio/mmio-buffer.h> |
| #include <lib/zx/result.h> |
| #include <zircon/errors.h> |
| |
| #include <atomic> |
| #include <cstdint> |
| |
| #include <fake-mmio-reg/fake-mmio-reg.h> |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| #include <mock-mmio-range/mock-mmio-range.h> |
| |
| #include "src/graphics/display/drivers/intel-i915/scoped-value-change.h" |
| |
| namespace i915 { |
| |
| namespace { |
| |
| // MMIO addresses from IHD-OS-KBL-Vol 12-1.17 "Sequences for Changing CD Clock |
| // Frequency", pages 138-139 |
| |
| constexpr uint32_t kMailboxInterfaceOffset = 0x138124; |
| constexpr uint32_t kMailboxData0Offset = 0x138128; |
| constexpr uint32_t kMailboxData1Offset = 0x13812c; |
| |
| class PowerControllerTest : public ::testing::Test { |
| public: |
| PowerControllerTest() |
| : previous_timeout_change_( |
| PowerController::OverridePreviousCommandTimeoutUsForTesting(kLargeTimeout)), |
| voltage_level_reply_timeout_change_( |
| PowerController::OverrideVoltageLevelRequestReplyTimeoutUsForTesting(kLargeTimeout)), |
| voltage_level_timeout_change_( |
| PowerController::OverrideVoltageLevelRequestTotalTimeoutUsForTesting(kLargeTimeout)), |
| typec_blocking_reply_timeout_change_( |
| PowerController::OverrideTypeCColdBlockingChangeReplyTimeoutUsForTesting( |
| kLargeTimeout)), |
| typec_blocking_timeout_change_( |
| PowerController::OverrideTypeCColdBlockingChangeTotalTimeoutUsForTesting( |
| kLargeTimeout)), |
| system_agent_enablement_reply_timeout_change_( |
| PowerController::OverrideSystemAgentEnablementChangeReplyTimeoutUsForTesting( |
| kLargeTimeout)), |
| system_agent_enablement_timeout_change_( |
| PowerController::OverrideSystemAgentEnablementChangeTotalTimeoutUsForTesting( |
| kLargeTimeout)), |
| memory_subsystem_info_reply_timeout_change_( |
| PowerController::OverrideGetMemorySubsystemInfoReplyTimeoutUsForTesting(kLargeTimeout)), |
| memory_latency_reply_timeout_change_( |
| PowerController::OverrideGetMemoryLatencyReplyTimeoutUsForTesting(kLargeTimeout)) {} |
| ~PowerControllerTest() override = default; |
| |
| void SetUp() override {} |
| void TearDown() override { mmio_range_.CheckAllAccessesReplayed(); } |
| |
| protected: |
| // Ensures that the tests don't time out due to external factors (such as |
| // being pre-empted by the scheduler) while replaying MMIO access lists. |
| constexpr static int kLargeTimeout = 1'000'000'000; |
| |
| // Large enough (1 second) that having the test pre-empted by the scheduler |
| // for a bit won't cause the request retry loop to be completely skipped. |
| // Small enough so the tests don't become a significant burden on the |
| // continuous integration systems. |
| constexpr static int kRealClockTestTimeout = 1'000'000; |
| |
| constexpr static int kMmioRangeSize = 0x140000; |
| ddk_mock::MockMmioRange mmio_range_{kMmioRangeSize, ddk_mock::MockMmioRange::Size::k32}; |
| fdf::MmioBuffer mmio_buffer_{mmio_range_.GetMmioBuffer()}; |
| |
| ScopedValueChange<int> previous_timeout_change_; |
| ScopedValueChange<int> voltage_level_reply_timeout_change_; |
| ScopedValueChange<int> voltage_level_timeout_change_; |
| ScopedValueChange<int> typec_blocking_reply_timeout_change_; |
| ScopedValueChange<int> typec_blocking_timeout_change_; |
| ScopedValueChange<int> system_agent_enablement_reply_timeout_change_; |
| ScopedValueChange<int> system_agent_enablement_timeout_change_; |
| ScopedValueChange<int> memory_subsystem_info_reply_timeout_change_; |
| ScopedValueChange<int> memory_latency_reply_timeout_change_; |
| }; |
| |
| TEST_F(PowerControllerTest, TransactImmediateSuccess) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x9abc'def0, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x1234'5678, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0042'4140}, |
| {.address = kMailboxData0Offset, .value = 0x7654'3210}, |
| {.address = kMailboxData1Offset, .value = 0xfedc'ba98}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| zx::result<uint64_t> result = power_controller.Transact({ |
| .command = 0x40, |
| .param1 = 0x41, |
| .param2 = 0x42, |
| .data = 0x1234'5678'9abc'def0, |
| .timeout_us = 3, |
| }); |
| ASSERT_TRUE(result.is_ok()) << result.status_string(); |
| EXPECT_EQ(0xfedcba98'76543210u, result.value()); |
| } |
| |
| TEST_F(PowerControllerTest, TransactSuccessAfterDelay) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x9abc'def0, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x1234'5678, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0042'4140}, |
| {.address = kMailboxData0Offset, .value = 0x7654'3210}, |
| {.address = kMailboxData1Offset, .value = 0xfedc'ba98}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| zx::result<uint64_t> result = power_controller.Transact({ |
| .command = 0x40, |
| .param1 = 0x41, |
| .param2 = 0x42, |
| .data = 0x1234'5678'9abc'def0, |
| .timeout_us = 3, |
| }); |
| ASSERT_TRUE(result.is_ok()) << result.status_string(); |
| EXPECT_EQ(0xfedc'ba98'7654'3210u, result.value()); |
| } |
| |
| TEST_F(PowerControllerTest, TransactCommandTimeout) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x9abc'def0, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x1234'5678, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<uint64_t> result = power_controller.Transact({ |
| .command = 0x40, |
| .param1 = 0x41, |
| .param2 = 0x42, |
| .data = 0x1234'5678'9abc'def0, |
| .timeout_us = 3, |
| }); |
| EXPECT_EQ(ZX_ERR_IO_MISSED_DEADLINE, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, TransactCommandZeroTimeout) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x9abc'def0, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x1234'5678, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140, .write = true}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| zx::result<uint64_t> result = power_controller.Transact({ |
| .command = 0x40, |
| .param1 = 0x41, |
| .param2 = 0x42, |
| .data = 0x1234'5678'9abc'def0, |
| .timeout_us = 0, |
| }); |
| ASSERT_TRUE(result.is_ok()) << result.status_string(); |
| EXPECT_EQ(0u, result.value()); |
| } |
| |
| TEST_F(PowerControllerTest, TransactSuccessAfterPriorCommandDelay) { |
| previous_timeout_change_.reset(); |
| previous_timeout_change_ = |
| PowerController::OverridePreviousCommandTimeoutUsForTesting(kLargeTimeout); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0007}, |
| {.address = kMailboxData0Offset, .value = 0x9abc'def0, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x1234'5678, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0042'4140}, |
| {.address = kMailboxData0Offset, .value = 0x7654'3210}, |
| {.address = kMailboxData1Offset, .value = 0xfedc'ba98}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| zx::result<uint64_t> result = power_controller.Transact({ |
| .command = 0x40, |
| .param1 = 0x41, |
| .param2 = 0x42, |
| .data = 0x1234'5678'9abc'def0, |
| .timeout_us = 3, |
| }); |
| ASSERT_TRUE(result.is_ok()) << result.status_string(); |
| EXPECT_EQ(0xfedc'ba98'7654'3210u, result.value()); |
| } |
| |
| TEST_F(PowerControllerTest, TransactSuccessAfterPriorAndCurrentCommandDelay) { |
| previous_timeout_change_.reset(); |
| previous_timeout_change_ = |
| PowerController::OverridePreviousCommandTimeoutUsForTesting(kLargeTimeout); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0007}, |
| {.address = kMailboxData0Offset, .value = 0x9abc'def0, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x1234'5678, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0042'4140}, |
| {.address = kMailboxData0Offset, .value = 0x7654'3210}, |
| {.address = kMailboxData1Offset, .value = 0xfedc'ba98}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| zx::result<uint64_t> result = power_controller.Transact({ |
| .command = 0x40, |
| .param1 = 0x41, |
| .param2 = 0x42, |
| .data = 0x1234'5678'9abc'def0, |
| .timeout_us = 3, |
| }); |
| ASSERT_TRUE(result.is_ok()) << result.status_string(); |
| EXPECT_EQ(0xfedc'ba98'7654'3210u, result.value()); |
| } |
| |
| TEST_F(PowerControllerTest, TransactPreviousCommandTimeout) { |
| previous_timeout_change_.reset(); |
| previous_timeout_change_ = PowerController::OverridePreviousCommandTimeoutUsForTesting(0); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0x8042'4140}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<uint64_t> result = power_controller.Transact({ |
| .command = 0x40, |
| .param1 = 0x41, |
| .param2 = 0x42, |
| .data = 0x1234'5678'9abc'def0, |
| .timeout_us = 3, |
| }); |
| EXPECT_EQ(ZX_ERR_IO_MISSED_DEADLINE, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, RequestDisplayVoltageLevelNoRetrySuccess) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0003, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0007}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = |
| power_controller.RequestDisplayVoltageLevel(3, PowerController::RetryBehavior::kNoRetry); |
| EXPECT_TRUE(result.is_ok()) << result.status_string(); |
| } |
| |
| TEST_F(PowerControllerTest, RequestDisplayVoltageLevelLowLevelNoRetrySuccess) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0007}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = |
| power_controller.RequestDisplayVoltageLevel(1, PowerController::RetryBehavior::kNoRetry); |
| EXPECT_TRUE(result.is_ok()) << result.status_string(); |
| } |
| |
| TEST_F(PowerControllerTest, RequestDisplayVoltageLevelLowLevelNoRetryRefused) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0007}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = |
| power_controller.RequestDisplayVoltageLevel(1, PowerController::RetryBehavior::kNoRetry); |
| EXPECT_EQ(ZX_ERR_IO_REFUSED, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, RequestDisplayVoltageLevelLowLevelNoRetryReplyTimeout) { |
| voltage_level_reply_timeout_change_.reset(); |
| voltage_level_reply_timeout_change_ = |
| PowerController::OverrideVoltageLevelRequestReplyTimeoutUsForTesting(1); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007, .write = true}, |
| |
| // Setting the reply timeout to 1 results in exactly 2 mailbox checks. |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = |
| power_controller.RequestDisplayVoltageLevel(1, PowerController::RetryBehavior::kNoRetry); |
| EXPECT_EQ(ZX_ERR_IO_MISSED_DEADLINE, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, RequestDisplayVoltageLevelRetryImmediateSuccess) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0003, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0007}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.RequestDisplayVoltageLevel( |
| 3, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_TRUE(result.is_ok()) << result.status_string(); |
| } |
| |
| TEST_F(PowerControllerTest, RequestDisplayVoltageLevelRetrySuccessAfterRetries) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0003, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0007}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| |
| // First retry. |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0007}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0003, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0007}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| |
| // Second retry. |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0007}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0003, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0007}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.RequestDisplayVoltageLevel( |
| 3, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_TRUE(result.is_ok()) << result.status_string(); |
| } |
| |
| TEST_F(PowerControllerTest, RequestDisplayVoltageLevelRetryTimeoutBeforeRetry) { |
| voltage_level_timeout_change_.reset(); |
| voltage_level_timeout_change_ = |
| PowerController::OverrideVoltageLevelRequestTotalTimeoutUsForTesting(0); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0003, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0007}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.RequestDisplayVoltageLevel( |
| 3, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_EQ(ZX_ERR_IO_REFUSED, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, RequestDisplayVoltageLevelRetryTimeoutAfterRetry) { |
| voltage_level_timeout_change_.reset(); |
| voltage_level_timeout_change_ = |
| PowerController::OverrideVoltageLevelRequestTotalTimeoutUsForTesting(kRealClockTestTimeout); |
| |
| bool report_busy_mailbox = false; |
| |
| ddk_fake::FakeMmioRegRegion fake_mmio_region(sizeof(uint32_t), 0x140000 / sizeof(uint32_t)); |
| |
| fake_mmio_region[kMailboxInterfaceOffset].SetWriteCallback([&](uint64_t value) { |
| EXPECT_EQ(0x8000'0007, value) << "Unexpected command"; |
| report_busy_mailbox = true; |
| }); |
| fake_mmio_region[kMailboxInterfaceOffset].SetReadCallback([&]() -> uint64_t { |
| if (report_busy_mailbox) { |
| // Report busy once, so RequestDisplayVoltageLevelRetryTimeout() gets some |
| // sleep between retries. |
| report_busy_mailbox = false; |
| return 0x8000'0007; |
| } |
| return 0x0000'0007; |
| }); |
| fake_mmio_region[kMailboxData0Offset].SetReadCallback([&]() -> uint64_t { |
| // Always produce the result "voltage level not applied", so |
| // RequestDisplayVoltageLevel() retries. |
| return 0x0000'0000; |
| }); |
| |
| fdf::MmioBuffer fake_mmio_buffer = fake_mmio_region.GetMmioBuffer(); |
| PowerController power_controller(&fake_mmio_buffer); |
| |
| const zx::result<> result = power_controller.RequestDisplayVoltageLevel( |
| 2, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_EQ(ZX_ERR_IO_REFUSED, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, RequestDisplayVoltageLevelRetryReplyTimeout) { |
| voltage_level_reply_timeout_change_.reset(); |
| voltage_level_reply_timeout_change_ = |
| PowerController::OverrideVoltageLevelRequestReplyTimeoutUsForTesting(1); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0003, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007, .write = true}, |
| |
| // Setting the reply timeout to 1 results in exactly 2 mailbox checks. |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0007}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.RequestDisplayVoltageLevel( |
| 3, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_EQ(ZX_ERR_IO_MISSED_DEADLINE, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, SetDisplayTypeCColdBlockingTigerLakeOnNoRetrySuccess) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0026, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0026}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetDisplayTypeCColdBlockingTigerLake( |
| true, PowerController::RetryBehavior::kNoRetry); |
| EXPECT_TRUE(result.is_ok()) << result.status_string(); |
| } |
| |
| TEST_F(PowerControllerTest, SetDisplayTypeCColdBlockingTigerLakeOffNoRetrySuccess) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0026, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0026}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetDisplayTypeCColdBlockingTigerLake( |
| false, PowerController::RetryBehavior::kNoRetry); |
| EXPECT_TRUE(result.is_ok()) << result.status_string(); |
| } |
| |
| TEST_F(PowerControllerTest, SetDisplayTypeCColdBlockingTigerLakeOffNoRetryRefused) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0026, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0026}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetDisplayTypeCColdBlockingTigerLake( |
| false, PowerController::RetryBehavior::kNoRetry); |
| EXPECT_EQ(ZX_ERR_IO_REFUSED, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, SetDisplayTypeCColdBlockingTigerLakeOffNoRetryReplyTimeout) { |
| typec_blocking_reply_timeout_change_.reset(); |
| typec_blocking_reply_timeout_change_ = |
| PowerController::OverrideTypeCColdBlockingChangeReplyTimeoutUsForTesting(1); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0026, .write = true}, |
| |
| // Setting the reply timeout results in exactly 2 mailbox checks. |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0026}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0026}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetDisplayTypeCColdBlockingTigerLake( |
| false, PowerController::RetryBehavior::kNoRetry); |
| EXPECT_EQ(ZX_ERR_IO_MISSED_DEADLINE, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, SetDisplayTypeCColdBlockingTigerLakeOnRetryImmediateSuccess) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0026, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0026}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetDisplayTypeCColdBlockingTigerLake( |
| true, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_TRUE(result.is_ok()) << result.status_string(); |
| } |
| |
| TEST_F(PowerControllerTest, SetDisplayTypeCColdBlockingTigerLakeOnRetrySuccessAfterRetries) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0026, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0026}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| |
| // First retry. |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0026}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0026, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0026}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| |
| // Second retry. |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0026}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0026, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0026}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetDisplayTypeCColdBlockingTigerLake( |
| true, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_TRUE(result.is_ok()) << result.status_string(); |
| } |
| |
| TEST_F(PowerControllerTest, SetDisplayTypeCColdBlockingTigerLakeOnRetryTimeoutBeforeRetry) { |
| typec_blocking_timeout_change_.reset(); |
| typec_blocking_timeout_change_ = |
| PowerController::OverrideTypeCColdBlockingChangeTotalTimeoutUsForTesting(0); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0026, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0026}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetDisplayTypeCColdBlockingTigerLake( |
| true, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_EQ(ZX_ERR_IO_REFUSED, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, SetDisplayTypeCColdBlockingTigerLakeOnRetryTimeoutAfterRetry) { |
| typec_blocking_timeout_change_.reset(); |
| typec_blocking_timeout_change_ = |
| PowerController::OverrideTypeCColdBlockingChangeTotalTimeoutUsForTesting( |
| kRealClockTestTimeout); |
| |
| bool report_busy_mailbox = false; |
| |
| ddk_fake::FakeMmioRegRegion fake_mmio_region(sizeof(uint32_t), 0x140000 / sizeof(uint32_t)); |
| fake_mmio_region[kMailboxInterfaceOffset].SetWriteCallback([&](uint64_t value) { |
| EXPECT_EQ(0x8000'0026, value) << "Unexpected command"; |
| report_busy_mailbox = true; |
| }); |
| fake_mmio_region[kMailboxInterfaceOffset].SetReadCallback([&]() -> uint64_t { |
| if (report_busy_mailbox) { |
| // Report busy once, so SetDisplayTypeCColdBlockingTigerLake() gets some |
| // sleep between retries. |
| report_busy_mailbox = false; |
| return 0x8000'0026; |
| } |
| return 0x0000'0026; |
| }); |
| fake_mmio_region[kMailboxData0Offset].SetReadCallback([&]() -> uint64_t { |
| // Always produce the result "in TCCOLD", so |
| // SetDisplayTypeCColdBlockingTigerLake() retries. |
| return 0x0000'0001; |
| }); |
| |
| fdf::MmioBuffer fake_mmio_buffer = fake_mmio_region.GetMmioBuffer(); |
| PowerController power_controller(&fake_mmio_buffer); |
| |
| const zx::result<> result = power_controller.SetDisplayTypeCColdBlockingTigerLake( |
| true, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_EQ(ZX_ERR_IO_REFUSED, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, SetDisplayTypeCColdBlockingTigerLakeOffOnRetryReplyTimeout) { |
| typec_blocking_reply_timeout_change_.reset(); |
| typec_blocking_reply_timeout_change_ = |
| PowerController::OverrideTypeCColdBlockingChangeReplyTimeoutUsForTesting(1); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0026, .write = true}, |
| |
| // Setting the reply timeout results in exactly 2 mailbox checks. |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0026}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0026}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetDisplayTypeCColdBlockingTigerLake( |
| false, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_EQ(ZX_ERR_IO_MISSED_DEADLINE, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, SetSystemAgentGeyservilleEnabledFalseNoRetrySuccess) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0021, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0021}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetSystemAgentGeyservilleEnabled( |
| false, PowerController::RetryBehavior::kNoRetry); |
| EXPECT_TRUE(result.is_ok()) << result.status_string(); |
| } |
| |
| TEST_F(PowerControllerTest, SetSystemAgentGeyservilleEnabledTrueNoRetrySuccess) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0003, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0021, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0021}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetSystemAgentGeyservilleEnabled( |
| true, PowerController::RetryBehavior::kNoRetry); |
| EXPECT_TRUE(result.is_ok()) << result.status_string(); |
| } |
| |
| TEST_F(PowerControllerTest, SetSystemAgentGeyservilleEnabledTrueNoRetryRefused) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0003, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0021, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0021}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetSystemAgentGeyservilleEnabled( |
| true, PowerController::RetryBehavior::kNoRetry); |
| EXPECT_EQ(ZX_ERR_IO_REFUSED, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, SetSystemAgentGeyservilleEnabledTrueNoRetryReplyTimeout) { |
| system_agent_enablement_reply_timeout_change_.reset(); |
| system_agent_enablement_reply_timeout_change_ = |
| PowerController::OverrideSystemAgentEnablementChangeReplyTimeoutUsForTesting(1); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0003, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0021, .write = true}, |
| |
| // Setting the reply timeout results in exactly 2 mailbox checks. |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0021}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0021}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetSystemAgentGeyservilleEnabled( |
| true, PowerController::RetryBehavior::kNoRetry); |
| EXPECT_EQ(ZX_ERR_IO_MISSED_DEADLINE, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, SetSystemAgentGeyservilleEnabledFalseRetryImmediateSuccess) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0021, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0021}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetSystemAgentGeyservilleEnabled( |
| false, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_TRUE(result.is_ok()) << result.status_string(); |
| } |
| |
| TEST_F(PowerControllerTest, SetSystemAgentGeyservilleEnabledFalseRetrySuccessAfterRetries) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0021, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0021}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| |
| // First retry. |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0021}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0021, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0021}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| |
| // Second retry. |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0021}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0021, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0021}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetSystemAgentGeyservilleEnabled( |
| false, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_TRUE(result.is_ok()) << result.status_string(); |
| } |
| |
| TEST_F(PowerControllerTest, SetSystemAgentGeyservilleEnabledFalseRetryTimeoutBeforeRetry) { |
| system_agent_enablement_timeout_change_.reset(); |
| system_agent_enablement_timeout_change_ = |
| PowerController::OverrideSystemAgentEnablementChangeTotalTimeoutUsForTesting(0); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0021, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0021}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetSystemAgentGeyservilleEnabled( |
| false, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_EQ(ZX_ERR_IO_REFUSED, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, SetSystemAgentGeyservilleEnabledFalseRetryTimeoutAfterRetry) { |
| system_agent_enablement_timeout_change_.reset(); |
| system_agent_enablement_timeout_change_ = |
| PowerController::OverrideSystemAgentEnablementChangeTotalTimeoutUsForTesting( |
| kRealClockTestTimeout); |
| |
| bool report_busy_mailbox = false; |
| |
| ddk_fake::FakeMmioRegRegion fake_mmio_region(sizeof(uint32_t), 0x140000 / sizeof(uint32_t)); |
| fake_mmio_region[kMailboxInterfaceOffset].SetWriteCallback([&](uint64_t value) { |
| EXPECT_EQ(0x8000'0021, value) << "Unexpected command"; |
| report_busy_mailbox = true; |
| }); |
| fake_mmio_region[kMailboxInterfaceOffset].SetReadCallback([&]() -> uint64_t { |
| if (report_busy_mailbox) { |
| // Report busy once, so SetSystemAgentGeyservilleEnabledRetryTimeout() gets some |
| // sleep between retries. |
| report_busy_mailbox = false; |
| return 0x8000'0021; |
| } |
| return 0x0000'0021; |
| }); |
| fake_mmio_region[kMailboxData0Offset].SetReadCallback([&]() -> uint64_t { |
| // Always produce the result "voltage level not applied", so |
| // SetSystemAgentGeyservilleEnabled() retries. |
| return 0x0000'0000; |
| }); |
| |
| fdf::MmioBuffer fake_mmio_buffer = fake_mmio_region.GetMmioBuffer(); |
| PowerController power_controller(&fake_mmio_buffer); |
| |
| const zx::result<> result = power_controller.SetSystemAgentGeyservilleEnabled( |
| false, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_EQ(ZX_ERR_IO_REFUSED, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, SetSystemAgentGeyservilleEnabledFalseRetryReplyTimeout) { |
| system_agent_enablement_reply_timeout_change_.reset(); |
| system_agent_enablement_reply_timeout_change_ = |
| PowerController::OverrideSystemAgentEnablementChangeReplyTimeoutUsForTesting(1); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0021, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0021}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0021}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<> result = power_controller.SetSystemAgentGeyservilleEnabled( |
| false, PowerController::RetryBehavior::kRetryUntilStateChanges); |
| EXPECT_EQ(ZX_ERR_IO_MISSED_DEADLINE, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, GetSystemAgentBlockTimeUsTigerLakeSuccess) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0023, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0042}, |
| {.address = kMailboxData1Offset, .value = 0xdead'beef}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<uint32_t> result = power_controller.GetSystemAgentBlockTimeUsTigerLake(); |
| ASSERT_TRUE(result.is_ok()) << result.status_string(); |
| EXPECT_EQ(0x42u, result.value()); |
| } |
| |
| TEST_F(PowerControllerTest, GetSystemAgentBlockTimeUsTigerLakeError) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0023, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0001}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0042}, |
| {.address = kMailboxData1Offset, .value = 0xdead'beef}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0001}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<uint32_t> result = power_controller.GetSystemAgentBlockTimeUsTigerLake(); |
| EXPECT_EQ(ZX_ERR_IO_REFUSED, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, GetSystemAgentBlockTimeUsTigerLakeTimeout) { |
| memory_latency_reply_timeout_change_.reset(); |
| memory_latency_reply_timeout_change_ = |
| PowerController::OverrideGetMemoryLatencyReplyTimeoutUsForTesting(1); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0023, .write = true}, |
| |
| // Setting the reply timeout results in exactly 2 mailbox checks. |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0023}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0023}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<uint32_t> result = power_controller.GetSystemAgentBlockTimeUsTigerLake(); |
| EXPECT_EQ(ZX_ERR_IO_MISSED_DEADLINE, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, GetSystemAgentBlockTimeUsKabyLake) { |
| PowerController power_controller(&mmio_buffer_); |
| const zx::result<uint32_t> result = power_controller.GetSystemAgentBlockTimeUsKabyLake(); |
| ASSERT_TRUE(result.is_ok()) << result.status_string(); |
| EXPECT_GT(result.value(), 0u); |
| } |
| |
| TEST_F(PowerControllerTest, GetRawMemoryLatencyDataUsSuccess) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0006, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x4443'4241}, |
| {.address = kMailboxData1Offset, .value = 0xdead'beef}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0006, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x4847'4645}, |
| {.address = kMailboxData1Offset, .value = 0xdead'beef}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<std::array<uint8_t, 8>> result = power_controller.GetRawMemoryLatencyDataUs(); |
| ASSERT_TRUE(result.is_ok()) << result.status_string(); |
| constexpr uint8_t kExpected[] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}; |
| EXPECT_THAT(result.value(), testing::ElementsAreArray(kExpected)); |
| } |
| |
| TEST_F(PowerControllerTest, GetRawMemoryLatencyDataUsGroupOneFailure) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0006, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0001}, |
| {.address = kMailboxData0Offset, .value = 0x4443'4241}, |
| {.address = kMailboxData1Offset, .value = 0xdead'beef}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0001}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<std::array<uint8_t, 8>> result = power_controller.GetRawMemoryLatencyDataUs(); |
| EXPECT_EQ(ZX_ERR_IO_REFUSED, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, GetRawMemoryLatencyDataUsGroupTwoFailure) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0006, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x4443'4241}, |
| {.address = kMailboxData1Offset, .value = 0xdead'beef}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0006, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0001}, |
| {.address = kMailboxData0Offset, .value = 0x4847'4645}, |
| {.address = kMailboxData1Offset, .value = 0xdead'beef}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0001}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<std::array<uint8_t, 8>> result = power_controller.GetRawMemoryLatencyDataUs(); |
| EXPECT_EQ(ZX_ERR_IO_REFUSED, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, GetRawMemoryLatencyDataUsGroupOneTimeout) { |
| memory_latency_reply_timeout_change_.reset(); |
| memory_latency_reply_timeout_change_ = |
| PowerController::OverrideGetMemoryLatencyReplyTimeoutUsForTesting(1); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0006, .write = true}, |
| |
| // Setting the reply timeout results in exactly 2 mailbox checks. |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0006}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0006}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<std::array<uint8_t, 8>> result = power_controller.GetRawMemoryLatencyDataUs(); |
| EXPECT_EQ(ZX_ERR_IO_MISSED_DEADLINE, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, GetRawMemoryLatencyDataUsGroupTwoTimeout) { |
| memory_latency_reply_timeout_change_.reset(); |
| memory_latency_reply_timeout_change_ = |
| PowerController::OverrideGetMemoryLatencyReplyTimeoutUsForTesting(1); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0006, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x4443'4241}, |
| {.address = kMailboxData1Offset, .value = 0xdead'beef}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0001, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0006, .write = true}, |
| |
| // Setting the reply timeout results in exactly 2 mailbox checks. |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0006}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'0006}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<std::array<uint8_t, 8>> result = power_controller.GetRawMemoryLatencyDataUs(); |
| EXPECT_EQ(ZX_ERR_IO_MISSED_DEADLINE, result.status_value()); |
| } |
| |
| TEST(MemorySubsystemInfoGlobalInfoTest, CreateFromMailboxDataTigerLake) { |
| auto dell_5420_info = MemorySubsystemInfo::GlobalInfo::CreateFromMailboxDataTigerLake(0x410); |
| EXPECT_EQ(MemorySubsystemInfo::RamType::kDoubleDataRam4, dell_5420_info.ram_type); |
| EXPECT_EQ(1, dell_5420_info.memory_channel_count); |
| EXPECT_EQ(4, dell_5420_info.agent_point_count); |
| |
| auto nuc_11_info = MemorySubsystemInfo::GlobalInfo::CreateFromMailboxDataTigerLake(0x120); |
| EXPECT_EQ(MemorySubsystemInfo::RamType::kDoubleDataRam4, dell_5420_info.ram_type); |
| EXPECT_EQ(2, nuc_11_info.memory_channel_count); |
| EXPECT_EQ(1, nuc_11_info.agent_point_count); |
| } |
| |
| TEST(MemorySubsystemInfoAgentPointTest, CreateFromMailboxDataTigerLake) { |
| auto dell_5420_point1 = |
| MemorySubsystemInfo::AgentPoint::CreateFromMailboxDataTigerLake(0x2308'0f0f'0080); |
| EXPECT_EQ(2'133'248, dell_5420_point1.dram_clock_khz); |
| EXPECT_EQ(15, dell_5420_point1.row_precharge_to_open_cycles); |
| EXPECT_EQ(15, dell_5420_point1.row_access_to_column_access_delay_cycles); |
| EXPECT_EQ(8, dell_5420_point1.read_to_precharge_cycles); |
| EXPECT_EQ(35, dell_5420_point1.row_activate_to_precharge_cycles); |
| |
| // NUC 11 has a single point with this configuration. |
| auto dell_5420_point3 = |
| MemorySubsystemInfo::AgentPoint::CreateFromMailboxDataTigerLake(0x340c'1616'00c0); |
| EXPECT_EQ(3'199'872, dell_5420_point3.dram_clock_khz); |
| EXPECT_EQ(22, dell_5420_point3.row_precharge_to_open_cycles); |
| EXPECT_EQ(22, dell_5420_point3.row_access_to_column_access_delay_cycles); |
| EXPECT_EQ(12, dell_5420_point3.read_to_precharge_cycles); |
| EXPECT_EQ(52, dell_5420_point3.row_activate_to_precharge_cycles); |
| |
| auto dell_5420_point4 = |
| MemorySubsystemInfo::AgentPoint::CreateFromMailboxDataTigerLake(0x2b0a'1313'00a0); |
| EXPECT_EQ(2'666'560, dell_5420_point4.dram_clock_khz); |
| EXPECT_EQ(19, dell_5420_point4.row_precharge_to_open_cycles); |
| EXPECT_EQ(19, dell_5420_point4.row_access_to_column_access_delay_cycles); |
| EXPECT_EQ(10, dell_5420_point4.read_to_precharge_cycles); |
| EXPECT_EQ(43, dell_5420_point4.row_activate_to_precharge_cycles); |
| } |
| |
| TEST_F(PowerControllerTest, GetMemorySubsystemInfoTigerLakeSuccessNoPoints) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'000d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0025}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<MemorySubsystemInfo> result = power_controller.GetMemorySubsystemInfoTigerLake(); |
| ASSERT_TRUE(result.is_ok()) << result.status_string(); |
| EXPECT_EQ(MemorySubsystemInfo::RamType::kLowPowerDoubleDataRam3, result->global_info.ram_type); |
| EXPECT_EQ(2, result->global_info.memory_channel_count); |
| EXPECT_EQ(0, result->global_info.agent_point_count); |
| } |
| |
| TEST_F(PowerControllerTest, GetMemorySubsystemInfoTigerLakeSuccessOnePoint) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'000d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0125}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'010d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x1616'00c0}, |
| {.address = kMailboxData1Offset, .value = 0x0000'340c}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<MemorySubsystemInfo> result = power_controller.GetMemorySubsystemInfoTigerLake(); |
| ASSERT_TRUE(result.is_ok()) << result.status_string(); |
| |
| EXPECT_EQ(MemorySubsystemInfo::RamType::kLowPowerDoubleDataRam3, result->global_info.ram_type); |
| EXPECT_EQ(2, result->global_info.memory_channel_count); |
| EXPECT_EQ(1, result->global_info.agent_point_count); |
| |
| EXPECT_EQ(3'199'872, result->points[0].dram_clock_khz); |
| EXPECT_EQ(22, result->points[0].row_precharge_to_open_cycles); |
| EXPECT_EQ(22, result->points[0].row_access_to_column_access_delay_cycles); |
| EXPECT_EQ(12, result->points[0].read_to_precharge_cycles); |
| EXPECT_EQ(52, result->points[0].row_activate_to_precharge_cycles); |
| } |
| |
| TEST_F(PowerControllerTest, GetMemorySubsystemInfoTigerLakeSuccessThreePoints) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'000d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0310}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'010d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x0f0f'0080}, |
| {.address = kMailboxData1Offset, .value = 0x0000'2308}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8001'010d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x1616'00c0}, |
| {.address = kMailboxData1Offset, .value = 0x0000'340c}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8002'010d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x1313'00a0}, |
| {.address = kMailboxData1Offset, .value = 0x0000'2b0a}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<MemorySubsystemInfo> result = power_controller.GetMemorySubsystemInfoTigerLake(); |
| ASSERT_TRUE(result.is_ok()) << result.status_string(); |
| |
| EXPECT_EQ(MemorySubsystemInfo::RamType::kDoubleDataRam4, result->global_info.ram_type); |
| EXPECT_EQ(1, result->global_info.memory_channel_count); |
| EXPECT_EQ(3, result->global_info.agent_point_count); |
| |
| EXPECT_EQ(2'133'248, result->points[0].dram_clock_khz); |
| EXPECT_EQ(15, result->points[0].row_precharge_to_open_cycles); |
| EXPECT_EQ(15, result->points[0].row_access_to_column_access_delay_cycles); |
| EXPECT_EQ(8, result->points[0].read_to_precharge_cycles); |
| EXPECT_EQ(35, result->points[0].row_activate_to_precharge_cycles); |
| |
| EXPECT_EQ(3'199'872, result->points[1].dram_clock_khz); |
| EXPECT_EQ(22, result->points[1].row_precharge_to_open_cycles); |
| EXPECT_EQ(22, result->points[1].row_access_to_column_access_delay_cycles); |
| EXPECT_EQ(12, result->points[1].read_to_precharge_cycles); |
| EXPECT_EQ(52, result->points[1].row_activate_to_precharge_cycles); |
| |
| EXPECT_EQ(2'666'560, result->points[2].dram_clock_khz); |
| EXPECT_EQ(19, result->points[2].row_precharge_to_open_cycles); |
| EXPECT_EQ(19, result->points[2].row_access_to_column_access_delay_cycles); |
| EXPECT_EQ(10, result->points[2].read_to_precharge_cycles); |
| EXPECT_EQ(43, result->points[2].row_activate_to_precharge_cycles); |
| } |
| |
| TEST_F(PowerControllerTest, GetMemorySubsystemInfoTigerLakePointOneFailure) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| // Based on the MMIO list in the SuccessOnePoint test. |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'000d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0125}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'010d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0001}, |
| {.address = kMailboxData0Offset, .value = 0x1616'00c0}, |
| {.address = kMailboxData1Offset, .value = 0x0000'340c}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0001}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<MemorySubsystemInfo> result = power_controller.GetMemorySubsystemInfoTigerLake(); |
| EXPECT_EQ(ZX_ERR_IO_REFUSED, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, GetMemorySubsystemInfoTigerLakePointTwoFailure) { |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| // Based on the MMIO list in the SuccessThreePoints test. |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'000d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0310}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'010d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x0f0f'0080}, |
| {.address = kMailboxData1Offset, .value = 0x0000'2308}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8001'010d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0001}, |
| {.address = kMailboxData0Offset, .value = 0x1616'00c0}, |
| {.address = kMailboxData1Offset, .value = 0x0000'340c}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0001}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<MemorySubsystemInfo> result = power_controller.GetMemorySubsystemInfoTigerLake(); |
| EXPECT_EQ(ZX_ERR_IO_REFUSED, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, GetMemorySubsystemInfoTigerLakeGlobalInfoTimeout) { |
| memory_subsystem_info_reply_timeout_change_.reset(); |
| memory_subsystem_info_reply_timeout_change_ = |
| PowerController::OverrideGetMemorySubsystemInfoReplyTimeoutUsForTesting(1); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'000d, .write = true}, |
| |
| // Setting the reply timeout results in exactly 2 mailbox checks. |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'000d}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'000d}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<MemorySubsystemInfo> result = power_controller.GetMemorySubsystemInfoTigerLake(); |
| EXPECT_EQ(ZX_ERR_IO_MISSED_DEADLINE, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, GetMemorySubsystemInfoTigerLakePointOneTimeout) { |
| memory_subsystem_info_reply_timeout_change_.reset(); |
| memory_subsystem_info_reply_timeout_change_ = |
| PowerController::OverrideGetMemorySubsystemInfoReplyTimeoutUsForTesting(1); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| // Based on the MMIO list in the PointOneFailure test. |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'000d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0125}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'010d, .write = true}, |
| |
| // Setting the reply timeout results in exactly 2 mailbox checks. |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'010d}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'010d}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<MemorySubsystemInfo> result = power_controller.GetMemorySubsystemInfoTigerLake(); |
| EXPECT_EQ(ZX_ERR_IO_MISSED_DEADLINE, result.status_value()); |
| } |
| |
| TEST_F(PowerControllerTest, GetMemorySubsystemInfoTigerLakePointTwoTimeout) { |
| memory_subsystem_info_reply_timeout_change_.reset(); |
| memory_subsystem_info_reply_timeout_change_ = |
| PowerController::OverrideGetMemorySubsystemInfoReplyTimeoutUsForTesting(1); |
| mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({ |
| // Based on the MMIO list in the PointTwoFailure test. |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'000d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0310}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000}, |
| |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8000'010d, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| {.address = kMailboxData0Offset, .value = 0x0f0f'0080}, |
| {.address = kMailboxData1Offset, .value = 0x0000'2308}, |
| {.address = kMailboxInterfaceOffset, .value = 0x0000'0000}, |
| |
| {.address = kMailboxInterfaceOffset, .value = 0}, |
| {.address = kMailboxData0Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxData1Offset, .value = 0x0000'0000, .write = true}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8001'010d, .write = true}, |
| |
| // Setting the reply timeout results in exactly 2 mailbox checks. |
| {.address = kMailboxInterfaceOffset, .value = 0x8001'010d}, |
| {.address = kMailboxInterfaceOffset, .value = 0x8001'010d}, |
| })); |
| PowerController power_controller(&mmio_buffer_); |
| |
| const zx::result<MemorySubsystemInfo> result = power_controller.GetMemorySubsystemInfoTigerLake(); |
| EXPECT_EQ(ZX_ERR_IO_MISSED_DEADLINE, result.status_value()); |
| } |
| |
| } // namespace |
| |
| } // namespace i915 |