92c314d3c8
Fixes #3332
1310 lines
36 KiB
C++
1310 lines
36 KiB
C++
/*
|
|
* \brief Broadwell MMIO definitions
|
|
* \author Josef Soentgen
|
|
* \data 2017-03-15
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2017 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
#ifndef _MMIO_H_
|
|
#define _MMIO_H_
|
|
|
|
/* Genode includes */
|
|
#include <base/log.h>
|
|
#include <util/mmio.h>
|
|
|
|
/* local includes */
|
|
#include <types.h>
|
|
|
|
|
|
namespace Igd {
|
|
|
|
class Mmio;
|
|
}
|
|
|
|
|
|
class Igd::Mmio : public Genode::Mmio
|
|
{
|
|
public:
|
|
|
|
enum {
|
|
/*
|
|
* XXX IDs are taken from Linux, still looking
|
|
* for a reference in the documentation
|
|
*/
|
|
RCS_ID = 0,
|
|
VCS_ID = 1,
|
|
BCS_ID = 2,
|
|
VECS_ID = 3,
|
|
VCS2_ID = 4,
|
|
|
|
NUM_ENGINES = 5,
|
|
NUM_FENCES = 32,
|
|
|
|
SIZE = 2u<<20,
|
|
};
|
|
|
|
static char const *engine_name(int id)
|
|
{
|
|
switch (id) {
|
|
case RCS_ID: return "RCS";
|
|
case VCS_ID: return "VCS";
|
|
case BCS_ID: return "BCS";
|
|
case VECS_ID: return "VECS";
|
|
case VCS2_ID: return "VCS2";
|
|
}
|
|
return "<unknown>";
|
|
}
|
|
|
|
/*************************
|
|
** Interrupt registers **
|
|
*************************/
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 953 ff.
|
|
*/
|
|
struct MASTER_INT_CTL : Register<0x44200, 32>
|
|
{
|
|
struct Master_interrupt_enable : Bitfield<31, 1> { };
|
|
struct Pcu_interrupts_pending : Bitfield<30, 1> { };
|
|
struct Audio_codec_interrupts_pending : Bitfield<24, 1> { };
|
|
struct De_pch_interrupts_pending : Bitfield<23, 1> { };
|
|
struct De_misc_interrupts_pending : Bitfield<22, 1> { };
|
|
struct De_port_interrupts_pending : Bitfield<20, 1> { };
|
|
struct De_pipe_c_interrupts_pending : Bitfield<18, 1> { };
|
|
struct De_pipe_b_interrupts_pending : Bitfield<17, 1> { };
|
|
struct De_pipe_a_interrupts_pending : Bitfield<16, 1> { };
|
|
struct Vebox_interrupts_pending : Bitfield< 6, 1> { };
|
|
struct Gtpm_interrupts_pending : Bitfield< 4, 1> { };
|
|
struct Vcs2_interrupts_pending : Bitfield< 3, 1> { };
|
|
struct Vcs1_interrupts_pending : Bitfield< 2, 1> { };
|
|
struct Blitter_interrupts_pending : Bitfield< 1, 1> { };
|
|
struct Render_interrupts_pending : Bitfield< 0, 1> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 658 ff.
|
|
*/
|
|
template <long int REG>
|
|
struct GT_0_INTERRUPT : Register<REG, 32>
|
|
{
|
|
using B = Register<REG, 32>;
|
|
|
|
struct Bcs_wait_on_semaphore : B::template Bitfield<27, 1> { };
|
|
struct Bcs_ctx_switch_interrupt : B::template Bitfield<24, 1> { };
|
|
struct Bcs_mi_flush_dw_notify : B::template Bitfield<20, 1> { };
|
|
struct Bcs_error_interrupt : B::template Bitfield<19, 1> { };
|
|
struct Bcs_mi_user_interrupt : B::template Bitfield<16, 1> { };
|
|
|
|
struct Cs_wait_on_semaphore : B::template Bitfield<11, 1> { };
|
|
struct Cs_l3_counter_slave : B::template Bitfield<10, 1> { };
|
|
struct Cs_ctx_switch_interrupt : B::template Bitfield< 8, 1> { };
|
|
struct Page_fault_error : B::template Bitfield< 7, 1> { };
|
|
struct Cs_watchdog_counter_expired : B::template Bitfield< 6, 1> { };
|
|
struct L3_parity_error : B::template Bitfield< 5, 1> { };
|
|
struct Cs_pipe_control_notify : B::template Bitfield< 4, 1> { };
|
|
struct Cs_error_interrupt : B::template Bitfield< 3, 1> { };
|
|
struct Cs_mi_user_interrupt : B::template Bitfield< 0, 1> { };
|
|
};
|
|
|
|
struct GT_0_INTERRUPT_ISR : GT_0_INTERRUPT<0x44300> { };
|
|
struct GT_0_INTERRUPT_IMR : GT_0_INTERRUPT<0x44304> { };
|
|
struct GT_0_INTERRUPT_IIR : GT_0_INTERRUPT<0x44308> { };
|
|
struct GT_0_INTERRUPT_IER : GT_0_INTERRUPT<0x4430C> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 673 ff.
|
|
*/
|
|
template <long int REG>
|
|
struct GT_1_INTERRUPT : Register<REG, 32>
|
|
{
|
|
using B = Register<REG, 32>;
|
|
|
|
struct Vcs2_wait_on_semaphore : B::template Bitfield<27, 1> { };
|
|
struct Vcs2_ctx_switch_interrupt : B::template Bitfield<24, 1> { };
|
|
struct Vcs2_watchdog_counter_expired : B::template Bitfield<22, 1> { };
|
|
struct Vcs2_mi_flush_dw_notify : B::template Bitfield<20, 1> { };
|
|
struct Vcs2_error_interrupt : B::template Bitfield<19, 1> { };
|
|
struct Vcs2_mi_user_interrupt : B::template Bitfield<16, 1> { };
|
|
|
|
struct Vcs1_wait_on_semaphore : B::template Bitfield<11, 1> { };
|
|
struct Vcs1_ctx_switch_interrupt : B::template Bitfield< 8, 1> { };
|
|
struct Vcs1_watchdog_counter_expired : B::template Bitfield< 6, 1> { };
|
|
struct Vcs1_pipe_control_notify : B::template Bitfield< 4, 1> { };
|
|
struct Vcs1_error_interrupt : B::template Bitfield< 3, 1> { };
|
|
struct Vcs1_mi_user_interrupt : B::template Bitfield< 0, 1> { };
|
|
};
|
|
|
|
struct GT_1_INTERRUPT_ISR : GT_1_INTERRUPT<0x44310> { };
|
|
struct GT_1_INTERRUPT_IMR : GT_1_INTERRUPT<0x44314> { };
|
|
struct GT_1_INTERRUPT_IIR : GT_1_INTERRUPT<0x44318> { };
|
|
struct GT_1_INTERRUPT_IER : GT_1_INTERRUPT<0x4431C> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 687 ff.
|
|
*/
|
|
template <long int REG>
|
|
struct GT_2_INTERRUPT : Register<REG, 32>
|
|
{
|
|
using B = Register<REG, 32>;
|
|
|
|
struct Unslice_frequency_control_up_interrupt : B::template Bitfield<13, 1> { };
|
|
struct Unslice_frequency_control_down_interrupt : B::template Bitfield<12, 1> { };
|
|
struct Nfafdl_frequency_up_interrupt : B::template Bitfield<11, 1> { };
|
|
struct Nfafdl_frequency_down_interrupt : B::template Bitfield<10, 1> { };
|
|
struct Gtpm_engines_idle_interrupt : B::template Bitfield< 8, 1> { };
|
|
struct Gtpm_uncore_to_core_trap_interrupt : B::template Bitfield< 7, 1> { };
|
|
struct Gtpm_render_frequency_downwards_timeout_during_rc6_interrupt : B::template Bitfield< 6, 1> { };
|
|
struct Gtpm_render_p_state_up_threshold_interrupt : B::template Bitfield< 5, 1> { };
|
|
struct Gtpm_render_p_state_down_threshold_interrupt : B::template Bitfield< 4, 1> { };
|
|
struct Gtpm_render_geyserville_up_evaluation_interval_interrupt : B::template Bitfield< 2, 1> { };
|
|
struct Gtpm_render_geyserville_down_evaluation_interval_interrupt : B::template Bitfield< 1, 1> { };
|
|
};
|
|
|
|
struct GT_2_INTERRUPT_ISR : GT_2_INTERRUPT<0x44320> { };
|
|
struct GT_2_INTERRUPT_IMR : GT_2_INTERRUPT<0x44324> { };
|
|
struct GT_2_INTERRUPT_IIR : GT_2_INTERRUPT<0x44328> { };
|
|
struct GT_2_INTERRUPT_IER : GT_2_INTERRUPT<0x4432C> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 689 ff.
|
|
*/
|
|
template <long int REG>
|
|
struct GT_3_INTERRUPT : Register<REG, 32>
|
|
{
|
|
using B = Register<REG, 32>;
|
|
|
|
struct Performance_monitoring_buffer_half_full_interrupt : B::template Bitfield<28, 1> { };
|
|
struct Vecs_wait_on_semaphore : B::template Bitfield<11, 1> { };
|
|
struct Vecs_ctx_switch_interrupt : B::template Bitfield< 8, 1> { };
|
|
struct Vecs_mi_flush_dw_notify : B::template Bitfield< 4, 1> { };
|
|
struct Vecs_error_interrupt : B::template Bitfield< 3, 1> { };
|
|
struct Vecs_mi_user_interrupt : B::template Bitfield< 0, 1> { };
|
|
};
|
|
|
|
struct GT_3_INTERRUPT_ISR : GT_3_INTERRUPT<0x44330> { };
|
|
struct GT_3_INTERRUPT_IMR : GT_3_INTERRUPT<0x44334> { };
|
|
struct GT_3_INTERRUPT_IIR : GT_3_INTERRUPT<0x44338> { };
|
|
struct GT_3_INTERRUPT_IER : GT_3_INTERRUPT<0x4433C> { };
|
|
|
|
/**************************
|
|
** Page-table registers **
|
|
**************************/
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 1169
|
|
*/
|
|
struct PAT_INDEX : Genode::Register<32>
|
|
{
|
|
struct Class_of_service : Bitfield<8, 2> { };
|
|
struct Lru_age : Bitfield<4, 2>
|
|
{
|
|
enum {
|
|
UCR = 0b00,
|
|
A0 = 0b01,
|
|
DNC = 0b10,
|
|
A3 = 0b11,
|
|
};
|
|
};
|
|
struct Target_cache : Bitfield<2, 2>
|
|
{
|
|
enum {
|
|
ELLC = 0b00,
|
|
LLC = 0b01,
|
|
LLCELLC = 0b10,
|
|
LLCeLLC = 0b11,
|
|
};
|
|
};
|
|
struct Mem_type : Bitfield<0, 2>
|
|
{
|
|
enum {
|
|
UC = 0b00,
|
|
WC = 0b01,
|
|
WT = 0b10,
|
|
WB = 0b11,
|
|
};
|
|
};
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 1170
|
|
*/
|
|
struct PAT_INDEX_H : Register<0x040E0, 32> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 1071
|
|
*/
|
|
struct PAT_INDEX_L : Register<0x040E4, 32> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 1516 ff.
|
|
*/
|
|
struct TIMESTAMP_CTR : Register<0x44070, 32> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 75
|
|
*
|
|
* TODO registers are not continuous
|
|
*/
|
|
struct FAULT_REG : Register_array<0x04000, 32, NUM_ENGINES, 32>
|
|
{
|
|
struct Engine_ID : Bitfield<12,3>
|
|
{
|
|
enum EID {
|
|
GFX = 0,
|
|
MFX0 = 1,
|
|
MFX1 = 2,
|
|
VEBX = 3,
|
|
BLT = 4
|
|
};
|
|
};
|
|
struct SRCID : Bitfield< 3,8> { };
|
|
struct Fault_Type : Bitfield< 1,2>
|
|
{
|
|
enum GFX_FT {
|
|
INVALID_PTE = 0,
|
|
INVALID_PDE = 1,
|
|
INVALID_PDPE = 2,
|
|
INVALID_PML4E = 3
|
|
};
|
|
};
|
|
struct Valid_Bit : Bitfield<0,1> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 446
|
|
*/
|
|
struct FAULT_TLB_RB_DATA0 : Register<0x04B10, 32>
|
|
{
|
|
struct Fault_cycle_va : Bitfield<0, 32> { }; /* 43:12 */
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 447
|
|
*/
|
|
struct FAULT_TLB_RB_DATA1 : Register<0x04B14, 32>
|
|
{
|
|
struct Cycle_gtt_sel : Bitfield<4, 1> { };
|
|
struct Fault_cycle_va : Bitfield<0, 4> { }; /* 47:44 */
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 1353 ff.
|
|
*/
|
|
struct RING_BUFFER_TAIL_RCSUNIT : Register<0x02030, 32>
|
|
{
|
|
struct Tail_Offset : Bitfield< 3, 18> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 1350 ff.
|
|
*/
|
|
struct RING_BUFFER_HEAD_RCSUNIT : Register<0x02034, 32>
|
|
{
|
|
struct Wrap_Count : Bitfield<21, 11> { };
|
|
struct Head_Offset : Bitfield< 2, 19> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 1352
|
|
*/
|
|
struct RING_BUFFER_START_RCSUNIT : Register<0x02038, 32>
|
|
{
|
|
struct Starting_Address : Bitfield<12, 20> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 1345 ff.
|
|
*/
|
|
struct RING_BUFFER_CTL_RCSUNIT : Register<0x0203C, 32>
|
|
{
|
|
struct Buffer_length : Bitfield<12, 9> { };
|
|
struct RBWait : Bitfield<11, 1> { };
|
|
struct Semaphore_wait : Bitfield<10, 1> { };
|
|
struct Automatic_report_head_pointer : Bitfield< 1, 2>
|
|
{
|
|
enum {
|
|
MI_AUTOREPORT_OFF = 0,
|
|
MI_AUTOREPORT_64KB = 1,
|
|
MI_AUTOREPORT_4KB = 2,
|
|
MI_AUTO_REPORT_128KB = 3
|
|
};
|
|
};
|
|
struct Ring_buffer_enable : Bitfield< 0, 1> { };
|
|
};
|
|
|
|
|
|
/*********************
|
|
** Debug registers **
|
|
*********************/
|
|
|
|
/*
|
|
* Ancient (2008) Volume 1: Graphics Core p. 228
|
|
*/
|
|
struct IPEIR : Register<0x2064, 32>
|
|
{
|
|
struct Batch_buffer_error : Bitfield<3, 1> { };
|
|
};
|
|
|
|
/*
|
|
* Ancient (2008) Volume 1: Graphics Core p. 229
|
|
*/
|
|
struct IPEHR : Register<0x2068, 32> { };
|
|
|
|
/*
|
|
* Ancient (2008) Volume 1: Graphics Core p. 229
|
|
*/
|
|
template <long int BASE>
|
|
struct INSTDONE_BASE : Register<BASE + 0x6C, 32>
|
|
{
|
|
enum { DEFAULT_VALUE = 0xffe7fffe, };
|
|
};
|
|
|
|
struct RCS_INSTDONE : INSTDONE_BASE<0x2000>
|
|
{
|
|
struct Row_0_eu_0_done : Bitfield<31, 1> { };
|
|
struct Row_0_eu_1_done : Bitfield<30, 1> { };
|
|
struct Row_0_eu_2_done : Bitfield<29, 1> { };
|
|
struct Row_0_eu_3_done : Bitfield<28, 1> { };
|
|
struct Row_1_eu_0_done : Bitfield<27, 1> { };
|
|
struct Row_1_eu_1_done : Bitfield<26, 1> { };
|
|
struct Row_1_eu_2_done : Bitfield<25, 1> { };
|
|
struct Row_1_eu_3_done : Bitfield<24, 1> { };
|
|
struct Sf_done : Bitfield<23, 1> { };
|
|
struct Se_done : Bitfield<22, 1> { };
|
|
struct Windower_done : Bitfield<21, 1> { };
|
|
struct Reserved1 : Bitfield<20, 1> { };
|
|
struct Reserved2 : Bitfield<19, 1> { };
|
|
struct Dip_done : Bitfield<18, 1> { };
|
|
struct Pl_done : Bitfield<17, 1> { };
|
|
struct Dg_done : Bitfield<16, 1> { };
|
|
struct Qc_done : Bitfield<15, 1> { };
|
|
struct Ft_done : Bitfield<14, 1> { };
|
|
struct Dm_done : Bitfield<13, 1> { };
|
|
struct Sc_done : Bitfield<12, 1> { };
|
|
struct Fl_done : Bitfield<11, 1> { };
|
|
struct By_done : Bitfield<10, 1> { };
|
|
struct Ps_done : Bitfield< 9, 1> { };
|
|
struct Cc_done : Bitfield< 8, 1> { };
|
|
struct Map_fl_done : Bitfield< 7, 1> { };
|
|
struct Map_l2_idle : Bitfield< 6, 1> { };
|
|
struct Msg_arb_0_done : Bitfield< 5, 1> { };
|
|
struct Msg_arb_1_done : Bitfield< 4, 1> { };
|
|
struct Ic_row_0_done : Bitfield< 3, 1> { };
|
|
struct Ic_row_1_done : Bitfield< 2, 1> { };
|
|
struct Cp_done : Bitfield< 1, 1> { };
|
|
struct Ring_0_enable : Bitfield< 0, 1> { };
|
|
};
|
|
|
|
/*
|
|
* Ancient (2008) Volume 1: Graphics Core p. 229
|
|
*/
|
|
template <long int BASE>
|
|
struct INSTDONE_1_BASE : Register<BASE + 0x7C, 32>
|
|
{
|
|
enum { DEFAULT_VALUE = 0x0, };
|
|
};
|
|
|
|
struct RCS_INSTDONE_1 : INSTDONE_1_BASE<0x2000> { };
|
|
|
|
/*
|
|
* Ancient (2008) Volume 1: Graphics Core p. 231
|
|
*/
|
|
template <long int BASE>
|
|
struct ACTHD_BASE : Register<BASE + 0x74, 32>
|
|
{
|
|
using B = Register<BASE + 0x74, 32>;
|
|
|
|
struct Head_pointer : B::template Bitfield<2, 30> { };
|
|
struct Reserved : B::template Bitfield<0, 2> { }; /* MBZ */
|
|
};
|
|
|
|
struct RCS_ACTHD : ACTHD_BASE<0x2000> { };
|
|
|
|
/*
|
|
* Ancient (2008) Volume 1: Graphics Core p. 205
|
|
*/
|
|
struct PGTBL_ER : Register<0x2024, 32> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 618 ff.
|
|
*/
|
|
struct GFX_MODE : Register<0x0229C, 32>
|
|
{
|
|
struct Mask_bits : Bitfield<16, 16> { };
|
|
|
|
struct Execlist_enable_mask : Bitfield<31, 1> { };
|
|
struct Execlist_enable : Bitfield<15, 1> { };
|
|
|
|
struct Ppgtt_enable_mask : Bitfield<25, 1> { };
|
|
struct Ppgtt_enable : Bitfield< 9, 1> { };
|
|
|
|
struct Virtual_addressing_enable_mask : Bitfield<23, 1> { };
|
|
struct Virtual_addressing_enable : Bitfield< 7, 1> { };
|
|
|
|
struct Privilege_check_disable_mask : Bitfield<16, 1> { };
|
|
struct Privilege_check_disable : Bitfield< 0, 1> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 6-11.15 p. 19 ff.
|
|
* IHD-OS-BDW-Vol 7-11.15 p. 42
|
|
*/
|
|
struct RCS_RING_CONTEXT_STATUS_PTR : Register<0x023A0, 32>
|
|
{
|
|
struct Read_pointer_mask : Bitfield<24, 8> { };
|
|
struct Write_pointer_mask : Bitfield<16, 8> { };
|
|
struct Read_pointer : Bitfield< 8, 8> { };
|
|
struct Write_pointer : Bitfield< 0, 8> { };
|
|
};
|
|
|
|
/*********************
|
|
** Error registers **
|
|
*********************/
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 413
|
|
*/
|
|
template <long int BASE>
|
|
struct EIR_BASE : Register<BASE + 0xB0, 32>
|
|
{
|
|
using B = Register<BASE + 0xB0, 32>;
|
|
|
|
struct Reserved : B::template Bitfield<16, 16> { }; /* MBZ */
|
|
struct Error_identity_bits : B::template Bitfield< 0, 16> { };
|
|
};
|
|
|
|
struct RCS_EIR : EIR_BASE<0x2000> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 414
|
|
*/
|
|
template <long int BASE>
|
|
struct EMR_BASE : Register<BASE + 0xB4, 32>
|
|
{
|
|
using B = Register<BASE + 0xB4, 32>;
|
|
|
|
struct Reserved : B::template Bitfield<8, 24> { }; /* MBO */
|
|
struct Error_mask_bits : B::template Bitfield<0, 8> { };
|
|
|
|
struct Error_page_table : B::template Bitfield<4, 1> { };
|
|
struct Error_mem_refresh : B::template Bitfield<1, 1> { };
|
|
};
|
|
|
|
struct RCS_EMR : EMR_BASE<0x2000> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 415 ff.
|
|
*/
|
|
/* struct ERR */
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 417
|
|
*/
|
|
template <long int BASE>
|
|
struct ESR_BASE : Register<BASE + 0xB8, 32>
|
|
{
|
|
using B = Register<BASE + 0xB8, 32>;
|
|
|
|
struct Reserved : B::template Bitfield<16, 16> { }; /* MBZ */
|
|
struct Error_status_bits : B::template Bitfield< 0, 16> { };
|
|
};
|
|
|
|
struct RCS_ESR : ESR_BASE<0x2000> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 944 ff.
|
|
*/
|
|
struct ERROR : Register<0x040A0, 32>
|
|
{
|
|
struct Ctx_fault_ctxt_not_prsnt_err : Bitfield<15, 1> { }; /* typo in PRM (prsmt) */
|
|
struct Ctx_fault_root_not_prsnt_err : Bitfield<14, 1> { }; /* " */
|
|
struct Ctx_fault_pasid_not_prsnt_err : Bitfield<13, 1> { };
|
|
struct Ctx_fault_pasid_ovflw_err : Bitfield<12, 1> { };
|
|
struct Ctx_fault_pasid_dis_err : Bitfield<11, 1> { };
|
|
|
|
struct Rstrm_fault_nowb_atomic_err : Bitfield<10, 1> { };
|
|
struct Unloaded_pd_error : Bitfield< 8, 1> { };
|
|
struct Hws_page_fault_error : Bitfield< 3, 1> { };
|
|
struct Invalid_page_directory_entry_error : Bitfield< 2, 1> { };
|
|
struct Ctx_page_fault_error : Bitfield< 1, 1> { };
|
|
struct Tlb_fault_error : Bitfield< 0, 1> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 948
|
|
*/
|
|
struct ERROR_2 : Register<0x040A4, 32>
|
|
{
|
|
struct Tlbpend_reg_faultcnt : Bitfield< 0, 6> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 1237
|
|
*/
|
|
struct PP_PFD : Register<0x04580, 32>
|
|
{
|
|
struct Fault_entry_page_address : Bitfield<12, 20> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 1315 ff.
|
|
*/
|
|
struct RC_CTRL0 : Register<0x0A090, 32> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 1317 ff.
|
|
*/
|
|
struct RC_CTRL1 : Register<0x0A094, 32>
|
|
{
|
|
struct Rc_state : Bitfield<18, 1> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 1095
|
|
*/
|
|
struct NDE_RSTWRN_OPT : Register<0x46408, 32>
|
|
{
|
|
struct Rst_pch_handshake_en : Bitfield<4, 1> { };
|
|
};
|
|
|
|
/*
|
|
* XXX documentation reference missing
|
|
*/
|
|
struct PWR_WELL_CTL2 : Register<0x45404, 32>
|
|
{
|
|
struct Misc_io_power_state : Bitfield< 0, 1> { };
|
|
struct Misc_io_power_request : Bitfield< 1, 1> { };
|
|
struct Ddi_a_and_ddi_e_io_power_state : Bitfield< 2, 1> { };
|
|
struct Ddi_a_and_ddi_e_io_power_request : Bitfield< 3, 1> { };
|
|
struct Ddi_b_io_power_state : Bitfield< 4, 1> { };
|
|
struct Ddi_b_io_power_request : Bitfield< 5, 1> { };
|
|
struct Ddi_c_io_power_state : Bitfield< 6, 1> { };
|
|
struct Ddi_c_io_power_request : Bitfield< 7, 1> { };
|
|
struct Ddi_d_io_power_state : Bitfield< 8, 1> { };
|
|
struct Ddi_d_io_power_request : Bitfield< 9, 1> { };
|
|
struct Power_well_1_state : Bitfield<28, 1> { };
|
|
struct Power_well_1_request : Bitfield<29, 1> { };
|
|
struct Power_well_2_state : Bitfield<30, 1> { };
|
|
struct Power_well_2_request : Bitfield<31, 1> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 853
|
|
*/
|
|
struct L3_LRA_1_GPGPU : Register<0x04DD4, 32> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 711
|
|
*/
|
|
struct HWSTAM : Register<0x02098, 32> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 712
|
|
*/
|
|
struct HWS_PGA_RCSUNIT : Register<0x02080, 32> { };
|
|
struct HWS_PGA_VCSUNIT0 : Register<0x12080, 32> { };
|
|
struct HWS_PGA_VECSUNIT : Register<0x1A080, 32> { };
|
|
struct HWS_PGA_VCSUNIT1 : Register<0x1C080, 32> { };
|
|
struct HWS_PGA_BCSUNIT : Register<0x22080, 32> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 1370
|
|
*/
|
|
struct RP_FREQ_NORMAL : Register<0x0A008, 32>
|
|
{
|
|
struct Turbo_disable : Bitfield<31, 1> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 1318
|
|
*/
|
|
struct RP_CTRL : Register<0xA024, 32> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 493
|
|
*/
|
|
/*
|
|
reg_post is in the same cacheline as FORCEWAKE and is
|
|
read after FORCEWAKE was written to prevent reordering
|
|
when reading from FORCEWAKE_ACK_HSW [1] (older driver
|
|
version used a different register for posting reads but
|
|
that did not work on certain older (~2012) machines.
|
|
|
|
[1] https://lists.freedesktop.org/archives/intel-gfx/2015-January/058101.html
|
|
*/
|
|
enum { FORCEWAKE_ID_RENDER = 0, };
|
|
struct FORCEWAKE_MT : Register<0x0A188, 32>
|
|
{
|
|
enum {
|
|
RESET = 0xffff0000u,
|
|
};
|
|
|
|
struct Multiple_force_wake_mask : Bitfield<16, 16> { };
|
|
|
|
struct Force_wake_request_for_thread_15 : Bitfield<15, 1> { };
|
|
struct Force_wake_request_for_thread_14 : Bitfield<14, 1> { };
|
|
struct Force_wake_request_for_thread_13 : Bitfield<13, 1> { };
|
|
struct Force_wake_request_for_thread_12 : Bitfield<12, 1> { };
|
|
struct Force_wake_request_for_thread_11 : Bitfield<11, 1> { };
|
|
struct Force_wake_request_for_thread_10 : Bitfield<10, 1> { };
|
|
struct Force_wake_request_for_thread_9 : Bitfield< 9, 1> { };
|
|
struct Force_wake_request_for_thread_8 : Bitfield< 8, 1> { };
|
|
struct Force_wake_request_for_thread_7 : Bitfield< 7, 1> { };
|
|
struct Force_wake_request_for_thread_6 : Bitfield< 6, 1> { };
|
|
struct Force_wake_request_for_thread_5 : Bitfield< 5, 1> { };
|
|
struct Force_wake_request_for_thread_4 : Bitfield< 4, 1> { };
|
|
struct Force_wake_request_for_thread_3 : Bitfield< 3, 1> { };
|
|
struct Force_wake_request_for_thread_2 : Bitfield< 2, 1> { };
|
|
struct Force_wake_request_for_thread_1 : Bitfield< 1, 1> { };
|
|
struct Force_wake_request_for_thread_0 : Bitfield< 0, 1> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 703
|
|
*
|
|
* also known as FORCEWAKE_ACK_HSW in the Linux driver
|
|
*/
|
|
struct GTSP1 : Register<0x130044, 32> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 606
|
|
*
|
|
* also known as ECOBUS in the Linux driver
|
|
*/
|
|
struct MISC_CTRL0 : Register<0x0A180, 32> { };
|
|
|
|
/*
|
|
* Reset control registers
|
|
*
|
|
* adds offset to given BASE address
|
|
*/
|
|
template <long int BASE>
|
|
struct RESET_CTRL_BASE : Register<BASE + 0xD0, 32>
|
|
{
|
|
using B = Register<BASE + 0xD0, 32>;
|
|
|
|
struct Mask_bits : B::template Bitfield<16, 15> { };
|
|
struct Ready_for_reset : B::template Bitfield< 1, 1> { };
|
|
struct Request_reset : B::template Bitfield< 0, 1> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 288
|
|
*/
|
|
struct CS_RESET_CTRL : RESET_CTRL_BASE<0x02000> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 165
|
|
*/
|
|
struct BCS_RESET_CTRL : RESET_CTRL_BASE<0x22000> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 609 ff.
|
|
*/
|
|
struct GDRST : Register<0x0941C, 32>
|
|
{
|
|
struct Graphics_media1_soft_reset_ctl : Bitfield<6, 1> { };
|
|
struct Graphics_widi_soft_reset_ctl : Bitfield<6, 1> { };
|
|
struct Graphics_vebox_soft_reset_ctl : Bitfield<4, 1> { };
|
|
struct Graphics_blitter_soft_reset_ctl : Bitfield<3, 1> { };
|
|
struct Graphics_media_soft_reset_ctl : Bitfield<2, 1> { };
|
|
struct Graphics_render_soft_reset_ctl : Bitfield<1, 1> { };
|
|
struct Graphics_full_soft_reset_ctl : Bitfield<0, 1> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 611 ff.
|
|
*/
|
|
struct FENCE_REG : Register_array<0x100000, 64, NUM_FENCES, 64>
|
|
{
|
|
struct Fence_upper_bound : Bitfield<44, 20> { };
|
|
struct Fence_pitch : Bitfield<32, 11> { };
|
|
struct Fence_lower_bound : Bitfield<12, 20> { };
|
|
struct Tile_walk : Bitfield< 1, 1> { };
|
|
struct Fence_valid : Bitfield< 0, 1> { };
|
|
};
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 12-11.15 p. 5
|
|
*/
|
|
struct GFX_FLSH_CNTL : Register<0x101008, 32> { };
|
|
|
|
|
|
/************************
|
|
** EXECLIST registers **
|
|
************************/
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 435
|
|
*/
|
|
template <long int BASE>
|
|
struct EXECLIST_STATUS_BASE : Register<BASE + 0x234, 64>
|
|
{
|
|
using B = Register<BASE + 0x234, 64>;
|
|
|
|
struct Current_context_id : B::template Bitfield<32, 32> { };
|
|
struct Arbitration_enable : B::template Bitfield<16, 1> { };
|
|
struct Current_active_element_status : B::template Bitfield<14, 2>
|
|
{
|
|
enum {
|
|
NO_ACTIVE_ELEMENT = 0b00,
|
|
ELEMENT_0_ACTIVE = 0b01,
|
|
ELEMENT_1_ACTIVE = 0b10,
|
|
RESERVERD = 0b11,
|
|
};
|
|
};
|
|
struct Last_context_switch_reason : B::template Bitfield< 5, 9> { };
|
|
struct Execlist_0_valid : B::template Bitfield< 4, 1> { };
|
|
struct Execlist_1_valid : B::template Bitfield< 3, 1> { };
|
|
struct Execlist_queue_full : B::template Bitfield< 2, 1> { };
|
|
struct Execlist_write_pointer : B::template Bitfield< 1, 1> { };
|
|
struct Current_execlist_pointer : B::template Bitfield< 0, 1> { };
|
|
};
|
|
|
|
struct EXECLIST_STATUS_RSCUNIT : EXECLIST_STATUS_BASE<0x02000> { };
|
|
struct EXECLIST_STATUS_VCSUNIT0 : EXECLIST_STATUS_BASE<0x12000> { };
|
|
struct EXECLIST_STATUS_VECSUNIT : EXECLIST_STATUS_BASE<0x1A000> { };
|
|
struct EXECLIST_STATUS_VCSUNIT1 : EXECLIST_STATUS_BASE<0x1C000> { };
|
|
struct EXECLIST_STATUS_BSCUNIT : EXECLIST_STATUS_BASE<0x22000> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 438
|
|
*/
|
|
template <long int BASE>
|
|
struct EXECLIST_SUBMITPORT_BASE : Register<BASE + 0x230, 32>
|
|
{
|
|
using B = Register<BASE + 0x230, 32>;
|
|
|
|
struct Context_descriptor_dw : B::template Bitfield<0, 32> { };
|
|
};
|
|
|
|
struct EXECLIST_SUBMITPORT_RSCUNIT : EXECLIST_SUBMITPORT_BASE<0x02000> { };
|
|
struct EXECLIST_SUBMITPORT_VCSUNIT0 : EXECLIST_SUBMITPORT_BASE<0x12000> { };
|
|
struct EXECLIST_SUBMITPORT_VECSUNIT : EXECLIST_SUBMITPORT_BASE<0x1A000> { };
|
|
struct EXECLIST_SUBMITPORT_VCSUNIT1 : EXECLIST_SUBMITPORT_BASE<0x1C000> { };
|
|
struct EXECLIST_SUBMITPORT_BSCUNIT : EXECLIST_SUBMITPORT_BASE<0x22000> { };
|
|
|
|
/*
|
|
* IHD-OS-BDW-Vol 2c-11.15 p. 266 ff.
|
|
* IHD-OS-BDW-Vol 6-11.15 p. 19 ff.
|
|
*/
|
|
enum {
|
|
CTXT_ST_BUF_QW_NUM = 8,
|
|
CTXT_ST_BUF_NUM = 6,
|
|
};
|
|
template <long int BASE>
|
|
struct CTXT_ST_BUF_BASE : Register_array<BASE + 0x370, 64, CTXT_ST_BUF_NUM, 64>
|
|
{
|
|
using B = Register_array<BASE + 0x370, 64, CTXT_ST_BUF_NUM, 64>;
|
|
|
|
/*
|
|
* Judging by the documentation it seems that one context status
|
|
* buffer in fact contains the same DWORD twice.
|
|
*/
|
|
struct Context_status_udw : B::template Bitfield<32, 32> { };
|
|
struct Context_status_ldw : B::template Bitfield< 0, 32> { };
|
|
};
|
|
|
|
struct CTXT_ST_BUF_RCSUNIT : CTXT_ST_BUF_BASE<0x2000> { };
|
|
|
|
struct PGTBL_CTL2 : Register<0x20C4, 32> { };
|
|
|
|
private:
|
|
|
|
Mmio::Delayer &_delayer;
|
|
|
|
void _fw_reset()
|
|
{
|
|
using namespace Genode;
|
|
|
|
/* "needs to be initialized by newly loaded gfx driver" */
|
|
write_post<FORCEWAKE_MT>(FORCEWAKE_MT::RESET);
|
|
read<MISC_CTRL0>();
|
|
}
|
|
|
|
/**
|
|
* Set forcewake state, i.e., prevent GT from powering down
|
|
*/
|
|
void _fw_enable(unsigned id)
|
|
{
|
|
using namespace Genode;
|
|
|
|
unsigned const i = 1u << id;
|
|
|
|
FORCEWAKE_MT::access_t v = 0;
|
|
FORCEWAKE_MT::Multiple_force_wake_mask::set(v, i);
|
|
FORCEWAKE_MT::Force_wake_request_for_thread_0::set(v, i);
|
|
|
|
write<FORCEWAKE_MT>(v);
|
|
read<MISC_CTRL0>();
|
|
|
|
try {
|
|
wait_for(Attempts(50), Microseconds(1000), _delayer,
|
|
GTSP1::Equal(1));
|
|
} catch (Polling_timeout) {
|
|
error("could not enable force-wake engine");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear forcewake state
|
|
*/
|
|
void _fw_disable(unsigned id)
|
|
{
|
|
using namespace Genode;
|
|
|
|
unsigned const i = 1u << id;
|
|
|
|
FORCEWAKE_MT::access_t v = 0;
|
|
FORCEWAKE_MT::Multiple_force_wake_mask::set(v, i);
|
|
|
|
write<FORCEWAKE_MT>(v);
|
|
read<MISC_CTRL0>();
|
|
|
|
try {
|
|
wait_for(Attempts(50), Microseconds(1000), _delayer,
|
|
GTSP1::Equal(0));
|
|
} catch (Polling_timeout) {
|
|
error("could not disable force-wake engine");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reset interrupts
|
|
*/
|
|
void _intr_reset()
|
|
{
|
|
write_post<MASTER_INT_CTL>(0);
|
|
|
|
write_post<GT_0_INTERRUPT_IMR>(0xffffffff);
|
|
write<GT_0_INTERRUPT_IER>(0);
|
|
|
|
/* do it like they do in Rome^WLinux */
|
|
write_post<GT_0_INTERRUPT_IIR>(0xffffffff);
|
|
write_post<GT_0_INTERRUPT_IIR>(0xffffffff);
|
|
|
|
/* mask all in the hardware status mask register */
|
|
write_post<HWSTAM>(0xffffffff);
|
|
|
|
/* TODO DE intr handling (p. 363) */
|
|
}
|
|
|
|
/**
|
|
* Enable interrupts
|
|
*/
|
|
void _intr_enable()
|
|
{
|
|
using namespace Genode;
|
|
|
|
/* GT0 RCS/BCS */
|
|
{
|
|
uint32_t tmp = read<GT_0_INTERRUPT_IIR>();
|
|
if (tmp != 0) { error("GT_0_INTERRUPT_IIR not zero"); }
|
|
|
|
GT_0_INTERRUPT_IER::access_t ier = 0;
|
|
GT_0_INTERRUPT_IER::Cs_mi_user_interrupt::set(ier, 1);
|
|
GT_0_INTERRUPT_IER::Cs_ctx_switch_interrupt::set(ier, 1);
|
|
GT_0_INTERRUPT_IER::Bcs_mi_user_interrupt::set(ier, 1);
|
|
GT_0_INTERRUPT_IER::Bcs_ctx_switch_interrupt::set(ier, 1);
|
|
write<GT_0_INTERRUPT_IER>(ier);
|
|
|
|
GT_0_INTERRUPT_IMR::access_t imr = ~0u;
|
|
GT_0_INTERRUPT_IMR::Cs_mi_user_interrupt::set(imr, 0);
|
|
GT_0_INTERRUPT_IMR::Cs_ctx_switch_interrupt::set(imr, 0);
|
|
GT_0_INTERRUPT_IMR::Bcs_mi_user_interrupt::set(imr, 0);
|
|
GT_0_INTERRUPT_IMR::Bcs_ctx_switch_interrupt::set(imr, 0);
|
|
write_post<GT_0_INTERRUPT_IMR>(imr);
|
|
|
|
/* demask also in the hardware status mask register */
|
|
write_post<HWSTAM>(imr);
|
|
}
|
|
|
|
/* GT1 VCS1/VCS2 */
|
|
{
|
|
uint32_t tmp = read<GT_1_INTERRUPT_IIR>();
|
|
if (tmp != 0) { error("GT_1_INTERRUPT_IIR not zero"); }
|
|
|
|
GT_1_INTERRUPT_IER::access_t ier = 0;
|
|
GT_1_INTERRUPT_IER::Vcs1_mi_user_interrupt::set(ier, 1);
|
|
GT_1_INTERRUPT_IER::Vcs1_ctx_switch_interrupt::set(ier, 1);
|
|
GT_1_INTERRUPT_IER::Vcs2_mi_user_interrupt::set(ier, 1);
|
|
GT_1_INTERRUPT_IER::Vcs2_ctx_switch_interrupt::set(ier, 1);
|
|
write<GT_1_INTERRUPT_IER>(ier);
|
|
|
|
GT_1_INTERRUPT_IMR::access_t imr = ~0u;
|
|
GT_1_INTERRUPT_IMR::Vcs1_mi_user_interrupt::set(imr, 0);
|
|
GT_1_INTERRUPT_IMR::Vcs1_ctx_switch_interrupt::set(imr, 0);
|
|
GT_1_INTERRUPT_IMR::Vcs2_mi_user_interrupt::set(imr, 0);
|
|
GT_1_INTERRUPT_IMR::Vcs2_ctx_switch_interrupt::set(imr, 0);
|
|
write_post<GT_1_INTERRUPT_IMR>(imr);
|
|
}
|
|
|
|
/* GT2 GTPM */
|
|
{
|
|
uint32_t tmp = read<GT_2_INTERRUPT_IIR>();
|
|
if (tmp != 0) { error("GT_2_INTERRUPT_IIR not zero"); }
|
|
|
|
GT_2_INTERRUPT_IER::access_t ier = 0;
|
|
write<GT_2_INTERRUPT_IER>(ier);
|
|
|
|
GT_2_INTERRUPT_IMR::access_t imr = ~0u;
|
|
write_post<GT_2_INTERRUPT_IMR>(imr);
|
|
}
|
|
|
|
/* GT3 VECS*/
|
|
{
|
|
uint32_t tmp = read<GT_3_INTERRUPT_IIR>();
|
|
if (tmp != 0) { error("GT_3_INTERRUPT_IIR not zero"); }
|
|
|
|
GT_3_INTERRUPT_IER::access_t ier = 0;
|
|
GT_3_INTERRUPT_IER::Vecs_mi_user_interrupt::set(ier, 1);
|
|
GT_3_INTERRUPT_IER::Vecs_ctx_switch_interrupt::set(ier, 1);
|
|
write<GT_3_INTERRUPT_IER>(ier);
|
|
|
|
GT_3_INTERRUPT_IMR::access_t imr = ~0u;
|
|
GT_3_INTERRUPT_IMR::Vecs_mi_user_interrupt::set(imr, 0);
|
|
GT_3_INTERRUPT_IMR::Vecs_ctx_switch_interrupt::set(imr, 0);
|
|
write_post<GT_3_INTERRUPT_IMR>(imr);
|
|
}
|
|
|
|
/* finally enable interrupts */
|
|
write_post<MASTER_INT_CTL::Master_interrupt_enable>(1);
|
|
}
|
|
|
|
/**
|
|
* Disable Render P-states
|
|
*/
|
|
void _disable_rps()
|
|
{
|
|
/*
|
|
* Set RC0 state -- does not matter at this point b/c
|
|
* we disable RC states entirely.
|
|
*/
|
|
write_post<RC_CTRL1::Rc_state>(0);
|
|
|
|
write<RC_CTRL0>(0);
|
|
write<RP_FREQ_NORMAL::Turbo_disable>(1);
|
|
write<RP_CTRL>(0);
|
|
}
|
|
|
|
/**
|
|
* Reset fence registers
|
|
*/
|
|
void _reset_fences()
|
|
{
|
|
for (int i = 0; i < NUM_FENCES; i++) {
|
|
write<FENCE_REG>(i, 0);
|
|
read<FENCE_REG>(i);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear fault registers of all engines
|
|
*/
|
|
void _clear_fault_regs()
|
|
{
|
|
/* TODO */
|
|
}
|
|
|
|
/**
|
|
* Flush GFX TLB in the system agent
|
|
*/
|
|
void _gfx_flush_cntl()
|
|
{
|
|
write_post<GFX_FLSH_CNTL>(1);
|
|
}
|
|
|
|
/**
|
|
* Setup page attributes
|
|
*/
|
|
void _set_page_attributes()
|
|
{
|
|
enum { NUM_PAT = 8, };
|
|
PAT_INDEX::access_t p[NUM_PAT] = {};
|
|
|
|
unsigned const mt[NUM_PAT] {
|
|
PAT_INDEX::Mem_type::WB,
|
|
PAT_INDEX::Mem_type::WC,
|
|
PAT_INDEX::Mem_type::WT,
|
|
PAT_INDEX::Mem_type::UC,
|
|
PAT_INDEX::Mem_type::WB,
|
|
PAT_INDEX::Mem_type::WB,
|
|
PAT_INDEX::Mem_type::WB,
|
|
PAT_INDEX::Mem_type::WB,
|
|
};
|
|
|
|
unsigned const tc[NUM_PAT] {
|
|
PAT_INDEX::Target_cache::LLC,
|
|
PAT_INDEX::Target_cache::LLCELLC,
|
|
PAT_INDEX::Target_cache::LLCELLC,
|
|
PAT_INDEX::Target_cache::ELLC,
|
|
PAT_INDEX::Target_cache::LLCELLC,
|
|
PAT_INDEX::Target_cache::LLCELLC,
|
|
PAT_INDEX::Target_cache::LLCELLC,
|
|
PAT_INDEX::Target_cache::LLCELLC,
|
|
};
|
|
|
|
unsigned const la[NUM_PAT] {
|
|
PAT_INDEX::Lru_age::UCR,
|
|
PAT_INDEX::Lru_age::UCR,
|
|
PAT_INDEX::Lru_age::UCR,
|
|
PAT_INDEX::Lru_age::UCR,
|
|
PAT_INDEX::Lru_age::UCR,
|
|
PAT_INDEX::Lru_age::A0,
|
|
PAT_INDEX::Lru_age::DNC,
|
|
PAT_INDEX::Lru_age::A3,
|
|
};
|
|
|
|
uint64_t v = 0u;
|
|
for (int i = 0; i < NUM_PAT; i++) {
|
|
PAT_INDEX::Lru_age::set( p[i], la[i]);
|
|
PAT_INDEX::Mem_type::set( p[i], mt[i]);
|
|
PAT_INDEX::Target_cache::set(p[i], tc[i]);
|
|
v |= (p[i] & 0xff) << (8 * i);
|
|
}
|
|
|
|
write<PAT_INDEX_L>(v);
|
|
write<PAT_INDEX_H>(v >> 32);
|
|
}
|
|
|
|
/**
|
|
* Reset engine
|
|
*/
|
|
template <typename REG>
|
|
bool _reset_engine()
|
|
{
|
|
typename REG::access_t v = 0;
|
|
REG::Mask_bits::set(v, 1);
|
|
REG::Request_reset::set(v, 1);
|
|
write_post<REG>(v);
|
|
try {
|
|
wait_for(Attempts(35), Microseconds(20), _delayer,
|
|
typename REG::Ready_for_reset::Equal(1));
|
|
} catch (Mmio::Polling_timeout) {
|
|
Genode::error("could not reset engine");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Reset engine by using hardware id
|
|
*
|
|
* \param id hardware id of the engine to be resetted
|
|
*/
|
|
bool _reset_engine(unsigned id)
|
|
{
|
|
switch (id) {
|
|
case RCS_ID: return _reset_engine<CS_RESET_CTRL>();
|
|
case BCS_ID: return _reset_engine<BCS_RESET_CTRL>();
|
|
default: return true;
|
|
}
|
|
}
|
|
|
|
bool _reset_engines()
|
|
{
|
|
for (int i = 0; i < NUM_ENGINES; i++) {
|
|
if (!_reset_engine(i)) { return false; }
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Reset device
|
|
*/
|
|
void _reset_device()
|
|
{
|
|
_fw_enable(FORCEWAKE_ID_RENDER);
|
|
|
|
bool res = _reset_engines();
|
|
if (!res) {
|
|
Genode::warning("cannot reset device, engines not ready");
|
|
return;
|
|
}
|
|
|
|
write<GDRST::Graphics_full_soft_reset_ctl>(1);
|
|
try {
|
|
wait_for(Attempts(50), Microseconds(10), _delayer,
|
|
GDRST::Graphics_full_soft_reset_ctl::Equal(0));
|
|
} catch (Mmio::Polling_timeout) {
|
|
Genode::error("resetting device failed");
|
|
}
|
|
|
|
_fw_disable(FORCEWAKE_ID_RENDER);
|
|
}
|
|
|
|
/**
|
|
* Disable north DE handshake
|
|
*/
|
|
void _disable_nde_handshake()
|
|
{
|
|
NDE_RSTWRN_OPT::access_t v = read<NDE_RSTWRN_OPT>();
|
|
NDE_RSTWRN_OPT::Rst_pch_handshake_en::set(v, 0);
|
|
write<NDE_RSTWRN_OPT>(v);
|
|
}
|
|
|
|
/**
|
|
* Enable execlist
|
|
*/
|
|
void _enable_execlist()
|
|
{
|
|
GFX_MODE::access_t v = read<GFX_MODE>();
|
|
|
|
GFX_MODE::Execlist_enable_mask::set(v, 1);
|
|
GFX_MODE::Execlist_enable::set(v, 1);
|
|
|
|
write<GFX_MODE>(v);
|
|
}
|
|
|
|
public:
|
|
|
|
Mmio(Mmio::Delayer &delayer, addr_t const base)
|
|
: Genode::Mmio(base), _delayer(delayer) { }
|
|
|
|
template <typename T>
|
|
void write_post(typename T::access_t const value)
|
|
{
|
|
write<T>(value);
|
|
(void)read<T>();
|
|
}
|
|
|
|
void forcewake_enable() { _fw_enable(FORCEWAKE_ID_RENDER); }
|
|
void forcewake_disable() { _fw_disable(FORCEWAKE_ID_RENDER); }
|
|
|
|
void reset()
|
|
{
|
|
_intr_reset();
|
|
_reset_device();
|
|
_fw_reset();
|
|
_reset_fences();
|
|
|
|
_disable_nde_handshake();
|
|
|
|
_set_page_attributes();
|
|
}
|
|
|
|
void init()
|
|
{
|
|
_disable_rps();
|
|
_enable_execlist();
|
|
}
|
|
|
|
void enable_intr()
|
|
{
|
|
write<Igd::Mmio::RCS_EMR>(0xffffff00);
|
|
|
|
_intr_enable();
|
|
}
|
|
|
|
void disable_master_irq()
|
|
{
|
|
write_post<Igd::Mmio::MASTER_INT_CTL::Master_interrupt_enable>(0);
|
|
}
|
|
|
|
void enable_master_irq()
|
|
{
|
|
write_post<Igd::Mmio::MASTER_INT_CTL::Master_interrupt_enable>(1);
|
|
}
|
|
|
|
void flush_gfx_tlb() { _gfx_flush_cntl(); }
|
|
|
|
void clear_errors()
|
|
{
|
|
write_post<ERROR>(0);
|
|
}
|
|
|
|
void update_context_status_pointer()
|
|
{
|
|
RCS_RING_CONTEXT_STATUS_PTR::access_t const wp = read<RCS_RING_CONTEXT_STATUS_PTR::Write_pointer>();
|
|
if (wp > 0x05) {
|
|
Genode::warning("ring context status write-pointer invalid");
|
|
return;
|
|
}
|
|
|
|
RCS_RING_CONTEXT_STATUS_PTR::access_t v = 0;
|
|
RCS_RING_CONTEXT_STATUS_PTR::Read_pointer_mask::set(v, 0xff);
|
|
RCS_RING_CONTEXT_STATUS_PTR::Read_pointer::set(v, wp);
|
|
write<RCS_RING_CONTEXT_STATUS_PTR>(v);
|
|
}
|
|
|
|
bool csb_unread()
|
|
{
|
|
RCS_RING_CONTEXT_STATUS_PTR::access_t const r = read<RCS_RING_CONTEXT_STATUS_PTR::Read_pointer>();
|
|
RCS_RING_CONTEXT_STATUS_PTR::access_t const w = read<RCS_RING_CONTEXT_STATUS_PTR::Write_pointer>();
|
|
|
|
return (r != w) && (r + 1) % CTXT_ST_BUF_NUM <= w; /* XXX */
|
|
}
|
|
|
|
|
|
uint32_t find_free_fence()
|
|
{
|
|
uint32_t id = 0xff;
|
|
|
|
for (int i = 0; i < NUM_FENCES; i++) {
|
|
if (!read<FENCE_REG::Fence_valid>(i)) {
|
|
id = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
uint32_t update_fence(uint32_t id, addr_t lower, addr_t upper,
|
|
uint32_t pitch, bool x)
|
|
{
|
|
FENCE_REG::access_t v = 0;
|
|
|
|
typename FENCE_REG::access_t const l = lower >> 12;
|
|
typename FENCE_REG::access_t const u = upper >> 12;
|
|
FENCE_REG::Fence_upper_bound::set(v, u);
|
|
FENCE_REG::Fence_lower_bound::set(v, l);
|
|
FENCE_REG::Fence_pitch::set(v, pitch);
|
|
enum { MI_TILE_XMAJOR = 0b00, MI_TILE_YMAJOR = 0b01, };
|
|
FENCE_REG::Tile_walk::set(v, x ? MI_TILE_XMAJOR : MI_TILE_YMAJOR);
|
|
FENCE_REG::Fence_valid::set(v, 1);
|
|
|
|
write<FENCE_REG>(v, id);
|
|
(void)read<FENCE_REG>(id);
|
|
return id;
|
|
}
|
|
|
|
void clear_fence(uint32_t const id)
|
|
{
|
|
write<FENCE_REG>(0, id);
|
|
(void)read<FENCE_REG>(id);
|
|
}
|
|
|
|
/**
|
|
* Check if fault
|
|
*/
|
|
bool fault_regs_valid()
|
|
{
|
|
bool result = false;
|
|
|
|
/* TODO */
|
|
|
|
return result;
|
|
}
|
|
|
|
/*********************
|
|
** DEBUG interface **
|
|
*********************/
|
|
|
|
void dump();
|
|
void power_dump();
|
|
void error_dump();
|
|
void intr_dump();
|
|
void fault_dump();
|
|
void execlist_status_dump();
|
|
void context_status_pointer_dump();
|
|
};
|
|
|
|
#endif /* _MMIO_H_ */
|