blob: 23e30567d3caa80729db57941fe8d414b174df7a [file] [log] [blame]
// Copyright 2017 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"
namespace registers {
class GpuId : public magma::RegisterBase {
public:
DEF_FIELD(3, 0, version_status);
DEF_FIELD(11, 4, minor_revision);
DEF_FIELD(15, 12, major_revision);
DEF_FIELD(31, 16, product_id);
static auto Get() { return magma::RegisterAddr<GpuId>(0); }
};
class L2Features : public magma::RegisterBase {
public:
DEF_FIELD(7, 0, log2_line_size);
DEF_FIELD(15, 8, associativity);
DEF_FIELD(23, 16, log2_cache_size);
DEF_FIELD(31, 24, external_bus_width);
static auto Get() { return magma::RegisterAddr<L2Features>(0x4); }
};
class TilerFeatures : public magma::RegisterBase {
public:
DEF_FIELD(5, 0, log2_bin_size_bytes);
DEF_FIELD(11, 8, max_active_levels);
static auto Get() { return magma::RegisterAddr<TilerFeatures>(0xc); }
};
class MemoryFeatures : public magma::RegisterBase {
public:
DEF_FIELD(1, 0, groups_l2_coherent);
DEF_FIELD(11, 8, num_l2_slices_minus1);
static auto Get() { return magma::RegisterAddr<MemoryFeatures>(0x10); }
};
class MmuFeatures : public magma::RegisterBase {
public:
DEF_FIELD(7, 0, va_bits);
DEF_FIELD(15, 8, pa_bits);
static auto Get() { return magma::RegisterAddr<MmuFeatures>(0x14); }
};
class ThreadFeatures : public magma::RegisterBase {
public:
DEF_FIELD(15, 0, max_registers);
DEF_FIELD(23, 16, max_task_queue);
DEF_FIELD(29, 24, max_thread_group_split);
DEF_FIELD(31, 30, impl_tech);
static auto Get() { return magma::RegisterAddr<ThreadFeatures>(0xac); }
};
class CoherencyFeatures : public magma::RegisterBase {
public:
// ACE-lite lets the GPU snoop on changes made by the CPU
DEF_BIT(0, ace_lite);
// ACE lets the GPU and CPU snoop on each other.
DEF_BIT(1, ace);
DEF_BIT(31, none);
static auto GetPresent() { return magma::RegisterAddr<CoherencyFeatures>(0x300); }
static auto GetEnable() { return magma::RegisterAddr<CoherencyFeatures>(0x304); }
};
class GpuStatus : public magma::RegisterBase {
public:
DEF_BIT(0, gpu_active);
DEF_BIT(1, power_active);
DEF_BIT(2, performance_counters_active);
DEF_BIT(6, cycle_count_active);
DEF_BIT(7, protected_mode_active);
static auto Get() { return magma::RegisterAddr<GpuStatus>(0x34); }
};
// May return incorrect value on rollover.
class CycleCount : public magma::RegisterPairBase {
public:
static auto Get() { return magma::RegisterAddr<CycleCount>(0x90); }
};
// May return incorrect value on rollover.
class Timestamp : public magma::RegisterPairBase {
public:
static auto Get() { return magma::RegisterAddr<Timestamp>(0x98); }
};
class GpuCommand {
public:
static constexpr uint32_t kOffset = 0x30;
enum {
kCmdNop = 0,
kCmdSoftReset = 0x1,
kCmdHardReset = 0x2,
kCmdClearPerformanceCounters = 0x3,
kCmdSamplePerformanceCounters = 0x4,
kCmdCycleCountStart = 0x5,
kCmdCycleCountStop = 0x6,
kCmdCleanCaches = 0x7,
kCmdCleanAndInvalidateCaches = 0x8,
kCmdSetProtectedMode = 0x9,
};
};
class GpuIrqFlags : public magma::RegisterBase {
public:
DEF_BIT(0, gpu_fault);
DEF_BIT(7, multiple_gpu_faults);
DEF_BIT(8, reset_completed);
DEF_BIT(9, power_changed_single);
DEF_BIT(10, power_changed_all);
DEF_BIT(16, performance_counter_sample_completed);
DEF_BIT(17, clean_caches_completed);
static auto GetRawStat() { return magma::RegisterAddr<GpuIrqFlags>(0x20); }
static auto GetIrqClear() { return magma::RegisterAddr<GpuIrqFlags>(0x24); }
static auto GetIrqMask() { return magma::RegisterAddr<GpuIrqFlags>(0x28); }
static auto GetStatus() { return magma::RegisterAddr<GpuIrqFlags>(0x2c); }
};
class MmuIrqFlags : public magma::RegisterBase {
public:
DEF_FIELD(15, 0, pf_flags);
DEF_FIELD(31, 16, bf_flags);
static auto GetRawStat() { return magma::RegisterAddr<MmuIrqFlags>(0x2000); }
static auto GetIrqClear() { return magma::RegisterAddr<MmuIrqFlags>(0x2004); }
static auto GetIrqMask() { return magma::RegisterAddr<MmuIrqFlags>(0x2008); }
static auto GetStatus() { return magma::RegisterAddr<MmuIrqFlags>(0x200c); }
};
class JobIrqFlags : public magma::RegisterBase {
public:
DEF_FIELD(15, 0, finished_slots);
DEF_FIELD(31, 16, failed_slots);
static auto GetRawStat() { return magma::RegisterAddr<JobIrqFlags>(0x1000); }
static auto GetIrqClear() { return magma::RegisterAddr<JobIrqFlags>(0x1004); }
static auto GetIrqMask() { return magma::RegisterAddr<JobIrqFlags>(0x1008); }
static auto GetStatus() { return magma::RegisterAddr<JobIrqFlags>(0x100c); }
};
class ShaderConfig : public magma::RegisterBase {
public:
DEF_BIT(16, ls_allow_attr_types);
DEF_BIT(17, tls_hashing_enable);
static auto Get() { return magma::RegisterAddr<ShaderConfig>(0xf04); }
};
// Not legal to write to while the performance counters are enabled.
class PerformanceCounterBase : public magma::RegisterPairBase {
public:
static auto Get() { return magma::RegisterAddr<PerformanceCounterBase>(0x60); }
};
class PerformanceCounterConfig : public magma::RegisterBase {
public:
enum Mode {
kModeDisabled = 0,
kModeManual = 1,
};
DEF_FIELD(3, 0, mode);
DEF_FIELD(7, 4, address_space);
static auto Get() { return magma::RegisterAddr<PerformanceCounterConfig>(0x68); }
};
// Not legal to write to while the performance counters are enabled.
class PerformanceCounterJmEnable : public magma::RegisterBase {
public:
static auto Get() { return magma::RegisterAddr<PerformanceCounterJmEnable>(0x6c); }
};
// Not legal to write to while the performance counters are enabled.
class PerformanceCounterShaderEnable : public magma::RegisterBase {
public:
static auto Get() { return magma::RegisterAddr<PerformanceCounterShaderEnable>(0x70); }
};
// Not legal to write to while the performance counters are enabled.
class PerformanceCounterTilerEnable : public magma::RegisterBase {
public:
static auto Get() { return magma::RegisterAddr<PerformanceCounterTilerEnable>(0x74); }
};
// Not legal to write to while the performance counters are enabled.
class PerformanceCounterMmuL2Enable : public magma::RegisterBase {
public:
static auto Get() { return magma::RegisterAddr<PerformanceCounterMmuL2Enable>(0x7c); }
};
class CoreReadyState {
public:
enum class CoreType {
kShader = 0x100,
kL2 = 0x120,
kTiler = 0x110,
kCoreStack = 0xe00,
};
enum class StatusType {
// Read-only: the set of cores that are physically present in the
// device.
kPresent = 0,
// Read-only: the set of cores that are powered on and ready to do
// work.
kReady = 0x40,
// Read-only: the set of cores that are changing power states.
kPowerTransitioning = 0x100,
// Read-only: the set of cores that are currently executing work.
kPowerActive = 0x140,
};
enum class ActionType {
// Write-only: power on the specified set of cores.
kActionPowerOn = 0x80,
// Write-only: power off the specified set of cores.
kActionPowerOff = 0xc0,
};
// Returns a bitmask of the cores in a specified state.
static uint64_t ReadBitmask(magma::RegisterIo* register_io, CoreType core_type,
StatusType action_type)
{
DASSERT(core_type != CoreType::kCoreStack);
uint32_t offset = static_cast<uint32_t>(core_type) + static_cast<uint32_t>(action_type);
return register_io->Read32(offset) |
(static_cast<uint64_t>(register_io->Read32(offset + 4)) << 32);
}
static void WriteState(magma::RegisterIo* register_io, enum CoreType core_type,
enum ActionType action_type, uint64_t value)
{
uint32_t offset = static_cast<uint32_t>(core_type) + static_cast<uint32_t>(action_type);
uint32_t value_low = value & 0xffffffff;
uint32_t value_high = (value >> 32) & 0xffffffff;
if (value_low)
register_io->Write32(offset, value_low);
if (value_high)
register_io->Write32(offset + 4, value_high);
}
};
class GpuFaultStatus : public magma::RegisterBase {
public:
static auto Get() { return magma::RegisterAddr<GpuFaultStatus>(0x3c); }
};
class GpuFaultAddress : public magma::RegisterPairBase {
public:
static auto Get() { return magma::RegisterAddr<GpuFaultAddress>(0x40); }
};
class AsTranslationTable : public magma::RegisterPairBase {
public:
static constexpr uint32_t kBaseAddr = 0x0;
};
class AsMemoryAttributes : public magma::RegisterPairBase {
public:
static constexpr uint32_t kBaseAddr = 0x8;
};
class AsLockAddress : public magma::RegisterPairBase {
public:
static constexpr uint32_t kBaseAddr = 0x10;
};
class AsCommand : public magma::RegisterBase {
public:
static constexpr uint32_t kBaseAddr = 0x18;
enum {
kCmdNop = 0x0,
kCmdUpdate = 0x1,
kCmdLock = 0x2,
kCmdUnlock = 0x3,
kCmdFlush = 0x4,
kCmdFlushPageTable = 0x4,
kCmdFlushMem = 0x5
};
};
class AsFaultStatus : public magma::RegisterBase {
public:
static constexpr uint32_t kBaseAddr = 0x1c;
};
class AsFaultAddress : public magma::RegisterPairBase {
public:
static constexpr uint32_t kBaseAddr = 0x20;
};
class AsStatus : public magma::RegisterBase {
public:
static constexpr uint32_t kBaseAddr = 0x28;
};
class AsTransConfig : public magma::RegisterPairBase {
public:
static constexpr uint32_t kBaseAddr = 0x30;
};
class AsFaultExtra : public magma::RegisterPairBase {
public:
static constexpr uint32_t kBaseAddr = 0x30;
};
class AsRegisters {
public:
static constexpr uint32_t kBaseAddr = 0x2400;
static constexpr uint32_t kAsStride = 0x40;
// Maximum registers.
static constexpr uint32_t kAddressSpacesCount = 16;
AsRegisters(uint32_t address_space) : address_space_(address_space)
{
DASSERT(address_space < kAddressSpacesCount);
}
uint32_t address_space() const { return address_space_; }
auto TranslationTable() { return GetReg<registers::AsTranslationTable>(); }
auto MemoryAttributes() { return GetReg<registers::AsMemoryAttributes>(); }
auto LockAddress() { return GetReg<registers::AsLockAddress>(); }
auto Command() { return GetReg<registers::AsCommand>(); }
auto FaultStatus() { return GetReg<registers::AsFaultStatus>(); }
auto FaultAddress() { return GetReg<registers::AsFaultAddress>(); }
auto Status() { return GetReg<registers::AsStatus>(); }
auto TransConfig() { return GetReg<registers::AsTransConfig>(); }
auto FaultExtra() { return GetReg<registers::AsFaultExtra>(); }
private:
template <class RegType> magma::RegisterAddr<RegType> GetReg()
{
return magma::RegisterAddr<RegType>(RegType::kBaseAddr + kBaseAddr +
kAsStride * address_space_);
}
uint32_t address_space_;
};
class JobSlotConfig : public magma::RegisterBase {
public:
static constexpr uint32_t kBaseAddr = 0x18;
static constexpr uint32_t kBaseAddrNext = 0x58;
DEF_FIELD(7, 0, address_space);
DEF_BIT(8, start_flush_clean);
DEF_BIT(9, start_flush_invalidate);
DEF_BIT(10, start_mmu);
DEF_BIT(11, job_chain_flag);
DEF_BIT(12, end_flush_clean);
DEF_BIT(13, end_flush_invalidate);
DEF_BIT(14, enable_flush_reduction);
DEF_BIT(15, disable_descriptor_write_back);
DEF_FIELD(23, 16, thread_priority);
};
class JobSlotHead : public magma::RegisterPairBase {
public:
static constexpr uint32_t kBaseAddr = 0x00;
static constexpr uint32_t kBaseAddrNext = 0x40;
};
class JobSlotAffinity : public magma::RegisterPairBase {
public:
static constexpr uint32_t kBaseAddr = 0x10;
static constexpr uint32_t kBaseAddrNext = 0x50;
};
class JobSlotXAffinity : public magma::RegisterBase {
public:
static constexpr uint32_t kBaseAddr = 0x1c;
static constexpr uint32_t kBaseAddrNext = 0x5c;
};
class JobSlotCommand : public magma::RegisterBase {
public:
static constexpr uint32_t kCommandNop = 0x0;
static constexpr uint32_t kCommandStart = 0x1;
static constexpr uint32_t kCommandSoftStop = 0x2;
static constexpr uint32_t kCommandHardStop = 0x3;
static constexpr uint32_t kCommandSoftStop_0 = 0x4;
static constexpr uint32_t kCommandHardStop_0 = 0x5;
static constexpr uint32_t kCommandStopStop_1 = 0x6;
static constexpr uint32_t kCommandHardStop_1 = 0x7;
static constexpr uint32_t kBaseAddr = 0x20;
static constexpr uint32_t kBaseAddrNext = 0x60;
};
class JobSlotStatus : public magma::RegisterBase {
public:
static constexpr uint32_t kBaseAddr = 0x24;
};
class JobSlotTail : public magma::RegisterPairBase {
public:
static constexpr uint32_t kBaseAddr = 0x08;
};
class JobSlotFlushId : public magma::RegisterBase {
public:
static constexpr uint32_t kBaseAddrNext = 0x70;
};
class JobSlotRegisters {
public:
static constexpr uint32_t kBaseAddr = 0x1000 + 0x800;
static constexpr uint32_t kJobSlotStride = 0x80;
// Maximum registers - actual hardware provides fewer.
static constexpr uint32_t kJobSlotsCount = 16;
JobSlotRegisters(uint32_t job_slot) : job_slot_(job_slot)
{
DASSERT(job_slot < kJobSlotsCount);
}
// These registers are for the currently executing job.
auto Head() { return GetReg<registers::JobSlotHead>(); }
auto Tail() { return GetReg<registers::JobSlotTail>(); }
auto Status() { return GetReg<registers::JobSlotStatus>(); }
auto Config() { return GetReg<registers::JobSlotConfig>(); }
auto Affinity() { return GetReg<registers::JobSlotAffinity>(); }
auto XAffinity() { return GetReg<registers::JobSlotXAffinity>(); }
auto Command() { return GetReg<registers::JobSlotCommand>(); }
// These registers are for the next job to execute. It can start executing
// once the start command is sent.
auto HeadNext() { return GetRegNext<registers::JobSlotHead>(); }
auto ConfigNext() { return GetRegNext<registers::JobSlotConfig>(); }
auto AffinityNext() { return GetRegNext<registers::JobSlotAffinity>(); }
auto XAffinityNext() { return GetRegNext<registers::JobSlotXAffinity>(); }
auto CommandNext() { return GetRegNext<registers::JobSlotCommand>(); }
private:
template <class RegType> magma::RegisterAddr<RegType> GetRegNext()
{
return magma::RegisterAddr<RegType>(RegType::kBaseAddrNext + kBaseAddr +
kJobSlotStride * job_slot_);
}
template <class RegType> magma::RegisterAddr<RegType> GetReg()
{
return magma::RegisterAddr<RegType>(RegType::kBaseAddr + kBaseAddr +
kJobSlotStride * job_slot_);
}
uint32_t job_slot_;
};
} // namespace registers
#endif // REGISTERS_H