gma adl: Add missing Alder Lake power & clock bits

Most notable changes are:
* ADL-P has different default CDClk frequency choices.
* There are new divisors for CDClk:
  + 3 (resulting in an odd `/ 1.5` for CDClk x2)
  + and 8.
* There are four DBUF slices now and we need to enable all of
  them (probably related to their position and distance to the
  display pipelines on the MBus).
* Programming of MBus ABOX credits is not needed anymore
  (Has_Mbus_Abox_Credits).
* The MBus configuration allows joining of DBUF slices. We
  enable this for our simple buffer allocation (Has_Mbus_Joining)
  (this could use a deeper investigation if we wanted to conserve
  power).

This is based on work by several authors that was originally
squashed into another commit:
https://review.coreboot.org/c/libgfxinit/+/67801/

Change-Id: I6402b9cdcc3571128d76026aa5c7c1bb48f8df33
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/libgfxinit/+/510
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Tested-by: Ada SPARK <gnatbot@sourcearcade.org>
Reviewed-by: Thomas Heijligen <src@posteo.de>
diff --git a/common/tigerlake/hw-gfx-gma-power_and_clocks.adb b/common/tigerlake/hw-gfx-gma-power_and_clocks.adb
index 48cdf60..d24d8d1 100644
--- a/common/tigerlake/hw-gfx-gma-power_and_clocks.adb
+++ b/common/tigerlake/hw-gfx-gma-power_and_clocks.adb
@@ -36,12 +36,20 @@
    DBUF_CTL_DBUF_POWER_REQUEST                    : constant := 1 * 2 ** 31;
    DBUF_CTL_TRACKER_STATE_SERVICE_MASK            : constant := 16#f8_0000#;
    DBUF_CTL_TRACKER_STATE_SERVICE_SHIFT           : constant := 19;
+   DBUF_CTL_MIN_TRACKER_STATE_SERVICE_SHIFT       : constant := 16;
+   DBUF_CTL_MIN_TRACKER_STATE_SERVICE_MASK        : constant := 16#7_0000#;
    DBUF_CTL_DBUF_POWER_STATE                      : constant := 1 * 2 ** 30;
 
-   type DBUF_Slices is (S1, S2);
+   type DBUF_Slices is (S1, S2, S3, S4);
+   subtype Enable_DBUF_Slices is DBUF_Slices -- TODO: Maybe decide at runtime?
+      range S1 .. (if Config.Gen_Tigerlake then S1 else S4);
+   subtype Disable_DBUF_Slices is DBUF_Slices
+      range S1 .. (if Config.Gen_Tigerlake then S2 else S4);
    DBUF_CTL : constant array (DBUF_Slices) of Registers.Registers_Index :=
      (Registers.DBUF_CTL_S0,
-      Registers.DBUF_CTL_S1);
+      Registers.DBUF_CTL_S1,
+      Registers.DBUF_CTL_S2,
+      Registers.DBUF_CTL_S3);
 
    ----------------------------------------------------------------------------
 
@@ -72,6 +80,15 @@
 
    ----------------------------------------------------------------------------
 
+   MBUS_JOIN                                      : constant := 1 * 2 ** 31;
+   MBUS_HASHING_MODE_MASK                         : constant := 1 * 2 ** 30;
+   MBUS_HASHING_MODE_2x2                          : constant := 0 * 2 ** 30;
+   MBUS_HASHING_MODE_1x4                          : constant := 1 * 2 ** 30;
+   MBUS_JOIN_PIPE_SELECT_MASK                     : constant := 16#1c00_0000#;
+   MBUS_JOIN_PIPE_SELECT_NONE                     : constant := 16#1c00_0000#;
+
+   ----------------------------------------------------------------------------
+
    DCPR_MASK_MAXLATENCY_MEMUP_CLR                 : constant := 1 * 2 ** 27;
    DCPR_MASK_LPMODE                               : constant := 1 * 2 ** 26;
    DCPR_SEND_RESP_IMM                             : constant := 1 * 2 ** 25;
