| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 1 | -- |
| 2 | -- Copyright (C) Google, LLC |
| Tim Wawrzynczak | fa9a0d2 | 2022-09-09 11:09:09 -0600 | [diff] [blame^] | 3 | -- Copyright (C) 2024 secunet Security Networks AG |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 4 | -- |
| 5 | -- This program is free software; you can redistribute it and/or modify |
| 6 | -- it under the terms of the GNU General Public License as published by |
| 7 | -- the Free Software Foundation; either version 2 of the License, or |
| 8 | -- (at your option) any later version. |
| 9 | -- |
| 10 | -- This program is distributed in the hope that it will be useful, |
| 11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | -- GNU General Public License for more details. |
| 14 | -- |
| 15 | |
| 16 | with HW.GFX.GMA.Config; |
| 17 | with HW.GFX.GMA.Registers; |
| 18 | with HW.GFX.GMA.Config_Helpers; |
| Tim Wawrzynczak | fa9a0d2 | 2022-09-09 11:09:09 -0600 | [diff] [blame^] | 19 | with HW.GFX.GMA.Connectors.TC; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 20 | |
| 21 | with HW.Debug; |
| 22 | with GNAT.Source_Info; |
| 23 | |
| 24 | package body HW.GFX.GMA.Port_Detect |
| 25 | is |
| Tim Wawrzynczak | fa9a0d2 | 2022-09-09 11:09:09 -0600 | [diff] [blame^] | 26 | SHOTPLUG_CTL_DDI_HPD_STATUS_MASK : constant := 16#0333#; |
| 27 | |
| 28 | function SHOTPLUG_CTL_DDI_HPD_ENABLE (P : Combo_Port) return Word32 is |
| 29 | (Shift_Left (8, 4 * (GPU_Port'Pos (P) - GPU_Port'Pos (Combo_Port'First)))); |
| 30 | |
| 31 | function SHOTPLUG_CTL_DDI_HPD_STATUS (P : Combo_Port) return Word32 is |
| 32 | (Shift_Left (3, 4 * (GPU_Port'Pos (P) - GPU_Port'Pos (Combo_Port'First)))); |
| 33 | |
| 34 | function SHOTPLUG_CTL_DDI_HPD_LONG_DETECT (P : Combo_Port) return Word32 is |
| 35 | (Shift_Left (2, 4 * (GPU_Port'Pos (P) - GPU_Port'Pos (Combo_Port'First)))); |
| 36 | |
| 37 | SHOTPLUG_CTL_TC_DDI_HPD_STATUS_MASK : constant := 16#0033_3333#; |
| 38 | |
| 39 | function SHOTPLUG_CTL_TC_DDI_HPD_ENABLE (P : USBC_Port) return Word32 is |
| 40 | (Shift_Left (8, 4 * (GPU_Port'Pos (P) - GPU_Port'Pos (USBC_Port'First)))); |
| 41 | |
| 42 | function SHOTPLUG_CTL_TC_DDI_HPD_STATUS (P : USBC_Port) return Word32 is |
| 43 | (Shift_Left (3, 4 * (GPU_Port'Pos (P) - GPU_Port'Pos (USBC_Port'First)))); |
| 44 | |
| 45 | function SHOTPLUG_CTL_TC_DDI_HPD_LONG_DETECT (P : USBC_Port) return Word32 is |
| 46 | (Shift_Left (2, 4 * (GPU_Port'Pos (P) - GPU_Port'Pos (USBC_Port'First)))); |
| 47 | |
| 48 | TC_HOTPLUG_CTL_HPD_STATUS_MASK : constant := 16#0033_3333#; |
| 49 | |
| 50 | function TC_HOTPLUG_CTL_HPD_ENABLE (P : USBC_Port) return Word32 renames |
| 51 | SHOTPLUG_CTL_TC_DDI_HPD_ENABLE; |
| 52 | |
| 53 | function TC_HOTPLUG_CTL_HPD_STATUS (P : USBC_Port) return Word32 renames |
| 54 | SHOTPLUG_CTL_TC_DDI_HPD_STATUS; |
| 55 | |
| 56 | procedure Initialize |
| 57 | is |
| 58 | Success : Boolean; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 59 | begin |
| 60 | pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); |
| Tim Wawrzynczak | fa9a0d2 | 2022-09-09 11:09:09 -0600 | [diff] [blame^] | 61 | |
| 62 | Registers.Unset_And_Set_Mask |
| 63 | (Register => Registers.SHPD_FILTER_CNT, |
| 64 | Mask_Unset => 16#1_ffff#, |
| 65 | Mask_Set => 16#1d9#); -- constant from i915 (SHPD_FILTER_CNT_500_ADJ) |
| 66 | |
| 67 | -- Hotplug for combo ports |
| 68 | Registers.Set_Mask |
| 69 | (Register => Registers.SHOTPLUG_CTL, |
| 70 | Mask => |
| 71 | SHOTPLUG_CTL_DDI_HPD_ENABLE (DIGI_A) or |
| 72 | SHOTPLUG_CTL_DDI_HPD_ENABLE (DIGI_B) or |
| 73 | SHOTPLUG_CTL_DDI_HPD_ENABLE (DIGI_C) or |
| 74 | SHOTPLUG_CTL_DDI_HPD_STATUS_MASK); -- clear status |
| 75 | |
| 76 | -- Validity can only be detected via hotplug. |
| 77 | -- DP3/HDMI3 doesn't exist in any TGL SKU. |
| 78 | for Port in DP1 .. DP2 loop |
| 79 | Config.Valid_Port (Port) := True; |
| 80 | end loop; |
| 81 | for Port in DP_TC1 .. DP_TC4 loop |
| 82 | Config.Valid_Port (Port) := True; |
| 83 | end loop; |
| 84 | for Port in HDMI1 .. HDMI2 loop |
| 85 | Config.Valid_Port (Port) := True; |
| 86 | end loop; |
| 87 | for Port in HDMI_TC1 .. HDMI_TC4 loop |
| 88 | Config.Valid_Port (Port) := True; |
| 89 | end loop; |
| 90 | for Port in USBC1 .. USBC4 loop |
| 91 | Config.Valid_Port (Port) := True; |
| 92 | end loop; |
| 93 | |
| 94 | for Port in DDI_TC1 .. Config.Last_TC_Port loop |
| 95 | -- Hotplug for Type-C ports in legacy mode |
| 96 | Registers.Set_Mask |
| 97 | (Register => Registers.SHOTPLUG_CTL_TC, |
| 98 | Mask => SHOTPLUG_CTL_TC_DDI_HPD_ENABLE (Port)); |
| 99 | -- Hotplug for Type-C ports in DP-Alt mode |
| 100 | Registers.Set_Mask |
| 101 | (Register => Registers.TC_HOTPLUG_CTL, |
| 102 | Mask => TC_HOTPLUG_CTL_HPD_ENABLE (Port)); |
| 103 | end loop; |
| 104 | |
| 105 | -- Clear status: |
| 106 | Registers.Set_Mask |
| 107 | (Register => Registers.SHOTPLUG_CTL_TC, |
| 108 | Mask => SHOTPLUG_CTL_TC_DDI_HPD_STATUS_MASK); |
| 109 | Registers.Set_Mask |
| 110 | (Register => Registers.TC_HOTPLUG_CTL, |
| 111 | Mask => TC_HOTPLUG_CTL_HPD_STATUS_MASK); |
| 112 | |
| 113 | -- TCCOLD should be blocked first before accessing FIA registers |
| 114 | -- during e.g. connect flows. It can be unblocked only after done |
| 115 | -- accessing FIA registers and there is no longer a connection |
| 116 | -- i.e., after all ports are disconnected. |
| 117 | -- In order to avoid keeping track of the state and constantly |
| 118 | -- blocking and unblocking, we just block it once at the beginning |
| 119 | -- and leave it that way. |
| 120 | Connectors.TC.TC_Cold_Request (Connectors.TC.Block, Success); |
| 121 | if not Success then |
| 122 | Debug.Put_Line ("Failed to block TCCOLD, Type-C will not work!"); |
| 123 | return; |
| 124 | end if; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 125 | end Initialize; |
| 126 | |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 127 | procedure Hotplug_Detect |
| 128 | (Port : in Active_Port_Type; |
| 129 | Detected : out Boolean) |
| 130 | is |
| Tim Wawrzynczak | fa9a0d2 | 2022-09-09 11:09:09 -0600 | [diff] [blame^] | 131 | GPU_Port : constant GMA.GPU_Port := Config_Helpers.To_GPU_Port (Pipe_Index'First, Port); |
| 132 | North32, South32 : Word32; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 133 | begin |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 134 | Detected := False; |
| Tim Wawrzynczak | fa9a0d2 | 2022-09-09 11:09:09 -0600 | [diff] [blame^] | 135 | |
| 136 | if GPU_Port in USBC_Port then |
| 137 | Registers.Read (Registers.TC_HOTPLUG_CTL, North32, Verbose => False); |
| 138 | Registers.Read (Registers.SHOTPLUG_CTL_TC, South32, Verbose => False); |
| 139 | |
| 140 | Detected := ((North32 or South32) and |
| 141 | SHOTPLUG_CTL_TC_DDI_HPD_LONG_DETECT (GPU_Port)) /= 0; |
| 142 | |
| 143 | if (North32 and TC_HOTPLUG_CTL_HPD_STATUS (GPU_Port)) /= 0 then |
| 144 | Registers.Unset_And_Set_Mask |
| 145 | (Register => Registers.TC_HOTPLUG_CTL, |
| 146 | Mask_Unset => TC_HOTPLUG_CTL_HPD_STATUS_MASK, |
| 147 | Mask_Set => TC_HOTPLUG_CTL_HPD_STATUS (GPU_Port)); |
| 148 | end if; |
| 149 | if (South32 and TC_HOTPLUG_CTL_HPD_STATUS (GPU_Port)) /= 0 then |
| 150 | Registers.Unset_And_Set_Mask |
| 151 | (Register => Registers.SHOTPLUG_CTL_TC, |
| 152 | Mask_Unset => SHOTPLUG_CTL_TC_DDI_HPD_STATUS_MASK, |
| 153 | Mask_Set => SHOTPLUG_CTL_TC_DDI_HPD_STATUS (GPU_Port)); |
| 154 | end if; |
| 155 | end if; |
| 156 | |
| 157 | if GPU_Port in Combo_Port then |
| 158 | Registers.Read (Registers.SHOTPLUG_CTL, South32, Verbose => False); |
| 159 | Detected := (South32 and SHOTPLUG_CTL_DDI_HPD_LONG_DETECT (GPU_Port)) /= 0; |
| 160 | |
| 161 | if (South32 and SHOTPLUG_CTL_DDI_HPD_STATUS (GPU_Port)) /= 0 then |
| 162 | Registers.Unset_And_Set_Mask |
| 163 | (Register => Registers.SHOTPLUG_CTL, |
| 164 | Mask_Unset => SHOTPLUG_CTL_DDI_HPD_STATUS_MASK, |
| 165 | Mask_Set => SHOTPLUG_CTL_DDI_HPD_STATUS (GPU_Port)); |
| 166 | end if; |
| 167 | end if; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 168 | end Hotplug_Detect; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 169 | |
| 170 | procedure Clear_Hotplug_Detect (Port : Active_Port_Type) |
| 171 | is |
| Tim Wawrzynczak | fa9a0d2 | 2022-09-09 11:09:09 -0600 | [diff] [blame^] | 172 | Ignored_HPD : Boolean; |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 173 | begin |
| Tim Wawrzynczak | fa9a0d2 | 2022-09-09 11:09:09 -0600 | [diff] [blame^] | 174 | pragma Warnings (GNATprove, Off, "unused assignment to ""Ignored_HPD""", |
| 175 | Reason => "We want to clear pending events only"); |
| 176 | Port_Detect.Hotplug_Detect (Port, Ignored_HPD); |
| 177 | pragma Warnings (GNATprove, On, "unused assignment to ""Ignored_HPD"""); |
| Tim Wawrzynczak | 605660b | 2022-06-08 12:48:19 -0600 | [diff] [blame] | 178 | end Clear_Hotplug_Detect; |
| 179 | |
| 180 | end HW.GFX.GMA.Port_Detect; |