gma tgl: Add support for allocating PLLs

This patch adds support for allocating both combo PHY PLLs and USB
Type-C PLLs for Tiger Lake.

Verified Combo PHY (HDMI, eDP) and Type-C (DP Alt mode) on
Google/delbin.

Squashed clean-ups:

  gma tgl: Clean up the code for gfx plls

  This patch improves code quality through various optimizations, such as
  replacing indexed array access with direct value access and simplifying
  variable declarations. It also simplifies function rewrites by using
  constructs like case-when instead of multiple range mappings or if else
  blocks. Additionally, the patch addresses minor typographical errors.
  These changes enhance the code's readability and maintainability
  without impacting functionality.

  Signed-off-by: Dinesh Gehlot <digehlot@google.com>

  gma tgl: Rename DKL PLL to Dekel_Phy

  This patch changes the name of a PLL "DKL" to "Dekel_Phy" to maintain
  consistency with the naming convention of other PHY PLLs

  Signed-off-by: Dinesh Gehlot <digehlot@google.com>

Change-Id: I9dd7e0d0180f70d73eb50d7e58718261e5e74071
Signed-off-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Reviewed-on: https://review.sourcearcade.org/c/libgfxinit/+/465
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Tested-by: Nico Huber <nico.h@gmx.de>
diff --git a/common/hw-gfx-gma-config.ads.template b/common/hw-gfx-gma-config.ads.template
index 7867268..6a6bc9c 100644
--- a/common/hw-gfx-gma-config.ads.template
+++ b/common/hw-gfx-gma-config.ads.template
@@ -281,6 +281,7 @@
    Has_Broadwell_CDClk           : <hswbool> := CPU_Broadwell;
    Can_Switch_CDClk              : <hswbool> := Broadwell_On;
    Has_Fractional_RawClk         : <genbool> := Cannon_Point_On;
+   Has_New_Type_C_PLL_Enable     : <tglbool> := Alderlake_On;
 
    ----------- DDI: -------------
    End_EDP_Training_Late         : <genbool> := Gen_Haswell;
diff --git a/common/tigerlake/Makefile.inc b/common/tigerlake/Makefile.inc
index e9ed51f..0082e25 100644
--- a/common/tigerlake/Makefile.inc
+++ b/common/tigerlake/Makefile.inc
@@ -6,3 +6,7 @@
 gfxinit-y += hw-gfx-gma-port_detect.adb
 gfxinit-y += hw-gfx-gma-plls.adb
 gfxinit-y += hw-gfx-gma-plls.ads