@@ -92,7 +109,9 @@
    CDCLK_PLL_ENABLE_PLL_LOCK                      : constant := 1 * 2 ** 30;
    CDCLK_CD2X_DIV_SEL_MASK                        : constant := 3 * 2 ** 22;
    CDCLK_CD2X_DIV_SEL_1                           : constant := 0 * 2 ** 22;
+   CDCLK_CD2X_DIV_SEL_1_5                         : constant := 1 * 2 ** 22;
    CDCLK_CD2X_DIV_SEL_2                           : constant := 2 * 2 ** 22;
+   CDCLK_CD2X_DIV_SEL_4                           : constant := 3 * 2 ** 22;
    CDCLK_CD2X_PIPE_NONE                           : constant := 7 * 2 ** 19;
    CDCLK_CTL_CD_FREQ_DECIMAL_MASK                 : constant := 16#7ff#;
 
@@ -152,21 +171,42 @@
    begin
       Get_RefClk (RefClk_Freq);
       Normalized :=
-        (case RefClk_Freq is
-         when 19_200_000 | 38_400_000 =>
-            (if    CDClk <= 172_800_000 then 172_800_000
-             elsif CDClk <= 192_000_000 then 192_000_000
-             elsif CDClk <= 307_200_000 then 307_200_000
-             elsif CDClk <= 326_400_000 then 326_400_000
-             elsif CDClk <= 556_800_000 then 556_800_000
-                                        else 652_800_000),
-         when others =>
-            (if    CDClk <= 180_000_000 then 180_000_000
-             elsif CDClk <= 192_000_000 then 192_000_000
-             elsif CDClk <= 312_000_000 then 312_000_000
-             elsif CDClk <= 324_000_000 then 324_000_000
-             elsif CDClk <= 552_000_000 then 552_000_000
-                                        else 648_000_000));
+        (if Config.Gen_Tigerlake then
+           (case RefClk_Freq is
+               when 19_200_000 | 38_400_000 =>
+                  (if    CDClk <= 172_800_000 then 172_800_000
+                   elsif CDClk <= 192_000_000 then 192_000_000
+                   elsif CDClk <= 307_200_000 then 307_200_000
+                   elsif CDClk <= 326_400_000 then 326_400_000
+                   elsif CDClk <= 556_800_000 then 556_800_000
+                                              else 652_800_000),
+               when others => -- 24_000_000
+                  (if    CDClk <= 180_000_000 then 180_000_000
+                   elsif CDClk <= 192_000_000 then 192_000_000
+                   elsif CDClk <= 312_000_000 then 312_000_000
+                   elsif CDClk <= 324_000_000 then 324_000_000
+                   elsif CDClk <= 552_000_000 then 552_000_000
+                                              else 648_000_000))
+         else
+           (case RefClk_Freq is
+               when 19_200_000 =>
+                 (if    CDClk <= 172_800_000 then 172_800_000
+                  elsif CDClk <= 192_000_000 then 192_000_000
+                  elsif CDClk <= 307_200_000 then 307_200_000
+                  elsif CDClk <= 556_800_000 then 556_800_000
+                                             else 652_800_000),
+               when 24_000_000 =>
+                 (if    CDClk <= 176_000_000 then 176_000_000
+                  elsif CDClk <= 192_000_000 then 192_000_000
+                  elsif CDClk <= 312_000_000 then 312_000_000
+                  elsif CDClk <= 552_000_000 then 552_000_000
+                                             else 648_000_000),
+               when others => -- 38_400_000
+                 (if    CDClk <= 179_200_000 then 179_200_000
+                  elsif CDClk <= 192_000_000 then 192_000_000
+                  elsif CDClk <= 307_200_000 then 307_200_000
+                  elsif CDClk <= 556_800_000 then 556_800_000
+                                             else 652_800_000)));
    end Normalize_CDClk;
 
    procedure Get_Cur_CDClk (CDClk : out CDClk_Range)
