blob: 310ae366a38bbb241aba41becfa19f13420f9000 [file] [log] [blame]
// Copyright 2016 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.
#ifndef REGISTERS_H
#define REGISTERS_H
#include "magma_util/macros.h"
#include "magma_util/register_bitfields.h"
#include "magma_util/register_io.h"
#include "types.h"
#include <vector>
namespace registers {
// from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part2.pdf p.733
class GmchGraphicsControl {
public:
static constexpr uint32_t kOffset = 0x50;
static constexpr uint32_t kGttSizeShift = 6;
static constexpr uint32_t kGttSizeMask = 0x3;
static uint32_t gtt_size(uint32_t val)
{
unsigned int size = (val >> kGttSizeShift) & kGttSizeMask;
return (size == 0) ? 0 : (1 << size) * 1024 * 1024;
}
};
// from intel-gfx-prm-osrc-bdw-vol02c-commandreference-registers_4.pdf p.712
class HardwareStatusPageAddress {
public:
static constexpr uint32_t kOffset = 0x80;
static void write(magma::RegisterIo* reg_io, uint64_t mmio_base, uint32_t addr)
{
reg_io->Write32(mmio_base + kOffset, addr);
reg_io->mmio()->PostingRead32(mmio_base + kOffset);
}
};
// from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part2.pdf p.500
class PatIndex {
public:
static constexpr uint32_t kOffsetLow = 0x40E0;
static constexpr uint32_t kOffsetHigh = 0x40E4;
static constexpr uint8_t kUncacheable = 0;
static constexpr uint8_t kWriteCombining = 1;
static constexpr uint8_t kWriteThrough = 2;
static constexpr uint8_t kWriteBack = 3;
static constexpr uint8_t kMemTypeMask = 0x3;
static constexpr uint8_t kEllc = 0;
static constexpr uint8_t kLlc = 1;
static constexpr uint8_t kLlcEllc = 2;
static constexpr uint8_t kTargetCacheMask = 3;
static constexpr uint8_t kLruAgeFromUncore = 0;
static constexpr uint8_t kLruAgeZero = 1;
static constexpr uint8_t kLruAgeNoChange = 2;
static constexpr uint8_t kLruAgeThree = 3;
static constexpr uint8_t kLruAgeMask = 0x3;
static void write(magma::RegisterIo* reg_io, uint64_t val)
{
reg_io->Write32(kOffsetLow, static_cast<uint32_t>(val));
reg_io->Write32(kOffsetHigh, static_cast<uint32_t>(val >> 32));
}
static uint64_t ppat(unsigned int index, uint8_t lru_age, uint8_t target_cache,
uint8_t mem_type)
{
DASSERT((lru_age & ~kLruAgeMask) == 0);
DASSERT((target_cache & ~kTargetCacheMask) == 0);
DASSERT((mem_type & ~kMemTypeMask) == 0);
uint64_t ppat = (lru_age << 4) | (target_cache << 2) | mem_type;
return ppat << (index * 8);
}
};
// from intel-gfx-prm-osrc-bdw-vol02c-commandreference-registers_4.pdf p.438
// and intel-gfx-prm-osrc-bdw-vol02d-commandreference-structures_3.pdf p.107
class ExeclistSubmitPort {
public:
static constexpr uint32_t kSubmitOffset = 0x230;
static constexpr uint32_t kStatusOffset = 0x234;
static uint64_t context_descriptor(gpu_addr_t gpu_addr, uint32_t context_id, bool ppgtt_enable)
{
constexpr uint32_t kValid = 1;
constexpr uint32_t kLegacyMode48bitPpgtt = 3 << 3;
constexpr uint32_t kLegacyModePpgttEnable = 1 << 8;
constexpr uint32_t kContextIdShift = 32;
uint64_t desc = gpu_addr;
desc |= kValid;
desc |= kLegacyMode48bitPpgtt;
if (ppgtt_enable)
desc |= kLegacyModePpgttEnable;
desc |= static_cast<uint64_t>(context_id) << kContextIdShift;
return desc;
}
static void write(magma::RegisterIo* reg_io, uint64_t mmio_base, uint64_t descriptor1,
uint64_t descriptor0)
{
uint32_t desc[4]{magma::upper_32_bits(descriptor1), magma::lower_32_bits(descriptor1),
magma::upper_32_bits(descriptor0), magma::lower_32_bits(descriptor0)};
// The last write triggers the context load.
reg_io->Write32(mmio_base + kSubmitOffset, desc[0]);
reg_io->Write32(mmio_base + kSubmitOffset, desc[1]);
reg_io->Write32(mmio_base + kSubmitOffset, desc[2]);
reg_io->Write32(mmio_base + kSubmitOffset, desc[3]);
reg_io->mmio()->PostingRead32(mmio_base + kStatusOffset);
}
};
class ExeclistStatus {
public:
static constexpr uint32_t kOffset = 0x234;
static constexpr uint32_t kExeclistCurrentPointerShift = 0;
static constexpr uint32_t kExeclistWritePointerShift = 1;
static constexpr uint32_t kExeclistQueueFullShift = 2;
static uint64_t read(magma::RegisterIo* reg_io, uint64_t mmio_base)
{
// Hmm 64-bit read would be better but kOffset is not 64bit aligned
uint64_t status = reg_io->Read32(mmio_base + kOffset + 4);
status = (status << 32) | reg_io->Read32(mmio_base + kOffset);
return status;
}
static uint32_t execlist_current_pointer(uint64_t status)
{
return (status >> kExeclistCurrentPointerShift) & 0x1;
}
static uint32_t execlist_write_pointer(uint64_t status)
{
return (status >> kExeclistWritePointerShift) & 0x1;
}
static bool execlist_queue_full(uint64_t status)
{
return (status >> kExeclistQueueFullShift) & 0x1;
}
};
// from intel-gfx-prm-osrc-kbl-vol02c-commandreference-registers-part1.pdf p.1
class ActiveHeadPointer {
public:
static constexpr uint32_t kOffset = 0x74;
static constexpr uint32_t kUpperOffset = 0x5C;
static uint64_t read(magma::RegisterIo* reg_io, uint64_t mmio_base)
{
uint64_t val = reg_io->Read32(mmio_base + kUpperOffset);
val = (val << 32) | reg_io->Read32(mmio_base + kOffset);
return val;
}
};
// from intel-gfx-prm-osrc-bdw-vol02c-commandreference-registers_4.pdf p.75
class AllEngineFault {
public:
static constexpr uint32_t kOffset = 0x4094;
static constexpr uint32_t kValid = 1;
static constexpr uint32_t kEngineShift = 12;
static constexpr uint32_t kEngineMask = 0x3;
static constexpr uint32_t kSrcShift = 3;
static constexpr uint32_t kSrcMask = 0xFF;
static constexpr uint32_t kTypeShift = 1;
static constexpr uint32_t kTypeMask = 0x3;
static uint32_t read(magma::RegisterIo* reg_io) { return reg_io->Read32(kOffset); }
static void clear(magma::RegisterIo* reg_io) { reg_io->Write32(kOffset, 0); }
static bool valid(uint32_t val) { return val & kValid; }
static uint32_t engine(uint32_t val) { return (val >> kEngineShift) & kEngineMask; }
static uint32_t src(uint32_t val) { return (val >> kSrcShift) & kSrcMask; }
static uint32_t type(uint32_t val) { return (val >> kTypeShift) & kTypeMask; }
};
// from intel-gfx-prm-osrc-bdw-vol02c-commandreference-registers_4.pdf p.446
class FaultTlbReadData {
public:
static constexpr uint32_t kOffset0 = 0x4B10;
static constexpr uint32_t kOffset1 = 0x4B14;
static constexpr uint64_t kGgttCycle = 1ull << 36;
static uint64_t read(magma::RegisterIo* reg_io)
{
return (static_cast<uint64_t>(reg_io->Read32(kOffset1)) << 32) |
static_cast<uint64_t>(reg_io->Read32(kOffset0));
}
static uint64_t addr(uint64_t val) { return (val & 0xFFFFFFFFFull) << 12; }
static bool is_ggtt(uint64_t val) { return val & kGgttCycle; }
};
// from intel-gfx-prm-osrc-bdw-vol02c-commandreference-registers_4.pdf p.493
class ForceWake {
public:
enum Domain { GEN9_RENDER };
static constexpr uint32_t kOffset = 0xA188;
static constexpr uint32_t kStatusOffset = 0x130044;
static constexpr uint32_t kRenderOffset = 0xA278;
static constexpr uint32_t kRenderStatusOffset = 0xD84;
static void reset(magma::RegisterIo* reg_io, Domain domain)
{
write(reg_io, domain, 0xFFFF, 0);
}
static void write(magma::RegisterIo* reg_io, Domain domain, uint16_t mask, uint16_t val)
{
uint32_t val32 = mask;
val32 = (val32 << 16) | val;
switch (domain) {
case GEN9_RENDER:
reg_io->Write32(kRenderOffset, val32);
break;
}
}
static uint16_t read_status(magma::RegisterIo* reg_io, Domain domain)
{
switch (domain) {
case GEN9_RENDER:
return static_cast<uint16_t>(reg_io->Read32(kRenderStatusOffset));
}
}
};
// from intel-gfx-prm-osrc-bdw-vol02c-commandreference-registers_4.pdf p.618
class GraphicsMode {
public:
static constexpr uint32_t kOffset = 0x29C;
static constexpr uint32_t kExeclistEnable = 1 << 15;
static void write(magma::RegisterIo* reg_io, uint64_t mmio_base, uint16_t mask, uint16_t val)
{
uint32_t val32 = mask;
val32 = (val32 << 16) | val;
reg_io->Write32(mmio_base + kOffset, val32);
reg_io->mmio()->PostingRead32(mmio_base + kOffset);
}
};
// from Intel-GFX-BSpec-NDA-SKL-20150707-b93797-r96240-Web register spec
class RenderPerformanceNormalFrequencyRequest {
public:
static constexpr uint32_t kOffset = 0xA008;
static void write_frequency_request_gen9(magma::RegisterIo* reg_io, uint32_t mhz)
{
// Register in units of 16.66Mhz on skylake
uint32_t val = mhz * 3 / 50;
DASSERT(val <= 0x1ff);
reg_io->Write32(kOffset, val << 23);
}
static uint32_t read(magma::RegisterIo* reg_io)
{
// Register in units of 16.66Mhz on skylake
return ((reg_io->Read32(kOffset) >> 23) & 0x1ff) * 50 / 3;
}
};
class RenderPerformanceStatus {
public:
static constexpr uint32_t kOffset = 0xA01C;
// Returns frequency in MHz
static uint32_t read_current_frequency_gen9(magma::RegisterIo* reg_io)
{
// Register in units of 16.66Mhz on skylake
return (reg_io->Read32(kOffset) >> 23) * 50 / 3;
}
};
class RenderPerformanceStateCapability {
public:
static constexpr uint32_t kOffset = 0x140000 + 0x5998;
// Returns frequency in Mhz
static uint32_t read_rp0_frequency(magma::RegisterIo* register_io)
{
// Register units are 50Mhz
return (register_io->Read32(kOffset) & 0xff) * 50;
}
};
// from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part2.pdf p.741
class ResetControl {
public:
static constexpr uint32_t kOffset = 0xd0;
static constexpr uint32_t kRequestResetBit = 0;
static constexpr uint32_t kReadyForResetBit = 1;
static void request(magma::RegisterIo* register_io, uint64_t mmio_base)
{
register_io->Write32(mmio_base + kOffset,
((1 << kRequestResetBit) << 16) | (1 << kRequestResetBit));
}
static bool ready_for_reset(magma::RegisterIo* register_io, uint64_t mmio_base)
{
return register_io->Read32(mmio_base + kOffset) & (1 << kReadyForResetBit);
}
};
// from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part1.pdf p.755
class GraphicsDeviceResetControl {
public:
enum Engine { RENDER_ENGINE };
static constexpr uint32_t kOffset = 0x941C;
static constexpr uint32_t kRenderResetBit = 1;
static void initiate_reset(magma::RegisterIo* register_io, Engine engine)
{
switch (engine) {
case RENDER_ENGINE:
register_io->Write32(kOffset, (1 << kRenderResetBit));
break;
}
}
static bool is_reset_complete(magma::RegisterIo* register_io, Engine engine)
{
switch (engine) {
case RENDER_ENGINE:
return (register_io->Read32(kOffset) & (1 << kRenderResetBit)) == 0;
}
}
};
// from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part2.pdf p.10
class MasterInterruptControl {
public:
static constexpr uint32_t kOffset = 0x44200;
static constexpr uint32_t kRenderInterruptsPendingBitMask = 1 << 0;
static constexpr uint32_t kDisplayEnginePipeAInterruptsPendingBit = 1 << 16;
static constexpr uint32_t kEnableBitMask = 1 << 31;
static void write(magma::RegisterIo* register_io, bool enable)
{
register_io->Write32(kOffset, enable ? kEnableBitMask : 0);
}
static uint32_t read(magma::RegisterIo* register_io) { return register_io->Read32(kOffset); }
};
class InterruptRegisterBase {
public:
enum Engine { RENDER_ENGINE };
enum Source { PAGE_FAULT, CONTEXT_SWITCH, USER };
enum MaskOp { MASK, UNMASK };
static constexpr uint32_t kUserInterruptBit = 1 << 0;
static constexpr uint32_t kPageFaultBit = 1 << 7;
static constexpr uint32_t kContextSwitchBit = 1 << 8;
protected:
static uint32_t source_bit(Source source)
{
switch (source) {
case USER:
return kUserInterruptBit;
case PAGE_FAULT:
return kPageFaultBit;
case CONTEXT_SWITCH:
return kContextSwitchBit;
}
}
static void write(magma::RegisterIo* register_io, uint64_t offset, Source source, bool set)
{
uint32_t bit = source_bit(source);
uint32_t val = register_io->Read32(offset);
val = set ? (val | bit) : (val & ~bit);
register_io->Write32(offset, val);
register_io->mmio()->PostingRead32(offset);
}
};
class HardwareStatusMask : public InterruptRegisterBase {
public:
static constexpr uint32_t kRenderOffset = 0x98;
static void write(magma::RegisterIo* register_io, uint64_t mmio_base, Engine engine,
Source source, MaskOp op)
{
switch (engine) {
case RENDER_ENGINE:
InterruptRegisterBase::write(register_io, mmio_base + kRenderOffset, source,
op == MASK);
break;
}
}
};
class GtInterruptMask0 : public InterruptRegisterBase {
public:
static constexpr uint32_t kOffset = 0x44304;
static void write(magma::RegisterIo* register_io, Engine engine, Source source, MaskOp op)
{
switch (engine) {
case RENDER_ENGINE:
InterruptRegisterBase::write(register_io, kOffset, source, op == MASK);
break;
}
}
};
class GtInterruptIdentity0 : public InterruptRegisterBase {
public:
static constexpr uint32_t kOffset = 0x44308;
static uint32_t read(magma::RegisterIo* register_io, Engine engine)
{
switch (engine) {
case RENDER_ENGINE:
return register_io->Read32(kOffset);
}
}
static void clear(magma::RegisterIo* register_io, Engine engine, Source source)
{
switch (engine) {
case RENDER_ENGINE:
register_io->Write32(kOffset, source_bit(source));
break;
}
}
};
class GtInterruptEnable0 : public InterruptRegisterBase {
public:
static constexpr uint32_t kOffset = 0x4430C;
static void write(magma::RegisterIo* register_io, Engine engine, Source source, bool enable)
{
switch (engine) {
case RENDER_ENGINE:
InterruptRegisterBase::write(register_io, kOffset, source, enable);
break;
}
}
};
// from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part1.pdf p.764
class MemoryObjectControlState {
public:
static constexpr uint32_t kGraphicsOffset = 0xC800;
static constexpr uint32_t kCacheabilityShift = 0;
static constexpr uint32_t kCacheShift = 2;
static constexpr uint32_t kLruManagementShift = 4;
enum Cacheability { PAGETABLE = 0, UNCACHED, WRITETHROUGH, WRITEBACK };
enum Cache { LLC_ELLC = 2 };
enum LruManagement { LRU_0 = 0, LRU_3 = 3 };
static uint32_t format(Cacheability cacheability, Cache cache, LruManagement lru_management)
{
return (lru_management << kLruManagementShift) | (cache << kCacheShift) |
(cacheability << kCacheabilityShift);
}
};
// from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part1.pdf p.1118
class LncfMemoryObjectControlState {
public:
static constexpr uint32_t kOffset = 0xB020;
static constexpr uint32_t kCacheabilityShift = 4;
enum Cacheability { DIRECT = 0, UNCACHED, WRITETHROUGH, WRITEBACK };
static uint16_t format(Cacheability cacheability) { return cacheability << kCacheabilityShift; }
};
// from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part2.pdf p.403
class Fuse2ControlDwordMirror {
public:
static constexpr uint32_t kOffset = 0x9120;
static constexpr uint32_t kSliceEnableShift = 25;
static constexpr uint32_t kSliceEnableMask = 0x7 << kSliceEnableShift;
static constexpr uint32_t kSubsliceDisableShift = 20;
static constexpr uint32_t kSubsliceDisableMask = 0xf << kSubsliceDisableShift;
static void read(magma::RegisterIo* register_io, uint32_t* slice_enable_mask_out,
uint32_t* subslice_enable_mask_out)
{
uint32_t val = register_io->Read32(kOffset);
*slice_enable_mask_out = (val & kSliceEnableMask) >> kSliceEnableShift;
*subslice_enable_mask_out = ((~val) & kSubsliceDisableMask) >> kSubsliceDisableShift;
}
};
// from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part2.pdf p.398
class MirrorEuDisable {
public:
static constexpr uint32_t kOffset = 0x9134;
static constexpr uint32_t kMaxSliceCount = 3;
static constexpr uint32_t kMaxSubsliceCount = 4;
static constexpr uint32_t kEuPerSubslice = 8;
static constexpr uint32_t kSubsliceMask = 0xff;
static_assert(kMaxSubsliceCount * kEuPerSubslice == sizeof(uint32_t) * 8,
"eu/subslice math is wrong");
static_assert(kSubsliceMask == (1 << kEuPerSubslice) - 1, "wrong kSubsliceMask");
static void read(magma::RegisterIo* register_io, uint8_t slice,
std::vector<uint32_t>& eu_disable_mask_out)
{
DASSERT(slice < kMaxSliceCount);
uint32_t val = register_io->Read32(kOffset + slice * sizeof(uint32_t));
eu_disable_mask_out.clear();
for (uint32_t subslice = 0; subslice < kMaxSubsliceCount; subslice++) {
eu_disable_mask_out.push_back(val & kSubsliceMask);
val >>= kEuPerSubslice;
}
}
};
// PWR_WELL_CTL: Power well control. This allows enabling or disabling
// power to various "power wells" (groups of functional units).
// from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part2.pdf
class PowerWellControl2 : public magma::RegisterBase {
public:
DEF_BIT(31, power_well_2_request);
DEF_BIT(30, power_well_2_state);
DEF_BIT(29, power_well_1_request);
DEF_BIT(28, power_well_1_state);
DEF_BIT(9, ddi_d_io_power_request);
DEF_BIT(8, ddi_d_io_power_state);
DEF_BIT(7, ddi_c_io_power_request);
DEF_BIT(6, ddi_c_io_power_state);
DEF_BIT(5, ddi_b_io_power_request);
DEF_BIT(4, ddi_b_io_power_state);
DEF_BIT(3, ddi_a_and_e_io_power_request);
DEF_BIT(2, ddi_a_and_e_io_power_state);
DEF_BIT(1, misc_io_power_request);
DEF_BIT(0, misc_io_power_state);
static auto Get() { return magma::RegisterAddr<PowerWellControl2>(0x45404); }
};
// from intel-gfx-prm-osrc-skl-vol02c-commandreference-registers-part1.pdf p.86
class ArbiterControl {
public:
static constexpr uint32_t kOffset = 0xb004;
static constexpr uint32_t kGapsTsvCreditFixEnable = 1 << 7;
static void workaround(magma::RegisterIo* register_io)
{
uint32_t value = register_io->Read32(kOffset) | kGapsTsvCreditFixEnable;
register_io->Write32(kOffset, value);
}
};
class RenderEngineTlbControl : public magma::RegisterBase {
public:
DEF_BIT(0, invalidate);
static auto Get() { return magma::RegisterAddr<RenderEngineTlbControl>(0x4260); }
};
} // namespace registers
#endif // REGISTERS_H