blob: d5f0330a1a1862528595a4495bc53f932bb5a2bf [file] [log] [blame]
// Copyright 2019 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 "as370-thermal.h"
#include <fuchsia/hardware/thermal/c/fidl.h>
#include <lib/fake_ddk/fidl-helper.h>
#include <fbl/algorithm.h>
#include <mock-mmio-reg/mock-mmio-reg.h>
#include <mock/ddktl/protocol/clock.h>
#include <mock/ddktl/protocol/power.h>
#include <zxtest/zxtest.h>
namespace {
bool FloatNear(float a, float b) { return std::abs(a - b) < 0.001f; }
} // namespace
namespace thermal {
using ThermalClient = llcpp::fuchsia::hardware::thermal::Device::SyncClient;
using llcpp::fuchsia::hardware::thermal::OperatingPoint;
using llcpp::fuchsia::hardware::thermal::OperatingPointEntry;
using llcpp::fuchsia::hardware::thermal::PowerDomain;
using llcpp::fuchsia::hardware::thermal::ThermalDeviceInfo;
class As370ThermalTest : public zxtest::Test {
public:
As370ThermalTest()
: reg_region_(reg_array_, sizeof(uint32_t), std::size(reg_array_)),
dut_(nullptr, ddk::MmioBuffer(reg_region_.GetMmioBuffer()), kThermalDeviceInfo,
ddk::ClockProtocolClient(clock_.GetProto()),
ddk::PowerProtocolClient(power_.GetProto())) {}
void SetUp() override {
ASSERT_OK(messenger_.SetMessageOp(
&dut_, [](void* ctx, fidl_incoming_msg_t* msg, fidl_txn_t* txn) -> zx_status_t {
return static_cast<As370Thermal*>(ctx)->DdkMessage(msg, txn);
}));
}
protected:
void VerifyAll() {
ASSERT_NO_FATAL_FAILURES(clock_.VerifyAndClear());
ASSERT_NO_FATAL_FAILURES(power_.VerifyAndClear());
}
fake_ddk::FidlMessenger messenger_;
ddk_mock::MockMmioRegRegion reg_region_;
ddk::MockClock clock_;
ddk::MockPower power_;
As370Thermal dut_;
private:
static constexpr ThermalDeviceInfo kThermalDeviceInfo = {
.active_cooling = false,
.passive_cooling = true,
.gpu_throttling = false,
.num_trip_points = 0,
.big_little = false,
.critical_temp_celsius = 0.0f,
.trip_point_info = {},
.opps =
fidl::Array<OperatingPoint, 2>{
OperatingPoint{
.opp =
fidl::Array<OperatingPointEntry, 16>{
// clang-format off
OperatingPointEntry{.freq_hz = 400'000'000, .volt_uv = 825'000},
OperatingPointEntry{.freq_hz = 800'000'000, .volt_uv = 825'000},
OperatingPointEntry{.freq_hz = 1'200'000'000, .volt_uv = 825'000},
OperatingPointEntry{.freq_hz = 1'400'000'000, .volt_uv = 825'000},
OperatingPointEntry{.freq_hz = 1'500'000'000, .volt_uv = 900'000},
OperatingPointEntry{.freq_hz = 1'800'000'000, .volt_uv = 900'000},
// clang-format on
},
.latency = 0,
.count = 6,
},
{
.opp = {},
.latency = 0,
.count = 0,
},
},
};
ddk_mock::MockMmioReg reg_array_[8];
};
TEST_F(As370ThermalTest, GetTemperature) {
ThermalClient client(std::move(messenger_.local()));
{
reg_region_[0x14].ReadReturns(0x17ff);
auto result = client.GetTemperatureCelsius();
EXPECT_OK(result->status);
EXPECT_TRUE(FloatNear(result->temp, 40.314f));
}
{
reg_region_[0x14].ReadReturns(0x182b);
auto result = client.GetTemperatureCelsius();
EXPECT_OK(result->status);
EXPECT_TRUE(FloatNear(result->temp, 43.019f));
}
}
TEST_F(As370ThermalTest, DvfsOperatingPoint) {
ThermalClient client(std::move(messenger_.local()));
{
// Success, sets operating point 0.
power_.ExpectRequestVoltage(ZX_OK, 825'000, 825'000);
clock_.ExpectSetRate(ZX_OK, 400'000'000);
auto set_result = client.SetDvfsOperatingPoint(0, PowerDomain::BIG_CLUSTER_POWER_DOMAIN);
EXPECT_OK(set_result->status);
ASSERT_NO_FATAL_FAILURES(VerifyAll());
}
{
auto get_result = client.GetDvfsOperatingPoint(PowerDomain::BIG_CLUSTER_POWER_DOMAIN);
EXPECT_OK(get_result->status);
EXPECT_EQ(get_result->op_idx, 0);
}
{
// Failure, unable to set exact voltage.
power_.ExpectRequestVoltage(ZX_OK, 825'000, 900'000);
auto set_result = client.SetDvfsOperatingPoint(2, PowerDomain::BIG_CLUSTER_POWER_DOMAIN);
EXPECT_NOT_OK(set_result->status);
ASSERT_NO_FATAL_FAILURES(VerifyAll());
}
{
auto get_result = client.GetDvfsOperatingPoint(PowerDomain::BIG_CLUSTER_POWER_DOMAIN);
EXPECT_OK(get_result->status);
EXPECT_EQ(get_result->op_idx, 0);
}
{
// Failure, unable to set frequency.
power_.ExpectRequestVoltage(ZX_OK, 825'000, 825'000);
clock_.ExpectSetRate(ZX_ERR_IO, 1'200'000'000);
auto set_result = client.SetDvfsOperatingPoint(2, PowerDomain::BIG_CLUSTER_POWER_DOMAIN);
EXPECT_NOT_OK(set_result->status);
ASSERT_NO_FATAL_FAILURES(VerifyAll());
}
{
auto get_result = client.GetDvfsOperatingPoint(PowerDomain::BIG_CLUSTER_POWER_DOMAIN);
EXPECT_OK(get_result->status);
EXPECT_EQ(get_result->op_idx, 0);
}
{
// Success, sets operating point 4.
power_.ExpectRequestVoltage(ZX_OK, 900'000, 900'000);
clock_.ExpectSetRate(ZX_OK, 1'500'000'000);
auto set_result = client.SetDvfsOperatingPoint(4, PowerDomain::BIG_CLUSTER_POWER_DOMAIN);
EXPECT_OK(set_result->status);
ASSERT_NO_FATAL_FAILURES(VerifyAll());
}
{
auto get_result = client.GetDvfsOperatingPoint(PowerDomain::BIG_CLUSTER_POWER_DOMAIN);
EXPECT_OK(get_result->status);
EXPECT_EQ(get_result->op_idx, 4);
}
{
// Failure, unable to set frequency.
clock_.ExpectSetRate(ZX_ERR_IO, 800'000'000);
auto set_result = client.SetDvfsOperatingPoint(1, PowerDomain::BIG_CLUSTER_POWER_DOMAIN);
EXPECT_NOT_OK(set_result->status);
ASSERT_NO_FATAL_FAILURES(VerifyAll());
}
{
auto get_result = client.GetDvfsOperatingPoint(PowerDomain::BIG_CLUSTER_POWER_DOMAIN);
EXPECT_OK(get_result->status);
EXPECT_EQ(get_result->op_idx, 4);
}
{
// Failure, unable to set voltage.
clock_.ExpectSetRate(ZX_OK, 800'000'000);
power_.ExpectRequestVoltage(ZX_ERR_IO, 825'000, 0);
auto set_result = client.SetDvfsOperatingPoint(1, PowerDomain::BIG_CLUSTER_POWER_DOMAIN);
EXPECT_NOT_OK(set_result->status);
ASSERT_NO_FATAL_FAILURES(VerifyAll());
}
{
auto get_result = client.GetDvfsOperatingPoint(PowerDomain::BIG_CLUSTER_POWER_DOMAIN);
EXPECT_OK(get_result->status);
EXPECT_EQ(get_result->op_idx, 4);
}
{
// Success, sets operating point 1.
clock_.ExpectSetRate(ZX_OK, 800'000'000);
power_.ExpectRequestVoltage(ZX_OK, 825'000, 825'000);
auto set_result = client.SetDvfsOperatingPoint(1, PowerDomain::BIG_CLUSTER_POWER_DOMAIN);
EXPECT_OK(set_result->status);
ASSERT_NO_FATAL_FAILURES(VerifyAll());
}
{
auto get_result = client.GetDvfsOperatingPoint(PowerDomain::BIG_CLUSTER_POWER_DOMAIN);
EXPECT_OK(get_result->status);
EXPECT_EQ(get_result->op_idx, 1);
}
}
TEST_F(As370ThermalTest, Init) {
power_.ExpectRegisterPowerDomain(ZX_OK, 825'000, 900'000);
power_.ExpectRequestVoltage(ZX_OK, 900'000, 900'000);
clock_.ExpectSetRate(ZX_OK, 1'800'000'000);
EXPECT_OK(dut_.Init());
ASSERT_NO_FATAL_FAILURES(VerifyAll());
}
} // namespace thermal