0001
0002
0003
0004
0005
0006 #include "i915_drv.h"
0007 #include "i915_iosf_mbi.h"
0008 #include "i915_reg.h"
0009 #include "vlv_sideband.h"
0010
0011
0012
0013
0014
0015
0016
0017 #define SB_MRD_NP 0x00
0018
0019 #define SB_MWR_NP 0x01
0020
0021 #define SB_CRRDDA_NP 0x06
0022
0023 #define SB_CRWRDA_NP 0x07
0024
0025 static void ping(void *info)
0026 {
0027 }
0028
0029 static void __vlv_punit_get(struct drm_i915_private *i915)
0030 {
0031 iosf_mbi_punit_acquire();
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 if (IS_VALLEYVIEW(i915)) {
0044 cpu_latency_qos_update_request(&i915->sb_qos, 0);
0045 on_each_cpu(ping, NULL, 1);
0046 }
0047 }
0048
0049 static void __vlv_punit_put(struct drm_i915_private *i915)
0050 {
0051 if (IS_VALLEYVIEW(i915))
0052 cpu_latency_qos_update_request(&i915->sb_qos,
0053 PM_QOS_DEFAULT_VALUE);
0054
0055 iosf_mbi_punit_release();
0056 }
0057
0058 void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports)
0059 {
0060 if (ports & BIT(VLV_IOSF_SB_PUNIT))
0061 __vlv_punit_get(i915);
0062
0063 mutex_lock(&i915->sb_lock);
0064 }
0065
0066 void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports)
0067 {
0068 mutex_unlock(&i915->sb_lock);
0069
0070 if (ports & BIT(VLV_IOSF_SB_PUNIT))
0071 __vlv_punit_put(i915);
0072 }
0073
0074 static int vlv_sideband_rw(struct drm_i915_private *i915,
0075 u32 devfn, u32 port, u32 opcode,
0076 u32 addr, u32 *val)
0077 {
0078 struct intel_uncore *uncore = &i915->uncore;
0079 const bool is_read = (opcode == SB_MRD_NP || opcode == SB_CRRDDA_NP);
0080 int err;
0081
0082 lockdep_assert_held(&i915->sb_lock);
0083 if (port == IOSF_PORT_PUNIT)
0084 iosf_mbi_assert_punit_acquired();
0085
0086
0087 if (intel_wait_for_register(uncore,
0088 VLV_IOSF_DOORBELL_REQ, IOSF_SB_BUSY, 0,
0089 5)) {
0090 drm_dbg(&i915->drm, "IOSF sideband idle wait (%s) timed out\n",
0091 is_read ? "read" : "write");
0092 return -EAGAIN;
0093 }
0094
0095 preempt_disable();
0096
0097 intel_uncore_write_fw(uncore, VLV_IOSF_ADDR, addr);
0098 intel_uncore_write_fw(uncore, VLV_IOSF_DATA, is_read ? 0 : *val);
0099 intel_uncore_write_fw(uncore, VLV_IOSF_DOORBELL_REQ,
0100 (devfn << IOSF_DEVFN_SHIFT) |
0101 (opcode << IOSF_OPCODE_SHIFT) |
0102 (port << IOSF_PORT_SHIFT) |
0103 (0xf << IOSF_BYTE_ENABLES_SHIFT) |
0104 (0 << IOSF_BAR_SHIFT) |
0105 IOSF_SB_BUSY);
0106
0107 if (__intel_wait_for_register_fw(uncore,
0108 VLV_IOSF_DOORBELL_REQ, IOSF_SB_BUSY, 0,
0109 10000, 0, NULL) == 0) {
0110 if (is_read)
0111 *val = intel_uncore_read_fw(uncore, VLV_IOSF_DATA);
0112 err = 0;
0113 } else {
0114 drm_dbg(&i915->drm, "IOSF sideband finish wait (%s) timed out\n",
0115 is_read ? "read" : "write");
0116 err = -ETIMEDOUT;
0117 }
0118
0119 preempt_enable();
0120
0121 return err;
0122 }
0123
0124 u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr)
0125 {
0126 u32 val = 0;
0127
0128 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT,
0129 SB_CRRDDA_NP, addr, &val);
0130
0131 return val;
0132 }
0133
0134 int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val)
0135 {
0136 return vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT,
0137 SB_CRWRDA_NP, addr, &val);
0138 }
0139
0140 u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg)
0141 {
0142 u32 val = 0;
0143
0144 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT,
0145 SB_CRRDDA_NP, reg, &val);
0146
0147 return val;
0148 }
0149
0150 void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val)
0151 {
0152 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT,
0153 SB_CRWRDA_NP, reg, &val);
0154 }
0155
0156 u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr)
0157 {
0158 u32 val = 0;
0159
0160 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_NC,
0161 SB_CRRDDA_NP, addr, &val);
0162
0163 return val;
0164 }
0165
0166 u32 vlv_iosf_sb_read(struct drm_i915_private *i915, u8 port, u32 reg)
0167 {
0168 u32 val = 0;
0169
0170 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), port,
0171 SB_CRRDDA_NP, reg, &val);
0172
0173 return val;
0174 }
0175
0176 void vlv_iosf_sb_write(struct drm_i915_private *i915,
0177 u8 port, u32 reg, u32 val)
0178 {
0179 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), port,
0180 SB_CRWRDA_NP, reg, &val);
0181 }
0182
0183 u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg)
0184 {
0185 u32 val = 0;
0186
0187 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCK,
0188 SB_CRRDDA_NP, reg, &val);
0189
0190 return val;
0191 }
0192
0193 void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val)
0194 {
0195 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCK,
0196 SB_CRWRDA_NP, reg, &val);
0197 }
0198
0199 u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg)
0200 {
0201 u32 val = 0;
0202
0203 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCU,
0204 SB_CRRDDA_NP, reg, &val);
0205
0206 return val;
0207 }
0208
0209 void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val)
0210 {
0211 vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCU,
0212 SB_CRWRDA_NP, reg, &val);
0213 }
0214
0215 static u32 vlv_dpio_phy_iosf_port(struct drm_i915_private *i915, enum dpio_phy phy)
0216 {
0217
0218
0219
0220
0221 if (IS_CHERRYVIEW(i915))
0222 return phy == DPIO_PHY0 ? IOSF_PORT_DPIO_2 : IOSF_PORT_DPIO;
0223 else
0224 return IOSF_PORT_DPIO;
0225 }
0226
0227 u32 vlv_dpio_read(struct drm_i915_private *i915, enum pipe pipe, int reg)
0228 {
0229 u32 port = vlv_dpio_phy_iosf_port(i915, DPIO_PHY(pipe));
0230 u32 val = 0;
0231
0232 vlv_sideband_rw(i915, DPIO_DEVFN, port, SB_MRD_NP, reg, &val);
0233
0234
0235
0236
0237
0238 drm_WARN(&i915->drm, val == 0xffffffff,
0239 "DPIO read pipe %c reg 0x%x == 0x%x\n",
0240 pipe_name(pipe), reg, val);
0241
0242 return val;
0243 }
0244
0245 void vlv_dpio_write(struct drm_i915_private *i915,
0246 enum pipe pipe, int reg, u32 val)
0247 {
0248 u32 port = vlv_dpio_phy_iosf_port(i915, DPIO_PHY(pipe));
0249
0250 vlv_sideband_rw(i915, DPIO_DEVFN, port, SB_MWR_NP, reg, &val);
0251 }
0252
0253 u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg)
0254 {
0255 u32 val = 0;
0256
0257 vlv_sideband_rw(i915, DPIO_DEVFN, IOSF_PORT_FLISDSI, SB_CRRDDA_NP,
0258 reg, &val);
0259 return val;
0260 }
0261
0262 void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val)
0263 {
0264 vlv_sideband_rw(i915, DPIO_DEVFN, IOSF_PORT_FLISDSI, SB_CRWRDA_NP,
0265 reg, &val);
0266 }