| // Copyright 2020 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 "aml-power.h" |
| |
| #include <fidl/fuchsia.hardware.pwm/cpp/wire_test_base.h> |
| #include <fidl/fuchsia.hardware.vreg/cpp/wire_test_base.h> |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/async-loop/default.h> |
| #include <lib/async/default.h> |
| #include <lib/async_patterns/testing/cpp/dispatcher_bound.h> |
| #include <lib/ddk/platform-defs.h> |
| |
| #include <list> |
| #include <memory> |
| #include <optional> |
| #include <utility> |
| #include <vector> |
| |
| #include <bind/fuchsia/amlogic/platform/cpp/bind.h> |
| #include <soc/aml-common/aml-pwm-regs.h> |
| #include <zxtest/zxtest.h> |
| |
| bool operator==(const fuchsia_hardware_pwm::wire::PwmConfig& lhs, |
| const fuchsia_hardware_pwm::wire::PwmConfig& rhs) { |
| return (lhs.polarity == rhs.polarity) && (lhs.period_ns == rhs.period_ns) && |
| (lhs.duty_cycle == rhs.duty_cycle) && |
| (lhs.mode_config.count() == rhs.mode_config.count()) && |
| (reinterpret_cast<aml_pwm::mode_config*>(lhs.mode_config.data())->mode == |
| reinterpret_cast<aml_pwm::mode_config*>(rhs.mode_config.data())->mode); |
| } |
| |
| namespace power { |
| |
| const std::vector<aml_voltage_table_t> kTestVoltageTable = { |
| {1'050'000, 0}, {1'040'000, 3}, {1'030'000, 6}, {1'020'000, 8}, {1'010'000, 11}, |
| {1'000'000, 14}, {990'000, 17}, {980'000, 20}, {970'000, 23}, {960'000, 26}, |
| {950'000, 29}, {940'000, 31}, {930'000, 34}, {920'000, 37}, {910'000, 40}, |
| {900'000, 43}, {890'000, 45}, {880'000, 48}, {870'000, 51}, {860'000, 54}, |
| {850'000, 56}, {840'000, 59}, {830'000, 62}, {820'000, 65}, {810'000, 68}, |
| {800'000, 70}, {790'000, 73}, {780'000, 76}, {770'000, 79}, {760'000, 81}, |
| {750'000, 84}, {740'000, 87}, {730'000, 89}, {720'000, 92}, {710'000, 95}, |
| {700'000, 98}, {690'000, 100}, |
| }; |
| |
| constexpr voltage_pwm_period_ns_t kTestPwmPeriodNs = 1250; |
| |
| class AmlPowerTestWrapper : public AmlPower { |
| public: |
| AmlPowerTestWrapper(std::vector<DomainInfo> domain_info) |
| : AmlPower(nullptr, std::move(domain_info)) {} |
| |
| static std::unique_ptr<AmlPowerTestWrapper> Create( |
| fidl::WireSyncClient<fuchsia_hardware_pwm::Pwm> mock_little_pwm, |
| std::vector<aml_voltage_table_t> voltage_table, voltage_pwm_period_ns_t pwm_period) { |
| std::vector<DomainInfo> domain_info; |
| domain_info.emplace_back(std::move(mock_little_pwm), std::move(voltage_table), pwm_period); |
| auto result = std::make_unique<AmlPowerTestWrapper>(std::move(domain_info)); |
| return result; |
| } |
| |
| static std::unique_ptr<AmlPowerTestWrapper> Create( |
| fidl::WireSyncClient<fuchsia_hardware_pwm::Pwm> mock_little_pwm, |
| fidl::ClientEnd<fuchsia_hardware_vreg::Vreg> mock_big_vreg, |
| std::vector<aml_voltage_table_t> voltage_table, voltage_pwm_period_ns_t pwm_period) { |
| std::vector<DomainInfo> domain_info; |
| domain_info.emplace_back(std::move(mock_little_pwm), std::move(voltage_table), pwm_period); |
| domain_info.emplace_back( |
| fidl::WireSyncClient<fuchsia_hardware_vreg::Vreg>(std::move(mock_big_vreg))); |
| auto result = std::make_unique<AmlPowerTestWrapper>(std::move(domain_info)); |
| return result; |
| } |
| |
| static std::unique_ptr<AmlPowerTestWrapper> Create( |
| fidl::WireSyncClient<fuchsia_hardware_pwm::Pwm> mock_little_pwm, |
| fidl::WireSyncClient<fuchsia_hardware_pwm::Pwm> mock_big_pwm, |
| std::vector<aml_voltage_table_t> voltage_table, voltage_pwm_period_ns_t pwm_period) { |
| std::vector<DomainInfo> domain_info; |
| domain_info.emplace_back(std::move(mock_little_pwm), voltage_table, pwm_period); |
| domain_info.emplace_back(std::move(mock_big_pwm), voltage_table, pwm_period); |
| auto result = std::make_unique<AmlPowerTestWrapper>(std::move(domain_info)); |
| return result; |
| } |
| |
| static std::unique_ptr<AmlPowerTestWrapper> Create( |
| fidl::ClientEnd<fuchsia_hardware_vreg::Vreg> mock_little_vreg, |
| fidl::ClientEnd<fuchsia_hardware_vreg::Vreg> mock_big_vreg) { |
| std::vector<DomainInfo> domain_info; |
| domain_info.emplace_back( |
| fidl::WireSyncClient<fuchsia_hardware_vreg::Vreg>(std::move(mock_little_vreg))); |
| domain_info.emplace_back( |
| fidl::WireSyncClient<fuchsia_hardware_vreg::Vreg>(std::move(mock_big_vreg))); |
| auto result = std::make_unique<AmlPowerTestWrapper>(std::move(domain_info)); |
| return result; |
| } |
| }; |
| |
| class MockPwmServer final : public fidl::testing::WireTestBase<fuchsia_hardware_pwm::Pwm> { |
| public: |
| void SetConfig(SetConfigRequestView request, SetConfigCompleter::Sync& completer) override { |
| ASSERT_TRUE(expect_configs_.size() > 0); |
| auto expect_config = expect_configs_.front(); |
| |
| ASSERT_EQ(request->config, expect_config); |
| |
| expect_configs_.pop_front(); |
| mode_config_buffers_.pop_front(); |
| completer.ReplySuccess(); |
| } |
| void Enable(EnableCompleter::Sync& completer) override { completer.ReplySuccess(); } |
| |
| void ExpectSetConfig(fuchsia_hardware_pwm::wire::PwmConfig config) { |
| std::unique_ptr<uint8_t[]> mode_config = |
| std::make_unique<uint8_t[]>(config.mode_config.count()); |
| memcpy(mode_config.get(), config.mode_config.data(), config.mode_config.count()); |
| auto copy = config; |
| copy.mode_config = |
| fidl::VectorView<uint8_t>::FromExternal(mode_config.get(), config.mode_config.count()); |
| expect_configs_.push_back(std::move(copy)); |
| mode_config_buffers_.push_back(std::move(mode_config)); |
| } |
| |
| void NotImplemented_(const std::string& name, ::fidl::CompleterBase& completer) override { |
| completer.Close(ZX_ERR_NOT_SUPPORTED); |
| } |
| |
| fidl::WireSyncClient<fuchsia_hardware_pwm::Pwm> BindServer() { |
| auto endpoints = fidl::Endpoints<fuchsia_hardware_pwm::Pwm>::Create(); |
| fidl::BindServer(async_get_default_dispatcher(), std::move(endpoints.server), this); |
| return fidl::WireSyncClient<fuchsia_hardware_pwm::Pwm>(std::move(endpoints.client)); |
| } |
| |
| void VerifyAndClear() { |
| ASSERT_TRUE(expect_configs_.size() == 0); |
| ASSERT_TRUE(mode_config_buffers_.size() == 0); |
| } |
| |
| private: |
| std::list<fuchsia_hardware_pwm::wire::PwmConfig> expect_configs_; |
| std::list<std::unique_ptr<uint8_t[]>> mode_config_buffers_; |
| }; |
| |
| class FakeVregServer final : public fidl::testing::WireTestBase<fuchsia_hardware_vreg::Vreg> { |
| public: |
| void SetRegulatorParams(uint32_t min_uv, uint32_t step_size_uv, uint32_t num_steps) { |
| min_uv_ = min_uv; |
| step_size_uv_ = step_size_uv; |
| num_steps_ = num_steps; |
| } |
| |
| void GetRegulatorParams(GetRegulatorParamsCompleter::Sync& completer) override { |
| completer.Reply(min_uv_, step_size_uv_, num_steps_); |
| } |
| |
| void SetVoltageStep(::fuchsia_hardware_vreg::wire::VregSetVoltageStepRequest* request, |
| SetVoltageStepCompleter::Sync& completer) override { |
| voltage_step_ = request->step; |
| completer.Reply(fit::success()); |
| } |
| |
| void GetVoltageStep(GetVoltageStepCompleter::Sync& completer) override { |
| completer.Reply(voltage_step_); |
| } |
| |
| void NotImplemented_(const std::string& name, ::fidl::CompleterBase& completer) override { |
| completer.Close(ZX_ERR_NOT_SUPPORTED); |
| } |
| |
| uint32_t voltage_step() const { return voltage_step_; } |
| |
| fidl::ClientEnd<fuchsia_hardware_vreg::Vreg> BindServer() { |
| auto endpoints = fidl::Endpoints<fuchsia_hardware_vreg::Vreg>::Create(); |
| binding_ref_ = |
| fidl::BindServer(async_get_default_dispatcher(), std::move(endpoints.server), this); |
| return std::move(endpoints.client); |
| } |
| |
| private: |
| uint32_t min_uv_; |
| uint32_t step_size_uv_; |
| uint32_t num_steps_; |
| uint32_t voltage_step_; |
| std::optional<fidl::ServerBindingRef<fuchsia_hardware_vreg::Vreg>> binding_ref_; |
| }; |
| |
| class AmlPowerTest : public zxtest::Test { |
| public: |
| void TearDown() override { |
| big_cluster_pwm_.SyncCall(&MockPwmServer::VerifyAndClear); |
| little_cluster_pwm_.SyncCall(&MockPwmServer::VerifyAndClear); |
| pwm_loop_.Shutdown(); |
| vreg_loop_.Shutdown(); |
| } |
| |
| zx_status_t Create(uint32_t pid, std::vector<aml_voltage_table_t> voltage_table, |
| voltage_pwm_period_ns_t pwm_period) { |
| EXPECT_OK(pwm_loop_.StartThread("pwm-servers")); |
| EXPECT_OK(vreg_loop_.StartThread("vreg-servers")); |
| auto little_cluster_pwm_client = little_cluster_pwm_.SyncCall(&MockPwmServer::BindServer); |
| auto big_cluster_pwm_client = big_cluster_pwm_.SyncCall(&MockPwmServer::BindServer); |
| auto little_cluster_vreg_client = little_cluster_vreg_.SyncCall(&FakeVregServer::BindServer); |
| auto big_cluster_vreg_client = big_cluster_vreg_.SyncCall(&FakeVregServer::BindServer); |
| switch (pid) { |
| case PDEV_PID_ASTRO: { |
| aml_power_ = AmlPowerTestWrapper::Create(std::move(little_cluster_pwm_client), |
| voltage_table, pwm_period); |
| return ZX_OK; |
| } |
| case PDEV_PID_SHERLOCK: { |
| aml_power_ = AmlPowerTestWrapper::Create(std::move(little_cluster_pwm_client), |
| std::move(big_cluster_pwm_client), voltage_table, |
| pwm_period); |
| return ZX_OK; |
| } |
| case PDEV_PID_LUIS: { |
| aml_power_ = AmlPowerTestWrapper::Create(std::move(little_cluster_pwm_client), |
| std::move(big_cluster_vreg_client), voltage_table, |
| pwm_period); |
| return ZX_OK; |
| } |
| case PDEV_PID_AMLOGIC_A311D: { |
| aml_power_ = AmlPowerTestWrapper::Create(std::move(little_cluster_vreg_client), |
| std::move(big_cluster_vreg_client)); |
| return ZX_OK; |
| } |
| default: |
| return ZX_ERR_INTERNAL; |
| } |
| } |
| |
| zx_status_t Create(uint32_t pid) { return Create(pid, kTestVoltageTable, kTestPwmPeriodNs); } |
| |
| protected: |
| std::unique_ptr<AmlPowerTestWrapper> aml_power_; |
| async::Loop pwm_loop_{&kAsyncLoopConfigNoAttachToCurrentThread}; |
| async::Loop vreg_loop_{&kAsyncLoopConfigNoAttachToCurrentThread}; |
| |
| // Mmio Regs and Regions |
| async_patterns::TestDispatcherBound<MockPwmServer> big_cluster_pwm_{pwm_loop_.dispatcher(), |
| std::in_place}; |
| async_patterns::TestDispatcherBound<MockPwmServer> little_cluster_pwm_{pwm_loop_.dispatcher(), |
| std::in_place}; |
| async_patterns::TestDispatcherBound<FakeVregServer> big_cluster_vreg_{vreg_loop_.dispatcher(), |
| std::in_place}; |
| async_patterns::TestDispatcherBound<FakeVregServer> little_cluster_vreg_{vreg_loop_.dispatcher(), |
| std::in_place}; |
| }; |
| |
| TEST_F(AmlPowerTest, SetVoltage) { |
| EXPECT_OK(Create(PDEV_PID_ASTRO)); |
| zx_status_t st; |
| constexpr uint32_t kTestVoltageInitial = 690'000; |
| constexpr uint32_t kTestVoltageFinal = 1'040'000; |
| |
| aml_pwm::mode_config on = {aml_pwm::Mode::kOn, {}}; |
| |
| // Initialize to 0.69V |
| fuchsia_hardware_pwm::wire::PwmConfig cfg = { |
| false, 1250, 100, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| |
| // Scale up to 1.05V |
| cfg = {false, 1250, 92, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 84, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 76, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 68, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 59, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 51, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 43, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 34, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 26, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 17, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 8, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 3, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| |
| uint32_t actual; |
| st = aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, kTestVoltageInitial, &actual); |
| EXPECT_EQ(kTestVoltageInitial, actual); |
| EXPECT_OK(st); |
| |
| st = aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, kTestVoltageFinal, &actual); |
| EXPECT_EQ(kTestVoltageFinal, actual); |
| EXPECT_OK(st); |
| } |
| |
| TEST_F(AmlPowerTest, ClusterIndexOutOfRange) { |
| constexpr uint32_t kTestVoltage = 690'000; |
| |
| EXPECT_OK(Create(PDEV_PID_ASTRO)); |
| |
| uint32_t actual; |
| zx_status_t st = aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG, kTestVoltage, &actual); |
| EXPECT_NOT_OK(st); |
| } |
| |
| TEST_F(AmlPowerTest, GetVoltageUnset) { |
| // Get the voltage before it's been set. Should return ZX_ERR_BAD_STATE. |
| EXPECT_OK(Create(PDEV_PID_ASTRO)); |
| |
| uint32_t voltage; |
| zx_status_t st = aml_power_->PowerImplGetCurrentVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, &voltage); |
| EXPECT_NOT_OK(st); |
| } |
| |
| TEST_F(AmlPowerTest, GetVoltage) { |
| // Get the voltage before it's been set. Should return ZX_ERR_BAD_STATE. |
| constexpr uint32_t kTestVoltage = 690'000; |
| zx_status_t st; |
| |
| EXPECT_OK(Create(PDEV_PID_ASTRO)); |
| |
| // Initialize to 0.69V |
| aml_pwm::mode_config on = {aml_pwm::Mode::kOn, {}}; |
| fuchsia_hardware_pwm::wire::PwmConfig cfg = { |
| false, 1250, 100, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| |
| uint32_t requested_voltage, actual_voltage; |
| st = aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, kTestVoltage, |
| &requested_voltage); |
| EXPECT_OK(st); |
| EXPECT_EQ(requested_voltage, kTestVoltage); |
| |
| st = aml_power_->PowerImplGetCurrentVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, &actual_voltage); |
| EXPECT_OK(st); |
| EXPECT_EQ(requested_voltage, actual_voltage); |
| } |
| |
| TEST_F(AmlPowerTest, GetVoltageOutOfRange) { |
| EXPECT_OK(Create(PDEV_PID_ASTRO)); |
| |
| uint32_t voltage; |
| zx_status_t st = aml_power_->PowerImplGetCurrentVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG, &voltage); |
| EXPECT_NOT_OK(st); |
| } |
| |
| TEST_F(AmlPowerTest, SetVoltageRoundDown) { |
| // Set a voltage that's not exactly supported and let the driver round down to the nearest |
| // voltage. |
| EXPECT_OK(Create(PDEV_PID_ASTRO)); |
| constexpr uint32_t kTestVoltageInitial = 830'000; |
| |
| // We expect the driver to give us the highest voltage that does not exceed the requested voltage. |
| constexpr uint32_t kTestVoltageFinalRequest = 935'000; |
| constexpr uint32_t kTestVoltageFinalActual = 930'000; |
| |
| aml_pwm::mode_config on = {aml_pwm::Mode::kOn, {}}; |
| fuchsia_hardware_pwm::wire::PwmConfig cfg = { |
| false, 1250, 62, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 54, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 45, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 37, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 34, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| |
| uint32_t actual; |
| zx_status_t st; |
| |
| st = aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, kTestVoltageInitial, &actual); |
| EXPECT_OK(st); |
| EXPECT_EQ(actual, kTestVoltageInitial); |
| |
| st = aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, kTestVoltageFinalRequest, |
| &actual); |
| EXPECT_OK(st); |
| EXPECT_EQ(actual, kTestVoltageFinalActual); |
| } |
| |
| TEST_F(AmlPowerTest, SetVoltageLittleCluster) { |
| // Set a voltage that's not exactly supported and let the driver round down to the nearest |
| // voltage. |
| EXPECT_OK(Create(PDEV_PID_SHERLOCK)); |
| constexpr uint32_t kTestVoltageInitial = 730'000; |
| constexpr uint32_t kTestVoltageFinal = 930'000; |
| |
| aml_pwm::mode_config on = {aml_pwm::Mode::kOn, {}}; |
| fuchsia_hardware_pwm::wire::PwmConfig cfg = { |
| false, 1250, 89, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 81, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 73, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 65, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 56, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 48, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 40, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| cfg = {false, 1250, 34, |
| fidl::VectorView<uint8_t>::FromExternal(reinterpret_cast<uint8_t*>(&on), sizeof(on))}; |
| little_cluster_pwm_.SyncCall(&MockPwmServer::ExpectSetConfig, cfg); |
| |
| uint32_t actual; |
| zx_status_t st; |
| |
| st = aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, kTestVoltageInitial, &actual); |
| EXPECT_OK(st); |
| EXPECT_EQ(actual, kTestVoltageInitial); |
| |
| st = aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, kTestVoltageFinal, &actual); |
| EXPECT_OK(st); |
| EXPECT_EQ(actual, kTestVoltageFinal); |
| } |
| |
| TEST_F(AmlPowerTest, DomainEnableDisable) { |
| EXPECT_OK(Create(PDEV_PID_SHERLOCK)); |
| |
| // Enable. |
| EXPECT_OK(aml_power_->PowerImplEnablePowerDomain( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE)); |
| EXPECT_OK(aml_power_->PowerImplEnablePowerDomain( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG)); |
| |
| // Disable. |
| EXPECT_OK(aml_power_->PowerImplDisablePowerDomain( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE)); |
| EXPECT_OK(aml_power_->PowerImplDisablePowerDomain( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG)); |
| |
| // Out of bounds. |
| EXPECT_NOT_OK(aml_power_->PowerImplDisablePowerDomain( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG + 1)); |
| EXPECT_NOT_OK(aml_power_->PowerImplEnablePowerDomain( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG + 1)); |
| } |
| |
| TEST_F(AmlPowerTest, GetDomainStatus) { |
| EXPECT_OK(Create(PDEV_PID_ASTRO)); |
| |
| // Happy case. |
| power_domain_status_t result; |
| EXPECT_OK(aml_power_->PowerImplGetPowerDomainStatus( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, &result)); |
| EXPECT_EQ(result, POWER_DOMAIN_STATUS_ENABLED); |
| |
| // Out of bounds. |
| EXPECT_NOT_OK(aml_power_->PowerImplGetPowerDomainStatus( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG, &result)); |
| } |
| |
| TEST_F(AmlPowerTest, LuisSetBigCluster) { |
| EXPECT_OK(Create(PDEV_PID_LUIS)); |
| |
| big_cluster_vreg_.SyncCall(&FakeVregServer::SetRegulatorParams, 100, 10, 10); |
| const uint32_t kTestVoltage = 155; |
| uint32_t actual; |
| EXPECT_OK(aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG, kTestVoltage, &actual)); |
| EXPECT_EQ(actual, 150); |
| EXPECT_EQ(big_cluster_vreg_.SyncCall(&FakeVregServer::voltage_step), 5); |
| |
| // Voltage is too low. |
| EXPECT_NOT_OK(aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG, 99, &actual)); |
| |
| // Set voltage to the threshold. |
| EXPECT_OK(aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG, 200, &actual)); |
| EXPECT_EQ(actual, 200); |
| EXPECT_EQ(big_cluster_vreg_.SyncCall(&FakeVregServer::voltage_step), 10); |
| |
| // Set voltage beyond the threshold. |
| EXPECT_NOT_OK(aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG, 300, &actual)); |
| } |
| |
| TEST_F(AmlPowerTest, LuisGetSupportedVoltageRange) { |
| EXPECT_OK(Create(PDEV_PID_LUIS)); |
| |
| big_cluster_vreg_.SyncCall(&FakeVregServer::SetRegulatorParams, 100, 10, 10); |
| |
| uint32_t max, min; |
| EXPECT_OK(aml_power_->PowerImplGetSupportedVoltageRange( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG, &min, &max)); |
| EXPECT_EQ(max, 200); |
| EXPECT_EQ(min, 100); |
| |
| EXPECT_OK(aml_power_->PowerImplGetSupportedVoltageRange( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, &min, &max)); |
| EXPECT_EQ(max, 1'050'000); |
| EXPECT_EQ(min, 690'000); |
| } |
| |
| TEST_F(AmlPowerTest, Vim3SetBigCluster) { |
| EXPECT_OK(Create(PDEV_PID_AMLOGIC_A311D)); |
| |
| big_cluster_vreg_.SyncCall(&FakeVregServer::SetRegulatorParams, 100, 10, 10); |
| const uint32_t kTestVoltage = 155; |
| uint32_t actual; |
| EXPECT_OK(aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG, kTestVoltage, &actual)); |
| EXPECT_EQ(actual, 150); |
| EXPECT_EQ(big_cluster_vreg_.SyncCall(&FakeVregServer::voltage_step), 5); |
| |
| // Voltage is too low. |
| EXPECT_NOT_OK(aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG, 99, &actual)); |
| |
| // Set voltage to the threshold. |
| EXPECT_OK(aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG, 200, &actual)); |
| EXPECT_EQ(actual, 200); |
| EXPECT_EQ(big_cluster_vreg_.SyncCall(&FakeVregServer::voltage_step), 10); |
| |
| // Set voltage beyond the threshold. |
| EXPECT_NOT_OK(aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG, 300, &actual)); |
| } |
| |
| TEST_F(AmlPowerTest, Vim3SetLittleCluster) { |
| EXPECT_OK(Create(PDEV_PID_AMLOGIC_A311D)); |
| |
| little_cluster_vreg_.SyncCall(&FakeVregServer::SetRegulatorParams, 100, 10, 10); |
| const uint32_t kTestVoltage = 155; |
| uint32_t actual; |
| EXPECT_OK(aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, kTestVoltage, &actual)); |
| EXPECT_EQ(actual, 150); |
| EXPECT_EQ(little_cluster_vreg_.SyncCall(&FakeVregServer::voltage_step), 5); |
| |
| // Voltage is too low. |
| EXPECT_NOT_OK(aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, 99, &actual)); |
| |
| // Set voltage to the threshold. |
| EXPECT_OK(aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, 200, &actual)); |
| EXPECT_EQ(actual, 200); |
| EXPECT_EQ(little_cluster_vreg_.SyncCall(&FakeVregServer::voltage_step), 10); |
| |
| // Set voltage beyond the threshold. |
| EXPECT_NOT_OK(aml_power_->PowerImplRequestVoltage( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, 300, &actual)); |
| } |
| |
| TEST_F(AmlPowerTest, Vim3GetSupportedVoltageRange) { |
| EXPECT_OK(Create(PDEV_PID_AMLOGIC_A311D)); |
| |
| big_cluster_vreg_.SyncCall(&FakeVregServer::SetRegulatorParams, 100, 10, 10); |
| |
| uint32_t max, min; |
| EXPECT_OK(aml_power_->PowerImplGetSupportedVoltageRange( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_BIG, &min, &max)); |
| EXPECT_EQ(max, 200); |
| EXPECT_EQ(min, 100); |
| |
| little_cluster_vreg_.SyncCall(&FakeVregServer::SetRegulatorParams, 100, 20, 5); |
| |
| EXPECT_OK(aml_power_->PowerImplGetSupportedVoltageRange( |
| bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE, &min, &max)); |
| EXPECT_EQ(max, 200); |
| EXPECT_EQ(min, 100); |
| } |
| |
| } // namespace power |