Home | History | Annotate | Line # | Download | only in i915
intel_sideband.c revision 1.2.20.1
      1 /*	$NetBSD: intel_sideband.c,v 1.2.20.1 2019/06/10 22:08:06 christos Exp $	*/
      2 
      3 /*
      4  * Copyright  2013 Intel Corporation
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the next
     14  * paragraph) shall be included in all copies or substantial portions of the
     15  * Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     23  * IN THE SOFTWARE.
     24  *
     25  */
     26 
     27 #include <sys/cdefs.h>
     28 __KERNEL_RCSID(0, "$NetBSD: intel_sideband.c,v 1.2.20.1 2019/06/10 22:08:06 christos Exp $");
     29 
     30 #include "i915_drv.h"
     31 #include "intel_drv.h"
     32 
     33 /*
     34  * IOSF sideband, see VLV2_SidebandMsg_HAS.docx and
     35  * VLV_VLV2_PUNIT_HAS_0.8.docx
     36  */
     37 
     38 /* Standard MMIO read, non-posted */
     39 #define SB_MRD_NP	0x00
     40 /* Standard MMIO write, non-posted */
     41 #define SB_MWR_NP	0x01
     42 /* Private register read, double-word addressing, non-posted */
     43 #define SB_CRRDDA_NP	0x06
     44 /* Private register write, double-word addressing, non-posted */
     45 #define SB_CRWRDA_NP	0x07
     46 
     47 static int vlv_sideband_rw(struct drm_i915_private *dev_priv, u32 devfn,
     48 			   u32 port, u32 opcode, u32 addr, u32 *val)
     49 {
     50 	u32 cmd, be = 0xf, bar = 0;
     51 	bool is_read = (opcode == SB_MRD_NP || opcode == SB_CRRDDA_NP);
     52 
     53 	cmd = (devfn << IOSF_DEVFN_SHIFT) | (opcode << IOSF_OPCODE_SHIFT) |
     54 		(port << IOSF_PORT_SHIFT) | (be << IOSF_BYTE_ENABLES_SHIFT) |
     55 		(bar << IOSF_BAR_SHIFT);
     56 
     57 	WARN_ON(!mutex_is_locked(&dev_priv->sb_lock));
     58 
     59 	if (wait_for((I915_READ(VLV_IOSF_DOORBELL_REQ) & IOSF_SB_BUSY) == 0, 5)) {
     60 		DRM_DEBUG_DRIVER("IOSF sideband idle wait (%s) timed out\n",
     61 				 is_read ? "read" : "write");
     62 		return -EAGAIN;
     63 	}
     64 
     65 	I915_WRITE(VLV_IOSF_ADDR, addr);
     66 	if (!is_read)
     67 		I915_WRITE(VLV_IOSF_DATA, *val);
     68 	I915_WRITE(VLV_IOSF_DOORBELL_REQ, cmd);
     69 
     70 	if (wait_for((I915_READ(VLV_IOSF_DOORBELL_REQ) & IOSF_SB_BUSY) == 0, 5)) {
     71 		DRM_DEBUG_DRIVER("IOSF sideband finish wait (%s) timed out\n",
     72 				 is_read ? "read" : "write");
     73 		return -ETIMEDOUT;
     74 	}
     75 
     76 	if (is_read)
     77 		*val = I915_READ(VLV_IOSF_DATA);
     78 	I915_WRITE(VLV_IOSF_DATA, 0);
     79 
     80 	return 0;
     81 }
     82 
     83 u32 vlv_punit_read(struct drm_i915_private *dev_priv, u32 addr)
     84 {
     85 	u32 val = 0;
     86 
     87 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
     88 
     89 	mutex_lock(&dev_priv->sb_lock);
     90 	vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT,
     91 			SB_CRRDDA_NP, addr, &val);
     92 	mutex_unlock(&dev_priv->sb_lock);
     93 
     94 	return val;
     95 }
     96 
     97 void vlv_punit_write(struct drm_i915_private *dev_priv, u32 addr, u32 val)
     98 {
     99 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
    100 
    101 	mutex_lock(&dev_priv->sb_lock);
    102 	vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT,
    103 			SB_CRWRDA_NP, addr, &val);
    104 	mutex_unlock(&dev_priv->sb_lock);
    105 }
    106 
    107 u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg)
    108 {
    109 	u32 val = 0;
    110 
    111 	vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT,
    112 			SB_CRRDDA_NP, reg, &val);
    113 
    114 	return val;
    115 }
    116 
    117 void vlv_bunit_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
    118 {
    119 	vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT,
    120 			SB_CRWRDA_NP, reg, &val);
    121 }
    122 
    123 u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr)
    124 {
    125 	u32 val = 0;
    126 
    127 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
    128 
    129 	mutex_lock(&dev_priv->sb_lock);
    130 	vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_NC,
    131 			SB_CRRDDA_NP, addr, &val);
    132 	mutex_unlock(&dev_priv->sb_lock);
    133 
    134 	return val;
    135 }
    136 
    137 u32 vlv_gpio_nc_read(struct drm_i915_private *dev_priv, u32 reg)
    138 {
    139 	u32 val = 0;
    140 	vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_GPIO_NC,
    141 			SB_CRRDDA_NP, reg, &val);
    142 	return val;
    143 }
    144 
    145 void vlv_gpio_nc_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
    146 {
    147 	vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_GPIO_NC,
    148 			SB_CRWRDA_NP, reg, &val);
    149 }
    150 
    151 u32 vlv_cck_read(struct drm_i915_private *dev_priv, u32 reg)
    152 {
    153 	u32 val = 0;
    154 	vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_CCK,
    155 			SB_CRRDDA_NP, reg, &val);
    156 	return val;
    157 }
    158 
    159 void vlv_cck_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
    160 {
    161 	vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_CCK,
    162 			SB_CRWRDA_NP, reg, &val);
    163 }
    164 
    165 u32 vlv_ccu_read(struct drm_i915_private *dev_priv, u32 reg)
    166 {
    167 	u32 val = 0;
    168 	vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_CCU,
    169 			SB_CRRDDA_NP, reg, &val);
    170 	return val;
    171 }
    172 
    173 void vlv_ccu_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
    174 {
    175 	vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_CCU,
    176 			SB_CRWRDA_NP, reg, &val);
    177 }
    178 
    179 u32 vlv_gps_core_read(struct drm_i915_private *dev_priv, u32 reg)
    180 {
    181 	u32 val = 0;
    182 	vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_GPS_CORE,
    183 			SB_CRRDDA_NP, reg, &val);
    184 	return val;
    185 }
    186 
    187 void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
    188 {
    189 	vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_GPS_CORE,
    190 			SB_CRWRDA_NP, reg, &val);
    191 }
    192 
    193 u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum i915_pipe pipe, int reg)
    194 {
    195 	u32 val = 0;
    196 
    197 	vlv_sideband_rw(dev_priv, DPIO_DEVFN, DPIO_PHY_IOSF_PORT(DPIO_PHY(pipe)),
    198 			SB_MRD_NP, reg, &val);
    199 
    200 	/*
    201 	 * FIXME: There might be some registers where all 1's is a valid value,
    202 	 * so ideally we should check the register offset instead...
    203 	 */
    204 	WARN(val == 0xffffffff, "DPIO read pipe %c reg 0x%x == 0x%x\n",
    205 	     pipe_name(pipe), reg, val);
    206 
    207 	return val;
    208 }
    209 
    210 void vlv_dpio_write(struct drm_i915_private *dev_priv, enum i915_pipe pipe, int reg, u32 val)
    211 {
    212 	vlv_sideband_rw(dev_priv, DPIO_DEVFN, DPIO_PHY_IOSF_PORT(DPIO_PHY(pipe)),
    213 			SB_MWR_NP, reg, &val);
    214 }
    215 
    216 /* SBI access */
    217 u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg,
    218 		   enum intel_sbi_destination destination)
    219 {
    220 	u32 value = 0;
    221 	WARN_ON(!mutex_is_locked(&dev_priv->sb_lock));
    222 
    223 	if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0,
    224 				100)) {
    225 		DRM_ERROR("timeout waiting for SBI to become ready\n");
    226 		return 0;
    227 	}
    228 
    229 	I915_WRITE(SBI_ADDR, (reg << 16));
    230 
    231 	if (destination == SBI_ICLK)
    232 		value = SBI_CTL_DEST_ICLK | SBI_CTL_OP_CRRD;
    233 	else
    234 		value = SBI_CTL_DEST_MPHY | SBI_CTL_OP_IORD;
    235 	I915_WRITE(SBI_CTL_STAT, value | SBI_BUSY);
    236 
    237 	if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0,
    238 				100)) {
    239 		DRM_ERROR("timeout waiting for SBI to complete read transaction\n");
    240 		return 0;
    241 	}
    242 
    243 	return I915_READ(SBI_DATA);
    244 }
    245 
    246 void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
    247 		     enum intel_sbi_destination destination)
    248 {
    249 	u32 tmp;
    250 
    251 	WARN_ON(!mutex_is_locked(&dev_priv->sb_lock));
    252 
    253 	if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0,
    254 				100)) {
    255 		DRM_ERROR("timeout waiting for SBI to become ready\n");
    256 		return;
    257 	}
    258 
    259 	I915_WRITE(SBI_ADDR, (reg << 16));
    260 	I915_WRITE(SBI_DATA, value);
    261 
    262 	if (destination == SBI_ICLK)
    263 		tmp = SBI_CTL_DEST_ICLK | SBI_CTL_OP_CRWR;
    264 	else
    265 		tmp = SBI_CTL_DEST_MPHY | SBI_CTL_OP_IOWR;
    266 	I915_WRITE(SBI_CTL_STAT, SBI_BUSY | tmp);
    267 
    268 	if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0,
    269 				100)) {
    270 		DRM_ERROR("timeout waiting for SBI to complete write transaction\n");
    271 		return;
    272 	}
    273 }
    274 
    275 u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg)
    276 {
    277 	u32 val = 0;
    278 	vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_FLISDSI, SB_CRRDDA_NP,
    279 			reg, &val);
    280 	return val;
    281 }
    282 
    283 void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
    284 {
    285 	vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_FLISDSI, SB_CRWRDA_NP,
    286 			reg, &val);
    287 }
    288