blob: 9115d7274e9fdca492409fa1b7c1132b50aaa0ee [file] [log] [blame]
// 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;
}