gma adl: Add missing Alder Lake TC bits
Add some missing ADL-P handling and workarounds for TC ports.
* Ownership is handled in DDI_BUF_CTL (Need_TC_PHY_Ownership).
* Additional "Loadgen" selection is needed in DKL PHY
configuration (Need_TC_Loadgen_Select).
* Explicit blocking of TC cold state is not needed (Block_TC_Cold).
* A workaround is needed to avoid PHYs hanging when switching from
TBT mode to DP-alt/legacy mode (Need_TBT_DP_Alt_Switch_Wa).
This is based on work by several authors that was originally
squashed into another commit:
https://review.coreboot.org/c/libgfxinit/+/67801/
Change-Id: I32fd558c27f4f9658aea799f1b6c679be4d31feb
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/libgfxinit/+/507
Reviewed-by: Thomas Heijligen <src@posteo.de>
Tested-by: Ada SPARK <gnatbot@sourcearcade.org>
diff --git a/common/hw-gfx-gma-config.ads.template b/common/hw-gfx-gma-config.ads.template
index 5801bfe..43c43d5 100644
--- a/common/hw-gfx-gma-config.ads.template
+++ b/common/hw-gfx-gma-config.ads.template
@@ -352,6 +352,10 @@
----------- Type-C: ----------
Has_Type_C_Ports : <genbool> := Tigerlake_On;
+ Need_TC_PHY_Ownership : <genbool> := AlderlakeP_On;
+ Need_TC_Loadgen_Select : <genbool> := AlderlakeP_On;
+ Need_TBT_DP_Alt_Switch_Wa : <genbool> := AlderlakeP_On;
+ Block_TC_Cold : <genbool> := Gen_Tigerlake;
----------- Rawclk -----------
Need_Rawclk_Numerator : <genbool> := Tigerlake_On;
diff --git a/common/tigerlake/hw-gfx-gma-connectors-tc.adb b/common/tigerlake/hw-gfx-gma-connectors-tc.adb
index 84eb4b0..ca87fff 100644
--- a/common/tigerlake/hw-gfx-gma-connectors-tc.adb
+++ b/common/tigerlake/hw-gfx-gma-connectors-tc.adb
@@ -28,7 +28,8 @@
then Registers.HIP_INDEX_REG0
else Registers.HIP_INDEX_REG1);
- function HIP_INDEX_VAL (P : USBC_Port; Val : Word32) return Word32 is
+ function HIP_INDEX_VAL (P : USBC_Port; Val : Word32) return Word32
+ is
(Val * 2 ** (8 * ((GPU_Port'Pos (P) - GPU_Port'Pos (DDI_TC1)) mod 4)));
DKL_DP_MODE : constant Port_Regs_Array :=
@@ -39,7 +40,15 @@
DDI_TC5 => Registers.DKL_DP_MODE_5,
DDI_TC6 => Registers.DKL_DP_MODE_6);
- function DP_PIN_ASSIGNMENT_SHIFT (P : USBC_Port) return Natural is
+ DKL_PCS_DW5 : constant Port_Regs_Array :=
+ (DDI_TC1 => Registers.DKL_PCS_DW5_1,
+ DDI_TC2 => Registers.DKL_PCS_DW5_2,
+ DDI_TC3 => Registers.DKL_PCS_DW5_3,
+ DDI_TC4 => Registers.DKL_PCS_DW5_4,
+ others => Registers.Invalid_Register);
+
+ function DP_PIN_ASSIGNMENT_SHIFT (P : USBC_Port) return Natural
+ is
(case P is
when DDI_TC1 => 0,
when DDI_TC2 => 4,
@@ -303,8 +312,9 @@
---------------------------------------------------------------------
procedure Set_Vswing_And_Deemphasis
- (Port : USBC_Port;
- Buf_Trans : Buffer_Trans)
+ (Port : USBC_Port;
+ Buf_Trans : Buffer_Trans;
+ HDMI : Boolean := False)
is
-- Preshoot Coeff, Deemphasis Coeff, VSwing Control,
DPcnt_Mask : constant Word32 := 16#3_ff07#;
@@ -313,6 +323,17 @@
Shift_Left (Buf_Trans.Deemphasis_Control, 8) or
Shift_Left (Buf_Trans.Preshoot_Control, 13);
DKL_TX_DP20BITMODE : constant := 1 * 2 ** 2;
+
+ function DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1 (N : Word32) return Word32
+ is
+ (Shift_Left (N and 16#3#, 3));
+
+ function DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2 (N : Word32) return Word32
+ is
+ (Shift_Left (N and 16#3#, 5));
+
+ DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK : constant := 16#18#;
+ DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK : constant := 16#60#;
begin
for Lane in 0 .. 1 loop
Set_HIP_For_Port (Port, Lane);
@@ -323,6 +344,31 @@
(Vswing_Regs (Port).DKL_TX_DPCNTL1, DPcnt_Mask, DPcnt_Val);
Registers.Unset_Mask
(Vswing_Regs (Port).DKL_TX_DPCNTL2, DKL_TX_DP20BITMODE);
+
+ if Config.Need_TC_Loadgen_Select then
+ declare
+ Val : Word32;
+ begin
+ if HDMI then
+ if Lane = 0 then
+ Val := DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1 (0) or
+ DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2 (2);
+ else
+ Val := DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1 (3) or
+ DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2 (3);
+ end if;
+ else
+ Val := DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1 (0) or
+ DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2 (0);
+ end if;
+
+ Registers.Unset_And_Set_Mask
+ (Register => Vswing_Regs (Port).DKL_TX_DPCNTL2,
+ Mask_Unset => DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK or
+ DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK,
+ Mask_Set => Val);
+ end;
+ end if;
end loop;
end Set_Vswing_And_Deemphasis;
@@ -334,6 +380,7 @@
Link : DP_Link;
Train_Set : DP_Info.Train_Set)
is
+ DKL_PCS_DW5_CORE_SOFTRESET : constant := 1 * 2 ** 11;
function To_Buf_Trans_Index
(Set : DP_Info.Train_Set) return Buffer_Trans_Range
is
@@ -395,13 +442,29 @@
Set_Vswing_And_Deemphasis (Port, Buf_Trans);
+ -- Wa_1309179469: Taken from i915's adlp_tbt_to_dp_alt_switch_wa()
+ if Config.Need_TBT_DP_Alt_Switch_Wa and then
+ Port in Valid_TC_Port and then
+ not Was_Enabled
+ then
+ for Lane in 0 .. 1 loop
+ Set_HIP_For_Port (Port, Lane);
+ Registers.Unset_Mask
+ (Register => DKL_PCS_DW5 (Port),
+ Mask => DKL_PCS_DW5_CORE_SOFTRESET);
+ end loop;
+ end if;
+
Registers.Unset_And_Set_Mask
(Register => DDI_BUF_CTL (Port),
Mask_Unset => DDI_BUF_CTL_TRANS_SELECT_MASK or
DDI_BUF_CTL_PORT_REVERSAL or
DDI_BUF_CTL_PORT_WIDTH_MASK,
Mask_Set => DDI_BUF_CTL_BUFFER_ENABLE or
- DDI_BUF_CTL_PORT_WIDTH (Link.Lane_Count));
+ DDI_BUF_CTL_PORT_WIDTH (Link.Lane_Count) or
+ (if Config.Need_TC_PHY_Ownership
+ then DDI_BUF_CTL_TC_PHY_OWNERSHIP else 0));
+
Registers.Posting_Read (DDI_BUF_CTL (Port));
if not Was_Enabled then
@@ -416,7 +479,7 @@
Buffer_Trans_HDMI (Buffer_Trans_HDMI'Last);
begin
Program_DP_Mode (Port, HDMI_Lane_Count);
- Set_Vswing_And_Deemphasis (Port, Buf_Trans);
+ Set_Vswing_And_Deemphasis (Port, Buf_Trans, HDMI => True);
Registers.Unset_And_Set_Mask
(Register => DDI_BUF_CTL (Port),
diff --git a/common/tigerlake/hw-gfx-gma-connectors-tc.ads b/common/tigerlake/hw-gfx-gma-connectors-tc.ads
index 9e637d0..6bebc73 100644
--- a/common/tigerlake/hw-gfx-gma-connectors-tc.ads
+++ b/common/tigerlake/hw-gfx-gma-connectors-tc.ads
@@ -36,7 +36,8 @@
-- And so far, no SKU needs more.
subtype Valid_TC_Port is USBC_Port range DDI_TC1 .. Config.Last_TC_Port;
- type Port_Regs_Array is array (USBC_Port) of Registers.Registers_Index;
+ type Port_Regs_Array is
+ array (USBC_Port) of Registers.Registers_Invalid_Index;
DDI_BUF_CTL_BUFFER_ENABLE : constant := 1 * 2 ** 31;
DDI_BUF_CTL_TRANS_SELECT_MASK : constant := 16#f# * 2 ** 24;
diff --git a/common/tigerlake/hw-gfx-gma-port_detect.adb b/common/tigerlake/hw-gfx-gma-port_detect.adb
index 9c8c27b..3e9c605 100644
--- a/common/tigerlake/hw-gfx-gma-port_detect.adb
+++ b/common/tigerlake/hw-gfx-gma-port_detect.adb
@@ -117,10 +117,12 @@
-- In order to avoid keeping track of the state and constantly
-- blocking and unblocking, we just block it once at the beginning
-- and leave it that way.
- Connectors.TC.TC_Cold_Request (Connectors.TC.Block, Success);
- if not Success then
- Debug.Put_Line ("Failed to block TCCOLD, Type-C will not work!");
- return;
+ if Config.Block_TC_Cold then
+ Connectors.TC.TC_Cold_Request (Connectors.TC.Block, Success);
+ if not Success then
+ Debug.Put_Line ("Failed to block TCCOLD, Type-C will not work!");
+ return;
+ end if;
end if;
end Initialize;