Initial upstream commit

The history contained unlicensed code so everything got squashed, sorry.

Change-Id: I9f5775208f9df6fb29074bf3bc498f68cb17b3a0
Signed-off-by: Nico Huber <nico.huber@secunet.com>
diff --git a/common/skylake/Makefile.inc b/common/skylake/Makefile.inc
new file mode 100644
index 0000000..2dec2ef
--- /dev/null
+++ b/common/skylake/Makefile.inc
@@ -0,0 +1,10 @@
+gfxinit-y += hw-gfx-gma-plls-dpll.adb
+gfxinit-y += hw-gfx-gma-plls-dpll.ads
+gfxinit-y += hw-gfx-gma-plls-dpll_0.adb
+gfxinit-y += hw-gfx-gma-plls-dpll_0.ads
+gfxinit-y += hw-gfx-gma-plls.adb
+gfxinit-y += hw-gfx-gma-plls.ads
+gfxinit-y += hw-gfx-gma-power_and_clocks.ads
+gfxinit-y += hw-gfx-gma-power_and_clocks_skylake.adb
+gfxinit-y += hw-gfx-gma-power_and_clocks_skylake.ads
+gfxinit-y += hw-gfx-gma-spll.ads
diff --git a/common/skylake/hw-gfx-gma-plls-dpll.adb b/common/skylake/hw-gfx-gma-plls-dpll.adb
new file mode 100644
index 0000000..c48f4ff
--- /dev/null
+++ b/common/skylake/hw-gfx-gma-plls-dpll.adb
@@ -0,0 +1,357 @@
+--
+-- Copyright (C) 2016 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
+-- the Free Software Foundation; version 2 of the License.
+--
+-- 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.Registers;
+
+package body HW.GFX.GMA.PLLs.DPLL is
+
+   -- NOTE: Order of DPLLs is twisted => always use named associations!
+
+   type Regs is array (Configurable_DPLLs) of Registers.Registers_Index;
+
+   DPLL_CTL : constant Regs := Regs'
+     (DPLL1 => Registers.LCPLL2_CTL,
+      DPLL2 => Registers.WRPLL_CTL_1,
+      DPLL3 => Registers.WRPLL_CTL_2);
+   DPLL_CTL_PLL_ENABLE                 : constant := 1 * 2 ** 31;
+
+   ----------------------------------------------------------------------------
+
+   DPLL_CFGR1 : constant Regs := Regs'
+     (DPLL1 => Registers.DPLL1_CFGR1,
+      DPLL2 => Registers.DPLL2_CFGR1,
+      DPLL3 => Registers.DPLL3_CFGR1);
+   DPLL_CFGR1_FREQUENCY_ENABLE         : constant :=        1 * 2 ** 31;
+   DPLL_CFGR1_DCO_FRACTION_SHIFT       : constant :=                  9;
+   DPLL_CFGR1_DCO_FRACTION_MASK        : constant := 16#7fff# * 2 **  9;
+   DPLL_CFGR1_DCO_INTEGER_MASK         : constant := 16#01ff# * 2 **  0;
+
+   DPLL_CFGR2 : constant Regs := Regs'
+     (DPLL1 => Registers.DPLL1_CFGR2,
+      DPLL2 => Registers.DPLL2_CFGR2,
+      DPLL3 => Registers.DPLL3_CFGR2);
+   DPLL_CFGR2_QDIV_RATIO_SHIFT         : constant :=            8;
+   DPLL_CFGR2_QDIV_RATIO_MASK          : constant := 255 * 2 ** 8;
+   DPLL_CFGR2_QDIV_MODE                : constant :=   1 * 2 ** 7;
+   DPLL_CFGR2_KDIV_SHIFT               : constant :=            5;
+   DPLL_CFGR2_KDIV_MASK                : constant :=   3 * 2 ** 5;
+   DPLL_CFGR2_PDIV_SHIFT               : constant :=            2;
+   DPLL_CFGR2_PDIV_MASK                : constant :=   7 * 2 ** 2;
+   DPLL_CFGR2_CENTRAL_FREQ_MASK        : constant :=   3 * 2 ** 0;
+   DPLL_CFGR2_CENTRAL_FREQ_9600MHZ     : constant :=   0 * 2 ** 0;
+   DPLL_CFGR2_CENTRAL_FREQ_9000MHZ     : constant :=   1 * 2 ** 0;
+   DPLL_CFGR2_CENTRAL_FREQ_8400MHZ     : constant :=   3 * 2 ** 0;
+
+   ----------------------------------------------------------------------------
+
+   HDMI_MODE            : constant := 1 * 2 **  5;
+   SSC                  : constant := 1 * 2 **  4;
+   LINK_RATE_MASK       : constant := 7 * 2 **  1;
+   LINK_RATE_2700MHZ    : constant := 0 * 2 **  1;
+   LINK_RATE_1350MHZ    : constant := 1 * 2 **  1;
+   LINK_RATE_810MHZ     : constant := 2 * 2 **  1;
+   LINK_RATE_1620MHZ    : constant := 3 * 2 **  1;
+   LINK_RATE_1080MHZ    : constant := 4 * 2 **  1;
+   LINK_RATE_2160MHZ    : constant := 5 * 2 **  1;
+   OVERRIDE             : constant := 1 * 2 **  0;
+
+   LOCK                 : constant := 1 * 2 **  0;
+
+   type Shifts is array (Configurable_DPLLs) of Natural;
+   DPLL_CTRL1_SHIFT : constant Shifts :=
+     (DPLL1 => 6, DPLL2 => 12, DPLL3 => 18);
+   DPLL_STATUS_SHIFT : constant Shifts :=
+     (DPLL1 => 8, DPLL2 => 16, DPLL3 => 24);
+
+   function LINK_RATE (Link_Rate : DP_Bandwidth) return Word32 is
+   begin
+      return (case Link_Rate is
+               when DP_Bandwidth_5_4   => LINK_RATE_2700MHZ,
+               when DP_Bandwidth_2_7   => LINK_RATE_1350MHZ,
+               when DP_Bandwidth_1_62  => LINK_RATE_810MHZ);
+   end LINK_RATE;
+
+   function DPLL_CTRL1_DPLLx
+     (Value : Word32;
+      PLL   : Configurable_DPLLs)
+      return Word32 is
+   begin
+      return Shift_Left (Value, DPLL_CTRL1_SHIFT (PLL));
+   end DPLL_CTRL1_DPLLx;
+
+   function DPLL_STATUS_DPLLx_LOCK (PLL : Configurable_DPLLs) return Word32 is
+   begin
+      return Shift_Left (LOCK, DPLL_STATUS_SHIFT (PLL));
+   end DPLL_STATUS_DPLLx_LOCK;
+
+   ----------------------------------------------------------------------------
+
+   subtype PDiv_Range is Pos64 range 1 ..   7;
+   subtype QDiv_Range is Pos64 range 1 .. 255;
+   subtype KDiv_Range is Pos64 range 1 ..   5;
+
+   type Central_Frequency is (CF_INVALID, CF_9600MHZ, CF_9000MHZ, CF_8400MHZ);
+   subtype Valid_Central_Freq is
+      Central_Frequency range CF_9600MHZ .. CF_8400MHZ;
+
+   type CF_Pos is array (Valid_Central_Freq) of Pos64;
+   CF_Pos64 : constant CF_Pos := CF_Pos'
+     (CF_9600MHZ  => 9_600_000_000,
+      CF_9000MHZ  => 9_000_000_000,
+      CF_8400MHZ  => 8_400_000_000);
+
+   subtype DCO_Frequency is
+      Pos64 range 1 .. CF_Pos64 (CF_9600MHZ) + CF_Pos64 (CF_9600MHZ) / 100;
+
+   function DPLL_CFGR1_DCO_FRACTION (DCO_Freq : DCO_Frequency) return Word32
+   with
+      Pre => True
+   is
+   begin
+      return Shift_Left
+        (Word32 ((DCO_Freq * 2 ** 15) / 24_000_000) and 16#7fff#,
+         DPLL_CFGR1_DCO_FRACTION_SHIFT);
+   end DPLL_CFGR1_DCO_FRACTION;
+
+   function DPLL_CFGR1_DCO_INTEGER (DCO_Freq : DCO_Frequency) return Word32
+   with
+      Pre => True
+   is
+   begin
+      return Word32 (DCO_Freq / 24_000_000);
+   end DPLL_CFGR1_DCO_INTEGER;
+
+   function DPLL_CFGR2_PDIV (PDiv : PDiv_Range) return Word32 is
+   begin
+      return Shift_Left
+        ((case PDiv is
+            when      1 => 0,
+            when      2 => 1,
+            when      3 => 2,
+            when      7 => 4,
+            when others => 4),
+         DPLL_CFGR2_PDIV_SHIFT);
+   end DPLL_CFGR2_PDIV;
+
+   function DPLL_CFGR2_QDIV (QDiv : QDiv_Range) return Word32 is
+   begin
+      return Shift_Left (Word32 (QDiv), DPLL_CFGR2_QDIV_RATIO_SHIFT) or
+             (if QDiv /= 1 then DPLL_CFGR2_QDIV_MODE else 0);
+   end DPLL_CFGR2_QDIV;
+
+   function DPLL_CFGR2_KDIV (KDiv : KDiv_Range) return Word32 is
+   begin
+      return Shift_Left
+        ((case KDiv is
+            when      5 => 0,
+            when      2 => 1,
+            when      3 => 2,
+            when      1 => 3,
+            when others => 0),
+         DPLL_CFGR2_KDIV_SHIFT);
+   end DPLL_CFGR2_KDIV;
+
+   function DPLL_CFGR2_CENTRAL_FREQ (CF : Valid_Central_Freq) return Word32 is
+   begin
+      return (case CF is
+               when CF_9600MHZ   => DPLL_CFGR2_CENTRAL_FREQ_9600MHZ,
+               when CF_9000MHZ   => DPLL_CFGR2_CENTRAL_FREQ_9000MHZ,
+               when CF_8400MHZ   => DPLL_CFGR2_CENTRAL_FREQ_8400MHZ);
+   end DPLL_CFGR2_CENTRAL_FREQ;
+
+   ----------------------------------------------------------------------------
+
+   procedure Calculate_DPLL
+     (Dotclock       : in     Frequency_Type;
+      Central_Freq   :    out Central_Frequency;
+      DCO_Freq       :    out DCO_Frequency;
+      PDiv           :    out PDiv_Range;
+      QDiv           :    out QDiv_Range;
+      KDiv           :    out KDiv_Range)
+   with
+      Pre => True
+   is
+      Max_Pos_Deviation : constant := 1;
+      Max_Neg_Deviation : constant := 6;
+
+      subtype Div_Range is Pos64 range 1 .. 98;
+      subtype Candidate_Index is Positive range 1 .. 36;
+      type Candidate_Array is array (Candidate_Index) of Div_Range;
+      type Candidate_List is record
+         Divs  : Candidate_Array;
+         Count : Candidate_Index;
+      end record;
+      type Parity_Type is (Even, Odd);
+      type Candidates_Type is array (Parity_Type) of Candidate_List;
+
+      Candidates : constant Candidates_Type := Candidates_Type'
+        (Even  => Candidate_List'
+           (Divs  => Candidate_Array'
+              (4, 6, 8, 10, 12, 14, 16, 18, 20, 24, 28, 30, 32, 36, 40, 42, 44,
+               48, 52, 54, 56, 60, 64, 66, 68, 70, 72, 76, 78, 80, 84, 88, 90,
+               92, 96, 98),
+            Count => 36),
+         Odd   => Candidate_List'
+           (Divs  => Candidate_Array'(3, 5, 7, 9, 15, 21, 35, others => 1),
+            Count => 7));
+
+      Temp_Freq,
+      Allowed_Deviation : Pos64;
+      Deviation         : Int64;
+      Temp_Central      : DCO_Frequency;
+      Min_Deviation     : Int64 := Int64'Last;
+      Div               : Div_Range := Div_Range'Last;
+   begin
+      Central_Freq   := CF_INVALID;
+      DCO_Freq       := 1;
+      PDiv           := 1;
+      QDiv           := 1;
+      KDiv           := 1;
+
+      for Parity in Parity_Type loop
+         for CF in Valid_Central_Freq loop
+            Temp_Central := CF_Pos64 (CF);
+            for I in Candidate_Index range 1 .. Candidates (Parity).Count loop
+               Temp_Freq := Candidates (Parity).Divs (I) * 5 * Dotclock;
+               if Temp_Freq > Temp_Central then
+                  Deviation         := Temp_Freq - Temp_Central;
+                  Allowed_Deviation := (Max_Pos_Deviation * Temp_Central) / 100;
+               else
+                  Deviation         := Temp_Central - Temp_Freq;
+                  Allowed_Deviation := (Max_Neg_Deviation * Temp_Central) / 100;
+               end if;
+               if Deviation < Min_Deviation and
+                  Deviation < Allowed_Deviation
+               then
+                  Min_Deviation  := Deviation;
+                  Central_Freq   := CF;
+                  DCO_Freq       := Temp_Freq;
+                  Div            := Candidates (Parity).Divs (I);
+               end if;
+            end loop;
+         end loop;
+         exit when Central_Freq /= CF_INVALID;
+      end loop;
+
+      if Central_Freq /= CF_INVALID then
+         if Div mod 2 = 0 then
+            pragma Assert (Div /= 1);
+            pragma Assert (Div > 1);
+            Div := Div / 2;
+            if Div = 1 or Div = 3 or Div = 5 then
+               -- 2, 6 and 10
+               PDiv := 2;
+               QDiv := 1;
+               KDiv := Div;
+            elsif Div mod 2 = 0 then
+               -- divisible by 4
+               PDiv := 2;
+               QDiv := Div / 2;
+               KDiv := 2;
+            elsif Div mod 3 = 0 then
+               -- divisible by 6
+               PDiv := 3;
+               QDiv := Div / 3;
+               KDiv := 2;
+            elsif Div mod 7 = 0  then
+               -- divisible by 14
+               PDiv := 7;
+               QDiv := Div / 7;
+               KDiv := 2;
+            end if;
+         elsif Div = 7 or Div = 21 or Div = 35 then
+            -- 7, 21 and 35
+            PDiv := 7;
+            QDiv := 1;
+            KDiv := Div / 7;
+         elsif Div = 3 or Div = 9 or Div = 15 then
+            -- 3, 9 and 15
+            PDiv := 3;
+            QDiv := 1;
+            KDiv := Div / 3;
+         elsif Div = 5 then
+            -- 5
+            PDiv := 5;
+            QDiv := 1;
+            KDiv := 1;
+         end if;
+      end if;
+   end Calculate_DPLL;
+
+   ----------------------------------------------------------------------------
+
+   procedure On
+     (PLL      : in     Configurable_DPLLs;
+      Port_Cfg : in     Port_Config;
+      Success  :    out Boolean)
+   is
+      Central_Freq   : Central_Frequency;
+      DCO_Freq       : DCO_Frequency;
+      PDiv           : PDiv_Range;
+      QDiv           : QDiv_Range;
+      KDiv           : KDiv_Range;
+   begin
+      if Port_Cfg.Display = DP then
+         Registers.Unset_And_Set_Mask
+           (Register    => Registers.DPLL_CTRL1,
+            Mask_Unset  => DPLL_CTRL1_DPLLx (HDMI_MODE, PLL) or
+                           DPLL_CTRL1_DPLLx (SSC, PLL) or
+                           DPLL_CTRL1_DPLLx (LINK_RATE_MASK, PLL),
+            Mask_Set    => DPLL_CTRL1_DPLLx (LINK_RATE
+                             (Port_Cfg.DP.Bandwidth), PLL) or
+                           DPLL_CTRL1_DPLLx (OVERRIDE, PLL));
+         Registers.Posting_Read (Registers.DPLL_CTRL1);
+         Success := True;
+      else
+         Calculate_DPLL
+           (Port_Cfg.Mode.Dotclock, Central_Freq, DCO_Freq, PDiv, QDiv, KDiv);
+         Success := Central_Freq /= CF_INVALID;
+         if Success then
+            Registers.Unset_And_Set_Mask
+              (Register    => Registers.DPLL_CTRL1,
+               Mask_Unset  => DPLL_CTRL1_DPLLx (SSC, PLL),
+               Mask_Set    => DPLL_CTRL1_DPLLx (HDMI_MODE, PLL) or
+                              DPLL_CTRL1_DPLLx (OVERRIDE, PLL));
+            Registers.Write
+              (Register    => DPLL_CFGR1 (PLL),
+               Value       => DPLL_CFGR1_FREQUENCY_ENABLE or
+                              DPLL_CFGR1_DCO_FRACTION (DCO_Freq) or
+                              DPLL_CFGR1_DCO_INTEGER (DCO_Freq));
+            Registers.Write
+              (Register    => DPLL_CFGR2 (PLL),
+               Value       => DPLL_CFGR2_QDIV (QDiv) or
+                              DPLL_CFGR2_KDIV (KDiv) or
+                              DPLL_CFGR2_PDIV (PDiv) or
+                              DPLL_CFGR2_CENTRAL_FREQ (Central_Freq));
+            Registers.Posting_Read (Registers.DPLL_CTRL1);
+            Registers.Posting_Read (DPLL_CFGR1 (PLL));
+            Registers.Posting_Read (DPLL_CFGR2 (PLL));
+         end if;
+      end if;
+
+      if Success then
+         Registers.Write
+           (Register => DPLL_CTL (PLL),
+            Value    => DPLL_CTL_PLL_ENABLE);
+         Registers.Wait_Set_Mask
+           (Register => Registers.DPLL_STATUS,
+            Mask     => DPLL_STATUS_DPLLx_LOCK (PLL));
+      end if;
+   end On;
+
+   procedure Off (PLL : Configurable_DPLLs) is
+   begin
+      Registers.Unset_Mask (DPLL_CTL (PLL), DPLL_CTL_PLL_ENABLE);
+   end Off;
+
+end HW.GFX.GMA.PLLs.DPLL;
diff --git a/common/skylake/hw-gfx-gma-plls-dpll.ads b/common/skylake/hw-gfx-gma-plls-dpll.ads
new file mode 100644
index 0000000..61bd55e
--- /dev/null
+++ b/common/skylake/hw-gfx-gma-plls-dpll.ads
@@ -0,0 +1,27 @@
+--
+-- Copyright (C) 2016 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
+-- the Free Software Foundation; version 2 of the License.
+--
+-- 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.
+--
+
+private package HW.GFX.GMA.PLLs.DPLL is
+
+   type Value_Array is array (Configurable_DPLLs) of Word32;
+   Register_Value : constant Value_Array := Value_Array'
+     (DPLL1 => 1, DPLL2 => 2, DPLL3 => 3);
+
+   procedure On
+     (PLL      : in     Configurable_DPLLs;
+      Port_Cfg : in     Port_Config;
+      Success  :    out Boolean);
+
+   procedure Off (PLL : Configurable_DPLLs);
+
+end HW.GFX.GMA.PLLs.DPLL;
diff --git a/common/skylake/hw-gfx-gma-plls-dpll_0.adb b/common/skylake/hw-gfx-gma-plls-dpll_0.adb
new file mode 100644
index 0000000..f981940
--- /dev/null
+++ b/common/skylake/hw-gfx-gma-plls-dpll_0.adb
@@ -0,0 +1,48 @@
+--
+-- Copyright (C) 2016 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
+-- the Free Software Foundation; version 2 of the License.
+--
+-- 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.Registers;
+
+package body HW.GFX.GMA.PLLs.DPLL_0 is
+
+   DPLL_CTRL1_DPLL0_LINK_RATE_MASK     : constant := 7 * 2 **  1;
+   DPLL_CTRL1_DPLL0_LINK_RATE_2700MHZ  : constant := 0 * 2 **  1;
+   DPLL_CTRL1_DPLL0_LINK_RATE_1350MHZ  : constant := 1 * 2 **  1;
+   DPLL_CTRL1_DPLL0_LINK_RATE_810MHZ   : constant := 2 * 2 **  1;
+   DPLL_CTRL1_DPLL0_LINK_RATE_1620MHZ  : constant := 3 * 2 **  1;
+   DPLL_CTRL1_DPLL0_LINK_RATE_1080MHZ  : constant := 4 * 2 **  1;
+   DPLL_CTRL1_DPLL0_LINK_RATE_2160MHZ  : constant := 5 * 2 **  1;
+   DPLL_CTRL1_DPLL0_OVERRIDE           : constant := 1 * 2 **  0;
+
+   procedure Check_Link_Rate
+     (Link_Rate   : in     DP_Bandwidth;
+      Success     :    out Boolean)
+   is
+      DPLL_Ctrl1 : Word32;
+   begin
+      Registers.Read (Registers.DPLL_CTRL1, DPLL_Ctrl1);
+
+      case DPLL_Ctrl1 and DPLL_CTRL1_DPLL0_LINK_RATE_MASK is
+         when DPLL_CTRL1_DPLL0_LINK_RATE_2700MHZ =>
+            Success := Link_Rate = DP_Bandwidth_5_4;
+         when DPLL_CTRL1_DPLL0_LINK_RATE_1350MHZ =>
+            Success := Link_Rate = DP_Bandwidth_2_7;
+         when DPLL_CTRL1_DPLL0_LINK_RATE_810MHZ =>
+            Success := Link_Rate = DP_Bandwidth_1_62;
+         when others =>
+            Success := False;
+      end case;
+      Success := Success and (DPLL_Ctrl1 and DPLL_CTRL1_DPLL0_OVERRIDE) /= 0;
+   end Check_Link_Rate;
+
+end HW.GFX.GMA.PLLs.DPLL_0;
diff --git a/common/skylake/hw-gfx-gma-plls-dpll_0.ads b/common/skylake/hw-gfx-gma-plls-dpll_0.ads
new file mode 100644
index 0000000..a2fecfa
--- /dev/null
+++ b/common/skylake/hw-gfx-gma-plls-dpll_0.ads
@@ -0,0 +1,22 @@
+--
+-- Copyright (C) 2016 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
+-- the Free Software Foundation; version 2 of the License.
+--
+-- 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.
+--
+
+private package HW.GFX.GMA.PLLs.DPLL_0 is
+
+   Register_Value : constant Word32 := 0;
+
+   procedure Check_Link_Rate
+     (Link_Rate   : in     DP_Bandwidth;
+      Success     :    out Boolean);
+
+end HW.GFX.GMA.PLLs.DPLL_0;
diff --git a/common/skylake/hw-gfx-gma-plls.adb b/common/skylake/hw-gfx-gma-plls.adb
new file mode 100644
index 0000000..561f8ad
--- /dev/null
+++ b/common/skylake/hw-gfx-gma-plls.adb
@@ -0,0 +1,151 @@
+--
+-- Copyright (C) 2015-2016 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
+-- the Free Software Foundation; version 2 of the License.
+--
+-- 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.PLLs.DPLL_0;
+with HW.GFX.GMA.PLLs.DPLL;
+
+with HW.Debug;
+with GNAT.Source_Info;
+
+package body HW.GFX.GMA.PLLs
+with
+   Refined_State => (State => PLLs)
+is
+
+   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;
+
+   PLLs : PLL_State_Array;
+
+   procedure Initialize
+   is
+   begin
+      PLLs :=
+        (Configurable_DPLLs =>
+           (Use_Count   => 0,
+            Used_For_DP => False,
+            Link_Rate   => DP_Bandwidth'First,
+            Mode        => Invalid_Mode));
+   end Initialize;
+
+   procedure Alloc_Configurable
+     (Port_Cfg : in     Port_Config;
+      PLL      :    out T;
+      Success  :    out Boolean)
+   with
+      Pre => True
+   is
+      function Config_Matches (PE : 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
+      -- try to find shareable PLL
+      for P in Configurable_DPLLs loop
+         Success := PLLs (P).Use_Count /= 0 and
+                     PLLs (P).Use_Count /= Count_Range'Last and
+                     Config_Matches (PLLs (P));
+         if Success then
+            PLL := P;
+            PLLs (PLL).Use_Count := PLLs (PLL).Use_Count + 1;
+            return;
+         end if;
+      end loop;
+
+      -- try to find free PLL
+      for P in Configurable_DPLLs loop
+         if PLLs (P).Use_Count = 0 then
+            PLL := P;
+            DPLL.On (PLL, Port_Cfg, Success);
+            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;
+   end Alloc_Configurable;
+
+   procedure Alloc
+     (Port_Cfg : in     Port_Config;
+      PLL      :    out T;
+      Success  :    out Boolean)
+   is
+   begin
+      pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+      if Port_Cfg.Port = DIGI_A then
+         DPLL_0.Check_Link_Rate (Port_Cfg.DP.Bandwidth, Success);
+      else
+         Success := False;
+      end if;
+
+      if Success then
+         PLL := DPLL0;
+      else
+         Alloc_Configurable (Port_Cfg, PLL, Success);
+      end if;
+   end Alloc;
+
+   procedure Free (PLL : T)
+   is
+   begin
+      pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+      if PLL in Configurable_DPLLs then
+         if PLLs (PLL).Use_Count /= 0 then
+            PLLs (PLL).Use_Count := PLLs (PLL).Use_Count - 1;
+            if PLLs (PLL).Use_Count = 0 then
+               DPLL.Off (PLL);
+            end if;
+         end if;
+      end if;
+   end Free;
+
+   procedure All_Off
+   is
+   begin
+      pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+      for PLL in Configurable_DPLLs loop
+         DPLL.Off (PLL);
+      end loop;
+   end All_Off;
+
+   function Register_Value (PLL : T) return Word32
+   is
+   begin
+      return
+        (if    PLL = DPLL0                then DPLL_0.Register_Value
+         elsif PLL in Configurable_DPLLs  then DPLL.Register_Value (PLL)
+         else 0);
+   end Register_Value;
+
+end HW.GFX.GMA.PLLs;
diff --git a/common/skylake/hw-gfx-gma-plls.ads b/common/skylake/hw-gfx-gma-plls.ads
new file mode 100644
index 0000000..9407af0
--- /dev/null
+++ b/common/skylake/hw-gfx-gma-plls.ads
@@ -0,0 +1,42 @@
+--
+-- Copyright (C) 2015-2016 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
+-- the Free Software Foundation; version 2 of the License.
+--
+-- 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.
+--
+
+private package HW.GFX.GMA.PLLs
+with
+   Abstract_State => (State with Part_Of => GMA.State)
+is
+
+   -- NOTE: Order of DPLLs is twisted, as DPLL2 (WRPLL1)
+   --       should be selected as last choice.
+
+   -- XXX: Types should be private (but that triggers a bug in SPARK GPL 2016)
+   type T is (Invalid_PLL, DPLL0, DPLL1, DPLL3, DPLL2);
+   subtype Configurable_DPLLs is T range DPLL1 .. DPLL2;
+   Invalid : constant T := Invalid_PLL;
+
+   procedure Initialize
+   with
+      Global => (Output => State);
+
+   procedure Alloc
+     (Port_Cfg : in     Port_Config;
+      PLL      :    out T;
+      Success  :    out Boolean);
+
+   procedure Free (PLL : T);
+
+   procedure All_Off;
+
+   function Register_Value (PLL : T) return Word32;
+
+end HW.GFX.GMA.PLLs;
diff --git a/common/skylake/hw-gfx-gma-power_and_clocks.ads b/common/skylake/hw-gfx-gma-power_and_clocks.ads
new file mode 100644
index 0000000..bf54989
--- /dev/null
+++ b/common/skylake/hw-gfx-gma-power_and_clocks.ads
@@ -0,0 +1,17 @@
+--
+-- Copyright (C) 2016 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
+-- the Free Software Foundation; version 2 of the License.
+--
+-- 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.Power_And_Clocks_Skylake;
+
+private package HW.GFX.GMA.Power_And_Clocks
+   renames HW.GFX.GMA.Power_And_Clocks_Skylake;
diff --git a/common/skylake/hw-gfx-gma-power_and_clocks_skylake.adb b/common/skylake/hw-gfx-gma-power_and_clocks_skylake.adb
new file mode 100644
index 0000000..521ef8b
--- /dev/null
+++ b/common/skylake/hw-gfx-gma-power_and_clocks_skylake.adb
@@ -0,0 +1,351 @@
+--
+-- Copyright (C) 2014-2016 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
+-- the Free Software Foundation; version 2 of the License.
+--
+-- 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 GNAT.Source_Info;
+
+with HW.Time;
+with HW.Debug;
+with HW.GFX.GMA.Config;
+with HW.GFX.GMA.Registers;
+with HW.GFX.GMA.Power_And_Clocks_Haswell;
+
+use type HW.Word64;
+
+package body HW.GFX.GMA.Power_And_Clocks_Skylake is
+
+   type Power_Domain is (MISC_IO, PW1, PW2, DDI_AE, DDI_B, DDI_C, DDI_D);
+   subtype Power_Well is Power_Domain range PW1 .. PW2;
+   subtype Dynamic_Domain is Power_Domain range PW2 .. DDI_D;
+
+   NDE_RSTWRN_OPT_RST_PCH_Handshake_En : constant := 1 * 2 **  4;
+
+   FUSE_STATUS_DOWNLOAD_STATUS         : constant := 1 * 2 ** 31;
+   FUSE_STATUS_PG0_DIST_STATUS         : constant := 1 * 2 ** 27;
+
+   type Power_Domain_Values is array (Power_Domain) of Word32;
+   PWR_WELL_CTL_POWER_REQUEST : constant Power_Domain_Values :=
+     (MISC_IO  => 1 * 2 **  1,
+      DDI_AE   => 1 * 2 **  3,
+      DDI_B    => 1 * 2 **  5,
+      DDI_C    => 1 * 2 **  7,
+      DDI_D    => 1 * 2 **  9,
+      PW1      => 1 * 2 ** 29,
+      PW2      => 1 * 2 ** 31);
+   PWR_WELL_CTL_POWER_STATE : constant Power_Domain_Values :=
+     (MISC_IO  => 1 * 2 **  0,
+      DDI_AE   => 1 * 2 **  2,
+      DDI_B    => 1 * 2 **  4,
+      DDI_C    => 1 * 2 **  6,
+      DDI_D    => 1 * 2 **  8,
+      PW1      => 1 * 2 ** 28,
+      PW2      => 1 * 2 ** 30);
+
+   type Power_Well_Values is array (Power_Well) of Word32;
+   FUSE_STATUS_PGx_DIST_STATUS : constant Power_Well_Values :=
+     (PW1   => 1 * 2 ** 26,
+      PW2   => 1 * 2 ** 25);
+
+   DBUF_CTL_DBUF_POWER_REQUEST         : constant := 1 * 2 ** 31;
+   DBUF_CTL_DBUF_POWER_STATE           : constant := 1 * 2 ** 30;
+
+   ----------------------------------------------------------------------------
+
+   DPLL_CTRL1_DPLL0_LINK_RATE_MASK     : constant := 7 * 2 **  1;
+   DPLL_CTRL1_DPLL0_LINK_RATE_2700MHZ  : constant := 0 * 2 **  1;
+   DPLL_CTRL1_DPLL0_LINK_RATE_1350MHZ  : constant := 1 * 2 **  1;
+   DPLL_CTRL1_DPLL0_LINK_RATE_810MHZ   : constant := 2 * 2 **  1;
+   DPLL_CTRL1_DPLL0_LINK_RATE_1620MHZ  : constant := 3 * 2 **  1;
+   DPLL_CTRL1_DPLL0_LINK_RATE_1080MHZ  : constant := 4 * 2 **  1;
+   DPLL_CTRL1_DPLL0_LINK_RATE_2160MHZ  : constant := 5 * 2 **  1;
+   DPLL_CTRL1_DPLL0_OVERRIDE           : constant := 1 * 2 **  0;
+
+   LCPLL1_CTL_PLL_ENABLE               : constant := 1 * 2 ** 31;
+   LCPLL1_CTL_PLL_LOCK                 : constant := 1 * 2 ** 30;
+
+   ----------------------------------------------------------------------------
+
+   CDCLK_CTL_CD_FREQ_SELECT_MASK       : constant := 3 * 2 ** 26;
+   CDCLK_CTL_CD_FREQ_SELECT_450MHZ     : constant := 0 * 2 ** 26;
+   CDCLK_CTL_CD_FREQ_SELECT_540MHZ     : constant := 1 * 2 ** 26;
+   CDCLK_CTL_CD_FREQ_SELECT_337_5MHZ   : constant := 2 * 2 ** 26;
+   CDCLK_CTL_CD_FREQ_SELECT_675MHZ     : constant := 3 * 2 ** 26;
+   CDCLK_CTL_CD_FREQ_DECIMAL_MASK      : constant :=     16#7ff#;
+
+   SKL_PCODE_CDCLK_CONTROL             : constant := 7;
+   SKL_CDCLK_PREPARE_FOR_CHANGE        : constant := 3;
+   SKL_CDCLK_READY_FOR_CHANGE          : constant := 1;
+
+   GT_MAILBOX_READY                    : constant := 1 * 2 ** 31;
+
+   function CDCLK_CTL_CD_FREQ_DECIMAL
+     (Freq        : Positive;
+      Plus_Half   : Boolean)
+      return Word32 is
+   begin
+      return Word32 (2 * (Freq - 1)) or (if Plus_Half then 1 else 0);
+   end CDCLK_CTL_CD_FREQ_DECIMAL;
+
+   ----------------------------------------------------------------------------
+
+   procedure GT_Mailbox_Write (MBox : Word32; Value : Word64) is
+   begin
+      pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+      Registers.Wait_Unset_Mask (Registers.GT_MAILBOX, GT_MAILBOX_READY);
+      Registers.Write
+        (Registers.GT_MAILBOX_DATA, Word32 (Value and 16#ffff_ffff#));
+      Registers.Write
+        (Registers.GT_MAILBOX_DATA_1, Word32 (Shift_Right (Value, 32)));
+      Registers.Write (Registers.GT_MAILBOX, GT_MAILBOX_READY or MBox);
+
+      Registers.Wait_Unset_Mask (Registers.GT_MAILBOX, GT_MAILBOX_READY);
+   end GT_Mailbox_Write;
+
+   ----------------------------------------------------------------------------
+
+   procedure PD_Off (PD : Power_Domain)
+   is
+      Ctl1, Ctl2, Ctl3, Ctl4 : Word32;
+   begin
+      pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+      Registers.Read (Registers.PWR_WELL_CTL_BIOS, Ctl1);
+      Registers.Read (Registers.PWR_WELL_CTL_DRIVER, Ctl2);
+      Registers.Read (Registers.PWR_WELL_CTL_KVMR, Ctl3);
+      Registers.Read (Registers.PWR_WELL_CTL_DEBUG, Ctl4);
+      pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL5)); --  Result for debugging only
+      pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL6)); --  Result for debugging only
+
+      if ((Ctl1 or Ctl2 or Ctl3 or Ctl4) and
+          PWR_WELL_CTL_POWER_REQUEST (PD)) /= 0
+      then
+         Registers.Wait_Set_Mask
+           (Register => Registers.PWR_WELL_CTL_DRIVER,
+            Mask     => PWR_WELL_CTL_POWER_STATE (PD));
+      end if;
+
+      if (Ctl1 and PWR_WELL_CTL_POWER_REQUEST (PD)) /= 0 then
+         Registers.Unset_Mask
+           (Register => Registers.PWR_WELL_CTL_BIOS,
+            Mask     => PWR_WELL_CTL_POWER_REQUEST (PD));
+      end if;
+
+      if (Ctl2 and PWR_WELL_CTL_POWER_REQUEST (PD)) /= 0 then
+         Registers.Unset_Mask
+           (Register => Registers.PWR_WELL_CTL_DRIVER,
+            Mask     => PWR_WELL_CTL_POWER_REQUEST (PD));
+      end if;
+   end PD_Off;
+
+   procedure PD_On (PD : Power_Domain)
+   with
+      Pre => True
+   is
+      Ctl1, Ctl2, Ctl3, Ctl4 : Word32;
+   begin
+      pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+      Registers.Read (Registers.PWR_WELL_CTL_BIOS, Ctl1);
+      Registers.Read (Registers.PWR_WELL_CTL_DRIVER, Ctl2);
+      Registers.Read (Registers.PWR_WELL_CTL_KVMR, Ctl3);
+      Registers.Read (Registers.PWR_WELL_CTL_DEBUG, Ctl4);
+      pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL5)); --  Result for debugging only
+      pragma Debug (Registers.Posting_Read (Registers.PWR_WELL_CTL6)); --  Result for debugging only
+
+      if ((Ctl1 or Ctl2 or Ctl3 or Ctl4) and
+          PWR_WELL_CTL_POWER_REQUEST (PD)) = 0
+      then
+         Registers.Wait_Unset_Mask
+           (Register => Registers.PWR_WELL_CTL_DRIVER,
+            Mask     => PWR_WELL_CTL_POWER_STATE (PD));
+      end if;
+
+      if (Ctl2 and PWR_WELL_CTL_POWER_REQUEST (PD)) = 0 then
+         Registers.Set_Mask
+           (Register => Registers.PWR_WELL_CTL_DRIVER,
+            Mask     => PWR_WELL_CTL_POWER_REQUEST (PD));
+         Registers.Wait_Set_Mask
+           (Register => Registers.PWR_WELL_CTL_DRIVER,
+            Mask     => PWR_WELL_CTL_POWER_STATE (PD));
+
+         if PD in Power_Well then
+            Registers.Wait_Set_Mask
+              (Register => Registers.FUSE_STATUS,
+               Mask     => FUSE_STATUS_PGx_DIST_STATUS (PD));
+         end if;
+      end if;
+   end PD_On;
+
+   function Need_PD (PD : Dynamic_Domain; Configs : Configs_Type) return Boolean
+   is
+   begin
+      return (case PD is
+         when DDI_AE    => Configs (Primary).Port = Internal or
+                           Configs (Secondary).Port = Internal or
+                           Configs (Tertiary).Port = Internal,
+         when DDI_B     => Configs (Primary).Port = Digital1 or
+                           Configs (Primary).Port = DP1 or
+                           Configs (Secondary).Port = Digital1 or
+                           Configs (Secondary).Port = DP1 or
+                           Configs (Tertiary).Port = Digital1 or
+                           Configs (Tertiary).Port = DP1,
+         when DDI_C     => Configs (Primary).Port = Digital2 or
+                           Configs (Primary).Port = DP2 or
+                           Configs (Secondary).Port = Digital2 or
+                           Configs (Secondary).Port = DP2 or
+                           Configs (Tertiary).Port = Digital2 or
+                           Configs (Tertiary).Port = DP2,
+         when DDI_D     => Configs (Primary).Port = Digital3 or
+                           Configs (Primary).Port = DP3 or
+                           Configs (Secondary).Port = Digital3 or
+                           Configs (Secondary).Port = DP3 or
+                           Configs (Tertiary).Port = Digital3 or
+                           Configs (Tertiary).Port = DP3,
+         when PW2       => (Configs (Primary).Port /= Disabled and
+                            Configs (Primary).Port /= Internal) or
+                           Configs (Secondary).Port /= Disabled or
+                           Configs (Tertiary).Port /= Disabled);
+   end Need_PD;
+
+   ----------------------------------------------------------------------------
+
+   procedure Pre_All_Off is
+   begin
+      Power_And_Clocks_Haswell.PSR_Off;
+   end Pre_All_Off;
+
+   procedure Post_All_Off is
+   begin
+      for PD in reverse Dynamic_Domain loop
+         PD_Off (PD);
+      end loop;
+
+      Registers.Unset_Mask
+        (Register    => Registers.DBUF_CTL,
+         Mask        => DBUF_CTL_DBUF_POWER_REQUEST);
+      Registers.Wait_Unset_Mask
+        (Register    => Registers.DBUF_CTL,
+         Mask        => DBUF_CTL_DBUF_POWER_STATE);
+
+      Registers.Unset_Mask
+        (Register    => Registers.LCPLL1_CTL,
+         Mask        => LCPLL1_CTL_PLL_ENABLE);
+      Registers.Wait_Unset_Mask
+        (Register    => Registers.LCPLL1_CTL,
+         Mask        => LCPLL1_CTL_PLL_LOCK);
+
+      PD_Off (MISC_IO);
+      PD_Off (PW1);
+   end Post_All_Off;
+
+   procedure Initialize
+   is
+      CDClk_Change_Timeout : Time.T;
+      Timed_Out : Boolean;
+
+      MBox_Data0 : 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);
+      loop
+         GT_Mailbox_Write
+           (MBox        => SKL_PCODE_CDCLK_CONTROL,
+            Value       => SKL_CDCLK_PREPARE_FOR_CHANGE);
+         Timed_Out := Time.Timed_Out (CDClk_Change_Timeout);
+         Registers.Read (Registers.GT_MAILBOX_DATA, MBox_Data0);
+         if (MBox_Data0 and SKL_CDCLK_READY_FOR_CHANGE) =
+            SKL_CDCLK_READY_FOR_CHANGE
+         then
+            Timed_Out := False;
+            exit;
+         end if;
+         exit when Timed_Out;
+      end loop;
+
+      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);
+      end if;
+   end Initialize;
+
+   procedure Power_Set_To (Configs : Configs_Type) is
+   begin
+      for PD in reverse Dynamic_Domain loop
+         if not Need_PD (PD, Configs) then
+            PD_Off (PD);
+         end if;
+      end loop;
+      for PD in Dynamic_Domain loop
+         if Need_PD (PD, Configs) then
+            PD_On (PD);
+         end if;
+      end loop;
+   end Power_Set_To;
+
+   procedure Power_Up (Old_Configs, New_Configs : Configs_Type) is
+   begin
+      for PD in Dynamic_Domain loop
+         if not Need_PD (PD, Old_Configs) and Need_PD (PD, New_Configs) then
+            PD_On (PD);
+         end if;
+      end loop;
+   end Power_Up;
+
+   procedure Power_Down (Old_Configs, Tmp_Configs, New_Configs : Configs_Type)
+   is
+   begin
+      for PD in reverse Dynamic_Domain loop
+         if (Need_PD (PD, Old_Configs) or Need_PD (PD, Tmp_Configs)) and
+            not Need_PD (PD, New_Configs)
+         then
+            PD_Off (PD);
+         end if;
+      end loop;
+   end Power_Down;
+
+end HW.GFX.GMA.Power_And_Clocks_Skylake;
diff --git a/common/skylake/hw-gfx-gma-power_and_clocks_skylake.ads b/common/skylake/hw-gfx-gma-power_and_clocks_skylake.ads
new file mode 100644
index 0000000..017ca65
--- /dev/null
+++ b/common/skylake/hw-gfx-gma-power_and_clocks_skylake.ads
@@ -0,0 +1,25 @@
+--
+-- Copyright (C) 2016 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
+-- the Free Software Foundation; version 2 of the License.
+--
+-- 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.
+--
+
+private package HW.GFX.GMA.Power_And_Clocks_Skylake is
+
+   procedure Pre_All_Off;
+   procedure Post_All_Off;
+
+   procedure Initialize;
+
+   procedure Power_Set_To (Configs : Configs_Type);
+   procedure Power_Up (Old_Configs, New_Configs : Configs_Type);
+   procedure Power_Down (Old_Configs, Tmp_Configs, New_Configs : Configs_Type);
+
+end HW.GFX.GMA.Power_And_Clocks_Skylake;
diff --git a/common/skylake/hw-gfx-gma-spll.ads b/common/skylake/hw-gfx-gma-spll.ads
new file mode 100644
index 0000000..d9af288
--- /dev/null
+++ b/common/skylake/hw-gfx-gma-spll.ads
@@ -0,0 +1,23 @@
+--
+-- Copyright (C) 2016 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
+-- the Free Software Foundation; version 2 of the License.
+--
+-- 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.
+--
+
+package HW.GFX.GMA.SPLL is
+
+   -- Just for a common interface with Haswell's DDI.
+   -- There is no SPLL (no FDI) on Skylake.
+
+   procedure On is null;
+
+   procedure Off is null;
+
+end HW.GFX.GMA.SPLL;