| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 1 | -- |
| 2 | -- Copyright (C) 2022 Google, LLC |
| 3 | -- |
| 4 | -- This program is free software; you can redistribute it and/or modify |
| 5 | -- it under the terms of the GNU General Public License as published by |
| 6 | -- the Free Software Foundation; either version 2 of the License, or |
| 7 | -- (at your option) any later version. |
| 8 | -- |
| 9 | -- This program is distributed in the hope that it will be useful, |
| 10 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | -- GNU General Public License for more details. |
| 13 | -- |
| 14 | |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 15 | with GNAT.Source_Info; |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 16 | with HW.Debug; |
| 17 | with HW.GFX.GMA.Combo_Phy; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 18 | with HW.GFX.GMA.Config; |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 19 | with HW.GFX.GMA.PCode; |
| 20 | with HW.GFX.GMA.Registers; |
| 21 | with HW.GFX.GMA.Transcoder; |
| Tim Wawrzynczak | 5473d29 | 2023-02-06 16:46:33 -0700 | [diff] [blame] | 22 | with HW.GFX.GMA.Connectors.TC; |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 23 | |
| 24 | use type HW.Word64; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 25 | |
| 26 | package body HW.GFX.GMA.Power_And_Clocks is |
| 27 | |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 28 | subtype CDClk_Range is Config.CDClk_Range; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 29 | |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 30 | type Power_Domain is |
| 31 | (PW1, PW2, PW3, PW4, PW5, |
| 32 | DDI_A, DDI_B, DDI_C, |
| 33 | DDI_USBC1, DDI_USBC2, DDI_USBC3, DDI_USBC4, DDI_USBC5, DDI_USBC6, |
| 34 | AUX_A, AUX_B, AUX_C, |
| 35 | AUX_USBC1, AUX_USBC2, AUX_USBC3, AUX_USBC4, AUX_USBC5, AUX_USBC6); |
| 36 | type Power_Domain_Types is (Power_Well, Power_DDI, Power_AUX); |
| 37 | subtype Dynamic_Domain is Power_Domain range PW2 .. Power_Domain'Last; |
| 38 | subtype PW_Domain is Power_Domain range PW1 .. PW5; |
| 39 | subtype Dynamic_Well is Power_Domain range PW2 .. PW_Domain'Last; |
| 40 | subtype Port_Domain is Power_Domain range DDI_A .. AUX_USBC6; |
| 41 | subtype DDI_Domain is Power_Domain range DDI_A .. DDI_USBC6; |
| Tim Wawrzynczak | 5473d29 | 2023-02-06 16:46:33 -0700 | [diff] [blame] | 42 | subtype DDI_USBC_Domain is Power_Domain range DDI_USBC1 .. DDI_USBC6; |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 43 | subtype AUX_Domain is Power_Domain range AUX_A .. AUX_USBC6; |
| 44 | subtype AUX_USBC_Domain is Power_Domain range AUX_USBC1 .. AUX_USBC6; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 45 | |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 46 | function PW_Index (PW : PW_Domain) return Natural |
| 47 | is |
| 48 | (Power_Domain'Pos (PW) - Power_Domain'Pos (PW_Domain'First)); |
| 49 | |
| 50 | function DDI_Index (DDI : DDI_Domain) return Natural |
| 51 | is |
| 52 | (Power_Domain'Pos (DDI) - Power_Domain'Pos (DDI_Domain'First)); |
| 53 | |
| 54 | function AUX_Index (AUX : AUX_Domain) return Natural |
| 55 | is |
| 56 | (Power_Domain'Pos (AUX) - Power_Domain'Pos (AUX_Domain'First)); |
| 57 | |
| 58 | function AUX_USBC_Index (AUX: AUX_USBC_Domain) return Natural |
| 59 | is |
| 60 | (Power_Domain'Pos (AUX) - Power_Domain'Pos (AUX_USBC_Domain'First)); |
| 61 | |
| 62 | ---------------------------------------------------------------------------- |
| 63 | |
| 64 | function Power_Domain_Type (PD : Power_Domain) return Power_Domain_Types |
| 65 | is |
| 66 | (if PD in PW_Domain then Power_Well |
| 67 | elsif PD in DDI_Domain then Power_DDI |
| 68 | else Power_AUX); |
| 69 | |
| 70 | type Power_Well_Regs is array (Power_Domain_Types) of Registers.Registers_Index; |
| 71 | PWR_CTL_BIOS : constant Power_Well_Regs := |
| 72 | (Power_Well => Registers.PWR_WELL_CTL_BIOS, |
| 73 | Power_DDI => Registers.PWR_DDI_CTL_BIOS, |
| 74 | Power_AUX => Registers.PWR_AUX_CTL_BIOS); |
| 75 | PWR_CTL_DRIVER : constant Power_Well_Regs := |
| 76 | (Power_Well => Registers.PWR_WELL_CTL_DRIVER, |
| 77 | Power_DDI => Registers.PWR_DDI_CTL_DRIVER, |
| 78 | Power_AUX => Registers.PWR_AUX_CTL_DRIVER); |
| 79 | |
| 80 | function Power_State_Mask (PD : Power_Domain) return Word32 |
| 81 | is |
| 82 | (case PD is |
| 83 | when PW_Domain'Range => 1 * 2 ** (2 * PW_Index (PD)), |
| 84 | when DDI_Domain'Range => 1 * 2 ** (2 * DDI_Index (PD)), |
| 85 | when AUX_Domain'Range => 1 * 2 ** (2 * AUX_Index (PD))); |
| 86 | |
| 87 | function Power_Request_Mask (PD : Power_Domain) return Word32 is |
| 88 | begin |
| 89 | return Shift_Left (Power_State_Mask (PD), 1); |
| 90 | end Power_Request_Mask; |
| 91 | |
| 92 | ---------------------------------------------------------------------------- |
| 93 | |
| 94 | PCH_DPMGUNIT_CLOCK_GATE_DISABLE : constant := 1 * 2 ** 15; |
| 95 | NDE_RSTWRN_OPT_RST_PCH_Handshake_En : constant := 1 * 2 ** 4; |
| 96 | |
| 97 | ---------------------------------------------------------------------------- |
| 98 | |
| 99 | DBUF_CTL_DBUF_POWER_REQUEST : constant := 1 * 2 ** 31; |
| 100 | DBUF_CTL_TRACKER_STATE_SERVICE_MASK : constant := 16#f8_0000#; |
| 101 | DBUF_CTL_TRACKER_STATE_SERVICE_SHIFT : constant := 19; |
| 102 | DBUF_CTL_DBUF_POWER_STATE : constant := 1 * 2 ** 30; |
| 103 | |
| 104 | type DBUF_Slices is (S1, S2); |
| 105 | DBUF_CTL : constant array (DBUF_Slices) of Registers.Registers_Index := |
| 106 | (Registers.DBUF_CTL_S0, |
| 107 | Registers.DBUF_CTL_S1); |
| 108 | |
| 109 | ---------------------------------------------------------------------------- |
| 110 | |
| 111 | MBUS_ABOX_CTL_BW_CREDITS_MASK : constant := 16#3# * 2 ** 20; |
| 112 | MBUS_ABOX_CTL_B_CREDITS_MASK : constant := 16#f# * 2 ** 16; |
| 113 | MBUS_ABOX_CTL_BT_CREDITS_POOL1_MASK : constant := 16#1f# * 2 ** 0; |
| 114 | MBUS_ABOX_CTL_BT_CREDITS_POOL2_MASK : constant := 16#1f# * 2 ** 8; |
| 115 | MBUS_ABOX_CTL_BW_CREDITS_SHIFT : constant := 20; |
| 116 | MBUS_ABOX_CTL_B_CREDITS_SHIFT : constant := 16; |
| 117 | MBUS_ABOX_CTL_BT_CREDITS_POOL1_SHIFT : constant := 0; |
| 118 | MBUS_ABOX_CTL_BT_CREDITS_POOL2_SHIFT : constant := 8; |
| 119 | |
| 120 | MBUS_ABOX_MASK : constant Word32 := |
| 121 | (MBUS_ABOX_CTL_BW_CREDITS_MASK or |
| 122 | MBUS_ABOX_CTL_B_CREDITS_MASK or |
| 123 | MBUS_ABOX_CTL_BT_CREDITS_POOL1_MASK or |
| 124 | MBUS_ABOX_CTL_BT_CREDITS_POOL2_MASK); |
| 125 | MBUS_ABOX_CREDITS : constant Word32 := |
| 126 | ( 1 * 2 ** MBUS_ABOX_CTL_BW_CREDITS_SHIFT or |
| 127 | 1 * 2 ** MBUS_ABOX_CTL_B_CREDITS_SHIFT or |
| 128 | 16 * 2 ** MBUS_ABOX_CTL_BT_CREDITS_POOL1_SHIFT or |
| 129 | 16 * 2 ** MBUS_ABOX_CTL_BT_CREDITS_POOL2_SHIFT); |
| 130 | |
| 131 | MBUS_ABOX_CTL : constant array (0 .. 2) of Registers.Registers_Index := |
| 132 | (Registers.MBUS_ABOX_CTL, |
| 133 | Registers.MBUS_ABOX1_CTL, |
| 134 | Registers.MBUS_ABOX2_CTL); |
| 135 | |
| 136 | ---------------------------------------------------------------------------- |
| 137 | |
| 138 | DCPR_MASK_MAXLATENCY_MEMUP_CLR : constant := 1 * 2 ** 27; |
| 139 | DCPR_MASK_LPMODE : constant := 1 * 2 ** 26; |
| 140 | DCPR_SEND_RESP_IMM : constant := 1 * 2 ** 25; |
| 141 | DCPR_CLEAR_MEMSTAT_DIS : constant := 1 * 2 ** 24; |
| 142 | |
| 143 | ---------------------------------------------------------------------------- |
| 144 | |
| 145 | function HIP_INDEX_REG (Aux : AUX_USBC_Domain) return Registers.Registers_Index |
| 146 | is |
| 147 | (if Aux <= AUX_USBC4 |
| 148 | then Registers.HIP_INDEX_REG0 |
| 149 | else Registers.HIP_INDEX_REG1); |
| 150 | |
| 151 | function HIP_INDEX_VAL (Aux : AUX_USBC_Domain; Val : Word32) return Word32 |
| 152 | is |
| 153 | (Val * 2 ** (8 * (AUX_USBC_Index (Aux) mod 4))); |
| 154 | |
| 155 | type DKL_Regs is array (AUX_USBC_Domain) of Registers.Registers_Index; |
| 156 | DKL_CMN_UC_DW_27 : constant DKL_Regs := |
| 157 | (AUX_USBC1 => Registers.DKL_CMN_UC_DW_27_1, |
| 158 | AUX_USBC2 => Registers.DKL_CMN_UC_DW_27_2, |
| 159 | AUX_USBC3 => Registers.DKL_CMN_UC_DW_27_3, |
| 160 | AUX_USBC4 => Registers.DKL_CMN_UC_DW_27_4, |
| 161 | AUX_USBC5 => Registers.DKL_CMN_UC_DW_27_5, |
| 162 | AUX_USBC6 => Registers.DKL_CMN_UC_DW_27_6); |
| 163 | |
| 164 | ---------------------------------------------------------------------------- |
| 165 | |
| 166 | FUSE_STATUS_PG0_DIST_STATUS : constant := 1 * 2 ** 27; |
| 167 | FUSE_STATUS_PGx_DIST_STATUS : constant array (PW_Domain) of Word32 := |
| 168 | (PW1 => 1 * 2 ** 26, |
| 169 | PW2 => 1 * 2 ** 25, |
| 170 | PW3 => 1 * 2 ** 24, |
| 171 | PW4 => 1 * 2 ** 23, |
| 172 | PW5 => 1 * 2 ** 22); |
| 173 | |
| 174 | ---------------------------------------------------------------------------- |
| 175 | |
| 176 | TGL_PCODE_MEM_SUBSYSTEM_INFO : constant := 16#d#; |
| 177 | TGL_PCODE_MEM_SS_READ_GLOBAL_INFO : constant := 0 * 2 ** 8; |
| 178 | TGL_PCODE_CDCLK_CONTROL : constant := 7; |
| 179 | TGL_CDCLK_PREPARE_FOR_CHANGE : constant := 3; |
| 180 | TGL_CDCLK_READY_FOR_CHANGE : constant := 1; |
| 181 | |
| 182 | ---------------------------------------------------------------------------- |
| 183 | |
| 184 | CDCLK_PLL_ENABLE_PLL_RATIO_MASK : constant := 16#ff#; |
| 185 | CDCLK_PLL_ENABLE_PLL_ENABLE : constant := 1 * 2 ** 31; |
| 186 | CDCLK_PLL_ENABLE_PLL_LOCK : constant := 1 * 2 ** 30; |
| 187 | CDCLK_CD2X_DIV_SEL_MASK : constant := 3 * 2 ** 22; |
| 188 | CDCLK_CD2X_DIV_SEL_1 : constant := 0 * 2 ** 22; |
| 189 | CDCLK_CD2X_DIV_SEL_2 : constant := 2 * 2 ** 22; |
| 190 | CDCLK_CD2X_PIPE_NONE : constant := 7 * 2 ** 19; |
| 191 | CDCLK_CTL_CD_FREQ_DECIMAL_MASK : constant := 16#7ff#; |
| 192 | |
| 193 | ---------------------------------------------------------------------------- |
| 194 | |
| 195 | type AUX_CTL_Array is array (AUX_USBC_Domain) of Registers.Registers_Index; |
| 196 | AUX_CTL_Regs : constant AUX_CTL_Array := |
| 197 | (AUX_USBC1 => Registers.DDI_AUX_CTL_USBC1, |
| 198 | AUX_USBC2 => Registers.DDI_AUX_CTL_USBC2, |
| 199 | AUX_USBC3 => Registers.DDI_AUX_CTL_USBC3, |
| 200 | AUX_USBC4 => Registers.DDI_AUX_CTL_USBC4, |
| 201 | AUX_USBC5 => Registers.DDI_AUX_CTL_USBC5, |
| 202 | AUX_USBC6 => Registers.DDI_AUX_CTL_USBC6); |
| 203 | |
| 204 | ---------------------------------------------------------------------------- |
| 205 | |
| 206 | function To_GPU_Port (PD : Port_Domain) return GPU_Port |
| 207 | is |
| 208 | (case PD is |
| 209 | when DDI_A | AUX_A => DIGI_A, |
| 210 | when DDI_B | AUX_B => DIGI_B, |
| 211 | when DDI_C | AUX_C => DIGI_C, |
| 212 | when DDI_USBC1 | AUX_USBC1 => DDI_TC1, |
| 213 | when DDI_USBC2 | AUX_USBC2 => DDI_TC2, |
| 214 | when DDI_USBC3 | AUX_USBC3 => DDI_TC3, |
| 215 | when DDI_USBC4 | AUX_USBC4 => DDI_TC4, |
| 216 | when DDI_USBC5 | AUX_USBC5 => DDI_TC5, |
| 217 | when DDI_USBC6 | AUX_USBC6 => DDI_TC6); |
| 218 | |
| Tim Wawrzynczak | 5473d29 | 2023-02-06 16:46:33 -0700 | [diff] [blame] | 219 | procedure Pre_PD_On (PD : in Power_Domain; Success : out Boolean) |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 220 | is |
| 221 | DP_AUX_CH_CTL_TBT_IO : constant := 1 * 2 ** 11; |
| 222 | begin |
| 223 | if PD in AUX_USBC_Domain then |
| 224 | -- Disable TBT IO mode for AUX |
| 225 | Registers.Unset_Mask |
| 226 | (Register => AUX_CTL_Regs (PD), |
| 227 | Mask => DP_AUX_CH_CTL_TBT_IO); |
| Tim Wawrzynczak | 5473d29 | 2023-02-06 16:46:33 -0700 | [diff] [blame] | 228 | Connectors.TC.Claimed (To_GPU_Port (PD), Success); |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 229 | elsif PD = PW1 then |
| 230 | Registers.Wait_Set_Mask |
| 231 | (Register => Registers.FUSE_STATUS, |
| Tim Wawrzynczak | 5473d29 | 2023-02-06 16:46:33 -0700 | [diff] [blame] | 232 | Mask => FUSE_STATUS_PG0_DIST_STATUS, |
| 233 | Success => Success); |
| 234 | else |
| 235 | Success := True; |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 236 | end if; |
| 237 | end Pre_PD_On; |
| 238 | |
| 239 | procedure Post_PD_On (PD : Power_Domain) |
| 240 | is |
| 241 | DKL_CMN_UC_DW_27_UC_HEALTH : constant := 1 * 2 ** 15; |
| 242 | begin |
| 243 | if PD in PW_Domain then |
| 244 | Registers.Wait_Set_Mask |
| 245 | (Register => Registers.FUSE_STATUS, |
| 246 | Mask => FUSE_STATUS_PGx_DIST_STATUS (PD), |
| 247 | TOut_MS => 1); |
| 248 | elsif PD in AUX_USBC_Domain then |
| 249 | Registers.Write (HIP_INDEX_REG (PD), HIP_INDEX_VAL (PD, 2)); |
| 250 | Registers.Wait_Set_Mask |
| 251 | (Register => DKL_CMN_UC_DW_27 (PD), |
| 252 | Mask => DKL_CMN_UC_DW_27_UC_HEALTH, |
| 253 | TOut_MS => 1); |
| 254 | end if; |
| 255 | end Post_PD_On; |
| 256 | |
| Tim Wawrzynczak | 5473d29 | 2023-02-06 16:46:33 -0700 | [diff] [blame] | 257 | procedure Pre_PD_Off (PD : Power_Domain) is |
| 258 | begin |
| 259 | if PD in DDI_USBC_Domain then |
| 260 | -- Could be moved to a higher level, but right now it's |
| 261 | -- convenient to do it here: When requested to turn the |
| 262 | -- power off, we know exactly that we don't want to use |
| 263 | -- the port (anymore). |
| 264 | Connectors.TC.Disconnect (To_GPU_Port (PD)); |
| 265 | end if; |
| 266 | end Pre_PD_Off; |
| 267 | |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 268 | procedure PD_On (PD : Power_Domain) |
| 269 | is |
| 270 | Ctl1, Ctl2 : Word32; |
| 271 | PD_Type : constant Power_Domain_Types := Power_Domain_Type (PD); |
| 272 | Success : Boolean; |
| 273 | begin |
| 274 | Registers.Read (PWR_CTL_BIOS (PD_Type), Ctl1); |
| 275 | Registers.Read (PWR_CTL_DRIVER (PD_Type), Ctl2); |
| 276 | |
| 277 | if ((Ctl1 or Ctl2) and Power_Request_Mask (PD)) = 0 then |
| 278 | Registers.Wait_Unset_Mask |
| 279 | (Register => PWR_CTL_DRIVER (PD_Type), |
| 280 | Mask => Power_State_Mask (PD), |
| 281 | TOut_MS => 1); |
| 282 | end if; |
| 283 | |
| 284 | if (Ctl2 and Power_Request_Mask (PD)) = 0 then |
| Tim Wawrzynczak | 5473d29 | 2023-02-06 16:46:33 -0700 | [diff] [blame] | 285 | Pre_PD_On (PD, Success); |
| 286 | if not Success then |
| 287 | pragma Debug (Debug.Put_Line ("Connection flow failed!")); |
| 288 | return; |
| 289 | end if; |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 290 | |
| 291 | Registers.Set_Mask (PWR_CTL_DRIVER (PD_Type), Power_Request_Mask (PD)); |
| 292 | |
| 293 | Registers.Wait_Set_Mask |
| 294 | (Register => PWR_CTL_DRIVER (PD_Type), |
| 295 | Mask => Power_State_Mask (PD), |
| 296 | TOut_MS => 1, |
| 297 | Success => Success); |
| 298 | pragma Debug (not Success, Debug.Put_Line ("Failed to enable power domain!")); |
| 299 | |
| 300 | if Success then |
| 301 | Post_PD_On (PD); |
| 302 | end if; |
| 303 | end if; |
| 304 | end PD_On; |
| 305 | |
| 306 | procedure PD_Off (PD : Power_Domain) |
| 307 | is |
| 308 | Ctl1, Ctl2 : Word32; |
| 309 | PD_Type : constant Power_Domain_Types := Power_Domain_Type (PD); |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 310 | begin |
| 311 | pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 312 | |
| 313 | Registers.Read (PWR_CTL_BIOS (PD_Type), Ctl1); |
| 314 | Registers.Read (PWR_CTL_DRIVER (PD_Type), Ctl2); |
| 315 | |
| 316 | if ((Ctl1 or Ctl2) and Power_Request_Mask (PD)) /= 0 then |
| 317 | Registers.Wait_Set_Mask |
| 318 | (Register => PWR_CTL_DRIVER (PD_Type), |
| 319 | Mask => Power_State_Mask (PD), |
| 320 | TOut_MS => 1); |
| 321 | |
| Tim Wawrzynczak | 5473d29 | 2023-02-06 16:46:33 -0700 | [diff] [blame] | 322 | Pre_PD_Off (PD); |
| 323 | |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 324 | Registers.Unset_Mask (PWR_CTL_DRIVER (PD_Type), Power_Request_Mask (PD)); |
| 325 | Registers.Unset_Mask (PWR_CTL_BIOS (PD_Type), Power_Request_Mask (PD)); |
| 326 | end if; |
| 327 | end PD_Off; |
| 328 | |
| 329 | function Need_PW (PW : Dynamic_Well; Configs : Pipe_Configs) return Boolean |
| 330 | is |
| 331 | function Any_TC_Port return Boolean is |
| 332 | (for some Pipe in Pipe_Index => |
| 333 | Configs (Pipe).Port /= Disabled and then |
| 334 | Config_Helpers.To_GPU_Port (Pipe, Configs (Pipe).Port) in USBC_Port); |
| 335 | |
| 336 | function Any_Pipe_From (First : Pipe_Index) return Boolean is |
| 337 | (for some Pipe in First .. Pipe_Index'Last => Configs (Pipe).Port /= Disabled); |
| 338 | |
| 339 | function VGA return Boolean is |
| 340 | (Configs (Primary).Framebuffer.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET); |
| 341 | begin |
| 342 | case PW is |
| 343 | when PW2 | PW3 => |
| 344 | return Any_Pipe_From (Secondary) or Any_TC_Port or VGA; |
| 345 | when PW4 => |
| 346 | return Any_Pipe_From (Tertiary); |
| 347 | when PW5 => |
| 348 | return False; -- Fourth pipe not supported yet. |
| 349 | end case; |
| 350 | end Need_PW; |
| 351 | |
| 352 | function Need_PD (PD : Dynamic_Domain; Configs : Pipe_Configs) return Boolean |
| 353 | is |
| 354 | function Any_Port_Is (Port : GPU_Port) return Boolean is |
| 355 | (for some Pipe in Pipe_Index => |
| 356 | Configs (Pipe).Port /= Disabled and then |
| 357 | Config_Helpers.To_GPU_Port (Pipe, Configs (Pipe).Port) = Port); |
| 358 | begin |
| 359 | return |
| 360 | (case PD is |
| 361 | when Dynamic_Well'Range => Need_PW (PD, Configs), |
| 362 | when Port_Domain'Range => Any_Port_Is (To_GPU_Port (PD))); |
| 363 | end Need_PD; |
| 364 | |
| 365 | procedure Get_RefClk (Refclk : out Refclk_Range) |
| 366 | is |
| 367 | DSSM : Word32; |
| 368 | DSSM_REFERENCE_FREQUENCY_MASK : constant := 16#e000_0000#; |
| 369 | DSSM_REFERENCE_FREQUENCY_24MHZ : constant := 16#0000_0000#; |
| 370 | DSSM_REFERENCE_FREQUENCY_19_2MHZ : constant := 16#2000_0000#; |
| 371 | DSSM_REFERENCE_FREQUENCY_38_4MHZ : constant := 16#4000_0000#; |
| 372 | begin |
| 373 | Registers.Read (Registers.DSSM, DSSM); |
| 374 | Refclk := |
| 375 | (case DSSM and DSSM_REFERENCE_FREQUENCY_MASK is |
| 376 | when DSSM_REFERENCE_FREQUENCY_24MHZ => 24_000_000, |
| 377 | when DSSM_REFERENCE_FREQUENCY_19_2MHZ => 19_200_000, |
| 378 | when DSSM_REFERENCE_FREQUENCY_38_4MHZ => 38_400_000, |
| 379 | when others => 24_000_000); |
| 380 | end Get_Refclk; |
| 381 | |
| 382 | procedure Get_RawClk (Rawclk : out Frequency_Type) |
| 383 | is |
| 384 | Raw_Frequency_24_MHz : Boolean; |
| 385 | SFUSE_STRAP_RAW_FREQUENCY : constant := 1 * 2 ** 8; |
| 386 | begin |
| 387 | Rawclk := Config.Default_RawClk_Freq; |
| 388 | Registers.Is_Set_Mask |
| 389 | (Register => Registers.SFUSE_STRAP, |
| 390 | Mask => SFUSE_STRAP_RAW_FREQUENCY, |
| 391 | Result => Raw_Frequency_24_MHz); |
| 392 | |
| 393 | if not Raw_Frequency_24_MHz then |
| 394 | Rawclk := 19_200_000; |
| 395 | end if; |
| 396 | end Get_RawClk; |
| 397 | |
| 398 | procedure Get_Max_CDClk (CDClk : out CDClk_Range) |
| 399 | is |
| 400 | Refclk_Freq : Refclk_Range; |
| 401 | begin |
| 402 | Get_Refclk (Refclk_Freq); |
| 403 | CDClk := |
| 404 | (case Refclk_Freq is |
| 405 | when 24_000_000 => 648_000_000, |
| 406 | when others => 652_800_000); |
| 407 | end Get_Max_CDClk; |
| 408 | |
| 409 | procedure Normalize_CDClk |
| 410 | (CDClk : in Int64; |
| 411 | Normalized : out CDClk_Range) |
| 412 | with |
| 413 | Post => Normalized >= 172_800_000 |
| 414 | is |
| 415 | Refclk_Freq : Refclk_Range; |
| 416 | begin |
| 417 | Get_Refclk (Refclk_Freq); |
| 418 | Normalized := |
| 419 | (case Refclk_Freq is |
| 420 | when 19_200_000 | 38_400_000 => |
| 421 | (if CDClk <= 172_800_000 then 172_800_000 |
| 422 | elsif CDClk <= 192_000_000 then 192_000_000 |
| 423 | elsif CDClk <= 307_200_000 then 307_200_000 |
| 424 | elsif CDClk <= 326_400_000 then 326_400_000 |
| 425 | elsif CDClk <= 556_800_000 then 556_800_000 |
| 426 | else 652_800_000), |
| 427 | when others => |
| 428 | (if CDClk <= 180_000_000 then 180_000_000 |
| 429 | elsif CDClk <= 192_000_000 then 192_000_000 |
| 430 | elsif CDClk <= 312_000_000 then 312_000_000 |
| 431 | elsif CDClk <= 324_000_000 then 324_000_000 |
| 432 | elsif CDClk <= 552_000_000 then 552_000_000 |
| 433 | else 648_000_000)); |
| 434 | end Normalize_CDClk; |
| 435 | |
| 436 | procedure Get_Cur_CDClk (CDClk : out CDClk_Range) |
| 437 | with |
| 438 | Post => CDClk >= 172_800_000 |
| 439 | is |
| 440 | CDCLK_CTL : Word32; |
| 441 | begin |
| 442 | Registers.Read (Registers.CDCLK_CTL, CDCLK_CTL); |
| 443 | CDCLK_CTL := CDCLK_CTL and CDCLK_CTL_CD_FREQ_DECIMAL_MASK; |
| 444 | Normalize_CDClk (Int64 (CDCLK_CTL) * 500_000 + 1_000_000, CDClk); |
| 445 | end Get_Cur_CDClk; |
| 446 | |
| 447 | procedure Set_CDClk (CDClk_In : CDClk_Range) |
| 448 | is |
| 449 | subtype PLL_Ratio_Range is Word32 range 0 .. 68; |
| 450 | function Ratio_For_19_2_MHz (CDClk : CDClk_Range) return PLL_Ratio_Range is |
| 451 | begin |
| 452 | case CDClk is |
| 453 | when 172_800_000 => return 18; |
| 454 | when 192_000_000 => return 20; |
| 455 | when 307_200_000 => return 32; |
| 456 | when 326_400_000 | 652_800_000 => return 68; |
| 457 | when 556_800_000 => return 58; |
| 458 | when others => return 0; |
| 459 | end case; |
| 460 | end Ratio_For_19_2_MHz; |
| 461 | |
| 462 | function Ratio_For_24_MHz (CDCLk : CDClk_Range) return PLL_Ratio_Range is |
| 463 | begin |
| 464 | case CDClk is |
| 465 | when 180_800_000 => return 15; |
| 466 | when 192_000_000 => return 16; |
| 467 | when 312_000_000 => return 26; |
| 468 | when 324_000_000 | 648_000_000 => return 54; |
| 469 | when 552_000_000 => return 46; |
| 470 | when others => return 0; |
| 471 | end case; |
| 472 | end Ratio_For_24_MHz; |
| 473 | |
| 474 | function CDCLK_CTL_CD_FREQ_DECIMAL (Freq : CDClk_Range) return Word32 |
| 475 | with |
| 476 | Pre => Freq > 1_000_000 |
| 477 | is |
| 478 | begin |
| 479 | -- Weirdest representation: CDClk - 1MHz in 10.1 (10 + 1 fractional bit) |
| 480 | return Word32 (Div_Round_Closest (Pos64 (Freq) - 1_000_000, 500_000)); |
| 481 | end CDCLK_CTL_CD_FREQ_DECIMAL; |
| 482 | |
| 483 | Success : Boolean; |
| 484 | CD2X : Word32; |
| 485 | PLL_Ratio : PLL_Ratio_Range; |
| 486 | CDClk : CDClk_Range; |
| 487 | Refclk_Freq : Refclk_Range; |
| 488 | VCO : Pos64; |
| 489 | begin |
| 490 | pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); |
| 491 | |
| 492 | Normalize_CDClk (CDClk_Range'Min (CDClk_In, Config.Max_CDClk), CDClk); |
| 493 | Get_Refclk (Refclk_Freq); |
| 494 | PLL_Ratio := (case Refclk_Freq is |
| 495 | when 19_200_000 => Ratio_For_19_2_MHz (CDClk), |
| 496 | when 38_400_000 => Ratio_For_19_2_MHz (CDClk) / 2, |
| 497 | when 24_000_000 => Ratio_For_24_MHz (CDClk), |
| 498 | when others => 0); |
| 499 | |
| 500 | if PLL_Ratio = 0 then |
| 501 | pragma Debug (Debug.Put_Line |
| 502 | ("ERROR: Invalid Refclk frequency, bad hardware?")); |
| 503 | return; |
| 504 | end if; |
| 505 | |
| 506 | PCode.Mailbox_Request |
| 507 | (Mbox => TGL_PCODE_CDCLK_CONTROL, |
| 508 | Command => TGL_CDCLK_PREPARE_FOR_CHANGE, |
| 509 | Reply_Mask => TGL_CDCLK_READY_FOR_CHANGE, |
| 510 | Wait_Ready => True, |
| 511 | Success => Success); |
| 512 | |
| 513 | if not Success then |
| 514 | pragma Debug (Debug.Put_Line |
| 515 | ("ERROR: PCODE not ready for frequency change.")); |
| 516 | return; |
| 517 | end if; |
| 518 | |
| 519 | Registers.Unset_Mask |
| 520 | (Register => Registers.CDCLK_PLL_ENABLE, |
| 521 | Mask => CDCLK_PLL_ENABLE_PLL_ENABLE); |
| 522 | Registers.Wait_Unset_Mask |
| 523 | (Register => Registers.CDCLK_PLL_ENABLE, |
| 524 | Mask => CDCLK_PLL_ENABLE_PLL_LOCK); |
| 525 | |
| 526 | Registers.Write |
| 527 | (Register => Registers.CDCLK_PLL_ENABLE, |
| 528 | Value => PLL_Ratio); |
| 529 | Registers.Write |
| 530 | (Register => Registers.CDCLK_PLL_ENABLE, |
| 531 | Value => PLL_Ratio or CDCLK_PLL_ENABLE_PLL_ENABLE); |
| 532 | Registers.Wait_Set_Mask |
| 533 | (Register => Registers.CDCLK_PLL_ENABLE, |
| 534 | Mask => CDCLK_PLL_ENABLE_PLL_LOCK, |
| 535 | Success => Success); |
| 536 | |
| 537 | if not Success then |
| 538 | Debug.Put_Line ("CDClk PLL failed to lock!"); |
| 539 | return; |
| 540 | end if; |
| 541 | |
| 542 | VCO := (Refclk_Freq / 1_000) * Pos64 (PLL_Ratio); |
| 543 | CD2X := |
| 544 | (case (Div_Round_Closest (VCO, CDClk / 1_000)) is |
| 545 | when 2 => CDCLK_CD2X_DIV_SEL_1, |
| 546 | when 4 => CDCLK_CD2X_DIV_SEL_2, |
| 547 | when others => CDCLK_CD2X_DIV_SEL_1); |
| 548 | |
| 549 | Registers.Write |
| 550 | (Register => Registers.CDCLK_CTL, |
| 551 | Value => CDCLK_CTL_CD_FREQ_DECIMAL (CDClk) or |
| 552 | CDCLK_CD2X_PIPE_NONE or CD2X); |
| 553 | |
| 554 | PCode.Mailbox_Write |
| 555 | (MBox => TGL_PCODE_CDCLK_CONTROL, |
| 556 | Command => (if CDClk <= 312_000_000 then 0 |
| 557 | elsif CDClk <= 326_400_000 then 1 |
| 558 | elsif CDClk <= 556_800_000 then 2 |
| 559 | else 3)); |
| 560 | Config.CDClk := CDClk; |
| 561 | |
| 562 | pragma Debug (Debug.Put ("Set CDClk to ")); |
| 563 | pragma Debug (Debug.Put_Int64 (CDClk / 1_000_000)); |
| 564 | pragma Debug (Debug.Put (".")); |
| 565 | pragma Debug (Debug.Put_Int64 ((CDClk mod 1_000_000) / 100_000)); |
| 566 | pragma Debug (Debug.Put_Line ("MHz.")); |
| 567 | end Set_CDClk; |
| 568 | |
| 569 | procedure Configure_Bandwidth_Buddy |
| 570 | is |
| 571 | BW_BUDDY_DISABLE : constant := 1 * 2 ** 31; |
| 572 | BW_BUDDY_TLB_REQ_TIMER_MASK : constant := 16#3f_0000#; |
| 573 | |
| 574 | type DRAM_Module_Type is (DDR4, DDR5, LPDDR4, LPDDR5); |
| 575 | type Bw_Buddy_Info is record |
| 576 | DRAM_Channels : Natural; |
| 577 | DRAM_Type : DRAM_Module_Type; |
| 578 | BW_BUDDY_MASK : Word32; |
| 579 | end record; |
| 580 | type Bw_Buddy_Info_Array is array (1 .. 8) of Bw_Buddy_Info; |
| 581 | |
| 582 | Buddy_Info : constant Bw_Buddy_Info_Array := |
| 583 | ((1, DDR4, 16#0f#), |
| 584 | (1, DDR5, 16#0f#), |
| 585 | (2, LPDDR4, 16#1c#), |
| 586 | (2, LPDDR5, 16#1c#), |
| 587 | (2, DDR4, 16#1f#), |
| 588 | (2, DDR5, 16#1e#), |
| 589 | (4, LPDDR4, 16#38#), |
| 590 | (4, LPDDR5, 16#38#)); |
| 591 | |
| 592 | -- TODO: use for ADL-S, RKL A0/B0 |
| 593 | Buddy_Info_Wa_1409767108 : constant Bw_Buddy_Info_Array := |
| 594 | ((1, DDR4, 1), |
| 595 | (1, DDR5, 1), |
| 596 | (1, LPDDR4, 1), |
| 597 | (1, LPDDR5, 1), |
| 598 | (2, DDR4, 3), |
| 599 | (2, DDR5, 3), |
| 600 | (2, LPDDR4, 3), |
| 601 | (2, LPDDR5, 3)); |
| 602 | |
| 603 | Result : Word64; |
| 604 | Module_Type: DRAM_Module_Type; |
| 605 | Channels : Natural; |
| 606 | Success : Boolean; |
| 607 | begin |
| 608 | PCode.Mailbox_Read(MBox => TGL_PCODE_MEM_SUBSYSTEM_INFO or |
| 609 | TGL_PCODE_MEM_SS_READ_GLOBAL_INFO, |
| 610 | Wait_Ready => True, |
| 611 | Reply => Result, |
| 612 | Success => Success); |
| 613 | if not Success then |
| 614 | pragma Debug (Debug.Put_Line |
| 615 | ("ERROR: PCODE didn't return memory info.")); |
| 616 | return; |
| 617 | end if; |
| 618 | |
| 619 | case (Result and 16#f#) is |
| 620 | when 0 => Module_Type := DDR4; |
| 621 | when 1 => Module_Type := DDR5; |
| 622 | when 2 => Module_Type := LPDDR5; |
| 623 | when 3 => Module_Type := LPDDR4; |
| 624 | when others => |
| 625 | pragma Debug (Debug.Put_Line ("ERROR: Invalid DRAM Module Type.")); |
| 626 | return; |
| 627 | end case; |
| 628 | |
| 629 | Channels := Natural (Shift_Right (Result and 16#f0#, 4)); |
| 630 | for I in Buddy_Info'Range loop |
| 631 | if Buddy_Info (I).DRAM_Type = Module_Type and |
| 632 | Buddy_Info (I).DRAM_Channels = Channels |
| 633 | then |
| 634 | Registers.Set_Mask |
| 635 | (Register => Registers.BW_BUDDY1_PAGE_MASK, |
| 636 | Mask => Buddy_Info (I).BW_BUDDY_MASK); |
| 637 | Registers.Set_Mask |
| 638 | (Register => Registers.BW_BUDDY2_PAGE_MASK, |
| 639 | Mask => Buddy_Info (I).BW_BUDDY_MASK); |
| 640 | |
| 641 | -- Wa_22010178259:tgl,rkl |
| 642 | Registers.Unset_And_Set_Mask |
| 643 | (Register => Registers.BW_BUDDY1_CTL, |
| 644 | Mask_Unset => BW_BUDDY_TLB_REQ_TIMER_MASK, |
| 645 | Mask_Set => 8 * 2 ** 16); |
| 646 | Registers.Unset_And_Set_Mask |
| 647 | (Register => Registers.BW_BUDDY2_CTL, |
| 648 | Mask_Unset => BW_BUDDY_TLB_REQ_TIMER_MASK, |
| 649 | Mask_Set => 8 * 2 ** 16); |
| 650 | |
| 651 | return; |
| 652 | end if; |
| 653 | end loop; |
| 654 | |
| 655 | Registers.Write (Registers.BW_BUDDY1_CTL, BW_BUDDY_DISABLE); |
| 656 | Registers.Write (Registers.BW_BUDDY2_CTL, BW_BUDDY_DISABLE); |
| 657 | end Configure_Bandwidth_Buddy; |
| 658 | |
| 659 | ---------------------------------------------------------------------------- |
| 660 | |
| 661 | procedure Initialize |
| 662 | is |
| 663 | RawClk : Frequency_Type; |
| 664 | begin |
| 665 | pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); |
| 666 | |
| 667 | -- Wa_14011294188:ehl,jsl,tgl,rkl,adl-s,adl-p |
| 668 | Registers.Set_Mask |
| 669 | (Register => Registers.PCH_DSPCLK_GATE_D, |
| 670 | Mask => PCH_DPMGUNIT_CLOCK_GATE_DISABLE); |
| 671 | |
| 672 | Registers.Set_Mask |
| 673 | (Register => Registers.NDE_RSTWRN_OPT, |
| 674 | Mask => NDE_RSTWRN_OPT_RST_PCH_Handshake_En); |
| 675 | |
| 676 | PD_On (PW1); |
| 677 | |
| 678 | Get_Cur_CDClk (Config.CDClk); |
| 679 | Get_Max_CDClk (Config.Max_CDClk); |
| 680 | if Config.CDClk < Config.Default_CDClk_Freq then |
| 681 | Set_CDClk (Config.Default_CDClk_Freq); |
| 682 | end if; |
| 683 | |
| 684 | Get_RawClk (RawClk); |
| 685 | Config.Raw_Clock := RawClk; |
| 686 | |
| 687 | -- TGL: Set DBUF Tracker State Service to 8 |
| 688 | Registers.Unset_And_Set_Mask |
| 689 | (Register => DBUF_CTL (S1), |
| 690 | Mask_Unset => DBUF_CTL_TRACKER_STATE_SERVICE_MASK, |
| 691 | Mask_Set => 8 * 2 ** DBUF_CTL_TRACKER_STATE_SERVICE_SHIFT); |
| 692 | |
| 693 | -- Enable first DBUF slice (TODO: Is this ok to use for all pipes?) |
| 694 | Registers.Set_Mask (DBUF_CTL (S1), DBUF_CTL_DBUF_POWER_REQUEST); |
| 695 | Registers.Wait_Set_Mask (DBUF_CTL (S1), DBUF_CTL_DBUF_POWER_STATE); |
| 696 | |
| 697 | for I in MBUS_ABOX_CTL'Range loop |
| 698 | Registers.Unset_And_Set_Mask |
| 699 | (Register => MBUS_ABOX_CTL (I), |
| 700 | Mask_Unset => MBUS_ABOX_MASK, |
| 701 | Mask_Set => MBUS_ABOX_CREDITS); |
| 702 | end loop; |
| 703 | |
| 704 | Configure_Bandwidth_Buddy; |
| 705 | |
| 706 | -- Display WA #14011508470 tgl,dg1,rkl,adl-s,adl-p,dg2 |
| 707 | Registers.Set_Mask |
| 708 | (Register => Registers.GEN11_CHICKEN_DCPR_2, |
| 709 | Mask => DCPR_MASK_MAXLATENCY_MEMUP_CLR or DCPR_MASK_LPMODE or |
| 710 | DCPR_SEND_RESP_IMM or DCPR_CLEAR_MEMSTAT_DIS); |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 711 | end Initialize; |
| 712 | |
| 713 | procedure Limit_Dotclocks |
| 714 | (Configs : in out Pipe_Configs; |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 715 | CDClk_Switch : out Boolean) |
| 716 | is |
| 717 | CDClk : CDClk_Range; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 718 | begin |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 719 | Config_Helpers.Limit_Dotclocks (Configs, Config.Max_CDClk); |
| 720 | Normalize_CDClk (Config_Helpers.Highest_Dotclock (Configs), CDClk); |
| 721 | CDClk_Switch := Config.CDClk /= CDClk; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 722 | end Limit_Dotclocks; |
| 723 | |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 724 | procedure Update_CDClk (Configs : in out Pipe_Configs) |
| 725 | is |
| 726 | New_CDClk : constant Frequency_Type := |
| 727 | Config_Helpers.Highest_Dotclock (Configs); |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 728 | begin |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 729 | Set_CDClk (New_CDClk); |
| 730 | Config_Helpers.Limit_Dotclocks (Configs, Config.CDClk); |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 731 | end Update_CDClk; |
| 732 | |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 733 | procedure Enable_CDClk is |
| 734 | begin |
| 735 | if Config.CDClk < Config.Default_CDClk_Freq then |
| 736 | Set_CDClk (Config.Default_CDClk_Freq); |
| 737 | end if; |
| 738 | end Enable_CDClk; |
| 739 | |
| 740 | ---------------------------------------------------------------------------- |
| 741 | |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 742 | procedure Power_Set_To (Configs : Pipe_Configs) is |
| 743 | begin |
| 744 | pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 745 | |
| 746 | for PD in reverse Dynamic_Domain loop |
| 747 | if not Need_PD (PD, Configs) then |
| 748 | PD_Off (PD); |
| 749 | end if; |
| 750 | end loop; |
| 751 | |
| 752 | for PD in Dynamic_Domain loop |
| 753 | if Need_PD (PD, Configs) then |
| 754 | PD_On (PD); |
| 755 | end if; |
| 756 | end loop; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 757 | end Power_Set_To; |
| 758 | |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 759 | procedure Power_Up (Port : Active_Port_Type; Success : out Boolean) |
| 760 | is |
| 761 | GPU_Port : constant GMA.GPU_Port := |
| 762 | Config_Helpers.To_GPU_Port (Pipe_Index'First, Port); |
| 763 | |
| 764 | procedure On (Aux : AUX_Domain; DDI : DDI_Domain) is |
| 765 | begin |
| 766 | PD_On (PW1); |
| 767 | if GPU_Port in USBC_Port then |
| 768 | PD_On (PW2); |
| 769 | PD_On (PW3); |
| 770 | end if; |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 771 | PD_On (DDI); |
| Tim Wawrzynczak | 5473d29 | 2023-02-06 16:46:33 -0700 | [diff] [blame] | 772 | |
| 773 | if GPU_Port in USBC_Port then |
| 774 | Connectors.TC.Claim |
| 775 | (Port => GPU_Port, |
| 776 | DP_Alt => Port in Physical_USBC_Ports, |
| 777 | Success => Success); |
| 778 | if not Success then |
| 779 | return; |
| 780 | end if; |
| 781 | end if; |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 782 | PD_On (Aux); |
| 783 | |
| Tim Wawrzynczak | 5473d29 | 2023-02-06 16:46:33 -0700 | [diff] [blame] | 784 | Success := True; |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 785 | end On; |
| Nico Huber | 41e8674 | 2024-07-17 17:10:28 +0200 | [diff] [blame] | 786 | begin |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 787 | pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); |
| 788 | |
| 789 | case GPU_Port is |
| 790 | when GMA.DIGI_A => On (AUX_A, DDI_A); |
| 791 | when GMA.DIGI_B => On (AUX_B, DDI_B); |
| 792 | when GMA.DIGI_C => On (AUX_C, DDI_C); |
| 793 | when GMA.DDI_TC1 => On (AUX_USBC1, DDI_USBC1); |
| 794 | when GMA.DDI_TC2 => On (AUX_USBC2, DDI_USBC2); |
| 795 | when GMA.DDI_TC3 => On (AUX_USBC3, DDI_USBC3); |
| 796 | when GMA.DDI_TC4 => On (AUX_USBC4, DDI_USBC4); |
| 797 | when GMA.DDI_TC5 => On (AUX_USBC5, DDI_USBC5); |
| 798 | when GMA.DDI_TC6 => On (AUX_USBC6, DDI_USBC6); |
| 799 | when others => Success := True; |
| 800 | end case; |
| Nico Huber | 41e8674 | 2024-07-17 17:10:28 +0200 | [diff] [blame] | 801 | end Power_Up; |
| 802 | |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 803 | procedure Power_Up (Old_Configs, New_Configs : Pipe_Configs) is |
| 804 | begin |
| 805 | pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 806 | |
| 807 | -- Power wells only, Aux/DDI domains are enabled later on explicit request. |
| 808 | for PW in Dynamic_Well loop |
| 809 | if not Need_PW (PW, Old_Configs) and Need_PW (PW, New_Configs) then |
| 810 | PD_On (PW); |
| 811 | end if; |
| 812 | end loop; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 813 | end Power_Up; |
| 814 | |
| 815 | procedure Power_Down (Old_Configs, Tmp_Configs, New_Configs : Pipe_Configs) |
| 816 | is |
| 817 | begin |
| 818 | pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 819 | |
| 820 | for PD in reverse Dynamic_Domain loop |
| 821 | if (Need_PD (PD, Old_Configs) or Need_PD (PD, Tmp_Configs)) and |
| 822 | not Need_PD (PD, New_Configs) |
| 823 | then |
| 824 | PD_Off (PD); |
| 825 | end if; |
| 826 | end loop; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 827 | end Power_Down; |
| 828 | |
| Tim Wawrzynczak | 6db27c4 | 2022-09-09 10:49:55 -0600 | [diff] [blame] | 829 | procedure Pre_All_Off is |
| 830 | begin |
| 831 | Transcoder.PSR_Off; |
| 832 | end Pre_All_Off; |
| 833 | |
| 834 | procedure Post_All_Off is |
| 835 | begin |
| 836 | pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); |
| 837 | |
| 838 | for S in reverse DBUF_CTL'Range loop |
| 839 | Registers.Unset_Mask |
| 840 | (DBUF_CTL (S), DBUF_CTL_DBUF_POWER_REQUEST); |
| 841 | Registers.Wait_Unset_Mask |
| 842 | (DBUF_CTL (S), DBUF_CTL_DBUF_POWER_STATE); |
| 843 | end loop; |
| 844 | |
| 845 | -- Disable CDClk PLL. FIXME: Not implemented yet. |
| 846 | Set_CDClk (CDClk_Range'First); |
| 847 | |
| 848 | for PD in reverse Power_Domain loop |
| 849 | PD_Off (PD); |
| 850 | end loop; |
| 851 | |
| 852 | Combo_Phy.All_Off; |
| 853 | end Post_All_Off; |
| 854 | |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 855 | end HW.GFX.GMA.Power_And_Clocks; |