+gfxinit-y += hw-gfx-gma-plls-combo_phy.adb
+gfxinit-y += hw-gfx-gma-plls-combo_phy.ads
+gfxinit-y += hw-gfx-gma-plls-dekel_phy.adb
+gfxinit-y += hw-gfx-gma-plls-dekel_phy.ads
diff --git a/common/tigerlake/hw-gfx-gma-plls-combo_phy.adb b/common/tigerlake/hw-gfx-gma-plls-combo_phy.adb
new file mode 100644
index 0000000..7424b98
--- /dev/null
+++ b/common/tigerlake/hw-gfx-gma-plls-combo_phy.adb
@@ -0,0 +1,377 @@
+--
+-- Copyright (C) 2022 Google, LLC
+--
+-- 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
+-- the Free Software Foundation; either version 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+
+with HW.GFX.GMA.Config;
+with HW.GFX.GMA.Registers;
+with HW.GFX.GMA.Power_And_Clocks;
+
+package body HW.GFX.GMA.PLLs.Combo_Phy is
+
+   subtype HDMI_Clock_Range is Frequency_Type range
+      25_000_000 .. Config.HDMI_Max_Clock_24bpp;
+   subtype DCO_Range is Pos64 range
+      7_998_000_000 .. 10_000_000_000;
+
+   type PLL_Regs_Record is record
+      DPLL_ENABLE : Registers.Registers_Index;
+      DPLL_CFGCR0 : Registers.Registers_Index;
+      DPLL_CFGCR1 : Registers.Registers_Index;
+      DPLL_SSC    : Registers.Registers_Index;
+   end record;
+   type PLL_Regs_Array is array (Combo_DPLLs) of PLL_Regs_Record;
+   PLL_Regs : constant PLL_Regs_Array :=
+      PLL_Regs_Array'
+     (DPLL0 =>
+        (Registers.DPLL_0_ENABLE,
+         Registers.DPLL_0_CFGCR0,
+         Registers.DPLL_0_CFGCR1,
+         Registers.DPLL_0_SSC),
+      DPLL1 =>
+        (Registers.DPLL_1_ENABLE,
+         Registers.DPLL_1_CFGCR0,
+         Registers.DPLL_1_CFGCR1,
+         Registers.DPLL_1_SSC));
+
+   DPLL_ENABLE_PLL_ENABLE   : constant := 1 * 2 ** 31;
+   DPLL_ENABLE_PLL_LOCK     : constant := 1 * 2 ** 30;
+   DPLL_ENABLE_POWER_ENABLE : constant := 1 * 2 ** 27;
+   DPLL_ENABLE_POWER_STATE  : constant := 1 * 2 ** 26;
+   DPLL_SSC_DP              : constant := 16#200#;
+
+   procedure Encode_DCO (DCO_Integer, DCO_Fraction : out Word32; DCO : DCO_Range)
+   is
+      Refclk_Freq : Power_And_Clocks.Refclk_Range;
+      Enc_DCO : Int64;
+   begin
+      Power_And_Clocks.Get_Refclk (Refclk_Freq);
+
+      -- DPLL will auto-divide by 2 if refclk is 38.4 MHz
+      if Refclk_Freq = 38_400_000 then
+         Refclk_Freq := 19_200_000;
+      end if;
+
+      Enc_DCO := (DCO / 1_000) * (2 ** 15) / (Refclk_Freq / 1_000);
+      DCO_Integer := Word32 (Enc_DCO / (2 ** 15));
+      DCO_Fraction := Word32 (Enc_DCO) and 16#7fff#;
+   end Encode_DCO;
+
+   subtype PDiv_Range is Positive range 2 .. 7
+   with
+      Static_Predicate => (PDiv_Range in 2 | 3 | 5 | 7);
+
+   type Encoded_PDiv is new Positive range 1 .. 8
+   with
+      Static_Predicate => (Encoded_PDiv in 1 | 2 | 4 | 8);
+
+   function Encode_PDiv (PDiv : PDiv_Range) return Encoded_PDiv
+   is
+     (case PDiv is
+         when 2 => 2#0001#,
+         when 3 => 2#0010#,
+         when 5 => 2#0100#,
+         when 7 => 2#1000#);
+
+   subtype QDiv_Range is Positive range 1 .. 255;
+
+   type Encoded_QDiv is new Natural range 0 .. QDiv_Range'Last;
+
+   function Encode_QDiv (QDiv : QDiv_Range) return Encoded_QDiv
+   is
+     (Encoded_QDiv (QDiv));
+
+   function QDiv_Mode (QDiv : Encoded_QDiv) return Natural
+   is
+     (if QDiv <= 1 then 0 else 1);
+
+   subtype KDiv_Range is Positive range 1 .. 3;
+
+   type Encoded_KDiv is new Positive range 1 .. 4
+   with
+      Static_Predicate => (Encoded_KDiv in 1 | 2 | 4);
+
+   function Encode_KDiv (KDiv : KDiv_Range) return Encoded_KDiv
+   is
+     (case KDiv is
+         when 1 => 2#001#,
+         when 2 => 2#010#,
+         when 3 => 2#100#);
+
+   type PLL_Params is record
+      DCO_Integer    : Word32;
+      DCO_Fraction   : Word32;
+      PDiv           : Encoded_PDiv;
+      KDiv           : Encoded_KDiv;
+      QDiv           : Encoded_QDiv;
+   end record;
+
+   type DP_PLL_Params_Array is array (DP_Bandwidth) of PLL_Params;
+
+   PLL_Params_19_2MHz : constant DP_PLL_Params_Array := DP_PLL_Params_Array'
+     (DP_Bandwidth_5_4 =>
+        (DCO_Integer  => 16#1a5#,
+         DCO_Fraction => 16#7000#,
+         PDiv         => 2,
+         KDiv         => 1,
+         QDiv         => 0),
+      DP_Bandwidth_2_7 =>
+        (DCO_Integer  => 16#1a5#,
+         DCO_Fraction => 16#7000#,
+         PDiv         => 2,
+         KDiv         => 2,
+         QDiv         => 0),
+      DP_Bandwidth_1_62 =>
+        (DCO_Integer  => 16#1a5#,
+         DCO_Fraction => 16#7000#,
+         PDiv         => 4,
+         KDiv         => 2,
+         QDiv         => 0));
+
+   PLL_Params_24MHz : constant DP_PLL_Params_Array := DP_PLL_Params_Array'
+     (DP_Bandwidth_5_4 =>
+        (DCO_Integer  => 16#151#,
+         DCO_Fraction => 16#4000#,
+         PDiv         => 2,
+         KDiv         => 1,
+         QDiv         => 0),
+      DP_Bandwidth_2_7 =>
+        (DCO_Integer  => 16#151#,
+         DCO_Fraction => 16#4000#,
+         PDiv         => 2,
+         KDiv         => 2,
+         QDiv         => 0),
+      DP_Bandwidth_1_62 =>
+        (DCO_Integer  => 16#151#,
+         DCO_Fraction => 16#4000#,
+         PDiv         => 4,
+         KDiv         => 2,
+         QDiv         => 0));
+
+   procedure Calc_DP_PLL_Dividers
+     (Bandwidth : in     DP_Bandwidth;
+      Params    :    out PLL_Params)
+   is
+      Refclk : Frequency_Type;
+   begin
+      Power_And_Clocks.Get_Refclk (Refclk);
+      if Refclk = 24_000_000 then
+         Params := PLL_Params_24MHz (Bandwidth);
+      else
+         Params := PLL_Params_19_2MHz (Bandwidth);
+      end if;
+   end Calc_DP_PLL_Dividers;
+
+   procedure Calc_HDMI_PLL_Dividers
+     (Dotclock : in     Frequency_Type;
+      Params   :    out PLL_Params;
+      Success  :    out Boolean)
+   is
+      subtype Div_Range is Pos64 range 2 .. 102;
+      subtype Candidate_Index is Positive range 1 .. 46;
+      type Candidate_Array is array (Candidate_Index) of Div_Range;
+      Candidates : constant Candidate_Array := Candidate_Array'
+        (2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 24, 28, 30, 32, 36, 40, 42, 44,
+         48, 50, 52, 54, 56, 60, 64, 66, 68, 70, 72, 76, 78, 80, 84, 88, 90,
+         92, 96, 98, 100, 102, 3, 5, 7, 9, 15, 21);
+      AFE_Clk : constant Int64 := Dotclock * 5;
+      DCO_Mid : constant Int64 := (DCO_Range'First + DCO_Range'Last) / 2;
+      Best_DCO_Centrality : Int64 := Frequency_Type'Last;
+      Best_Div_Index : Candidate_Index := Candidate_Index'First;
+      Best_Div : Div_Range;
+      Best_DCO : DCO_Range := DCO_Range'First;
+      DCO_Found : Boolean := False;
+      PDiv : PDiv_Range;
+      QDiv : QDiv_Range;
+      KDiv : KDiv_Range;
+   begin
+      for Index in Candidate_Index loop
+         declare
+            DCO : constant Int64 := AFE_Clk * Candidates(Index);
+            DCO_Centrality : constant Int64 := abs (DCO - DCO_Mid);
+         begin
+            if DCO <= DCO_Range'Last and DCO >= DCO_Range'First and
+               DCO_Centrality < Best_DCO_Centrality
+            then
+               DCO_Found := True;
+               Best_DCO_Centrality := DCO_Centrality;
+               Best_Div_Index := Index;
+               Best_DCO := DCO;
+            end if;
+         end;
+      end loop;
+
+      if not DCO_Found then
+         Params := (DCO_Integer => 0,
+                    DCO_Fraction => 0,
+                    PDiv => Encoded_PDiv'First_Valid,
+                    KDiv => Encoded_KDiv'First_Valid,
+                    QDiv => Encoded_QDiv'First_Valid);
+         Success := False;
+         return;
+      end if;
+
+      Best_Div := Candidates (Best_Div_Index);
+      if Best_Div mod 2 = 0 then
+         if Best_Div = 2 then
+            PDiv := 2;
+            QDiv := 1;
+            KDiv := 1;
+         elsif Best_Div mod 4 = 0 then
+            PDiv := 2;
+            QDiv := QDiv_Range (Best_Div / 4);
+            KDiv := 2;
+         elsif Best_Div mod 6 = 0 then
+            PDiv := 3;
+            QDiv := QDiv_Range (Best_Div / 6);
+            KDiv := 2;
+         elsif Best_Div mod 5 = 0 then
+            PDiv := 5;
+            QDiv := QDiv_Range (Best_Div / 10);
+            KDiv := 2;
+         else
+            -- Use `else`, not `elsif`, to prove we covered all cases.
+            pragma Assert (Best_Div mod 14 = 0);
+            PDiv := 7;
+            QDiv := QDiv_Range (Best_Div / 14);
+            KDiv := 2;
+         end if;
+      else
+         if Best_Div = 3 or Best_Div = 5 or Best_Div = 7 then
+            PDiv := PDiv_Range (Best_Div);
+            QDiv := 1;
+            KDiv := 1;
+         else
+            pragma Assert (Best_Div mod 3 = 0);
+            PDiv := PDiv_Range (Best_Div / 3);
+            QDiv := 1;
+            KDiv := 3;
+         end if;
+      end if;
+
+      -- PRM: If Kdiv != 2, then Qdiv must be 1. Else Qdiv can be 1 to 255.
+      pragma Assert (if KDiv /= 2 then QDiv = 1);
+
+      Params.KDiv := Encode_KDiv (KDiv);
+      Params.PDiv := Encode_PDiv (PDiv);
+      Params.QDiv := Encode_QDiv (QDiv);
+      Encode_DCO (Params.DCO_Integer, Params.DCO_Fraction, Best_DCO);
+
+      Success := True;
+   end Calc_HDMI_PLL_Dividers;
+
+   procedure On
+     (PLL      : in     Combo_DPLLs;
+      Port_Cfg : in     Port_Config;
+      Success  :    out Boolean)
+   is
+      Params : PLL_Params;
+      Refclk : Frequency_Type;
+   begin
+      if Port_Cfg.Display = DP then
+         Calc_DP_PLL_Dividers (Port_Cfg.DP.Bandwidth, Params);
+         Success := True;
+      else
+         if Port_Cfg.Mode.Dotclock not in HDMI_Clock_Range then
+            Debug.Put_Line ("Unsupported HDMI Pixel clock");
+            Success := False;
+            return;
+         end if;
+         declare
+            Color_Depth : constant Int64 := Port_Cfg.Mode.BPC * 3;
+            Pll_Freq : constant Frequency_Type := Color_Depth * Port_Cfg.Mode.Dotclock / 24;
+         begin
+            Calc_HDMI_PLL_Dividers (Pll_Freq, Params, Success);
+         end;
+      end if;
+
+      if not Success then
+         Debug.Put_Line ("Failed to calculate PLL dividers!");
+         return;
+      end if;
+
+      -- Display WA #22010492432: ehl, tgl, adl-p
+      -- Program half of the nominal DCO divider fraction value
+      -- for 38.4 MHz refclk
+      Power_And_Clocks.Get_Refclk (Refclk);
+      if Refclk = 38_400_000 then
+         Params.DCO_Fraction := Shift_Right (Params.DCO_Fraction, 1);
+      end if;
+
+      Registers.Set_Mask
+        (Register => PLL_Regs (PLL).DPLL_ENABLE,
+         Mask     => DPLL_ENABLE_POWER_ENABLE);
+      Registers.Wait_Set_Mask
+        (Register => PLL_Regs (PLL).DPLL_ENABLE,
+         Mask     => DPLL_ENABLE_POWER_STATE,
+         Success  => Success);
+
+      if not Success then
+         Debug.Put_Line ("Failed to enable PLL!");
+         return;
+      end if;
+
+      -- Configure DPLL_SSC
+      Registers.Write
+        (Register => PLL_Regs (PLL).DPLL_SSC,
+         Value    => (if Port_Cfg.Display = DP then DPLL_SSC_DP else 0));
+
+      Registers.Write
+        (Register => PLL_Regs (PLL).DPLL_CFGCR0,
+         Value => Shift_Left (Params.DCO_Fraction, 10) or
+                  Params.DCO_Integer);
+
+      Registers.Write
+        (Register => PLL_Regs (PLL).DPLL_CFGCR1,
+         Value => Shift_Left (Word32 (Params.QDiv), 10) or
+                  Shift_Left (Word32 (QDiv_Mode (Params.QDiv)), 9) or
+                  Shift_left (Word32 (Params.KDiv), 6) or
+                  Shift_Left (Word32 (Params.PDiv), 2));
+      Registers.Posting_Read(PLL_Regs (PLL).DPLL_CFGCR1);
+
+      -- Enable DPLL
+      Registers.Set_Mask
+        (Register => PLL_Regs (PLL).DPLL_ENABLE,
+         Mask     => DPLL_ENABLE_PLL_ENABLE);
+      -- Wait for PLL Lock status
+      Registers.Wait_Set_Mask
+        (Register => PLL_Regs (PLL).DPLL_ENABLE,
+         Mask     => DPLL_ENABLE_PLL_LOCK,
+         Success  => Success);
+   end On;
+
+   procedure Free (PLL : Combo_DPLLs)
+   is
+   begin
+      Registers.Unset_Mask
+        (Register => PLL_Regs (PLL).DPLL_ENABLE,
+         Mask     => DPLL_ENABLE_PLL_ENABLE);
+      Registers.Wait_Unset_Mask
+        (Register => PLL_Regs (PLL).DPLL_ENABLE,
+         Mask     => DPLL_ENABLE_PLL_LOCK);
+
+      Registers.Unset_Mask
+        (Register => PLL_Regs (PLL).DPLL_ENABLE,
+         Mask     => DPLL_ENABLE_POWER_ENABLE);
+      Registers.Wait_Unset_Mask
+        (Register => PLL_Regs (PLL).DPLL_ENABLE,
+         Mask     => DPLL_ENABLE_POWER_STATE);
+   end Free;
+
+   procedure All_Off is
+   begin
+      for PLL in Combo_DPLLs loop
+         Free (PLL);
+      end loop;
+   end All_Off;
+
+end HW.GFX.GMA.PLLs.Combo_Phy;
diff --git a/common/tigerlake/hw-gfx-gma-plls-combo_phy.ads b/common/tigerlake/hw-gfx-gma-plls-combo_phy.ads
new file mode 100644
index 0000000..8857b8c
--- /dev/null
+++ b/common/tigerlake/hw-gfx-gma-plls-combo_phy.ads
@@ -0,0 +1,33 @@
+--
+-- Copyright (C) 2022 Google, LLC
+--
+-- 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
+-- the Free Software Foundation; either version 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+
+with HW.Debug;
+with GNAT.Source_Info;
+
+private package HW.GFX.GMA.PLLs.Combo_Phy is
+
+   procedure On
+     (PLL      : in     Combo_DPLLs;
+      Port_Cfg : in     Port_Config;
+      Success  :    out Boolean);
+
+   procedure Free (PLL : Combo_DPLLs);
+
+   procedure All_Off;
+
+   type Value_Array is array (Combo_DPLLs) of Word32;
+   Register_Value : constant Value_Array := Value_Array'
+     (DPLL0 => 0, DPLL1 => 1);
+
+end HW.GFX.GMA.PLLs.Combo_Phy;
diff --git a/common/tigerlake/hw-gfx-gma-plls-dekel_phy.adb b/common/tigerlake/hw-gfx-gma-plls-dekel_phy.adb
new file mode 100644
index 0000000..9172dad
--- /dev/null
+++ b/common/tigerlake/hw-gfx-gma-plls-dekel_phy.adb
@@ -0,0 +1,400 @@
+--
+-- Copyright (C) 2022 Google, LLC
+--
+-- 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
+-- the Free Software Foundation; either version 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+
+with HW.GFX.GMA.Config;
+with HW.GFX.GMA.Registers;
+with HW.GFX.GMA.Power_And_Clocks;
+
+package body HW.GFX.GMA.PLLs.Dekel_Phy is
+
+   use type HW.Word64;
+
+   subtype Frequency_KHz is Pos64
+     range (Frequency_Type'First / 1_000) .. (Frequency_Type'Last / 1_000);
+   subtype DCO_Range_KHz is Pos64 range 7_992_000 .. 10_000_000;
+
+   DPLL_ENABLE_PLL_ENABLE   : constant := 1 * 2 ** 31;
+   DPLL_ENABLE_PLL_LOCK     : constant := 1 * 2 ** 30;
+   DPLL_ENABLE_POWER_ENABLE : constant := 1 * 2 ** 27;
+   DPLL_ENABLE_POWER_STATE  : constant := 1 * 2 ** 26;
+
+   function HIP_INDEX_REG (P : DKL_DPLLs) return Registers.Registers_Index
+   is (if P <= TCPLL4
+       then Registers.HIP_INDEX_REG0
+       else Registers.HIP_INDEX_REG1);
+
+   function HIP_INDEX_VAL (P : DKL_DPLLs; Val : Word32) return Word32 is
+     (case P is
+      when TCPLL1 => Val * 2 ** 0,
+      when TCPLL2 => Val * 2 ** 8,
+      when TCPLL3 => Val * 2 ** 16,
+      when TCPLL4 => Val * 2 ** 24,
+      when TCPLL5 => Val * 2 ** 0,
+      when TCPLL6 => Val * 2 ** 8);
+
+   function DKL_PLL_ENABLE (P : DKL_DPLLs) return Registers.Registers_Index is
+     (if Config.Has_New_Type_C_PLL_Enable then
+        (case P is
+            when TCPLL1 => Registers.PORTTC1_PLL1_ENABLE,
+            when TCPLL2 => Registers.PORTTC2_PLL1_ENABLE,
+            when TCPLL3 => Registers.PORTTC3_PLL1_ENABLE,
+            when TCPLL4 => Registers.PORTTC4_PLL1_ENABLE,
+            when TCPLL5 => Registers.MGPLL5_ENABLE,
+            when TCPLL6 => Registers.MGPLL6_ENABLE)
+      else
+        (case P is
+            when TCPLL1 => Registers.MGPLL1_ENABLE,
+            when TCPLL2 => Registers.MGPLL2_ENABLE,
+            when TCPLL3 => Registers.MGPLL3_ENABLE,
+            when TCPLL4 => Registers.MGPLL4_ENABLE,
+            when TCPLL5 => Registers.MGPLL5_ENABLE,
+            when TCPLL6 => Registers.MGPLL6_ENABLE));
+
+   type PLL_Regs_Record is record
+      DKL_REFCLKIN_CTL        : Registers.Registers_Index;
+      DKL_CLKTOP2_CORECLKCTL1 : Registers.Registers_Index;
+      DKL_CLKTOP2_HSCLKCTL    : Registers.Registers_Index;
+      DKL_PLL_DIV0            : Registers.Registers_Index;
+      DKL_PLL_DIV1            : Registers.Registers_Index;
+      DKL_PLL_SSC             : Registers.Registers_Index;
+      DKL_PLL_BIAS            : Registers.Registers_Index;
+      DKL_PLL_COLDST_BIAS     : Registers.Registers_Index;
+   end record;
+
+   type PLL_Regs_Array is array (DKL_DPLLs) of PLL_Regs_Record;
+   PLL_Regs : constant PLL_Regs_Array :=
+      PLL_Regs_Array'
+     (TCPLL1 =>
+        (Registers.DKL_REFCLKIN_CTL_1,
+         Registers.DKL_CLKTOP2_CCC1_1,
+         Registers.DKL_CLKTOP2_HSCC_1,
+         Registers.DKL_PLL_DIV0_1,
+         Registers.DKL_PLL_DIV1_1,
+         Registers.DKL_PLL_SSC_1,
+         Registers.DKL_PLL_BIAS_1,
+         Registers.DKL_PLL_COLDST_BIAS_1),
+      TCPLL2 =>
+        (Registers.DKL_REFCLKIN_CTL_2,
+         Registers.DKL_CLKTOP2_CCC1_2,
+         Registers.DKL_CLKTOP2_HSCC_2,
+         Registers.DKL_PLL_DIV0_2,
+         Registers.DKL_PLL_DIV1_2,
+         Registers.DKL_PLL_SSC_2,
+         Registers.DKL_PLL_BIAS_2,
+         Registers.DKL_PLL_COLDST_BIAS_2),
+      TCPLL3 =>
+        (Registers.DKL_REFCLKIN_CTL_3,
+         Registers.DKL_CLKTOP2_CCC1_3,
+         Registers.DKL_CLKTOP2_HSCC_3,
+         Registers.DKL_PLL_DIV0_3,
+         Registers.DKL_PLL_DIV1_3,
+         Registers.DKL_PLL_SSC_3,
+         Registers.DKL_PLL_BIAS_3,
+         Registers.DKL_PLL_COLDST_BIAS_3),
+      TCPLL4 =>
+        (Registers.DKL_REFCLKIN_CTL_4,
+         Registers.DKL_CLKTOP2_CCC1_4,
+         Registers.DKL_CLKTOP2_HSCC_4,
+         Registers.DKL_PLL_DIV0_4,
+         Registers.DKL_PLL_DIV1_4,
+         Registers.DKL_PLL_SSC_4,
+         Registers.DKL_PLL_BIAS_4,
+         Registers.DKL_PLL_COLDST_BIAS_4),
+      TCPLL5 =>
+        (Registers.DKL_REFCLKIN_CTL_5,
+         Registers.DKL_CLKTOP2_CCC1_5,
+         Registers.DKL_CLKTOP2_HSCC_5,
+         Registers.DKL_PLL_DIV0_5,
+         Registers.DKL_PLL_DIV1_5,
+         Registers.DKL_PLL_SSC_5,
+         Registers.DKL_PLL_BIAS_5,
+         Registers.DKL_PLL_COLDST_BIAS_5),
+      TCPLL6 =>
+        (Registers.DKL_REFCLKIN_CTL_6,
+         Registers.DKL_CLKTOP2_CCC1_6,
+         Registers.DKL_CLKTOP2_HSCC_6,
+         Registers.DKL_PLL_DIV0_6,
+         Registers.DKL_PLL_DIV1_6,
+         Registers.DKL_PLL_SSC_6,
+         Registers.DKL_PLL_BIAS_6,
+         Registers.DKL_PLL_COLDST_BIAS_6));
+
+   DKL_REFCLKIN_CTL_OD_2_MUX_MASK          : constant := 7 * 2 ** 8;
+   DKL_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK : constant := 16#ff# * 2 ** 8;
+   DKL_CLKTOP2_HSCLKCTL_MASK               : constant := 16#1_FF00#;
+   DKL_PLL_DIV0_MASK                       : constant := 16#1F_FFFF#;
+   DKL_PLL_DIV1_MASK                       : constant := 16#1F_00FF#;
+   DKL_PLL_SSC_MASK                        : constant := 16#E0FF_3A00#;
+   DKL_PLL_BIAS_MASK                       : constant := 16#7FFF_FF00#;
+   DKL_PLL_COLD_BIAS_MASK                  : constant := 16#ffff#;
+   DKL_PLL_BIAS_FRAC_EN_H                  : constant := 1 * 2 ** 30;
+
+   procedure Calc_Dividers
+      (Clock                   : in     Frequency_Type;
+       Display                 : in     Display_Type;
+       DKL_Refclkin_Ctl        :    out Word32;
+       DKL_Clktop2_Coreclkctl1 :    out Word32;
+       DKL_Clktop2_HSClkCtl    :    out Word32;
+       DCO_Khz                 :    out DCO_Range_KHz;
+       Success                 :    out Boolean)
+   is
+      DCO_Min_Freq, DCO_Max_Freq : Int64;
+      type Dividers_List is array (1 .. 4) of Int64;
+      Dividers : constant Dividers_List := (7, 5, 3, 2);
+      DKL_CLKTOP2_HSCLKCTL_HSDIV_RATIO_2 : constant := 0 * 2 ** 12;
+      DKL_CLKTOP2_HSCLKCTL_HSDIV_RATIO_3 : constant := 1 * 2 ** 12;
+      DKL_CLKTOP2_HSCLKCTL_HSDIV_RATIO_5 : constant := 2 * 2 ** 12;
+      DKL_CLKTOP2_HSCLKCTL_HSDIV_RATIO_7 : constant := 3 * 2 ** 12;
+      function DKL_REFCLKIN_CTL_OD_2_MUX (N : Word32) return Word32
+         is (Shift_Left (N, 8));
+      function DKL_CLKTOP2_CORECLKCTL1_A_DIVRATIO  (N : Word32) return Word32
+         is (Shift_Left (N, 8));
+      function DKL_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL (N : Word32) return Word32
+         is (Shift_Left (N, 14));
+      function DKL_CLKTOP2_HSCLKCTL_CORE_INPUTSEL (N : Word32) return Word32
+         is (Shift_Left (N, 16));
+      function DKL_CLKTOP2_HSCLKCTL_DSDIV_RATIO (N : Word32) return Word32
+         is (Shift_Left (N, 8));
+      Clock_Khz : constant Frequency_KHz := Frequency_KHz(Clock / 1_000);
+   begin
+      if Display = DP then
+         DCO_Min_Freq := 8_100_000;
+         DCO_Max_Freq := 8_100_000;
+      else
+         DCO_Min_Freq := DCO_Range_KHz'First;
+         DCO_Max_Freq := DCO_Range_KHz'Last;
+      end if;
+
+      DKL_Refclkin_Ctl := 0;
+      DKL_clktop2_coreclkctl1 := 0;
+      DKL_CLKTOP2_hsclkctl := 0;
+
+      DCO_KHz := DCO_Min_Freq;
+      Success := False;
+      for I in Dividers'Range loop
+         pragma Loop_Invariant (DCO_KHz >= DCO_Min_Freq and DCO_KHz <= DCO_Max_Freq);
+         for Div2 in reverse 1 .. 10 loop
+            declare
+               Tmp : constant Pos64 := Dividers (I) * Pos64 (Div2) * Pos64(Clock_Khz) * 5;
+               A_DivRatio, TLineDrv, Inputsel, Hsdiv : Word32;
+            begin
+               if Tmp >= DCO_Min_Freq and then Tmp <= DCO_Max_Freq then
+                  DCO_KHz := Tmp;
+                  if Div2 >= 2 then
+                     A_DivRatio := (if Display = DP then 10 else 5);
+                     TLineDrv := 1;
+                  else
+                     A_DivRatio := 5;
+                     TLineDrv := 0;
+                  end if;
+                  Inputsel := (if Display = DP then 0 else 1);
+                  Hsdiv := (case Dividers (I) is
+                            when 2 => DKL_CLKTOP2_HSCLKCTL_HSDIV_RATIO_2,
+                            when 3 => DKL_CLKTOP2_HSCLKCTL_HSDIV_RATIO_3,
+                            when 5 => DKL_CLKTOP2_HSCLKCTL_HSDIV_RATIO_5,
+                            when 7 => DKL_CLKTOP2_HSCLKCTL_HSDIV_RATIO_7,
+                            when others => DKL_CLKTOP2_HSCLKCTL_HSDIV_RATIO_2);
+                  DKL_Refclkin_Ctl := DKL_REFCLKIN_CTL_OD_2_MUX (1);
+                  DKL_clktop2_coreclkctl1 :=
+                                DKL_CLKTOP2_CORECLKCTL1_A_DIVRATIO (A_DivRatio);
+                  DKL_CLKTOP2_hsclkctl :=
+                     DKL_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL (TLineDrv) or
+                     DKL_CLKTOP2_HSCLKCTL_CORE_INPUTSEL (Inputsel) or
+                     Hsdiv or
+                     DKL_CLKTOP2_HSCLKCTL_DSDIV_RATIO (Word32 (Div2));
+                  Success := True;
+               end if;
+               exit when Success;
+            end;
+         end loop;
+         exit when Success;
+      end loop;
+   end Calc_Dividers;
+
+   procedure On
+     (PLL      : in     DKL_DPLLs;
+      Port_Cfg : in     Port_Config;
+      Success  :    out Boolean)
+   is
+      DKL_Refclkin_Ctl : Word32;
+      DKL_Clktop2_Coreclkctl1 : Word32;
+      DKL_Clktop2_HSClkCtl : Word32;
+      DCO_Khz : DCO_Range_KHz;
+      Clock : Frequency_Type;
+   begin
+      if Port_Cfg.Display = HDMI then
+         Clock := Port_Cfg.Mode.Dotclock;
+      else
+         Clock := Frequency_Type (DP_Symbol_Rate (Port_Cfg.DP.Bandwidth));
+      end if;
+
+      Calc_Dividers
+        (Clock                   => Clock,
+         Display                 => Port_Cfg.Display,
+         DKL_Refclkin_Ctl        => DKL_Refclkin_Ctl,
+         DKL_Clktop2_Coreclkctl1 => DKL_Clktop2_Coreclkctl1,
+         DKL_Clktop2_HSClkCtl    => DKL_Clktop2_HSClkCtl,
+         DCO_Khz                 => DCO_Khz,
+         Success                 => Success);
+
+      if not Success then
+         Debug.Put_Line ("Could not find dividers for port!");
+         return;
+      end if;
+
+      Registers.Set_Mask
+        (Register => DKL_PLL_ENABLE (PLL),
+         Mask     => DPLL_ENABLE_POWER_ENABLE);
+
+      Registers.Wait_Set_Mask
+        (Register => DKL_PLL_ENABLE (PLL),
+         Mask     => DPLL_ENABLE_POWER_STATE);
+
+      declare
+         Tmp : Int64;
+         Refclk : Power_And_Clocks.Refclk_Range;
+         Refclk_Khz : Power_And_Clocks.Refclk_Range_KHz;
+         FeedFwGain : Word32;
+         M1Div : constant := 2;
+         M2Div_Int, M2Div_Rem: Int64;
+         M2Div_Frac : Word32;
+         TDC_Target : Word32;
+         Prop_Coeff, Int_Coeff : Word32;
+         IRef_Ndiv, Iref_Itrim : Word32;
+      begin
+         Power_And_Clocks.Get_Refclk (Refclk);
+         Refclk_Khz := Power_And_Clocks.Refclk_Range_KHz (Refclk / 1_000);
+         M2Div_Int := Int64(DCO_Khz / (Refclk_Khz * M1Div));
+         M2Div_Rem := Int64(DCO_Khz rem (Refclk_Khz * M1Div));
+         Tmp := M2Div_Rem * 2 ** 22;
+         M2Div_Frac := Word32 (Tmp / Int64(Refclk_Khz * M1Div));
+
+         case Refclk is
+            when 24_000_000 =>
+               Iref_Ndiv := 1;
+               Iref_Itrim := 25;
+            when 38_400_000 =>
+               Iref_Ndiv := 2;
+               Iref_Itrim := 28;
+            when others =>
+               Iref_Ndiv := 1;
+               Iref_Itrim := 28;
+         end case;
+
+         -- Real number math converted to fixed point
+         -- see note in i915 about these calculations
+         TDC_Target := Word32 (2 * 1_000 * 100_000 * 10 / (132 * Refclk_Khz) + 5) / 10;
+
+         if M2Div_Rem > 0 then
+            FeedFwGain := (M1Div * 1_000_000 * 100) / (Word32 (DCO_Khz) * 3 / 10);
+         else
+            FeedFwGain := 0;
+         end if;
+
+         if DCO_Khz >= 9_000_000 then
+            Prop_Coeff := 5;
+            Int_Coeff := 10;
+         else
+            Prop_Coeff := 4;
+            Int_Coeff := 8;
+         end if;
+
+         -- The following DKL registers are at MMIO index 2
+         Registers.Write (HIP_INDEX_REG (PLL), HIP_INDEX_VAL (PLL, 2));
+
+         Registers.Unset_And_Set_Mask
+           (Register   => PLL_Regs (PLL).DKL_REFCLKIN_CTL,
+            Mask_Unset => DKL_REFCLKIN_CTL_OD_2_MUX_MASK,
+            Mask_Set   => DKL_Refclkin_Ctl);
+
+         Registers.Unset_And_Set_Mask
+           (Register   => PLL_Regs (PLL).DKL_CLKTOP2_CORECLKCTL1,
+            Mask_Unset => DKL_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK,
+            Mask_Set   => DKL_Clktop2_Coreclkctl1);
+
+         Registers.Unset_And_Set_Mask
+           (Register   => PLL_Regs (PLL).DKL_CLKTOP2_HSCLKCTL,
+            Mask_Unset => DKL_CLKTOP2_HSCLKCTL_MASK,
+            Mask_Set   => DKL_CLKTOP2_hsclkctl);
+
+         Registers.Unset_And_Set_mask
+           (Register   => PLL_Regs (PLL).DKL_PLL_DIV0,
+            Mask_Unset => DKL_PLL_DIV0_MASK,
+            Mask_Set   => Shift_Left (Int_Coeff, 16) or
+                          Shift_Left (Prop_Coeff, 12) or
+                          Shift_Left (M1Div, 8) or
+                          Word32(M2Div_Int));
+
+         Registers.Unset_And_Set_Mask
+           (Register   => PLL_Regs (PLL).DKL_PLL_DIV1,
+            Mask_Unset => DKL_PLL_DIV1_MASK,
+            Mask_Set   => Shift_Left (Iref_Itrim, 16) or
+                          TDC_Target);
+
+         Registers.Unset_And_Set_Mask
+           (Register   => PLL_Regs (PLL).DKL_PLL_SSC,
+            Mask_Unset => DKL_PLL_SSC_MASK,
+            Mask_Set   => Shift_Left (Iref_Ndiv, 29) or
+                          Shift_Left (4, 11)); -- SSC_STEP_NUM (always 4)
+
+         Registers.Unset_And_Set_Mask
+           (Register   => PLL_Regs (PLL).DKL_PLL_BIAS,
+            Mask_Unset => DKL_PLL_BIAS_MASK,
+            Mask_Set   => Shift_Left (M2Div_Frac, 8) or
+                          (if M2Div_Frac > 0 then DKL_PLL_BIAS_FRAC_EN_H else 0));
+
+         Registers.Unset_And_Set_Mask
+           (Register   => PLL_Regs (PLL).DKL_PLL_COLDST_BIAS,
+            Mask_Unset => DKL_PLL_COLD_BIAS_MASK,
+            Mask_Set   => FeedFwGain);
+
+         -- Read back the last programmed PHY PLL register
+         Registers.Posting_Read (PLL_Regs (PLL).DKL_PLL_COLDST_BIAS);
+
+         Registers.Set_Mask
+           (Register => DKL_PLL_ENABLE (PLL),
+            Mask     => DPLL_ENABLE_PLL_ENABLE);
+
+         Registers.Wait_Set_Mask
+           (Register => DKL_PLL_ENABLE (PLL),
+            Mask     => DPLL_ENABLE_PLL_LOCK);
+      end;
+   end On;
+
+   procedure Free (PLL : DKL_DPLLs)
+   is
+   begin
+      Registers.Unset_Mask
+        (Register => DKL_PLL_ENABLE (PLL),
+         Mask     => DPLL_ENABLE_PLL_ENABLE);
+      Registers.Wait_Unset_Mask
+        (Register => DKL_PLL_ENABLE (PLL),
+         Mask     => DPLL_ENABLE_PLL_LOCK);
+
+      Registers.Unset_Mask
+        (Register => DKL_PLL_ENABLE (PLL),
+         Mask     => DPLL_ENABLE_POWER_ENABLE);
+      Registers.Wait_Unset_Mask
+        (Register => DKL_PLL_ENABLE (PLL),
+         Mask     => DPLL_ENABLE_POWER_STATE);
+   end Free;
+
+   procedure All_Off is
+   begin
+      for PLL in DKL_DPLLs loop
+         Free (PLL);
+      end loop;
+   end All_Off;
+
+end HW.GFX.GMA.PLLs.Dekel_Phy;
diff --git a/common/tigerlake/hw-gfx-gma-plls-dekel_phy.ads b/common/tigerlake/hw-gfx-gma-plls-dekel_phy.ads
new file mode 100644
index 0000000..37f94fa
--- /dev/null
+++ b/common/tigerlake/hw-gfx-gma-plls-dekel_phy.ads
@@ -0,0 +1,29 @@
+--
+-- Copyright (C) 2022 Google, LLC
+--
+-- 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
+-- the Free Software Foundation; either version 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+
+with HW.Debug;
+with GNAT.Source_Info;
+
+private package HW.GFX.GMA.PLLs.Dekel_Phy is
+
+   procedure On
+     (PLL      : in     DKL_DPLLs;
+      Port_Cfg : in     Port_Config;
+      Success  :    out Boolean);
+
+   procedure Free (PLL : DKL_DPLLs);
+
+   procedure All_Off;
+
+end HW.GFX.GMA.PLLs.Dekel_Phy;
diff --git a/common/tigerlake/hw-gfx-gma-plls.adb b/common/tigerlake/hw-gfx-gma-plls.adb
index 2823870..48be928 100644
--- a/common/tigerlake/hw-gfx-gma-plls.adb
+++ b/common/tigerlake/hw-gfx-gma-plls.adb
@@ -14,16 +14,28 @@
 
 with HW.Debug;
 with GNAT.Source_Info;
+with HW.GFX.GMA.PLLs.Combo_Phy;
+with HW.GFX.GMA.PLLs.Dekel_Phy;
+with HW.GFX.GMA.Config;
 
 package body HW.GFX.GMA.PLLs
 with
    Refined_State => (State => PLLs)
 is
 
-   type Count_Range is new Natural range 0 .. 2;
+   type PLL_Type is (PLL_Unknown, PLL_Combo_Phy, PLL_DKL);
+   function Port_PLL_Type (Port : GPU_Port) return PLL_Type is
+     (case Port is
+         when Combo_Port => PLL_Combo_Phy,
+         when USBC_Port => PLL_DKL,
+         when others => PLL_Unknown);
 
+   type Count_Range is new Natural range 0 .. 2;
    type PLL_State is record
       Use_Count  : Count_Range;
+      Used_For_DP : Boolean;
+      Link_Rate   : DP_Bandwidth;
+      Mode        : Mode_Type;
    end record;
 
    type PLL_State_Array is array (Configurable_DPLLs) of PLL_State;
@@ -41,7 +53,10 @@
       pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
       PLLs :=
         (Configurable_DPLLs =>
-           (Use_Count => 0));
+           (Use_Count   => 0,
+            Used_For_DP => False,
+            Link_Rate   => DP_Bandwidth'First,
+            Mode        => Invalid_Mode));
    end Initialize;
 
    procedure Alloc
@@ -49,26 +64,94 @@
       PLL      :    out T;
       Success  :    out Boolean)
    is
+      function Port_PLL_Match (Port : GPU_Port; PLL : T) return Boolean is
+        (case Port is
+            when Combo_Port => PLL in Combo_DPLLs,
+            when DDI_TC1    => PLL = TCPLL1,
+            when DDI_TC2    => PLL = TCPLL2,
+            when DDI_TC3    => PLL = TCPLL3,
+            when DDI_TC4    => PLL = TCPLL4,
+            when DDI_TC5    => PLL = TCPLL5,
+            when DDI_TC6    => PLL = TCPLL6,
+            when others     => False);
+
+      function Config_Matches (PE : HW.GFX.GMA.PLLs.PLL_State) return Boolean
+      is
+      begin
+         return
+            PE.Used_For_DP = (Port_Cfg.Display = DP) and
+            ((PE.Used_For_DP and PE.Link_Rate = Port_Cfg.DP.Bandwidth) or
+             (not PE.Used_For_DP and PE.Mode = Port_Cfg.Mode));
+      end Config_Matches;
    begin
       pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
-      PLL := Invalid_PLL;
-      Success := True;
+
+      for P in Configurable_DPLLs loop
+         Success := PLLs (P).Use_Count /= 0 and
+                     PLLs (P).Use_Count /= Count_Range'Last and
+                     Port_PLL_Match (Port_Cfg.Port, P) and
+                     Config_Matches (PLLs (P));
+         if Success then
+            PLL := P;
+            PLLs (PLL).Use_Count := PLLs (PLL).Use_Count + 1;
+            return;
+         end if;
+      end loop;
+
+      for P in Configurable_DPLLs loop
+         if PLLs (P).Use_Count = 0 and Port_PLL_Match (Port_Cfg.Port, P) then
+            PLL := P;
+            case P is
+               when Combo_DPLLs => Combo_Phy.On (PLL, Port_Cfg, Success);
+               when DKL_DPLLs   => Dekel_Phy.On (PLL, Port_Cfg, Success);
+            end case;
+            if Success then
+               PLLs (PLL) :=
+                 (Use_Count   => 1,
+                  Used_For_DP => Port_Cfg.Display = DP,
+                  Link_Rate   => Port_Cfg.DP.Bandwidth,
+                  Mode        => Port_Cfg.Mode);
+            end if;
+            return;
+         end if;
+      end loop;
+
+      PLL := Invalid;
+      Success := False;
    end Alloc;
 
    procedure Free (PLL : T) is
    begin
       pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+      if PLL /= Invalid_PLL then
+         PLLs (PLL).Use_Count := 0;
+      end if;
+
+      case PLL is
+         when Combo_DPLLs => Combo_Phy.Free (PLL);
+         when DKL_DPLLs   => Dekel_Phy.Free (PLL);
+         when Invalid_PLL => null;
+      end case;
    end Free;
 
    procedure All_Off is
    begin
       pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+      Combo_Phy.All_Off;
+      Dekel_Phy.All_Off;
    end All_Off;
 
    function Register_Value (PLL : T) return Word32
    is
    begin
       pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
-      Return 0;
+
+      -- Only required for combo ports
+      if PLL in Combo_DPLLs then
+         return Combo_Phy.Register_Value (PLL);
+      end if;
+
+      return 0;
    end Register_Value;
 end HW.GFX.GMA.PLLs;
diff --git a/common/tigerlake/hw-gfx-gma-plls.ads b/common/tigerlake/hw-gfx-gma-plls.ads
index 3e55044..60b7dca 100644
--- a/common/tigerlake/hw-gfx-gma-plls.ads
+++ b/common/tigerlake/hw-gfx-gma-plls.ads
@@ -18,36 +18,25 @@
 is
 
    -- XXX: Types should be private (but that triggers a bug in SPARK GPL 2016)
-   type T is (Invalid_PLL, DPLL0, DPLL1, DPLL4, DPLL2);
-   subtype Configurable_DPLLs is T range DPLL0 .. DPLL4;
+   type T is (Invalid_PLL, DPLL0, DPLL1, TCPLL1, TCPLL2, TCPLL3, TCPLL4, TCPLL5, TCPLL6);
+   subtype Configurable_DPLLs is T range T'Succ (Invalid_PLL) .. T'Last;
+   subtype Combo_DPLLs is T range DPLL0 .. DPLL1;
+   subtype DKL_DPLLs is T range TCPLL1 .. TCPLL6;
    Invalid : constant T := Invalid_PLL;
 
    procedure Initialize
    with
       Global => (Output => State);
 
-   pragma Warnings (Off, "unused variable ""Port_Cfg""",
-                    Reason => "Not yet implemented.");
    procedure Alloc
      (Port_Cfg : in     Port_Config;
       PLL      :    out T;
       Success  :    out Boolean);
-   pragma Warnings (On, "unused variable ""Port_Cfg""");
 
-
-   pragma Warnings (Off, "subprogram ""Free"" has no effect",
-                    Reason => "Not yet implemented.");
    procedure Free (PLL : T);
-   pragma Warnings (On, "subprogram ""Free"" has no effect");
 
-   pragma Warnings (Off, "subprogram ""All_Off"" has no effect",
-                    Reason => "Not yet implemented.");
    procedure All_Off;
-   pragma Warnings (On, "subprogram ""All_Off"" has no effect");
 
-   pragma Warnings (Off, "unused variable ""PLL""",
-                    Reason => "Not yet implemented.");
    function Register_Value (PLL : T) return Word32;
-   pragma Warnings (On, "unused variable ""PLL""");
 
 end HW.GFX.GMA.PLLs;