1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2013-2021 Intel Corporation 4 */ 5 6 #include "i915_drv.h" 7 #include "i915_iosf_mbi.h" 8 #include "vlv_sideband.h" 9 10 /* 11 * IOSF sideband, see VLV2_SidebandMsg_HAS.docx and 12 * VLV_VLV2_PUNIT_HAS_0.8.docx 13 */ 14 15 /* Standard MMIO read, non-posted */ 16 #define SB_MRD_NP 0x00 17 /* Standard MMIO write, non-posted */ 18 #define SB_MWR_NP 0x01 19 /* Private register read, double-word addressing, non-posted */ 20 #define SB_CRRDDA_NP 0x06 21 /* Private register write, double-word addressing, non-posted */ 22 #define SB_CRWRDA_NP 0x07 23 24 static void ping(void *info) 25 { 26 } 27 28 static void __vlv_punit_get(struct drm_i915_private *i915) 29 { 30 iosf_mbi_punit_acquire(); 31 32 /* 33 * Prevent the cpu from sleeping while we use this sideband, otherwise 34 * the punit may cause a machine hang. The issue appears to be isolated 35 * with changing the power state of the CPU package while changing 36 * the power state via the punit, and we have only observed it 37 * reliably on 4-core Baytail systems suggesting the issue is in the 38 * power delivery mechanism and likely to be board/function 39 * specific. Hence we presume the workaround needs only be applied 40 * to the Valleyview P-unit and not all sideband communications. 41 */ 42 if (IS_VALLEYVIEW(i915)) { 43 cpu_latency_qos_update_request(&i915->sb_qos, 0); 44 on_each_cpu(ping, NULL, 1); 45 } 46 } 47 48 static void __vlv_punit_put(struct drm_i915_private *i915) 49 { 50 if (IS_VALLEYVIEW(i915)) 51 cpu_latency_qos_update_request(&i915->sb_qos, 52 PM_QOS_DEFAULT_VALUE); 53 54 iosf_mbi_punit_release(); 55 } 56 57 void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports) 58 { 59 if (ports & BIT(VLV_IOSF_SB_PUNIT)) 60 __vlv_punit_get(i915); 61 62 mutex_lock(&i915->sb_lock); 63 } 64 65 void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports) 66 { 67 mutex_unlock(&i915->sb_lock); 68 69 if (ports & BIT(VLV_IOSF_SB_PUNIT)) 70 __vlv_punit_put(i915); 71 } 72 73 static int vlv_sideband_rw(struct drm_i915_private *i915, 74 u32 devfn, u32 port, u32 opcode, 75 u32 addr, u32 *val) 76 { 77 struct intel_uncore *uncore = &i915->uncore; 78 const bool is_read = (opcode == SB_MRD_NP || opcode == SB_CRRDDA_NP); 79 int err; 80 81 lockdep_assert_held(&i915->sb_lock); 82 if (port == IOSF_PORT_PUNIT) 83 iosf_mbi_assert_punit_acquired(); 84 85 /* Flush the previous comms, just in case it failed last time. */ 86 if (intel_wait_for_register(uncore, 87 VLV_IOSF_DOORBELL_REQ, IOSF_SB_BUSY, 0, 88 5)) { 89 drm_dbg(&i915->drm, "IOSF sideband idle wait (%s) timed out\n", 90 is_read ? "read" : "write"); 91 return -EAGAIN; 92 } 93 94 preempt_disable(); 95 96 intel_uncore_write_fw(uncore, VLV_IOSF_ADDR, addr); 97 intel_uncore_write_fw(uncore, VLV_IOSF_DATA, is_read ? 0 : *val); 98 intel_uncore_write_fw(uncore, VLV_IOSF_DOORBELL_REQ, 99 (devfn << IOSF_DEVFN_SHIFT) | 100 (opcode << IOSF_OPCODE_SHIFT) | 101 (port << IOSF_PORT_SHIFT) | 102 (0xf << IOSF_BYTE_ENABLES_SHIFT) | 103 (0 << IOSF_BAR_SHIFT) | 104 IOSF_SB_BUSY); 105 106 if (__intel_wait_for_register_fw(uncore, 107 VLV_IOSF_DOORBELL_REQ, IOSF_SB_BUSY, 0, 108 10000, 0, NULL) == 0) { 109 if (is_read) 110 *val = intel_uncore_read_fw(uncore, VLV_IOSF_DATA); 111 err = 0; 112 } else { 113 drm_dbg(&i915->drm, "IOSF sideband finish wait (%s) timed out\n", 114 is_read ? "read" : "write"); 115 err = -ETIMEDOUT; 116 } 117 118 preempt_enable(); 119 120 return err; 121 } 122 123 u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr) 124 { 125 u32 val = 0; 126 127 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT, 128 SB_CRRDDA_NP, addr, &val); 129 130 return val; 131 } 132 133 int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val) 134 { 135 return vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT, 136 SB_CRWRDA_NP, addr, &val); 137 } 138 139 u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg) 140 { 141 u32 val = 0; 142 143 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT, 144 SB_CRRDDA_NP, reg, &val); 145 146 return val; 147 } 148 149 void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val) 150 { 151 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT, 152 SB_CRWRDA_NP, reg, &val); 153 } 154 155 u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr) 156 { 157 u32 val = 0; 158 159 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_NC, 160 SB_CRRDDA_NP, addr, &val); 161 162 return val; 163 } 164 165 u32 vlv_iosf_sb_read(struct drm_i915_private *i915, u8 port, u32 reg) 166 { 167 u32 val = 0; 168 169 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), port, 170 SB_CRRDDA_NP, reg, &val); 171 172 return val; 173 } 174 175 void vlv_iosf_sb_write(struct drm_i915_private *i915, 176 u8 port, u32 reg, u32 val) 177 { 178 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), port, 179 SB_CRWRDA_NP, reg, &val); 180 } 181 182 u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg) 183 { 184 u32 val = 0; 185 186 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCK, 187 SB_CRRDDA_NP, reg, &val); 188 189 return val; 190 } 191 192 void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val) 193 { 194 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCK, 195 SB_CRWRDA_NP, reg, &val); 196 } 197 198 u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg) 199 { 200 u32 val = 0; 201 202 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCU, 203 SB_CRRDDA_NP, reg, &val); 204 205 return val; 206 } 207 208 void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val) 209 { 210 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCU, 211 SB_CRWRDA_NP, reg, &val); 212 } 213 214 static u32 vlv_dpio_phy_iosf_port(struct drm_i915_private *i915, enum dpio_phy phy) 215 { 216 /* 217 * IOSF_PORT_DPIO: VLV x2 PHY (DP/HDMI B and C), CHV x1 PHY (DP/HDMI D) 218 * IOSF_PORT_DPIO_2: CHV x2 PHY (DP/HDMI B and C) 219 */ 220 if (IS_CHERRYVIEW(i915)) 221 return phy == DPIO_PHY0 ? IOSF_PORT_DPIO_2 : IOSF_PORT_DPIO; 222 else 223 return IOSF_PORT_DPIO; 224 } 225 226 u32 vlv_dpio_read(struct drm_i915_private *i915, enum pipe pipe, int reg) 227 { 228 u32 port = vlv_dpio_phy_iosf_port(i915, DPIO_PHY(pipe)); 229 u32 val = 0; 230 231 vlv_sideband_rw(i915, DPIO_DEVFN, port, SB_MRD_NP, reg, &val); 232 233 /* 234 * FIXME: There might be some registers where all 1's is a valid value, 235 * so ideally we should check the register offset instead... 236 */ 237 drm_WARN(&i915->drm, val == 0xffffffff, 238 "DPIO read pipe %c reg 0x%x == 0x%x\n", 239 pipe_name(pipe), reg, val); 240 241 return val; 242 } 243 244 void vlv_dpio_write(struct drm_i915_private *i915, 245 enum pipe pipe, int reg, u32 val) 246 { 247 u32 port = vlv_dpio_phy_iosf_port(i915, DPIO_PHY(pipe)); 248 249 vlv_sideband_rw(i915, DPIO_DEVFN, port, SB_MWR_NP, reg, &val); 250 } 251 252 u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg) 253 { 254 u32 val = 0; 255 256 vlv_sideband_rw(i915, DPIO_DEVFN, IOSF_PORT_FLISDSI, SB_CRRDDA_NP, 257 reg, &val); 258 return val; 259 } 260 261 void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val) 262 { 263 vlv_sideband_rw(i915, DPIO_DEVFN, IOSF_PORT_FLISDSI, SB_CRWRDA_NP, 264 reg, &val); 265 } 266