blob: 4eb7701ff48282d7bfe1ae5bcc17eda95e1c7402 [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 "msd_intel_register_io.h"
#include <lib/magma/platform/platform_trace.h>
#include <lib/magma/util/dlog.h>
#include <lib/magma/util/short_macros.h>
#include "registers.h"
MsdIntelRegisterIo::MsdIntelRegisterIo(Owner* owner, std::unique_ptr<magma::PlatformMmio> mmio,
uint32_t device_id)
: owner_(owner), register_io_(std::move(mmio)) {
if (DeviceId::is_gen12(device_id)) {
forcewake_map_ = &forcewake_map_gen12_;
}
}
std::shared_ptr<ForceWakeDomain> MsdIntelRegisterIo::GetForceWakeToken(ForceWakeDomain domain) {
// Ensure forcewake has been activated before we offer the first token.
if (forcewake_token_count(domain) == 0) {
DASSERT(owner_);
bool enabled = owner_->IsForceWakeDomainActive(domain);
DASSERT(enabled);
}
DASSERT(static_cast<size_t>(domain) < per_forcewake_.size());
per_forcewake_[static_cast<int>(domain)].last_request_time = std::chrono::steady_clock::now();
return per_forcewake_[static_cast<int>(domain)].token;
}
std::chrono::steady_clock::duration MsdIntelRegisterIo::GetForceWakeReleaseTimeout(
ForceWakeDomain forcewake_domain, uint64_t max_release_timeout_ms,
std::chrono::steady_clock::time_point now) {
// Don't timeout if a forcewake token is still held
if (forcewake_token_count(forcewake_domain) > 0)
return std::chrono::steady_clock::duration::max();
if (!owner_->IsForceWakeDomainActive(forcewake_domain))
return std::chrono::steady_clock::duration::max();
DASSERT(static_cast<size_t>(forcewake_domain) < per_forcewake_.size());
auto last_request_time = per_forcewake_[static_cast<int>(forcewake_domain)].last_request_time;
DASSERT(last_request_time != std::chrono::steady_clock::time_point::max());
return last_request_time + std::chrono::milliseconds(max_release_timeout_ms) - now;
}
void MsdIntelRegisterIo::CheckForcewake(uint32_t register_offset) {
// Skip the forcewake registers
switch (register_offset) {
case registers::ForceWakeRequest::kRenderOffset:
case registers::ForceWakeRequest::kGen9MediaOffset:
case registers::ForceWakeRequest::kGen12Vdbox0Offset:
case registers::ForceWakeStatus::kRenderStatusOffset:
case registers::ForceWakeStatus::kGen9MediaStatusOffset:
case registers::ForceWakeStatus::kGen12Vdbox0StatusOffset:
return;
}
if (!forcewake_map_ || forcewake_map_->empty())
return;
TRACE_DURATION("magma", "CheckForcewake");
auto iter = forcewake_map_->upper_bound(register_offset);
if (iter == forcewake_map_->begin())
return;
iter = std::prev(iter);
DASSERT(iter->first == iter->second.start_offset);
if (const Range& range = iter->second;
register_offset >= range.start_offset && register_offset <= range.end_offset) {
CheckForcewakeForRange(range, register_offset);
}
}
void MsdIntelRegisterIo::CheckForcewakeForRange(const Range& range, uint32_t register_offset) {
if (forcewake_active_check_for_test_) {
owner_->IsForceWakeDomainActive(range.forcewake_domain);
}
if (forcewake_token_count(range.forcewake_domain) == 0) {
MAGMA_LOG(WARNING, "Access missing forcewake: register 0x%x domain %d range 0x%x - 0x%x",
register_offset, static_cast<int>(range.forcewake_domain), range.start_offset,
range.end_offset);
DASSERT(false);
}
}
// static
constexpr std::pair<uint32_t, MsdIntelRegisterIo::Range> Entry(uint32_t start, uint32_t end,
ForceWakeDomain domain) {
return {start, {start, end, domain}};
}
// From:
// https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-tgl-vol13-generalassets.pdf
// p.1
// Does not include GT or empty regions.
// Commented lines refer to engines that may be supported eventually.
// clang-format off
const std::map<uint32_t, MsdIntelRegisterIo::Range> MsdIntelRegisterIo::forcewake_map_gen12_ = {
Entry(0x2000, 0x26FF, ForceWakeDomain::RENDER),
Entry(0x2800, 0x2AFF, ForceWakeDomain::RENDER),
Entry(0x3000, 0x3FFF, ForceWakeDomain::RENDER),
Entry(0x5200, 0x52FF, ForceWakeDomain::RENDER),
Entry(0x5300, 0x53FF, ForceWakeDomain::RENDER),
Entry(0x5500, 0x55FF, ForceWakeDomain::RENDER),
Entry(0x6000, 0x6FFF, ForceWakeDomain::RENDER),
Entry(0x7000, 0x7FFF, ForceWakeDomain::RENDER),
Entry(0x8140, 0x814F, ForceWakeDomain::RENDER),
Entry(0x8150, 0x815F, ForceWakeDomain::RENDER),
Entry(0x8300, 0x84FF, ForceWakeDomain::RENDER),
Entry(0x94D0, 0x951F, ForceWakeDomain::RENDER),
Entry(0x9520, 0x955F, ForceWakeDomain::RENDER),
Entry(0xB000, 0xB0FF, ForceWakeDomain::RENDER),
Entry(0xB100, 0xB3FF, ForceWakeDomain::RENDER),
Entry(0xD800, 0xD8FF, ForceWakeDomain::RENDER),
Entry(0xDC00, 0xDDFF, ForceWakeDomain::RENDER),
Entry(0xDE80, 0xDEFF, ForceWakeDomain::RENDER),
Entry(0xDF00, 0xDFFF, ForceWakeDomain::RENDER),
Entry(0xE000, 0xE0FF, ForceWakeDomain::RENDER),
Entry(0xE100, 0xE1FF, ForceWakeDomain::RENDER),
Entry(0xE200, 0xE3FF, ForceWakeDomain::RENDER),
Entry(0xE400, 0xE7FF, ForceWakeDomain::RENDER),
Entry(0xE800, 0xE8FF, ForceWakeDomain::RENDER),
Entry(0x14800, 0x14FFF, ForceWakeDomain::RENDER),
Entry(0x16E00, 0x16FFF, ForceWakeDomain::RENDER),
Entry(0x17000, 0x17FFF, ForceWakeDomain::RENDER),
Entry(0x18000, 0x19FFF, ForceWakeDomain::RENDER),
Entry(0x1A000, 0x1BFFF, ForceWakeDomain::RENDER),
Entry(0x20000, 0x20FFF, ForceWakeDomain::GEN12_VDBOX0),
// Entry(0x21000, 0x21FFF, ForceWakeDomain::GEN12_VDBOX2),
Entry(0x24A00, 0x24A7F, ForceWakeDomain::RENDER),
Entry(0x25600, 0x2567F, ForceWakeDomain::GEN12_VDBOX0),
// Entry(0x25680, 0x256FF, ForceWakeDomain::GEN12_VDBOX2),
Entry(0x25A00, 0x25A7F, ForceWakeDomain::GEN12_VDBOX0),
// Entry(0x25A80, 0x25AFF, ForceWakeDomain::GEN12_VDBOX2),
Entry(0x1C0000, 0x1C07FF, ForceWakeDomain::GEN12_VDBOX0),
Entry(0x1C0800, 0x1C0FFF, ForceWakeDomain::GEN12_VDBOX0),
Entry(0x1C1000, 0x1C1FFF, ForceWakeDomain::GEN12_VDBOX0),
Entry(0x1C2000, 0x1C27FF, ForceWakeDomain::GEN12_VDBOX0),
Entry(0x1C2800, 0x1C2AFF, ForceWakeDomain::GEN12_VDBOX0),
Entry(0x1C2B00, 0x1C2BFF, ForceWakeDomain::GEN12_VDBOX0),
Entry(0x1C2D00, 0x1C2DFF, ForceWakeDomain::GEN12_VDBOX0),
Entry(0x1C3F00, 0x1C3FFF, ForceWakeDomain::GEN12_VDBOX0),
// Entry(0x1C8000, 0x1C9FFF, ForceWakeDomain::GEN12_VEBOX0),
// Entry(0x1CA000, 0x1CA0FF, ForceWakeDomain::GEN12_VEBOX0),
// Entry(0x1CBF00, 0x1CBFFF, ForceWakeDomain::GEN12_VEBOX0),
Entry(0x1CC000, 0x1CCFFF, ForceWakeDomain::GEN12_VDBOX0),
// Entry(0x1D0000, 0x1D07FF, ForceWakeDomain::GEN12_VDBOX2),
// Entry(0x1D0800, 0x1D0FFF, ForceWakeDomain::GEN12_VDBOX2),
// Entry(0x1D1000, 0x1D1FFF, ForceWakeDomain::GEN12_VDBOX2),
// Entry(0x1D2000, 0x1D27FF, ForceWakeDomain::GEN12_VDBOX2),
// Entry(0x1D2800, 0x1D2AFF, ForceWakeDomain::GEN12_VDBOX2),
// Entry(0x1D2B00, 0x1D2BFF, ForceWakeDomain::GEN12_VDBOX2),
// Entry(0x1D2D00, 0x1D2DFF, ForceWakeDomain::GEN12_VDBOX2),
// Entry(0x1D3F00, 0x1D3FFF, ForceWakeDomain::GEN12_VDBOX2),
};
// clang-format on