| // 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 "forcewake.h" |
| |
| #include <lib/magma/platform/platform_trace.h> |
| #include <lib/magma/util/dlog.h> |
| #include <lib/magma/util/short_macros.h> |
| |
| #include <thread> |
| |
| #include "msd_intel_register_io.h" |
| |
| ForceWake::ForceWake(MsdIntelRegisterIo* register_io, uint32_t device_id) { |
| status_render_ = registers::ForceWakeStatus::GetRender(register_io); |
| |
| if (DeviceId::is_gen12(device_id)) { |
| status_gen12_vdbox0_ = registers::ForceWakeStatus::GetGen12Vdbox0(register_io); |
| } else { |
| status_gen9_media_ = registers::ForceWakeStatus::GetGen9Media(register_io); |
| } |
| } |
| |
| bool ForceWake::IsActive(MsdIntelRegisterIo* reg_io, ForceWakeDomain domain) { |
| get_status_register(domain)->ReadFrom(reg_io); |
| return is_active_cached(domain); |
| } |
| |
| bool ForceWake::Reset(MsdIntelRegisterIo* reg_io, ForceWakeDomain domain) { |
| TRACE_DURATION("magma", "ForceWakeReset"); |
| DLOG("ForceWake::Reset domain %d", static_cast<int>(domain)); |
| |
| registers::ForceWakeRequest::reset(reg_io, get_request_offset(domain)); |
| |
| return Wait(reg_io, domain, false); |
| } |
| |
| bool ForceWake::Request(MsdIntelRegisterIo* reg_io, ForceWakeDomain domain) { |
| TRACE_DURATION("magma", "ForceWakeRequest"); |
| |
| if (IsActive(reg_io, domain)) |
| return true; |
| |
| DLOG("ForceWake::Request domain %d", static_cast<int>(domain)); |
| |
| registers::ForceWakeRequest::write(reg_io, get_request_offset(domain), 1 << kThreadShift, |
| 1 << kThreadShift); |
| |
| return Wait(reg_io, domain, true); |
| } |
| |
| bool ForceWake::Release(MsdIntelRegisterIo* reg_io, ForceWakeDomain domain) { |
| TRACE_DURATION("magma", "ForceWakeRelease"); |
| |
| if (!IsActive(reg_io, domain)) |
| return true; |
| |
| DLOG("ForceWake::Release domain %d", static_cast<int>(domain)); |
| |
| registers::ForceWakeRequest::write(reg_io, get_request_offset(domain), 1 << kThreadShift, 0); |
| |
| return Wait(reg_io, domain, false); |
| } |
| |
| bool ForceWake::Wait(MsdIntelRegisterIo* register_io, ForceWakeDomain domain, bool set) { |
| TRACE_DURATION("magma", "ForceWakeWait"); |
| |
| registers::ForceWakeStatus* status_register = get_status_register(domain); |
| DASSERT(status_register); |
| |
| for (unsigned int i = 0; i < kMaxRetries; i++) { |
| status_register->ReadFrom(register_io); |
| |
| uint32_t status = status_register->status(); |
| if (((status >> kThreadShift) & 1) == (set ? 1 : 0)) |
| return true; |
| |
| std::this_thread::sleep_for(std::chrono::microseconds(kRetryDelayUs)); |
| } |
| MAGMA_LOG(WARNING, "Timed out waiting for forcewake domain %d set %d", static_cast<int>(domain), |
| set); |
| return false; |
| } |