Nico Huber has submitted this change. ( https://review.coreboot.org/c/libgfxinit/+/35614 )
Change subject: gma skl: Implement CDClk switching ......................................................................
gma skl: Implement CDClk switching
Flow is roughly the same as for Broadwell. Maximum CDClk is now completely controlled by fuses, though. The same frequencies are supported and dot clocks can run at full CDClk speed.
Change-Id: Ic14cf5981540d36d3f337a43bbec3574be0d3c99 Signed-off-by: Nico Huber nico.h@gmx.de Reviewed-on: https://review.coreboot.org/c/libgfxinit/+/35614 Reviewed-by: Matt DeVillier matt.devillier@gmail.com Reviewed-by: Arthur Heymans arthur@aheymans.xyz --- M common/hw-gfx-gma-registers.ads M common/skylake/hw-gfx-gma-power_and_clocks_skylake.adb M common/skylake/hw-gfx-gma-power_and_clocks_skylake.ads 3 files changed, 119 insertions(+), 35 deletions(-)
Approvals: Nico Huber: Verified Matt DeVillier: Looks good to me, but someone else must approve Arthur Heymans: Looks good to me, approved
diff --git a/common/hw-gfx-gma-registers.ads b/common/hw-gfx-gma-registers.ads index 4eb2c04..767284c 100644 --- a/common/hw-gfx-gma-registers.ads +++ b/common/hw-gfx-gma-registers.ads @@ -146,6 +146,7 @@ NDE_RSTWRN_OPT, BLC_PWM_CPU_CTL2, BLC_PWM_CPU_CTL, + DFSM, HTOTAL_A, HBLANK_A, HSYNC_A, @@ -1460,6 +1461,7 @@ PCH_HDMID => 16#0e_1160# / Register_Width,
-- Intel Registers + DFSM => 16#05_1000# / Register_Width, CPU_VGACNTRL => 16#04_1000# / Register_Width, GMCH_VGACNTRL => 16#07_1400# / Register_Width, FUSE_STATUS => 16#04_2000# / Register_Width, 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 2ab7f21..e8087ed 100644 --- a/common/skylake/hw-gfx-gma-power_and_clocks_skylake.adb +++ b/common/skylake/hw-gfx-gma-power_and_clocks_skylake.adb @@ -1,5 +1,5 @@ -- --- Copyright (C) 2014-2016 secunet Security Networks AG +-- Copyright (C) 2014-2016, 2019 secunet Security Networks AG -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by @@ -34,6 +34,12 @@ FUSE_STATUS_DOWNLOAD_STATUS : constant := 1 * 2 ** 31; FUSE_STATUS_PG0_DIST_STATUS : constant := 1 * 2 ** 27;
+ DFSM_DISPLAY_CDCLK_LIMIT_675MHZ : constant := 0 * 2 ** 23; + DFSM_DISPLAY_CDCLK_LIMIT_540MHZ : constant := 1 * 2 ** 23; + DFSM_DISPLAY_CDCLK_LIMIT_450MHZ : constant := 2 * 2 ** 23; + DFSM_DISPLAY_CDCLK_LIMIT_337_5MHZ : constant := 3 * 2 ** 23; + DFSM_DISPLAY_CDCLK_LIMIT_MASK : constant := 3 * 2 ** 23; + type Power_Domain_Values is array (Power_Domain) of Word32; PWR_WELL_CTL_POWER_REQUEST : constant Power_Domain_Values := (MISC_IO => 1 * 2 ** 1, @@ -87,12 +93,10 @@ SKL_CDCLK_PREPARE_FOR_CHANGE : constant := 3; SKL_CDCLK_READY_FOR_CHANGE : constant := 1;
- 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;
---------------------------------------------------------------------------- @@ -232,10 +236,81 @@ PD_Off (PW1); end Post_All_Off;
- procedure Initialize + function Normalize_CDClk (CDClk : in Int64) return Config.CDClk_Range is + ( if CDClk <= 337_500_000 then 337_500_000 + elsif CDClk <= 450_000_000 then 450_000_000 + elsif CDClk <= 540_000_000 then 540_000_000 + else 675_000_000); + + procedure Get_Cur_CDClk (CDClk : out Config.CDClk_Range) is + CDCLK_CTL : Word32; + begin + 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); + end Get_Cur_CDClk; + + procedure Get_Max_CDClk (CDClk : out Config.CDClk_Range) + is + DFSM : Word32; + begin + Registers.Read (Registers.DFSM, DFSM); + CDClk := + (case DFSM and DFSM_DISPLAY_CDCLK_LIMIT_MASK is + when DFSM_DISPLAY_CDCLK_LIMIT_675MHZ => 675_000_000, + when DFSM_DISPLAY_CDCLK_LIMIT_540MHZ => 540_000_000, + when DFSM_DISPLAY_CDCLK_LIMIT_450MHZ => 450_000_000, + when others => 337_500_000); + end Get_Max_CDClk; + + procedure Set_CDClk (CDClk_In : Frequency_Type) + is + CDClk : constant Config.CDClk_Range := + Normalize_CDClk (Frequency_Type'Min (CDClk_In, Config.Max_CDClk)); Success : Boolean; begin + PCode.Mailbox_Request + (MBox => SKL_PCODE_CDCLK_CONTROL, + Command => SKL_CDCLK_PREPARE_FOR_CHANGE, + Reply_Mask => SKL_CDCLK_READY_FOR_CHANGE, + Wait_Ready => True, + Success => Success); + + if not Success then + pragma Debug (Debug.Put_Line + ("ERROR: PCODE not ready for frequency change.")); + return; + end if; + + Registers.Write + (Register => Registers.CDCLK_CTL, + Value => (case CDClk 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 (CDClk)); + + PCode.Mailbox_Write + (MBox => SKL_PCODE_CDCLK_CONTROL, + Command => (case CDClk is + when 675_000_000 => 3, + when 540_000_000 => 2, + when 450_000_000 => 1, + when others => 0)); + 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); + + Config.CDClk := CDClk; + end Set_CDClk; + + procedure Initialize is + begin Registers.Set_Mask (Register => Registers.NDE_RSTWRN_OPT, Mask => NDE_RSTWRN_OPT_RST_PCH_Handshake_En); @@ -246,10 +321,6 @@ 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, @@ -262,34 +333,33 @@ (Register => Registers.LCPLL1_CTL, Mask => LCPLL1_CTL_PLL_LOCK);
- PCode.Mailbox_Request - (MBox => SKL_PCODE_CDCLK_CONTROL, - Command => SKL_CDCLK_PREPARE_FOR_CHANGE, - Reply_Mask => SKL_CDCLK_READY_FOR_CHANGE, - Wait_Ready => True, - Success => Success); - - pragma Debug (not Success, Debug.Put_Line - ("ERROR: PCODE not ready for frequency change.")); - - if Success then - PCode.Mailbox_Write - (MBox => SKL_PCODE_CDCLK_CONTROL, - Command => 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); - end if; + Get_Cur_CDClk (Config.CDClk); + Get_Max_CDClk (Config.Max_CDClk); + Set_CDClk (Config.Default_CDClk_Freq);
Config.Raw_Clock := Config.Default_RawClk_Freq; end Initialize;
+ procedure Limit_Dotclocks + (Configs : in out Pipe_Configs; + CDClk_Switch : out Boolean) + is + begin + Config_Helpers.Limit_Dotclocks (Configs, Config.Max_CDClk); + CDClk_Switch := + Config.CDClk /= Normalize_CDClk + (Config_Helpers.Highest_Dotclock (Configs)); + end Limit_Dotclocks; + + procedure Update_CDClk (Configs : in out Pipe_Configs) + is + New_CDClk : constant Frequency_Type := + Config_Helpers.Highest_Dotclock (Configs); + begin + Set_CDClk (New_CDClk); + Config_Helpers.Limit_Dotclocks (Configs, Config.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..d5b9685 100644 --- a/common/skylake/hw-gfx-gma-power_and_clocks_skylake.ads +++ b/common/skylake/hw-gfx-gma-power_and_clocks_skylake.ads @@ -12,6 +12,8 @@ -- GNU General Public License for more details. --
+with HW.GFX.GMA.Config_Helpers; + private package HW.GFX.GMA.Power_And_Clocks_Skylake is
procedure Pre_All_Off; @@ -19,6 +21,16 @@
procedure Initialize;
+ procedure Limit_Dotclocks + (Configs : in out Pipe_Configs; + CDClk_Switch : out Boolean) + with + Post => Config_Helpers.Stable_FB (Configs'Old, Configs); + procedure Update_CDClk (Configs : in out Pipe_Configs) + with + Post => Config_Helpers.Stable_FB (Configs'Old, Configs); + procedure Enable_CDClk is null; + 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);