aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2013-04-02 11:23:05 -0700
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-04-02 21:00:06 +0200
commita0e4e199ad18070e17d15b920a39c6ec9d95b793 (patch)
tree269f1c328d220ee13596f509d6191762f709cde9
parent453c542059cfa1988cabcf84f715307cd9789163 (diff)
drm/i915: add Punit read/write routines for VLV v2
Slightly different than other platforms. v2 [Jani]: Fix IOSF_BYTE_ENABLES_SHIFT shift. Use common routine. v3: drop turbo defines from this patch (Ville) use PCI_DEVFN(2,0) instead of open coding (Ville) Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Jani Nikula <jani.nikula@intel.com> [danvet: Add checkpatch bikeshed about missing space.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h14
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c53
3 files changed, 69 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c895a846561..2338c73ec21 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1863,6 +1863,8 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val);
int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val);
+int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val);
+int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val);
#define __i915_read(x, y) \
u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 37663696a56..058686c0dbb 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4381,6 +4381,20 @@
#define GEN6_PCODE_DATA 0x138128
#define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8
+#define VLV_IOSF_DOORBELL_REQ 0x182100
+#define IOSF_DEVFN_SHIFT 24
+#define IOSF_OPCODE_SHIFT 16
+#define IOSF_PORT_SHIFT 8
+#define IOSF_BYTE_ENABLES_SHIFT 4
+#define IOSF_BAR_SHIFT 1
+#define IOSF_SB_BUSY (1<<0)
+#define IOSF_PORT_PUNIT 0x4
+#define VLV_IOSF_DATA 0x182104
+#define VLV_IOSF_ADDR 0x182108
+
+#define PUNIT_OPCODE_REG_READ 6
+#define PUNIT_OPCODE_REG_WRITE 7
+
#define GEN6_GT_CORE_STATUS 0x138060
#define GEN6_CORE_CPD_STATE_MASK (7<<4)
#define GEN6_RCn_MASK 7
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 27f94cd19ee..f48227ad5d3 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4536,3 +4536,56 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val)
return 0;
}
+
+static int vlv_punit_rw(struct drm_i915_private *dev_priv, u8 opcode,
+ u8 addr, u32 *val)
+{
+ u32 cmd, devfn, port, be, bar;
+
+ bar = 0;
+ be = 0xf;
+ port = IOSF_PORT_PUNIT;
+ devfn = PCI_DEVFN(2, 0);
+
+ cmd = (devfn << IOSF_DEVFN_SHIFT) | (opcode << IOSF_OPCODE_SHIFT) |
+ (port << IOSF_PORT_SHIFT) | (be << IOSF_BYTE_ENABLES_SHIFT) |
+ (bar << IOSF_BAR_SHIFT);
+
+ WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+ if (I915_READ(VLV_IOSF_DOORBELL_REQ) & IOSF_SB_BUSY) {
+ DRM_DEBUG_DRIVER("warning: pcode (%s) mailbox access failed\n",
+ opcode == PUNIT_OPCODE_REG_READ ?
+ "read" : "write");
+ return -EAGAIN;
+ }
+
+ I915_WRITE(VLV_IOSF_ADDR, addr);
+ if (opcode == PUNIT_OPCODE_REG_WRITE)
+ I915_WRITE(VLV_IOSF_DATA, *val);
+ I915_WRITE(VLV_IOSF_DOORBELL_REQ, cmd);
+
+ if (wait_for((I915_READ(VLV_IOSF_DOORBELL_REQ) & IOSF_SB_BUSY) == 0,
+ 500)) {
+ DRM_ERROR("timeout waiting for pcode %s (%d) to finish\n",
+ opcode == PUNIT_OPCODE_REG_READ ? "read" : "write",
+ addr);
+ return -ETIMEDOUT;
+ }
+
+ if (opcode == PUNIT_OPCODE_REG_READ)
+ *val = I915_READ(VLV_IOSF_DATA);
+ I915_WRITE(VLV_IOSF_DATA, 0);
+
+ return 0;
+}
+
+int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val)
+{
+ return vlv_punit_rw(dev_priv, PUNIT_OPCODE_REG_READ, addr, val);
+}
+
+int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val)
+{
+ return vlv_punit_rw(dev_priv, PUNIT_OPCODE_REG_WRITE, addr, &val);
+}