@@ -183,29 +223,30 @@
    procedure Set_CDClk (CDClk_In : CDClk_Range)
    is
       subtype PLL_Ratio_Range is Word32 range 0 .. 68;
-      function Ratio_For_19_2_MHz (CDClk : CDClk_Range) return PLL_Ratio_Range is
-      begin
-         case CDClk is
-            when 172_800_000 => return 18;
-            when 192_000_000 => return 20;
-            when 307_200_000 => return 32;
-            when 326_400_000 | 652_800_000 => return 68;
-            when 556_800_000 => return 58;
-            when others => return 0;
-         end case;
-      end Ratio_For_19_2_MHz;
+      function Ratio_For_19_2_MHz (CDClk : CDClk_Range) return PLL_Ratio_Range
+      is
+        (case CDClk is
+            when 172_800_000 =>
+              (if Config.Gen_Tigerlake
+                           then 18
+                           else 27),-- ADL_P: only used with 19.2MHz
+            when 179_200_000 => 28, -- ADL_P: only used with 38.4MHz
+            when 192_000_000 => 20,
+            when 307_200_000 => 32,
+            when 326_400_000 | 652_800_000 => 68,
+            when 556_800_000 => 58,
+            when others => 0);
 
-      function Ratio_For_24_MHz (CDClk : CDClk_Range) return PLL_Ratio_Range is
-      begin
-         case CDClk is
-            when 180_800_000 => return 15;
-            when 192_000_000 => return 16;
-            when 312_000_000 => return 26;
-            when 324_000_000 | 648_000_000 => return 54;
-            when 552_000_000 => return 46;
-            when others => return 0;
-         end case;
-      end Ratio_For_24_MHz;
+      function Ratio_For_24_MHz (CDClk : CDClk_Range) return PLL_Ratio_Range
+      is
+        (case CDClk is
+            when 176_000_000 => 22, -- only ADL_P
+            when 180_000_000 => 15, -- only TGL
+            when 192_000_000 => 16,
+            when 312_000_000 => 26,
+            when 324_000_000 | 648_000_000 => 54,
+            when 552_000_000 => 46,
+            when others => 0);
 
       function CDCLK_CTL_CD_FREQ_DECIMAL (Freq : CDClk_Range) return Word32
       with
@@ -279,7 +320,9 @@
       CD2X :=
          (case (Div_Round_Closest (VCO, CDClk / 1_000)) is
           when 2 => CDCLK_CD2X_DIV_SEL_1,
+          when 3 => CDCLK_CD2X_DIV_SEL_1_5,
           when 4 => CDCLK_CD2X_DIV_SEL_2,
+          when 8 => CDCLK_CD2X_DIV_SEL_4,
           when others => CDCLK_CD2X_DIV_SEL_1);
 
       Registers.Write
@@ -374,15 +417,17 @@
               (Register => Registers.BW_BUDDY2_PAGE_MASK,
                Mask     => Buddy_Info (I).BW_BUDDY_MASK);
 
-            -- Wa_22010178259:tgl,rkl
-            Registers.Unset_And_Set_Mask
-              (Register   => Registers.BW_BUDDY1_CTL,
-               Mask_Unset => BW_BUDDY_TLB_REQ_TIMER_MASK,
-               Mask_Set   => 8 * 2 ** 16);
-            Registers.Unset_And_Set_Mask
-              (Register   => Registers.BW_BUDDY2_CTL,
-               Mask_Unset => BW_BUDDY_TLB_REQ_TIMER_MASK,
-               Mask_Set   => 8 * 2 ** 16);
+            if Config.Gen_Tigerlake then
+               -- Wa_22010178259:tgl,rkl
+               Registers.Unset_And_Set_Mask
+                 (Register   => Registers.BW_BUDDY1_CTL,
+                  Mask_Unset => BW_BUDDY_TLB_REQ_TIMER_MASK,
+                  Mask_Set   => 8 * 2 ** 16);
+               Registers.Unset_And_Set_Mask
+                 (Register   => Registers.BW_BUDDY2_CTL,
+                  Mask_Unset => BW_BUDDY_TLB_REQ_TIMER_MASK,
+                  Mask_Set   => 8 * 2 ** 16);
+            end if;
 
             return;
          end if;
