Angel Pons has uploaded this change for review. ( https://review.coreboot.org/c/libgfxinit/+/46631 )
Change subject: [HACK] Switch LSPCON to PCON mode ......................................................................
[HACK] Switch LSPCON to PCON mode
Change-Id: I3c9e67caf9511d62b19c0c175e8e75080fb7ac7d Signed-off-by: Angel Pons th3fanbus@gmail.com --- M common/hw-gfx-dp_aux_ch.adb M common/hw-gfx-dp_aux_ch.ads M common/hw-gfx-dp_info.adb 3 files changed, 156 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/libgfxinit refs/changes/31/46631/1
diff --git a/common/hw-gfx-dp_aux_ch.adb b/common/hw-gfx-dp_aux_ch.adb index b8eb510..7406d5e 100644 --- a/common/hw-gfx-dp_aux_ch.adb +++ b/common/hw-gfx-dp_aux_ch.adb @@ -371,6 +371,42 @@
----------------------------------------------------------------------------
+ procedure I2C_Write_Byte + (Port : in T; + Address : in I2C.Transfer_Address; + Offset : in Word8; + Value : in Word8; + Success : out Boolean) + is + Index_Payload : constant DP_Defs.Aux_Payload := (Offset, Value, others => 16#00#); + + Length : constant I2C.Transfer_Length := 1; + Data : constant I2C.Transfer_Data := (Value, others => 16#00#); + begin + Do_I2C_Write (Port, Address, 1 + Length, Index_Payload, Success); + end I2C_Write_Byte; + + procedure I2C_Read_Byte + (Port : in T; + Address : in I2C.Transfer_Address; + Offset : in Word8; + Value : out Word8; + Success : out Boolean) + is + Index_Payload : constant DP_Defs.Aux_Payload := (Offset, others => 16#00#); + + Length : I2C.Transfer_Length := 1; + Data : I2C.Transfer_Data := (others => 16#00#); + begin + Do_I2C_Write (Port, Address, 1, Index_Payload, Success); + + if Success then + Do_I2C_Read (Port, Address, Length, Data, Success); + Success := Success and Length = 1; + end if; + Value := Data (0); + end I2C_Read_Byte; + procedure I2C_Read (Port : in T; Address : in I2C.Transfer_Address; diff --git a/common/hw-gfx-dp_aux_ch.ads b/common/hw-gfx-dp_aux_ch.ads index 85fddd0..78709a8 100644 --- a/common/hw-gfx-dp_aux_ch.ads +++ b/common/hw-gfx-dp_aux_ch.ads @@ -45,6 +45,20 @@
----------------------------------------------------------------------------
+ procedure I2C_Write_Byte + (Port : in T; + Address : in I2C.Transfer_Address; + Offset : in Word8; + Value : in Word8; + Success : out Boolean); + + procedure I2C_Read_Byte + (Port : in T; + Address : in I2C.Transfer_Address; + Offset : in Word8; + Value : out Word8; + Success : out Boolean); + procedure I2C_Read (Port : in T; Address : in I2C.Transfer_Address; diff --git a/common/hw-gfx-dp_info.adb b/common/hw-gfx-dp_info.adb index bf09933..93a1caf 100644 --- a/common/hw-gfx-dp_info.adb +++ b/common/hw-gfx-dp_info.adb @@ -15,15 +15,115 @@ with Ada.Unchecked_Conversion;
with HW.Debug; +with HW.Time; with GNAT.Source_Info;
with HW.GFX.DP_Defs; +with HW.GFX.I2C;
use type HW.Word8; use type HW.Word16;
package body HW.GFX.DP_Info is
+ procedure Read_Lspcon_Mode + (Port : in T; + Mode : out Word8; + Success : out Boolean) + is + begin + pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); + + for I in 1 .. 6 loop + Aux_Ch.I2C_Read_Byte + (Port => Port, + Address => 16#40#, + Offset => 16#41#, + Value => Mode, + Success => Success); + exit when Success; + Time.U_Delay (500); + end loop; + end Read_Lspcon_Mode; + + procedure Write_Lspcon_Mode + (Port : in T; + Mode : in Word8; + Success : out Boolean) + is + begin + pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); + + for I in 1 .. 6 loop + Aux_Ch.I2C_Write_Byte + (Port => Port, + Address => 16#40#, + Offset => 16#40#, + Value => 16#01#, + Success => Success); + exit when Success; + Time.U_Delay (500); + end loop; + end Write_Lspcon_Mode; + + procedure Set_Lspcon_To_Pcon_Mode (Port : in T; Success : out Boolean) + is + Timeout : constant Natural := 20; + Lspcon_Mode : Word8; + begin + pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); + + Read_Lspcon_Mode + (Port => Port, + Mode => Lspcon_Mode, + Success => Success); + + if not Success then + pragma Debug (Debug.Put_Line ("Could not determine LSPCON mode.")); + return; + end if; + + pragma Debug (Debug.Put_Line ("Current LSPCON mode: " & Lspcon_Mode'Image)); + + if Lspcon_Mode /= 0 then + pragma Debug (Debug.Put_Line ("LSPCON mode is good enough.")); + return; + end if; + + -- Change to PCON mode if necessary + Write_Lspcon_Mode + (Port => Port, + Mode => Lspcon_Mode, + Success => Success); + + if not Success then + pragma Debug (Debug.Put_Line ("Could not write new LSPCON mode.")); + return; + end if; + + for I in 1 .. Timeout loop + Read_Lspcon_Mode + (Port => Port, + Mode => Lspcon_Mode, + Success => Success); + if not Success then + pragma Debug (Debug.Put_Line ("Could not determine new LSPCON mode.")); + return; + end if; + if Lspcon_Mode /= 0 then + pragma Debug (Debug.Put_Line ("Successfully set LSPCON to PCON mode.")); + pragma Debug (Debug.Put_Line ("Current LSPCON mode: " & Lspcon_Mode'Image)); + return; + end if; + Time.M_Delay (100); + end loop; + if Success then + pragma Debug (Debug.Put_Line ("Timed out waiting for LSPCON mode change.")); + pragma Debug (Debug.Put_Line ("Current LSPCON mode: " & Lspcon_Mode'Image)); + Success := False; + end if; + end Set_Lspcon_To_Pcon_Mode; + procedure Read_Caps (Link : in out DP_Link; Port : in T; @@ -36,6 +136,12 @@ begin pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+ Set_Lspcon_To_Pcon_Mode (Port, Success); + + if not Success then + pragma Debug (Debug.Put_Line ("Could not change LSPCON mode.")); + end if; + Length := Caps_Size; Aux_Ch.Aux_Read (Port => Port,