blob: dcb9c308f30eb75617bee418e7d398886288ca5b [file] [log] [blame]
// Copyright 2023 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 SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_REGISTERS_MEMORY_CONTROLLER_H_
#define SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_REGISTERS_MEMORY_CONTROLLER_H_
#include <zircon/assert.h>
#include <algorithm>
#include <cstdint>
#include <hwreg/bitfields.h>
#include "src/graphics/display/drivers/intel-i915/hardware-common.h"
namespace registers {
// The registers of the processor's memory controller are exposed via MMIO in
// the MCHBAR (Memory Controller Hub Base Address Range). This header only
// covers the registers that are relevant to the display engine's operation.
//
// The memory controller registers are typically documented in Volume 2 of the
// respective processor's datasheet. This header references the following
// documents.
//
// Raptor Lake: 13th Generation Intel Core Processor Datasheet, Volume 2 of 2,
// document 743846-001
// Alder Lake S: 12th Generation Intel Core Processors Datasheet, Volume 2 of 2,
// document 655259-003
// Alder Lake H: 12th Generation Intel Core Processors Datasheet, Volume 2 of 2,
// document 710723-003
// Rocket Lake: 11th Generation Intel Core Processor Datasheet, Volume 2 of 2,
// document 636761-004
// Tiger Lake U: 11th Generation Intel Core Processors Datasheet,
// Volume 2a of 2, document 631122-003
// Tiger Lake H: 11th Generation Intel Core Processors Datasheet,
// Volume 2b of 2, document 643524-003
// Ice Lake: 10th Generation Intel Processor Families Datasheet, Volume 2 of 2,
// document 341078-004
// Comet Lake: 10th Generation Intel Processor Families Datasheet,
// Volume 2 of 2, document 615212-003
// Coffee Lake: 8th and 9th Generation Intel Core Processor Families and Intel
// Xeon E Processor Family Datasheet, Volume 2 of 2,
// document 337345-003
// Whiskey Lake: 8th Generation Intel Core Processor Families Datasheet,
// Volume 2 of 2, document 338024-001
// Amber Lake: 7th Generation Intel Processor Families for U/Y Platforms and 8th
// Generation Intel Processor Family for U Quad Core Datasheet,
// Volume 2 of 2, document 334662-005
// Kaby Lake S: 7th Generation Intel Processor Families for S Platforms and
// Intel Core X-Series Processor Family Datasheet, Volume 2 of 2,
// document 335196-002
// Kaby Lake H: 7th Generation Intel Processor Families for H Platforms
// Datasheet, Volume 2 of 2, document 335191-003
// Skylake U: 6th Generation Intel Processor Families for U/Y Platforms
// Datasheet, Volume 2 of 2, document 332991-003
// Skylake S: 6th Generation Intel Processor Datasheet for S-Platforms
// Datasheet – Volume 2 of 2, document 332688-003
// Skylake H: 6th Generation Intel® Processor Families for H Platforms
// Datasheet, Volume 2 of 2, document 332987-003
//
// Many processor datasheets are listed at
// https://www.intel.com/content/www/us/en/products/docs/processors/core/core-technical-resources.html
// MCHBAR (Memory Controller Hub Base Address Range) Aperture
//
// A subset of the memory controller's MMIO address space is mirrored in the
// graphics MMIO space, so the graphics drivers can conveniently read DRAM
// configuration information.
//
// This aperture is documented in a "GFX MMIO – MCHBAR Aperture" section in most
// recent PRMs. While the section is missing from the Tiger Lake PRMs, we have
// experimentally confirmed that the aperture still works.
//
// Lakefield: IHD-OS-LKF-Vol 13-4.21, page 9
// Ice Lake: IHD-OS-ICLLP-Vol 13-1.20, page 9
// Kaby Lake: IHD-OS-KBL-Vol 5-1.17, page 2
// Skylake: IHD-OS-SKL-Vol 5-05.16, page 2
constexpr uint32_t kMemoryControllerBarMirrorOffset = 0x140'000;
// TC_PRE_0_0_0_MCHBAR (PRE Command Timing)
//
// Raptor Lake: 743846-001 Section 3.2.70 pages 143-144
// Alder Lake S: 655259-003 Section 3.2.66 pages 126-127
// Alder Lake H: 710723-003 Section 3.2.66 pages 155-156
class MemoryChannelTimingsAlderLake
: public hwreg::RegisterBase<MemoryChannelTimingsAlderLake, uint64_t> {
public:
DEF_RSVDZ_BIT(63);
// Value added to DRAM timings when the LPDDR dimm is hot.
//
// This field must be zero for non-LP (Low-Power) DDR.
DEF_FIELD(62, 59, derating_extensions);
// tRCD DDR timing parameter.
//
// The minimum delay between ACT and CAS in the same bank.
//
// On LPDDR5x, this delay only applies to RD (read) CAS, and the minimum delay
// between ACT and WR (write) CAS is specified separately the `t_rcdw` field.
// On other technologies, this delay applies to both RD and WR.
DEF_FIELD(58, 51, t_rcd);
// tRAS DDR timing parameter.
//
// The minimum delay between ACT and PRE in the same bank.
DEF_FIELD(50, 42, t_ras);
// tWRPRE DDR timing parameter.
//
// The minimum delay between WR and PRE in the same bank.
DEF_FIELD(41, 32, t_wrpre);
// t_RCDW DDR timing parameter.
//
// The minimum delay between ACT and CAS WR in the same bank. This delay is
// only relevant in LPDDR5x configurations.
DEF_FIELD(31, 24, t_rcdw);
// tPPD DDR timing parameter.
//
// The minimum delay between PRE/PREALL commands in the same rank.
//
// This field is not used in DDR5 configurations.
DEF_FIELD(23, 20, t_ppd);
// tRDPRE DDR timing parameter.
//
// The minimum delay between RD and PRE commands in the same bank.
DEF_FIELD(19, 13, t_rdpre);
// tRPab - tRBpb LPDDR timing parameter value.
//
// The difference between the minimum delay between PREALL and ACT and the
// minimum delay between PRE and ACT. Must be zero for DDR, because only LPDDR
// allows this difference.
DEF_FIELD(12, 8, t_rpab_ext);
// tRP DDR timing parameter.
//
// The minimum delay between PRE and ACT in the same bank.
DEF_FIELD(7, 0, t_rp);
static auto GetForControllerAndChannel(int memory_controller_index, int channel_index) {
// The MMIO offsets for the 2nd memory channel and controller are documented
// in the "[Processor] Memory Controller (MCHBAR) Registers" section of the
// Volume 2 in the processor datasheets.
//
// Raptor Lake: 743846-001 Section 3.2 pages 99-100
// Alder Lake S: 655259-003 Section 3.2 pages 83-34
// Alder Lake H: 710723-003 Section 3.2 pages 112-113
ZX_ASSERT(memory_controller_index >= 0);
ZX_ASSERT(memory_controller_index <= 1);
ZX_ASSERT(channel_index >= 0);
ZX_ASSERT(channel_index <= 1);
return hwreg::RegisterAddr<MemoryChannelTimingsAlderLake>(
kMemoryControllerBarMirrorOffset + 0xe000 + 0x10000 * memory_controller_index +
0x800 * channel_index);
}
};
// TC_PRE_0_0_0_MCHBAR (PRE Command Timing)
//
// See `MemoryChannelTimingsAlderLake` for field semantics.
//
// Tiger Lake U: 631122-003 Section 3.2.2 pages 110-111
// Tiger Lake H: 643524-003 Section 3.2.24 pages 128-129
class MemoryChannelTimingsTigerLake
: public hwreg::RegisterBase<MemoryChannelTimingsTigerLake, uint64_t> {
public:
DEF_RSVDZ_FIELD(63, 48);
DEF_FIELD(47, 41, t_rcd);
DEF_FIELD(40, 33, t_ras);
DEF_RSVDZ_FIELD(32, 30);
DEF_FIELD(29, 21, t_wrpre);
DEF_FIELD(20, 17, t_ppd);
DEF_FIELD(16, 11, t_rdpre);
DEF_FIELD(10, 7, t_rpab_ext);
DEF_FIELD(6, 0, t_rp);
// For Tiger Lake U and H35 SKUs.
//
// `memory_controller_index` and `channel_index` are 0-based.
static auto GetForUControllerAndChannel(int memory_controller_index, int channel_index) {
// The MMIO offsets for the 2nd memory channel and controller are documented
// in the "[Processor] Memory Controller (MCHBAR) Registers" section of the
// Volume 2 in the processor datasheets.
//
// Tiger Lake U: 631122-003 Section 3.2 pages 106-107
ZX_ASSERT(memory_controller_index >= 0);
ZX_ASSERT(memory_controller_index <= 1);
ZX_ASSERT(channel_index >= 0);
ZX_ASSERT(channel_index <= 1);
return hwreg::RegisterAddr<MemoryChannelTimingsTigerLake>(
kMemoryControllerBarMirrorOffset + 0x4000 + 0x10000 * memory_controller_index +
0x400 * channel_index);
}
// For Tiger Lake H SKUs.
//
// `memory_controller_index` and `channel_index` are 0-based.
static auto GetForHControllerAndChannel(int memory_controller_index, int channel_index) {
// The MMIO offsets for the 2nd memory channel and controller are documented
// in the "[Processor] Memory Controller (MCHBAR) Registers" section of the
// Volume 2 in the processor datasheets.
//
// Tiger Lake H: 643524-003 Section 3.2 pages 110-111
ZX_ASSERT(memory_controller_index >= 0);
ZX_ASSERT(memory_controller_index <= 1);
ZX_ASSERT(channel_index >= 0);
ZX_ASSERT(channel_index <= 1);
return hwreg::RegisterAddr<MemoryChannelTimingsTigerLake>(
kMemoryControllerBarMirrorOffset + 0xe000 + 0x10000 * memory_controller_index +
0x800 * channel_index);
}
};
// TC_PRE_0_0_0_MCHBAR (PRE Command Timing)
//
// See `MemoryChannelTimingsAlderLake` for field semantics.
//
// Rocket Lake: 636761-004 Section 3.2.2 pages 98-99
// Ice Lake: 341078-004 Section 3.2.2 pages 101-102
class MemoryChannelTimingsIceLake
: public hwreg::RegisterBase<MemoryChannelTimingsIceLake, uint32_t> {
public:
DEF_FIELD(31, 24, t_wrpre);
DEF_FIELD(23, 21, t_ppd);
DEF_FIELD(20, 16, t_rdpre);
DEF_FIELD(15, 9, t_ras);
DEF_FIELD(8, 6, t_rpab_ext);
// tRCD and tRP DDR timing parameters.
DEF_FIELD(5, 0, t_rp_rcd);
// `channel_index` is 0-based.
static auto GetForChannel(int channel_index) {
// The MMIO offsets for the 2nd memory channel are documented in the
// "[Processor] Memory Controller (MCHBAR) Registers" section of the Volume
// 2 in the processor datasheets.
//
// Rocket Lake: 636761-004 Section 3.2 page 96
// Ice Lake: 341078-004 Section 3.2 pages 99-100
ZX_ASSERT(channel_index >= 0);
ZX_ASSERT(channel_index <= 1);
return hwreg::RegisterAddr<MemoryChannelTimingsIceLake>(kMemoryControllerBarMirrorOffset +
0x4000 + 0x400 * channel_index);
}
};
// TC_PRE_0_0_0_MCHBAR (PRE Command Timing)
//
// See `MemoryChannelTimingsAlderLake` for field semantics.
//
// In older documentation, this register's instances are documented as
// MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR and MCHBAR_CH1_CR_TC_PRE_0_0_0_MCHBAR.
//
// Comet Lake: 615212-003 Section 7.1 pages 147-148
// Coffee Lake: 337345-003 Section 7.1 page 158
// Whiskey Lake: 338024-001 Section 7.1 pages 144-145
// Amber Lake: 334662-005 Section 6.1 pages 123-124
// Kaby Lake S: 335196-002 Section 7.1 pages 155-156
// Kaby Lake H: 335191-003 Section 7.1 pages 160-161
// Skylake U: 332991-003 Section 7.1 pages 157-158
// Skylake S: 332688-003 Section 7.1 page 146
// Skylake H: 332987-003 Section 7.1 pages 157-158
class MemoryChannelTimingsSkylake
: public hwreg::RegisterBase<MemoryChannelTimingsSkylake, uint32_t> {
public:
DEF_FIELD(30, 24, t_wrpre);
DEF_FIELD(19, 16, t_rdpre);
DEF_FIELD(14, 8, t_ras);
DEF_FIELD(7, 6, t_rpab_ext);
// tRCD and tRP DDR timing parameters.
DEF_FIELD(5, 0, t_rp_rcd);
// `channel_index` is 0-based.
static auto GetForChannel(int channel_index) {
// The 2nd memory channel MMIO offset is documented in the "[Processor]
// Memory Controller (MCHBAR) Registers" section of the Volume 2 in more
// recent processor datasheets.
//
// Comet Lake: 615212-003 Section 7 page 146
// Whiskey Lake: 338024-001 Section 7 page 142
//
// In older processor datasheets, the 2nd memory channel offsets are only
// documented implicitly, by the presence of registers such as
// MCHBAR_CH1_CR_TC_PRE_0_0_0_MCHBAR.
//
// Coffee Lake: 337345-003 Section 7.13 page 170
// Amber Lake: 334662-005 Section 6.11 page 134
// Kaby Lake S: 335196-002 Section 7.11 page 166
// Kaby Lake H: Section 7.13 page 172
// Skylake U: 332991-003 Section 7.11 pages 167-168
// Skylake S: 332688-003 Section 7.11 page 154
// Skylake H: 332987-003 Section 7.11 pages 167-168
ZX_ASSERT(channel_index >= 0);
ZX_ASSERT(channel_index <= 1);
return hwreg::RegisterAddr<MemoryChannelTimingsSkylake>(kMemoryControllerBarMirrorOffset +
0x4000 + 0x400 * channel_index);
}
};
// MAD_INTER_CHANNEL_0_0_0_MCHBAR (Inter-Channel Decode Parameters).
//
// Raptor Lake: 743846-001 Section 3.2.46 pages 126-127
// Alder Lake S: 655259-003 Section 3.2.42 pages 107-108
// Alder Lake H: 710723-003 Section 3.2.42 pages 136-137
// Rocket Lake: 636761-004 Section 3.2.36 pages 125-126
// Tiger Lake U: 631122-003 Section 3.2.38 pages 139-140
// Tiger Lake H: 643524-003 Section 3.2.6 pages 115-116
// Ice Lake: 341078-004 Section 3.2.35 pages 128-129
class MemoryAddressDecoderInterChannelConfigIceLake
: public hwreg::RegisterBase<MemoryAddressDecoderInterChannelConfigIceLake, uint32_t> {
public:
// Documented values for `channel_width_select`.
enum class ChannelWidthTigerLakeValue {
kX16 = 0b00,
kX32 = 0b01,
kX64 = 0b10,
kReserved = 0b11,
};
// Documented values for `ddr_type_select`.
enum class DdrTypeValue {
kDoubleDataRam4 = 0, // DDRAM 4
kDoubleDataRam5 = 1, // DDRAM 5
kLowPowerDoubleDataRam5 = 2, // LPDDRAM5
kLowPowerDoubleDataRam4 = 3, // LPDDRAM4
};
// If true, the memory controller operates on 32-byte requests.
//
// By default, the memory controller operates on 64-byte cache lines.
//
// This field is not defined on some platforms (Rocket Lake, Ice Lake, Comet
// Lake). The underlying bit is reserved MBZ (must be zero). This results in
// correct read semantics, as the feature appears disabled on these platforms.
DEF_BIT(31, half_cacheline_mode_enabled);
DEF_RSVDZ_FIELD(30, 29);
// This field is not documented on some platforms (Ice Lake, Comet Lake). The
// underlying bits are MBZ (must be zero).
DEF_ENUM_FIELD(ChannelWidthTigerLakeValue, 28, 27, channel_width_select_tiger_lake);
DEF_RSVDZ_FIELD(26, 20);
// The size of Channel S in 512MB units.
//
// Valid values are 0-128.
DEF_FIELD(19, 12, channel_s_size_512);
DEF_RSVDZ_FIELD(11, 5);
// If false, Channel L is the physical channel 0.
DEF_BIT(4, channel_l_is_physical_channel1);
// If true, the channel operates as two 32-bit channels.
//
// This field should only be set to true in LPDDR4 configurations. By default,
// LPDDR4 has a single 64-bit channel.
//
// This bit is reserved MBZ (must be zero) on some platforms (Raptor Lake,
// Alder Lake, Tiger Lake). This gives us the right read semantics, as the
// feature appears disabled on these platforms.
DEF_BIT(3, enhanced_channel_mode);
// The type of DDR memory installed in the system.
DEF_ENUM_FIELD(DdrTypeValue, 2, 0, ddr_type_select);
// For Rocket Lake, Tiger Lake U/H35, and Ice Lake.
//
// `memory_controller_index` is 0-based. Rocket Lake and Ice Lake processors
// have a single memory controller.
static auto GetForController(int memory_controller_index) {
// The MMIO offsets for 2nd memory controller are documented in the
// "[Processor] Memory Controller (MCHBAR) Registers" section of the Volume
// 2 in the processor datasheets.
//
// Rocket Lake: 636761-004 Section 3.2 page 96 (no 2nd memory controller)
// Tiger Lake U: 631122-003 Section 3.2 pages 106-107
// Ice Lake: 341078-004 Section 3.2 pages 99-100 (no 2nd memory controller)
ZX_ASSERT(memory_controller_index >= 0);
ZX_ASSERT(memory_controller_index <= 1);
return hwreg::RegisterAddr<MemoryAddressDecoderInterChannelConfigIceLake>(
kMemoryControllerBarMirrorOffset + 0x5000 + 0x10000 * memory_controller_index);
}
// For Raptor Lake, Alder Lake, and Tiger Lake H.
//
// `memory_controller_index` is 0-based
static auto GetForAlderLakeController(int memory_controller_index) {
// The MMIO offsets for 2nd memory controller are documented in the
// "[Processor] Memory Controller (MCHBAR) Registers" section of the Volume
// 2 in the processor datasheets.
//
// Raptor Lake: 743846-001 Section 3.2 pages 99-100
// Alder Lake S: 655259-003 Section 3.2 pages 83-34
// Alder Lake H: 710723-003 Section 3.2 pages 112-113
// Tiger Lake H: 643524-003 Section 3.2 pages 110-111
ZX_ASSERT(memory_controller_index >= 0);
ZX_ASSERT(memory_controller_index <= 1);
return hwreg::RegisterAddr<MemoryAddressDecoderInterChannelConfigIceLake>(
kMemoryControllerBarMirrorOffset + 0xd800 + 0x10000 * memory_controller_index);
}
};
// MAD_INTER_CHANNEL_0_0_0_MCHBAR (Address decoder inter channel configuration).
//
// Comet Lake: 615212-003 Section 8.33 pages 191-192
// Coffee Lake: 337345-003 Section 7.37 page 193
// Whiskey Lake: 338024-001 Section 7.10 page 153
// Amber Lake: 334662-005 Section 6.31 page 154
// Kaby Lake S: 335196-002 Section 7.31 page 186
// Kaby Lake H: 335191-003 Section 7.37 page 195
// Skylake U: 332991-003 Section 7.31 page 187
// Skylake S: 332688-003 Section 7.31 page 169
// Skylake H: 332987-003 Section 7.31 page 187
class MemoryAddressDecoderInterChannelConfigSkylake
: public hwreg::RegisterBase<MemoryAddressDecoderInterChannelConfigSkylake, uint32_t> {
public:
// Documented values for `ddr_type_select`.
enum class DdrTypeValue {
kDoubleDataRam4 = 0b000, // DDR4
kDoubleDataRam3 = 0b011, // DDR3
kLowPowerDoubleDataRam3 = 0b010, // LPDDR3
kLowPowerDoubleDataRam4 = 0b011, // LPDDR4, reserved before Comet Lake
};
DEF_RSVDZ_FIELD(31, 29);
// True if the attached memory is DDR4-E.
//
// This bit should be zero if `ddr_type_select` does not indicate DDR4.
//
// This bit is only defined on Comet Lake, and is reserved MBZ (must be zero)
// on all other platforms. This gives us the right read semantics, as the
// feature appears disabled on these platforms.
DEF_BIT(28, uses_ddr4e_memory);
DEF_RSVDZ_FIELD(27, 19);
// The size of Channel S in 1GB units.
//
// Valid values are 0-64.
//
// This field value is does not match the Comet Lake datasheet. Comet Lake
// memory controllers use the field layout in the
// `MemoryAddressDecoderInterChannelConfigIceLake` class. `channel_s_size`
// uses bits 19:12 and expresses the channel size in multiples of 512 MB. See
// `ddr_type_select` for why we use this class for Comet Lake.
DEF_FIELD(18, 12, channel_s_size_1gb);
DEF_RSVDZ_FIELD(11, 5);
// If false, Channel L is the physical channel 0.
DEF_BIT(4, channel_l_is_physical_channel1);
// If true, the channel operates as two 32-bit channels.
//
// This bit must be true in LPDDR4 configurations, and can be set to
// true for LPDDR3. In all other configurations, this bit must be false.
//
// This bit is only defined on Comet Lake, and is reserved MBZ (must be zero)
// on all other platforms. This gives us the right read semantics, as the
// feature appears disabled on these platforms.
DEF_BIT(3, enhanced_channel_mode);
// The type of DDR memory installed in the system.
//
// Bit 2 only belongs to this field on Comet Lake. On other platforms, bit 2
// is reserved MBZ (must be zero). This gives us the right read semantics,
// because all documented DDR type values have bit 2 set to zero.
//
// Comet Lake memory controllers use the DDR type values documented here, in
// `DdrTypeValue`. This is the main reason we use this class for Comet Lake,
// instead of `MemoryAddressDecoderInterChannelConfigIceLake`.
DEF_ENUM_FIELD(DdrTypeValue, 2, 0, ddr_type_select);
static auto Get() {
return hwreg::RegisterAddr<MemoryAddressDecoderInterChannelConfigSkylake>(
kMemoryControllerBarMirrorOffset + 0x5000);
}
};
// MAD_DIMM_CH0_0_0_0_MCHBAR (Channel 0 DIMM Characteristics)
// MAD_DIMM_CH1_0_0_0_MCHBAR (Channel 1 DIMM Characteristics)
//
// Raptor Lake: 743846-001 Sections 3.2.49-3.2.50 pages 128-130
// Alder Lake S: 655259-003 Sections 3.2.45-3.2.46 pages 110-112
// Alder Lake H: 710723-003 Sections 3.2.45-3.2.46 pages 136-137
class MemoryAddressDecoderDimmParametersAlderLake
: public hwreg::RegisterBase<MemoryAddressDecoderDimmParametersAlderLake, uint32_t> {
public:
enum class DdrChipWidthValue {
kX8 = 0b00,
kX16 = 0b01,
kX32 = 0b10,
kReserved = 0b11,
};
// If true, XaB (extended bank hashing B) is enabled in the address decoder.
DEF_BIT(31, enable_extended_bank_hashing_b);
// If true, XbB (extended bank hashing A) is enabled in the address decoder.
DEF_BIT(30, enable_extended_bank_hashing_a);
// Selects how zone address bits feed into BG and CAS bits.
//
// This field's value influences the computation of BG0/1 (Bank Group bits 0
// and 1) and CAS5/6 (column address bits 5 and 6). The address computation
// depends on the DDR type and the value in this field.
DEF_FIELD(29, 28, bank_group_bit_options);
// The number of ranks in DIMM S. 0 = 1 rank, ... 3 = 4 ranks.
//
// Values above 1 (2 ranks) are not valid for for DIMM S.
DEF_FIELD(27, 26, dimm_s_rank_count_minus_1);
// The DDR chip width for DIMM S.
DEF_ENUM_FIELD(DdrChipWidthValue, 25, 24, dimm_s_ddr_chip_width_select);
DEF_RSVDZ_BIT(23);
// Size of DIMM S in multiples of 0.5 GB (512 MB).
DEF_FIELD(22, 16, dimm_s_size_512mb);
DEF_RSVDZ_FIELD(15, 13);
// If false, DIMM L capacity exceeds 8GB.
//
// This bit must be false for non-DDR5 configurations.
DEF_BIT(12, ddr5_dimm_l_capacity_is_8gb);
// If false, DIMM S capacity exceeds 8GB.
//
// This bit must be false for non-DDR5 configurations.
DEF_BIT(11, ddr5_dimm_s_capacity_is_8gb);
// The number of ranks in DIMM L. 0 = 1 rank, 1 = 2 ranks ... 3 = 4 ranks.
//
// Values above 1 (2 ranks) are only valid in ERM (Enhanced Rank Mode).
DEF_FIELD(10, 9, dimm_l_rank_count_minus_1);
DEF_ENUM_FIELD(DdrChipWidthValue, 8, 7, dimm_l_ddr_chip_width_select);
// Size of DIMM L in multiples of 0.5 GB (512 MB).
DEF_FIELD(6, 0, dimm_l_size_512mb);
// The width of the DDR chips in DIMM S.
int dimm_s_ddr_chip_width() const {
return DdrChipWidthValueToInteger(dimm_s_ddr_chip_width_select());
}
// The width of the DDR chips in DIMM L.
int dimm_l_ddr_chip_width() const {
return DdrChipWidthValueToInteger(dimm_l_ddr_chip_width_select());
}
// The number of ranks in DIMM S.
int dimm_s_rank_count() const {
// The cast and the addition will not overflow (causing UB) because the
// underlying field is a 2-bit integer.
return static_cast<int>(dimm_s_rank_count_minus_1()) + 1;
}
// The number of ranks in DIMM L.
int dimm_l_rank_count() const {
// The cast and the addition will not overflow (causing UB) because the
// underlying field is a 2-bit integer.
return static_cast<int>(dimm_l_rank_count_minus_1()) + 1;
}
// The size of DIMM S, in MB.
int dimm_s_size_mb() const {
// The cast and the multiplication will not overflow (causing UB) because
// the underlying field is a 7-bit integer.
return static_cast<int>(dimm_s_size_512mb()) * 512;
}
// The size of DIMM L, in MB.
int dimm_l_size_mb() const {
// The cast and the multiplication will not overflow (causing UB) because
// the underlying field is a 7-bit integer.
return static_cast<int>(dimm_l_size_512mb()) * 512;
}
static auto GetForControllerAndChannel(int memory_controller_index, int channel_index) {
ZX_ASSERT(memory_controller_index >= 0);
ZX_ASSERT(memory_controller_index <= 1);
ZX_ASSERT(channel_index >= 0);
ZX_ASSERT(channel_index <= 1);
return hwreg::RegisterAddr<MemoryAddressDecoderDimmParametersAlderLake>(
kMemoryControllerBarMirrorOffset + 0xd80c + 0x10000 * memory_controller_index +
4 * channel_index);
}
private:
static int DdrChipWidthValueToInteger(DdrChipWidthValue value) {
return 8 << static_cast<int>(value);
}
};
// MAD_DIMM_CH0_0_0_0_MCHBAR (Channel 0 DIMM Characteristics)
// MAD_DIMM_CH1_0_0_0_MCHBAR (Channel 1 DIMM Characteristics)
//
// Rocket Lake: 636761-004 Sections 3.2.39-3.2.40 pages 128-129
// Tiger Lake U: 631122-003 Sections 3.2.41-3.2.42 pages 141-143
// Tiger Lake H: 643524-003 Sections 3.2.9-3.2.10 pages 117-119
// Ice Lake: 341078-004 Sections 3.2.38-3.2.39 pages 131-132
// Comet Lake: 615212-003 Sections 8.36-8.37 pages 194-196
class MemoryAddressDecoderDimmParametersCometLake
: public hwreg::RegisterBase<MemoryAddressDecoderDimmParametersCometLake, uint32_t> {
public:
enum class DdrChipWidthValue {
kX8 = 0b00,
kX16 = 0b01,
kX32 = 0b10,
kReserved = 0b11,
};
DEF_RSVDZ_BIT(31);
// If false, DDR5 capacity exceeds 8GB.
//
// This bit must be false for non-DDR5 configurations.
//
// This bit is only defined on Tiger Lake H, and is reserved MBZ (must be
// zero) on all other platforms. This results in correct read semantics, as
// the feature appears disabled on these platforms.
DEF_BIT(30, ddr5_capacity_is_8gb);
// Selects how zone address bits feed into BG and CAS bits.
//
// If this bit is true, channel address bit 6 becomes BG (bank group) bit 0,
// and channel address bit 11 becomes CAS (column address) bit 7.
DEF_BIT(29, swap_channel_address_bits_6_11);
// If true, DIMM S is built from 8 GB DRAM modules.
//
// This bit must be false on non-DDR3 configurations.
//
// This bit is only defined on Comet Lake. It is reserved MBZ (must be zero)
// on later memory controllers. This results in correct read semantics, as the
// feature appears disabled on these platforms.
DEF_BIT(28, dimm_s_built_from_8gb_modules);
// The number of ranks in DIMM S. 0 = 1 rank, ... 3 = 4 ranks.
//
// Values above 1 (2 ranks) are not valid for for DIMM S.
DEF_FIELD(27, 26, dimm_s_rank_count_minus_1);
// The DDR chip width for DIMM S.
DEF_ENUM_FIELD(DdrChipWidthValue, 25, 24, dimm_s_ddr_chip_width_select);
DEF_RSVDZ_BIT(23);
// Size of DIMM S in multiples of 0.5 GB (512 MB).
DEF_FIELD(22, 16, dimm_s_size_512mb);
DEF_RSVDZ_FIELD(15, 12);
// If true, DIMM L is built from 8 GB DRAM modules.
//
// This bit must be false on non-DDR3 configurations.
//
// This bit is only defined on Comet Lake. It is reserved MBZ (must be zero)
// on later memory controllers. This results in correct read semantics, as the
// feature appears disabled on these platforms.
DEF_BIT(11, dimm_l_built_from_8gb_modules);
// The number of ranks in DIMM L. 0 = 1 rank, 1 = 2 ranks ... 3 = 4 ranks.
//
// Values above 1 (2 ranks) are only valid in ERM (Enhanced Rank Mode).
DEF_FIELD(10, 9, dimm_l_rank_count_minus_1);
DEF_ENUM_FIELD(DdrChipWidthValue, 8, 7, dimm_l_ddr_chip_width_select);
// Size of DIMM L in multiples of 0.5 GB (512 MB).
DEF_FIELD(6, 0, dimm_l_size_512mb);
// The width of the DDR chips in DIMM S.
int dimm_s_ddr_chip_width() const {
return DdrChipWidthValueToInteger(dimm_s_ddr_chip_width_select());
}
// The width of the DDR chips in DIMM L.
int dimm_l_ddr_chip_width() const {
return DdrChipWidthValueToInteger(dimm_l_ddr_chip_width_select());
}
// The number of ranks in DIMM S.
int dimm_s_rank_count() const {
// The cast and the addition will not overflow (causing UB) because the
// underlying field is a 2-bit integer.
return static_cast<int>(dimm_s_rank_count_minus_1()) + 1;
}
// The number of ranks in DIMM L.
int dimm_l_rank_count() const {
// The cast and the addition will not overflow (causing UB) because the
// underlying field is a 2-bit integer.
return static_cast<int>(dimm_l_rank_count_minus_1()) + 1;
}
// The size of DIMM S, in MB.
int dimm_s_size_mb() const {
// The cast and the multiplication will not overflow (causing UB) because
// the underlying field is a 7-bit integer.
return static_cast<int>(dimm_s_size_512mb()) * 512;
}
// The size of DIMM L, in MB.
int dimm_l_size_mb() const {
// The cast and the multiplication will not overflow (causing UB) because
// the underlying field is a 7-bit integer.
return static_cast<int>(dimm_l_size_512mb()) * 512;
}
static auto GetForControllerAndChannel(int memory_controller_index, int channel_index) {
ZX_ASSERT(memory_controller_index >= 0);
ZX_ASSERT(memory_controller_index <= 1);
ZX_ASSERT(channel_index >= 0);
ZX_ASSERT(channel_index <= 1);
return hwreg::RegisterAddr<MemoryAddressDecoderDimmParametersCometLake>(
kMemoryControllerBarMirrorOffset + 0x500c + 0x10000 * memory_controller_index +
4 * channel_index);
}
// For Tiger Lake H SKUs.
//
// `memory_controller_index` and `channel_index` are 0-based.
static auto GetForTigerLakeHControllerAndChannel(int memory_controller_index, int channel_index) {
ZX_ASSERT(memory_controller_index >= 0);
ZX_ASSERT(memory_controller_index <= 1);
ZX_ASSERT(channel_index >= 0);
ZX_ASSERT(channel_index <= 1);
return hwreg::RegisterAddr<MemoryChannelTimingsTigerLake>(
kMemoryControllerBarMirrorOffset + 0xd80c + 0x10000 * memory_controller_index +
4 * channel_index);
}
private:
static int DdrChipWidthValueToInteger(DdrChipWidthValue value) {
return 8 << static_cast<int>(value);
}
};
// MAD_DIMM_CH0_0_0_0_MCHBAR (Channel 0 DIMM Characteristics)
// MAD_DIMM_CH1_0_0_0_MCHBAR (Channel 1 DIMM Characteristics)
//
// Coffee Lake: 337345-003 Sections 7.40-7.41 pages 196-199
// Whiskey Lake: 338024-001 Sections 7.11-7.12 pages 154-156
// Amber Lake: 334662-005 Sections 6.34-6.35 pages 157-160
// Kaby Lake S: 335196-002 Sections 7.34-7.35 pages 189-192
// Kaby Lake H: 335191-003 Sections 7.40-7.41 pages 198-201
// Skylake U: 332991-003 Sections 7.34-7.35 pages 190-193
// Skylake S: 332688-003 Sections 7.34-7.35 pages 172-174
// Skylake H: 332987-003 Sections 7.34-7.35 pages 190-193
class MemoryAddressDecoderDimmParametersSkylake
: public hwreg::RegisterBase<MemoryAddressDecoderDimmParametersSkylake, uint32_t> {
public:
enum class DdrChipWidthValue {
kX8 = 0b00,
kX16 = 0b01,
kX32 = 0b10,
kReserved = 0b11,
};
DEF_RSVDZ_FIELD(31, 28);
// If true, DIMM S is built from 8 GB DRAM modules.
//
// This bit is expected to be false on non-DDR3 configurations.
DEF_BIT(27, dimm_s_built_from_8gb_modules);
// The number of ranks in DIMM S. 0 = 1 rank, 1 = 2 ranks.
DEF_BIT(26, dimm_s_rank_count_minus_1);
// The width of the DDR chips in DIMM S.
DEF_ENUM_FIELD(DdrChipWidthValue, 25, 24, dimm_s_ddr_chip_width_select);
DEF_RSVDZ_FIELD(23, 22);
// Size of DIMM S in multiples of 1GB.
DEF_FIELD(21, 16, dimm_s_size_1gb);
DEF_RSVDZ_FIELD(15, 12);
// If true, DIMM L is built from 8 GB DRAM modules.
//
// This bit is expected to be false on non-DDR3 configurations.
DEF_BIT(11, dimm_l_built_from_8gb_modules);
// The number of ranks in DIMM L. 0 = 1 rank, 1 = 2 ranks.
DEF_BIT(10, dimm_l_rank_count_minus_1);
// The width of the DDR chips in DIMM L.
DEF_ENUM_FIELD(DdrChipWidthValue, 9, 8, dimm_l_ddr_chip_width_select);
DEF_RSVDZ_FIELD(7, 6);
// Size of DIMM L in multiples of 1GB.
DEF_FIELD(5, 0, dimm_l_size_1gb);
// The width of the DDR chips in DIMM S.
int dimm_s_ddr_chip_width() const {
return DdrChipWidthValueToInteger(dimm_s_ddr_chip_width_select());
}
// The width of the DDR chips in DIMM L.
int dimm_l_ddr_chip_width() const {
return DdrChipWidthValueToInteger(dimm_l_ddr_chip_width_select());
}
// The number of ranks in DIMM S.
int dimm_s_rank_count() const {
// The cast and the addition will not overflow (causing UB) because the
// underlying field is a 1-bit integer.
return static_cast<int>(dimm_s_rank_count_minus_1()) + 1;
}
// The number of ranks in DIMM L.
int dimm_l_rank_count() const {
// The cast and the addition will not overflow (causing UB) because the
// underlying field is a 1-bit integer.
return static_cast<int>(dimm_l_rank_count_minus_1()) + 1;
}
// The size of DIMM S, in MB.
int dimm_s_size_mb() const {
// The cast and the multiplication will not overflow (causing UB) because
// the underlying field is a 6-bit integer.
return static_cast<int>(dimm_s_size_1gb()) * 1024;
}
// The size of DIMM L, in MB.
int dimm_l_size_mb() const {
// The cast and the multiplication will not overflow (causing UB) because
// the underlying field is a 6-bit integer.
return static_cast<int>(dimm_l_size_1gb()) * 1024;
}
static auto GetForChannel(int channel_index) {
ZX_ASSERT(channel_index >= 0);
ZX_ASSERT(channel_index <= 1);
return hwreg::RegisterAddr<MemoryAddressDecoderDimmParametersSkylake>(
kMemoryControllerBarMirrorOffset + 0x500c + 4 * channel_index);
}
private:
static int DdrChipWidthValueToInteger(DdrChipWidthValue value) {
return 8 << static_cast<int>(value);
}
};
// MC_BIOS_REQ_0_0_0_MCHBAR_PCU (Memory Controller BIOS Request)
// MC_BIOS_DATA_0_0_0_MCHBAR_PCU (Memory Controller BIOS Data)
//
// Raptor Lake: 743846-001 Sections 3.3.42-3.3.43 pages 202-204
// Alder Lake S: 655259-003 Section 3.3.41-3.3.42 pages 184-187
// Alder Lake H: 710723-003 Section 3.3.41-3.3.42 pages 213-216
// Rocket Lake: 636761-004 Sections 3.3.45-3.3.46 pages 172-174
// Tiger Lake U: 631122-003 Sections 3.3.44-3.3.45 pages 197-199
// Tiger Lake H: 643524-003 Sections 3.3.45-3.3.46 pages 190-192
// Ice Lake: 341078-004 Section 3.3.44-3.3.45 pages 177-179
class MemoryControllerBiosDataIceLake
: public hwreg::RegisterBase<MemoryControllerBiosDataIceLake, uint32_t> {
public:
// Documented values for `memory_controller_frequency_base_select`.
enum class ControllerFrequencyBaseValue {
k133Mhz = 0b000,
k100Mhz = 0b001,
};
// If true, the PCU (power controller) has not yet applied this configuration.
//
// The system firmware sets this bit to true when it writes a new value to
// this register. The PCU firmware clears this bit after it applies the
// requested configuration changes.
//
// This bit is only meaningful for the MC_BIOS_REQ_0_0_0_MCHBAR_PCU (Memory
// Controller BIOS Request) register. It must be zero in the
// MC_BIOS_DATA_0_0_0_MCHBAR_PCU (Memory Controller BIOS Data) register.
DEF_BIT(31, request_pending);
// Sets IccMax (the maximum current) on the VDDQ_TX (DDR data transmit) rail.
//
// The value is a multiplier with the base 250 mA.
//
// This field is reserved MBZ (must be zero) on Ice Lake and Rocket Lake.
DEF_FIELD(30, 27, data_transmit_rail_max_current_multiplier);
// Sets the voltage on the VDDQ_TX (DDR data transmit) rail.
//
// The value is a multiplier with the base 5mV.
//
// This field is reserved MBZ (must be zero) on Ice Lake and Rocket Lake.
DEF_FIELD(26, 17, data_transmit_rail_voltage_multiplier);
// Sets the DDR PHY bus clock relatively to the memory controller Qclk.
//
// This field is reserved MBZ (must be zero) on Alder Lake and Tiger Lake.
// Those platforms use the `ddr_phy_bus_clock_multiplier_shift_tiger_lake`
// field with the same semantics.
DEF_BIT(16, ddr_phy_bus_clock_multiplier_shift_ice_lake);
DEF_RSVDZ_FIELD(15, 14);
// 2-bit equivalent of `ddr_phy_bus_clock_multiplier_shift_ice_lake`.
//
// 0 = 1X multiplier, so the DDR bus matches Qclk. 1 = 2X multiplier, so the
// DDR bus operates at 2x Qclk. 2 = 4x multiplier.
//
// This field is reserved MBZ (must be zero) on Ice Lake and Rocket Lake.
DEF_FIELD(13, 12, ddr_phy_bus_clock_multiplier_shift_tiger_lake);
// The base for the memory controller Qclk (quad clock) frequency.
DEF_ENUM_FIELD(ControllerFrequencyBaseValue, 11, 8, controller_frequency_base_select);
// The multiplier for the memory controller Qclk (quad clock) frequency.
//
// After the MRC (Memory Reference initialization Code) runs, the multiplier
// should be greater than or equal to 3. A multiplier of 0 indicates that the
// memory controller PLL will be shut down. Multipliers 1 and 2 are reserved.
DEF_FIELD(7, 0, controller_frequency_multiplier);
// The maximum Icc (current) on the VDD_TX (DDR data transmit) rail.
//
// The return value is expressed in mA (milliamperes). A value of zero means
// that the field is not populated.
int32_t data_transmit_rail_max_current_milliamps() const {
static constexpr int32_t kCurrentBaseMilliamps = 250;
// The cast and the multiplication will not overflow (causing UB) because
// the underlying field is a 4-bit integer. The multiplication result fits
// in 12 bits, because the base fits in 8 bits.
return static_cast<int32_t>(data_transmit_rail_max_current_multiplier()) *
kCurrentBaseMilliamps;
}
// The voltage on the VDD_TX (DDR data transmit) rail.
//
// The return value is expressed in mV (millivolts). A value of zero means
// that the field is not populated.
int32_t data_transmit_rail_voltage_millivolts() const {
static constexpr int32_t kVoltageBaseMillivolts = 5;
// The cast and the multiplication will not overflow (causing UB) because
// the underlying field is a 10-bit integer. The multiplication result fits
// in 13 bits, because the base fits in 3 bits.
return static_cast<int32_t>(data_transmit_rail_voltage_multiplier()) * kVoltageBaseMillivolts;
}
// Sets the DDR PHY bus clock relatively to the memory controller Qclk.
//
// This field is a multiplier is relative to the memory controller Qclk (quad
// clock) frequency. The field value is represented in log2, so the multiplier
// is 1 << field_value.
int ddr_phy_bus_clock_multiplier_shift() const {
// The casts will not underflow (causing UB) because the underlying fields
// are 1 and 2-bit integers.
return std::max<int32_t>(static_cast<int32_t>(ddr_phy_bus_clock_multiplier_shift_ice_lake()),
static_cast<int32_t>(ddr_phy_bus_clock_multiplier_shift_tiger_lake()));
}
// The DDR PHY bus frequency, in Hz.
//
// Returns 0 if the memory controller PLL is disabled, or if the register has
// an invalid configuration.
int64_t ddr_phy_bus_frequency_hz() const {
// The cast and the multiplication will not overflow (causing UB) because
// the base is a 31-bit integer, and the multiplier is an 8-bit field. So,
// the multiplication result will fit in 39 bits.
const int64_t quad_clock_frequency_hz_x3 =
int64_t{controller_frequency_base_hz_x3()} *
static_cast<int32_t>(controller_frequency_multiplier());
// The shift will not overflow (causing UB) because
// `quad_clock_frequency_hz_x3` is a 39-bit integer, and the shift value is
// a 1-bit field.
const int64_t ddr_frequency_hz_x3 = quad_clock_frequency_hz_x3
<< ddr_phy_bus_clock_multiplier_shift();
return (ddr_frequency_hz_x3 + 1) / 3;
}
// The memory controller's Qclk (quad-clock) frequency, in Hz.
//
// Returns 0 if the memory controller PLL is disabled, or if the register has
// an invalid configuration.
int64_t controller_quad_clock_frequency_hz() const {
// The cast and the multiplication will not overflow (causing UB) because
// the base is a 31-bit integer, and the multiplier is an 8-bit field. So,
// the multiplication result will fit in 39 bits.
const int64_t frequency_hz_x3 = int64_t{controller_frequency_base_hz_x3()} *
static_cast<int32_t>(controller_frequency_multiplier());
// The addition will not overflow (causing UB) because `frequency_hz_x3`
// fits in 39 bits, so the result fits in 40 bits.
return (frequency_hz_x3 + 1) / 3;
}
// The memory controller's base frequency in Hz, multiplied by 3.
//
// Returns zero if the field is set to an undocumented value.
//
// The unusual return convention follows the datasheet recommendation for
// representing the memory controller's base frequency.
int32_t controller_frequency_base_hz_x3() const {
switch (controller_frequency_base_select()) {
case ControllerFrequencyBaseValue::k133Mhz:
return 400'000'000;
case ControllerFrequencyBaseValue::k100Mhz:
return 300'000'000;
}
return 0;
}
static auto Get() {
return hwreg::RegisterAddr<MemoryControllerBiosDataIceLake>(kMemoryControllerBarMirrorOffset +
0x5e04);
}
};
// MC_BIOS_DATA_0_0_0_MCHBAR_PCU (Memory Controller BIOS Data)
//
// The Kaby Lake and Skylake datasheets only document the
// PCU_CR_MC_BIOS_REQ_0_0_0_MCHBAR_PCU register, which has the same semantics as
// the MC_BIOS_REQ_0_0_0_MCHBAR_PCU register in the Ice Lake and Tiger Lake
// datasheets. The MC_BIOS_REQ_0_0_0_MCHBAR_PCU (Memory Controller BIOS Request)
// register carries the latest request from the software to the memory
// controller, whereas this register (Memory Controller BIOS Data) represents
// the last request issued by the MRC (Memory Reference Code).
//
// Comet Lake: 615212-003 Section 9.40 pages 238-239
// Coffee Lake: 337345-003 Section 7.91 pages 237-238
// Whiskey Lake: 338024-001 Section 7.60 pages 192-193
// Amber Lake: 334662-005 Sections 6.83 pages 197-198
// Kaby Lake S: 335196-002 Section 7.83 pages 229-230
// Kaby Lake H: 335191-003 Section 7.91 pages 239-240
// Skylake U: 332991-003 Section 7.83 pages 230-231
// Skylake S: 332688-003 Section 7.83 pages 206-207
// Skylake H: 332987-003 Section 7.83 pages 230-231
class MemoryControllerBiosDataSkylake
: public hwreg::RegisterBase<MemoryControllerBiosDataSkylake, uint32_t> {
public:
// The multipliers for the memory controller clock frequencies.
//
// After the MRC (Memory Reference initialization Code) runs, the multiplier
// should be greater than or equal to 3. A multiplier of 0 indicates that the
// memory controller PLL will be shut down. Multipliers 1 and 2 are reserved.
//
// The bases are 400/3 MHz for the memory controller's Dclk (double-clock) and
// 800/3 MHz for the memory controller's Qclk (quad-clock).
DEF_FIELD(3, 0, controller_frequency_multiplier);
// The memory controller's Qclk (quad-clock) frequency, in Hz.
//
// Returns 0 if the memory controller PLL is disabled.
int64_t controller_quad_clock_frequency_hz() const {
static constexpr int64_t kQuadClockBaseMultiplierHz = 800'000'000;
static constexpr int kQuadClockBaseDivider = 3;
return (static_cast<int>(controller_frequency_multiplier()) * kQuadClockBaseMultiplierHz +
(kQuadClockBaseDivider / 2)) /
kQuadClockBaseDivider;
}
static auto Get() {
return hwreg::RegisterAddr<MemoryControllerBiosDataSkylake>(kMemoryControllerBarMirrorOffset +
0x5e04);
}
};
} // namespace registers
#endif // SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_REGISTERS_MEMORY_CONTROLLER_H_