@@ -420,23 +465,50 @@
       Get_RawClk (RawClk);
       Config.Raw_Clock := RawClk;
 
-      -- TGL: Set DBUF Tracker State Service to 8
-      Registers.Unset_And_Set_Mask
-        (Register    => DBUF_CTL (S1),
-         Mask_Unset  => DBUF_CTL_TRACKER_STATE_SERVICE_MASK,
-         Mask_Set    => 8 * 2 ** DBUF_CTL_TRACKER_STATE_SERVICE_SHIFT);
-
-      -- Enable first DBUF slice (TODO: Is this ok to use for all pipes?)
-      Registers.Set_Mask (DBUF_CTL (S1), DBUF_CTL_DBUF_POWER_REQUEST);
-      Registers.Wait_Set_Mask (DBUF_CTL (S1), DBUF_CTL_DBUF_POWER_STATE);
-
-      for I in MBUS_ABOX_CTL'Range loop
+      -- Settings for joined MBUS. MBUS joining is usually used when buffers
+      -- from both DBUF slice pairs 1/2 and 3/4 are used for a single pipe.
+      -- TODO: Investigate if this is needed for our PLANE_BUF_CFG allocation.
+      if Config.Has_Mbus_Joining then
          Registers.Unset_And_Set_Mask
-           (Register    => MBUS_ABOX_CTL (I),
-            Mask_Unset  => MBUS_ABOX_MASK,
-            Mask_Set    => MBUS_ABOX_CREDITS);
+           (Register   => Registers.MBUS_CTL,
+            Mask_Unset => MBUS_HASHING_MODE_MASK or
+                          MBUS_JOIN or
+                          MBUS_JOIN_PIPE_SELECT_MASK,
+            Mask_Set   => MBUS_HASHING_MODE_1x4 or
+                          MBUS_JOIN or
+                          MBUS_JOIN_PIPE_SELECT_NONE);
+      end if;
+
+      -- TGL: Set DBUF Tracker State Service to 8
+      if Config.Gen_Tigerlake then
+         Registers.Unset_And_Set_Mask
+           (Register    => DBUF_CTL (S1),
+            Mask_Unset  => DBUF_CTL_TRACKER_STATE_SERVICE_MASK,
+            Mask_Set    => 8 * 2 ** DBUF_CTL_TRACKER_STATE_SERVICE_SHIFT);
+      end if;
+
+      if Config.Gen_AlderlakeP then
+         Registers.Unset_And_Set_Mask
+           (Register    => DBUF_CTL (S1),
+            Mask_Unset  => DBUF_CTL_MIN_TRACKER_STATE_SERVICE_MASK,
+            Mask_Set    => 3 * 2 ** DBUF_CTL_MIN_TRACKER_STATE_SERVICE_SHIFT);
+      end if;
+
+      -- Enable required DBUF slices
+      for S in Enable_DBUF_Slices loop
+         Registers.Set_Mask (DBUF_CTL (S), DBUF_CTL_DBUF_POWER_REQUEST);
+         Registers.Wait_Set_Mask (DBUF_CTL (S), DBUF_CTL_DBUF_POWER_STATE);
       end loop;
 
+      if Config.Has_Mbus_Abox_Credits then
+         for I in MBUS_ABOX_CTL'Range loop
+            Registers.Unset_And_Set_Mask
+              (Register    => MBUS_ABOX_CTL (I),
+               Mask_Unset  => MBUS_ABOX_MASK,
+               Mask_Set    => MBUS_ABOX_CREDITS);
+         end loop;
+      end if;
+
       Configure_Bandwidth_Buddy;
 
       -- Display WA #14011508470 tgl,dg1,rkl,adl-s,adl-p,dg2
