Nico Huber has uploaded this change for review. ( https://review.coreboot.org/c/libgfxinit/+/35614 )
Change subject: [WIP] gma skl: Implement CDClk switching ......................................................................
[WIP] gma skl: Implement CDClk switching
Change-Id: Ic14cf5981540d36d3f337a43bbec3574be0d3c99 Signed-off-by: Nico Huber nico.h@gmx.de --- M common/hw-gfx-gma.adb M common/hw-gfx.ads M common/skylake/hw-gfx-gma-power_and_clocks_skylake.adb M common/skylake/hw-gfx-gma-power_and_clocks_skylake.ads 4 files changed, 111 insertions(+), 52 deletions(-)
git pull ssh://review.coreboot.org:29418/libgfxinit refs/changes/14/35614/1
diff --git a/common/hw-gfx-gma.adb b/common/hw-gfx-gma.adb index 462f5c4..5898ab2 100644 --- a/common/hw-gfx-gma.adb +++ b/common/hw-gfx-gma.adb @@ -292,6 +292,8 @@ (New_Configs (P).Framebuffer, New_Configs (P).Mode, P)); end loop;
+ Power_And_Clocks.Update_CDClk (New_Configs); + -- enable all pipes that changed and should be active for Pipe in Pipe_Index loop declare diff --git a/common/hw-gfx.ads b/common/hw-gfx.ads index 93a3684..9a4015c 100644 --- a/common/hw-gfx.ads +++ b/common/hw-gfx.ads @@ -66,7 +66,7 @@ Rotation => No_Rotation, Offset => 0);
- subtype Frequency_Type is Pos64 range 19_200_000 .. 624_000_000; + subtype Frequency_Type is Pos64 range 19_200_000 .. 675_000_000;
type DP_Lane_Count is (DP_Lane_Count_1, DP_Lane_Count_2, DP_Lane_Count_4); subtype DP_Lane_Count_Type is Pos64 range 1 .. 4; diff --git a/common/skylake/hw-gfx-gma-power_and_clocks_skylake.adb b/common/skylake/hw-gfx-gma-power_and_clocks_skylake.adb index c6eb2cf..9383aef 100644 --- a/common/skylake/hw-gfx-gma-power_and_clocks_skylake.adb +++ b/common/skylake/hw-gfx-gma-power_and_clocks_skylake.adb @@ -17,6 +17,7 @@ with HW.Time; with HW.Debug; with HW.GFX.GMA.Config; +with HW.GFX.GMA.Config_Helpers; with HW.GFX.GMA.Registers; with HW.GFX.GMA.Power_And_Clocks_Haswell;
@@ -88,12 +89,10 @@
GT_MAILBOX_READY : constant := 1 * 2 ** 31;
- function CDCLK_CTL_CD_FREQ_DECIMAL - (Freq : Pos16; - Plus_Half : Boolean) - return Word32 is + function CDCLK_CTL_CD_FREQ_DECIMAL (CDClk : Frequency_Type) return Word32 is begin - return Word32 (2 * (Pos32 (Freq) - 1)) or (if Plus_Half then 1 else 0); + -- Weirdest representation: CDClk - 1MHz in 10.1 (10 + 1 fractional bit) + return Word32 ((CDClk - 1_000_000) / 500_000); end CDCLK_CTL_CD_FREQ_DECIMAL;
---------------------------------------------------------------------------- @@ -249,41 +248,36 @@ PD_Off (PW1); end Post_All_Off;
- procedure Initialize + function Normalize_CDClk (CDClk : in Int64) return Frequency_Type is + ( if CDClk > 540_000_000 then 675_000_000 + elsif CDClk > 450_000_000 then 540_000_000 + elsif CDClk > 337_500_000 then 450_000_000 + else 337_500_000); + + procedure Set_CDClk (CDClk : in out Frequency_Type) is - CDClk_Change_Timeout : Time.T; - Timed_Out : Boolean; + CDClk_Change_Timeout : constant Time.T := Time.MS_From_Now(3); + Timed_Out : Boolean := False;
MBox_Data0 : Word32; + + Want : constant Frequency_Type := Normalize_CDClk (CDClk); + CDCLK_CTL_CD_Freq : constant Word32 := + (case Want is + when 675_000_000 => CDCLK_CTL_CD_FREQ_SELECT_675MHZ, + when 540_000_000 => CDCLK_CTL_CD_FREQ_SELECT_540MHZ, + when 450_000_000 => CDCLK_CTL_CD_FREQ_SELECT_450MHZ, + when others => CDCLK_CTL_CD_FREQ_SELECT_337_5MHZ) or + CDCLK_CTL_CD_FREQ_DECIMAL (Want); + SKL_CDCLK_Voltage_Level : constant Word64 := + (case Want is + when 675_000_000 => 3, + when 540_000_000 => 2, + when 450_000_000 => 1, + when others => 0); + + CDCLK_CTL : Word32; begin - Registers.Set_Mask - (Register => Registers.NDE_RSTWRN_OPT, - Mask => NDE_RSTWRN_OPT_RST_PCH_Handshake_En); - - Registers.Wait_Set_Mask - (Register => Registers.FUSE_STATUS, - Mask => FUSE_STATUS_PG0_DIST_STATUS); - PD_On (PW1); - PD_On (MISC_IO); - - Registers.Write - (Register => Registers.CDCLK_CTL, - Value => CDCLK_CTL_CD_FREQ_SELECT_337_5MHZ or - CDCLK_CTL_CD_FREQ_DECIMAL (337, True)); - -- TODO: Set to preferred eDP rate: - -- Registers.Unset_And_Set_Mask - -- (Register => Registers.DPLL_CTRL1, - -- Unset_Mask => DPLL_CTRL1_DPLL0_LINK_RATE_MASK, - -- Set_Mask => DPLL_CTRL1_DPLL0_LINK_RATE_...); - Registers.Set_Mask - (Register => Registers.LCPLL1_CTL, - Mask => LCPLL1_CTL_PLL_ENABLE); - Registers.Wait_Set_Mask - (Register => Registers.LCPLL1_CTL, - Mask => LCPLL1_CTL_PLL_LOCK); - - CDClk_Change_Timeout := Time.MS_From_Now (3); - Timed_Out := False; loop GT_Mailbox_Write (MBox => SKL_PCODE_CDCLK_CONTROL, @@ -298,27 +292,79 @@
Timed_Out := Time.Timed_Out (CDClk_Change_Timeout); end loop; - pragma Debug (Timed_Out, Debug.Put_Line - ("ERROR: PCODE not ready for frequency change after 3ms."));
- if not Timed_Out then - GT_Mailbox_Write - (MBox => SKL_PCODE_CDCLK_CONTROL, - Value => 16#0000_0000#); -- 0 - 337.5MHz - -- 1 - 450.0MHz - -- 2 - 540.0MHz - -- 3 - 675.0MHz - Registers.Set_Mask - (Register => Registers.DBUF_CTL, - Mask => DBUF_CTL_DBUF_POWER_REQUEST); - Registers.Wait_Set_Mask - (Register => Registers.DBUF_CTL, - Mask => DBUF_CTL_DBUF_POWER_STATE); + if Timed_Out then + pragma Debug (Debug.Put_Line + ("ERROR: PCODE not ready for frequency change after 3ms.")); + Registers.Read(Registers.CDCLK_CTL, CDCLK_CTL); + CDCLK_CTL := CDCLK_CTL and CDCLK_CTL_CD_FREQ_DECIMAL_MASK; + CDClk := Normalize_CDClk (Int64 (CDCLK_CTL) * 500_000 + 1_000_000); + return; end if;
+ Registers.Write (Registers.CDCLK_CTL, CDCLK_CTL_CD_Freq); + CDClk := Want; + + GT_Mailbox_Write + (MBox => SKL_PCODE_CDCLK_CONTROL, + Value => SKL_CDCLK_Voltage_Level); + Registers.Set_Mask + (Register => Registers.DBUF_CTL, + Mask => DBUF_CTL_DBUF_POWER_REQUEST); + Registers.Wait_Set_Mask + (Register => Registers.DBUF_CTL, + Mask => DBUF_CTL_DBUF_POWER_STATE); + end Set_CDClk; + + procedure Initialize + is + Default_CDClk : Frequency_Type := 337_500_000; + begin + Registers.Set_Mask + (Register => Registers.NDE_RSTWRN_OPT, + Mask => NDE_RSTWRN_OPT_RST_PCH_Handshake_En); + + Registers.Wait_Set_Mask + (Register => Registers.FUSE_STATUS, + Mask => FUSE_STATUS_PG0_DIST_STATUS); + PD_On (PW1); + PD_On (MISC_IO); + + Registers.Write + (Register => Registers.CDCLK_CTL, + Value => CDCLK_CTL_CD_FREQ_SELECT_337_5MHZ or + CDCLK_CTL_CD_FREQ_DECIMAL (Default_CDClk)); + -- TODO: Set to preferred eDP rate: + -- Registers.Unset_And_Set_Mask + -- (Register => Registers.DPLL_CTRL1, + -- Unset_Mask => DPLL_CTRL1_DPLL0_LINK_RATE_MASK, + -- Set_Mask => DPLL_CTRL1_DPLL0_LINK_RATE_...); + Registers.Set_Mask + (Register => Registers.LCPLL1_CTL, + Mask => LCPLL1_CTL_PLL_ENABLE); + Registers.Wait_Set_Mask + (Register => Registers.LCPLL1_CTL, + Mask => LCPLL1_CTL_PLL_LOCK); + + pragma Warnings + (GNAT, Off, """Default_CDClk"" modified by call*", + Reason => "Can only be 337.5MHz here"); + pragma Warnings (GNATprove, Off, "*assignment to ""Default_CDClk"""); + Set_CDClk (Default_CDClk); + pragma Warnings (GNATprove, On, "*assignment to ""Default_CDClk"""); + pragma Warnings (GNAT, On, """Default_CDClk"" modified by call*"); + Config.Raw_Clock := Config.Default_RawClk_Freq; end Initialize;
+ procedure Update_CDClk (Configs : in out Pipe_Configs) + is + CDClk : Frequency_Type := Config_Helpers.Highest_Dotclock (Configs); + begin + Set_CDClk (CDClk); + Config_Helpers.Limit_Dotclock (Configs, CDClk); + end Update_CDClk; + procedure Power_Set_To (Configs : Pipe_Configs) is begin for PD in reverse Dynamic_Domain loop diff --git a/common/skylake/hw-gfx-gma-power_and_clocks_skylake.ads b/common/skylake/hw-gfx-gma-power_and_clocks_skylake.ads index 4db9ab5..75f2d2e 100644 --- a/common/skylake/hw-gfx-gma-power_and_clocks_skylake.ads +++ b/common/skylake/hw-gfx-gma-power_and_clocks_skylake.ads @@ -19,6 +19,17 @@
procedure Initialize;
+ procedure Update_CDClk (Configs : in out Pipe_Configs) + with + Post => + (for all P in Pipe_Index => + Configs (P).Port = Disabled or + (Configs (P).Port = Configs'Old (P).Port and + Configs (P).Framebuffer = Configs'Old (P).Framebuffer and + Configs (P).Cursor = Configs'Old (P).Cursor and + Configs (P).Mode.H_Visible = Configs'Old (P).Mode.H_Visible and + Configs (P).Mode.V_Visible = Configs'Old (P).Mode.V_Visible)); + procedure Power_Set_To (Configs : Pipe_Configs); procedure Power_Up (Old_Configs, New_Configs : Pipe_Configs); procedure Power_Down (Old_Configs, Tmp_Configs, New_Configs : Pipe_Configs);