@@ -444,6 +516,28 @@
         (Register => Registers.GEN11_CHICKEN_DCPR_2,
          Mask     => DCPR_MASK_MAXLATENCY_MEMUP_CLR or DCPR_MASK_LPMODE or
                      DCPR_SEND_RESP_IMM or DCPR_CLEAR_MEMSTAT_DIS);
+
+      if Config.Gen_AlderlakeP then
+         declare
+            DPCE_GATING_DIS      : constant := 1 * 2 ** 17;
+            DDI_CLOCK_REG_ACCESS : constant := 1 * 2 **  7;
+         begin
+            -- Display WA #14011503030 xelpd
+            Registers.Write
+              (Register => Registers.DISPLAY_ERR_FATAL_MASK,
+               Value    => 16#ffff_ffff#);
+
+            -- Wa_22011091694:adlp
+            Registers.Set_Mask
+              (Register => Registers.GEN9_CLKGATE_DIS_5,
+               Mask     => DPCE_GATING_DIS);
+
+            -- Bspec/49189 Initialize Sequence
+            Registers.Unset_Mask
+              (Register => Registers.GEN8_CHICKEN_DCPR_1,
+               Mask     => DDI_CLOCK_REG_ACCESS);
+         end;
+      end if;
    end Initialize;
 
    procedure Limit_Dotclocks
@@ -484,11 +578,9 @@
    begin
       pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
 
-      for S in reverse DBUF_CTL'Range loop
-         Registers.Unset_Mask
-            (DBUF_CTL (S), DBUF_CTL_DBUF_POWER_REQUEST);
-         Registers.Wait_Unset_Mask
-            (DBUF_CTL (S), DBUF_CTL_DBUF_POWER_STATE);
+      for S in reverse Disable_DBUF_Slices loop
+         Registers.Unset_Mask (DBUF_CTL (S), DBUF_CTL_DBUF_POWER_REQUEST);
+         Registers.Wait_Unset_Mask (DBUF_CTL (S), DBUF_CTL_DBUF_POWER_STATE);
       end loop;
 
       -- Disable CDClk PLL. FIXME: Not implemented yet.
diff --git a/common/tigerlake/hw-gfx-gma-power_domains_common.adb b/common/tigerlake/hw-gfx-gma-power_domains_common.adb
index 5c94c3f..94ca219 100644
--- a/common/tigerlake/hw-gfx-gma-power_domains_common.adb
+++ b/common/tigerlake/hw-gfx-gma-power_domains_common.adb
@@ -113,6 +113,11 @@
             Mask     => DP_AUX_CH_CTL_TBT_IO);
          Connectors.TC.Ownership.Claimed (To_GPU_Port (PD), Success);
       elsif PD = PW1 then
+         if Config.Gen_AlderlakeP then
+            Registers.Set_Mask
+              (Register => Registers.GEN8_CHICKEN_DCPR_1,
+               Mask     => 1 * 2 ** 15); -- DISABLE_FLR_SRC
+         end if;
          Registers.Wait_Set_Mask
            (Register => Registers.FUSE_STATUS,
             Mask     => FUSE_STATUS_PG0_DIST_STATUS,
@@ -183,7 +188,11 @@
             Success  => Success);
          pragma Debug (not Success, Debug.Put_Line ("Failed to enable power domain!"));
 
-         if Success then
+         if Success or else
+            (Config.Gen_AlderlakeP and then PD in AUX_USBC_Domain)
+         then
+            -- FIXME: Is it really expected?
+            pragma Debug (not Success, Debug.Put_Line ("AUX timeout expected."));
             Post_PD_On (PD);
          end if;
       end if;