summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2013-09-30 06:47:49 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2013-09-30 06:47:49 +0000
commite52f1fdae5dfd2bec14a1cc45f5e2ff5b19e6a55 (patch)
treed0e0e6e0e7160e1db153036337dbe63b81ca5e59 /sys
parent9e5c3ce91a15b3dd85ab37944b0fad7225a16c00 (diff)
move the read/write functions and macros closer to linux
noteably this uses the gt lock and force wake in some cases and includes a gen5/ironlake errata. ok kettenis@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.c176
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.h120
-rw-r--r--sys/dev/pci/drm/i915/i915_trace.h7
3 files changed, 272 insertions, 31 deletions
diff --git a/sys/dev/pci/drm/i915/i915_drv.c b/sys/dev/pci/drm/i915/i915_drv.c
index 0987df6528d..153239999f6 100644
--- a/sys/dev/pci/drm/i915/i915_drv.c
+++ b/sys/dev/pci/drm/i915/i915_drv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_drv.c,v 1.38 2013/09/08 11:59:44 jsg Exp $ */
+/* $OpenBSD: i915_drv.c,v 1.39 2013/09/30 06:47:48 jsg Exp $ */
/*
* Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org>
*
@@ -50,6 +50,7 @@
#include <dev/pci/drm/i915_drm.h>
#include "i915_drv.h"
#include "intel_drv.h"
+#include "i915_trace.h"
#include <machine/pmap.h>
@@ -2266,3 +2267,176 @@ intel_detect_pch(struct inteldrm_softc *dev_priv)
}
}
+/* We give fast paths for the really cool registers */
+#define NEEDS_FORCE_WAKE(dev, reg) \
+ ((HAS_FORCE_WAKE(dev)) && \
+ ((reg) < 0x40000) && \
+ ((reg) != FORCEWAKE))
+
+static bool IS_DISPLAYREG(u32 reg)
+{
+ /*
+ * This should make it easier to transition modules over to the
+ * new register block scheme, since we can do it incrementally.
+ */
+ if (reg >= VLV_DISPLAY_BASE)
+ return false;
+
+ if (reg >= RENDER_RING_BASE &&
+ reg < RENDER_RING_BASE + 0xff)
+ return false;
+ if (reg >= GEN6_BSD_RING_BASE &&
+ reg < GEN6_BSD_RING_BASE + 0xff)
+ return false;
+ if (reg >= BLT_RING_BASE &&
+ reg < BLT_RING_BASE + 0xff)
+ return false;
+
+ if (reg == PGTBL_ER)
+ return false;
+
+ if (reg >= IPEIR_I965 &&
+ reg < HWSTAM)
+ return false;
+
+ if (reg == MI_MODE)
+ return false;
+
+ if (reg == GFX_MODE_GEN7)
+ return false;
+
+ if (reg == RENDER_HWS_PGA_GEN7 ||
+ reg == BSD_HWS_PGA_GEN7 ||
+ reg == BLT_HWS_PGA_GEN7)
+ return false;
+
+ if (reg == GEN6_BSD_SLEEP_PSMI_CONTROL ||
+ reg == GEN6_BSD_RNCID)
+ return false;
+
+ if (reg == GEN6_BLITTER_ECOSKPD)
+ return false;
+
+ if (reg >= 0x4000c &&
+ reg <= 0x4002c)
+ return false;
+
+ if (reg >= 0x4f000 &&
+ reg <= 0x4f08f)
+ return false;
+
+ if (reg >= 0x4f100 &&
+ reg <= 0x4f11f)
+ return false;
+
+ if (reg >= VLV_MASTER_IER &&
+ reg <= GEN6_PMIER)
+ return false;
+
+ if (reg >= FENCE_REG_SANDYBRIDGE_0 &&
+ reg < (FENCE_REG_SANDYBRIDGE_0 + (16*8)))
+ return false;
+
+ if (reg >= VLV_IIR_RW &&
+ reg <= VLV_ISR)
+ return false;
+
+ if (reg == FORCEWAKE_VLV ||
+ reg == FORCEWAKE_ACK_VLV)
+ return false;
+
+ if (reg == GEN6_GDRST)
+ return false;
+
+ switch (reg) {
+ case _3D_CHICKEN3:
+ case IVB_CHICKEN3:
+ case GEN7_COMMON_SLICE_CHICKEN1:
+ case GEN7_L3CNTLREG1:
+ case GEN7_L3_CHICKEN_MODE_REGISTER:
+ case GEN7_ROW_CHICKEN2:
+ case GEN7_L3SQCREG4:
+ case GEN7_SQ_CHICKEN_MBCUNIT_CONFIG:
+ case GEN7_HALF_SLICE_CHICKEN1:
+ case GEN6_MBCTL:
+ case GEN6_UCGCTL2:
+ return false;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+static void
+ilk_dummy_write(struct drm_i915_private *dev_priv)
+{
+ /* WaIssueDummyWriteToWakeupFromRC6: Issue a dummy write to wake up the
+ * chip from rc6 before touching it for real. MI_MODE is masked, hence
+ * harmless to write 0 into. */
+ I915_WRITE_NOTRACE(MI_MODE, 0);
+}
+
+#define __i915_read(x, y) \
+u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
+ struct drm_device *dev = (struct drm_device *)dev_priv->drmdev; \
+ u##x val = 0; \
+ mtx_enter(&dev_priv->gt_lock); \
+ if (IS_GEN5(dev)) \
+ ilk_dummy_write(dev_priv); \
+ if (NEEDS_FORCE_WAKE((dev), (reg))) { \
+ if (dev_priv->forcewake_count == 0) \
+ dev_priv->gt.force_wake_get(dev_priv); \
+ val = read##x(dev_priv, reg); \
+ if (dev_priv->forcewake_count == 0) \
+ dev_priv->gt.force_wake_put(dev_priv); \
+ } else if (IS_VALLEYVIEW(dev) && IS_DISPLAYREG(reg)) { \
+ val = read##x(dev_priv, reg + 0x180000); \
+ } else { \
+ val = read##x(dev_priv, reg); \
+ } \
+ mtx_leave(&dev_priv->gt_lock); \
+ trace_i915_reg_rw(false, reg, val, sizeof(val)); \
+ return val; \
+}
+
+__i915_read(8, b)
+__i915_read(16, w)
+__i915_read(32, l)
+__i915_read(64, q)
+#undef __i915_read
+
+#define __i915_write(x, y) \
+void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
+ u32 __fifo_ret = 0; \
+ struct drm_device *dev = (struct drm_device *)dev_priv->drmdev; \
+ trace_i915_reg_rw(true, reg, val, sizeof(val)); \
+ mtx_enter(&dev_priv->gt_lock); \
+ if (NEEDS_FORCE_WAKE((dev), (reg))) { \
+ __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
+ } \
+ if (IS_GEN5(dev)) \
+ ilk_dummy_write(dev_priv); \
+ if (IS_HASWELL(dev) && (I915_READ_NOTRACE(GEN7_ERR_INT) & ERR_INT_MMIO_UNCLAIMED)) { \
+ DRM_ERROR("Unknown unclaimed register before writing to %x\n", reg); \
+ I915_WRITE_NOTRACE(GEN7_ERR_INT, ERR_INT_MMIO_UNCLAIMED); \
+ } \
+ if (IS_VALLEYVIEW(dev) && IS_DISPLAYREG(reg)) { \
+ write##x(dev_priv, reg + 0x180000, val); \
+ } else { \
+ write##x(dev_priv, reg, val); \
+ } \
+ if (unlikely(__fifo_ret)) { \
+ gen6_gt_check_fifodbg(dev_priv); \
+ } \
+ if (IS_HASWELL(dev) && (I915_READ_NOTRACE(GEN7_ERR_INT) & ERR_INT_MMIO_UNCLAIMED)) { \
+ DRM_ERROR("Unclaimed write to %x\n", reg); \
+ write32(dev_priv, GEN7_ERR_INT, ERR_INT_MMIO_UNCLAIMED); \
+ } \
+ mtx_leave(&dev_priv->gt_lock); \
+}
+__i915_write(8, b)
+__i915_write(16, w)
+__i915_write(32, l)
+__i915_write(64, q)
+#undef __i915_write
diff --git a/sys/dev/pci/drm/i915/i915_drv.h b/sys/dev/pci/drm/i915/i915_drv.h
index 9060a44a716..778c5bc7610 100644
--- a/sys/dev/pci/drm/i915/i915_drv.h
+++ b/sys/dev/pci/drm/i915/i915_drv.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_drv.h,v 1.28 2013/09/18 08:50:28 jsg Exp $ */
+/* $OpenBSD: i915_drv.h,v 1.29 2013/09/30 06:47:48 jsg Exp $ */
/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
*/
/*
@@ -1339,50 +1339,112 @@ int __gen6_gt_wait_for_fifo(struct inteldrm_softc *dev_priv);
int sandybridge_pcode_read(struct inteldrm_softc *dev_priv, u8 mbox, u32 *val);
int sandybridge_pcode_write(struct inteldrm_softc *dev_priv, u8 mbox, u32 val);
+static __inline void
+write8(struct inteldrm_softc *dev_priv, bus_size_t reg, uint8_t val)
+{
+ bus_space_write_1(dev_priv->regs->bst,dev_priv->regs->bsh, (reg),
+ (val));
+}
+
+static __inline void
+write16(struct inteldrm_softc *dev_priv, bus_size_t reg, uint16_t val)
+{
+ bus_space_write_2(dev_priv->regs->bst,dev_priv->regs->bsh, (reg),
+ (val));
+}
+
+static __inline void
+write32(struct inteldrm_softc *dev_priv, bus_size_t reg, uint32_t val)
+{
+ bus_space_write_4(dev_priv->regs->bst,dev_priv->regs->bsh, (reg),
+ (val));
+}
+
/* XXX need bus_space_write_8, this evaluated arguments twice */
static __inline void
-write64(struct inteldrm_softc *dev_priv, bus_size_t off, u_int64_t reg)
+write64(struct inteldrm_softc *dev_priv, bus_size_t reg, uint64_t val)
{
bus_space_write_4(dev_priv->regs->bst, dev_priv->regs->bsh,
- off, (u_int32_t)reg);
+ reg, (u_int32_t)val);
bus_space_write_4(dev_priv->regs->bst, dev_priv->regs->bsh,
- off + 4, upper_32_bits(reg));
+ reg + 4, upper_32_bits(val));
+}
+
+static __inline uint8_t
+read8(struct inteldrm_softc *dev_priv, bus_size_t reg)
+{
+ return (bus_space_read_1(dev_priv->regs->bst, dev_priv->regs->bsh,
+ (reg)));
}
-static __inline u_int64_t
-read64(struct inteldrm_softc *dev_priv, bus_size_t off)
+static __inline uint16_t
+read16(struct inteldrm_softc *dev_priv, bus_size_t reg)
+{
+ return (bus_space_read_2(dev_priv->regs->bst, dev_priv->regs->bsh,
+ (reg)));
+}
+
+static __inline uint32_t
+read32(struct inteldrm_softc *dev_priv, bus_size_t reg)
+{
+ return (bus_space_read_4(dev_priv->regs->bst, dev_priv->regs->bsh,
+ (reg)));
+}
+
+static __inline uint64_t
+read64(struct inteldrm_softc *dev_priv, bus_size_t reg)
{
u_int32_t low, high;
low = bus_space_read_4(dev_priv->regs->bst,
- dev_priv->regs->bsh, off);
+ dev_priv->regs->bsh, reg);
high = bus_space_read_4(dev_priv->regs->bst,
- dev_priv->regs->bsh, off + 4);
+ dev_priv->regs->bsh, reg + 4);
return ((u_int64_t)low | ((u_int64_t)high << 32));
}
-#define I915_READ64(off) read64(dev_priv, off)
-
-#define I915_WRITE64(off, reg) write64(dev_priv, off, reg)
-
-#define I915_READ(reg) bus_space_read_4(dev_priv->regs->bst, \
- dev_priv->regs->bsh, (reg))
-#define I915_READ_NOTRACE(reg) I915_READ(reg)
-#define I915_WRITE(reg,val) bus_space_write_4(dev_priv->regs->bst, \
- dev_priv->regs->bsh, (reg), (val))
-#define I915_WRITE_NOTRACE(reg,val) I915_WRITE(reg, val)
-#define I915_READ16(reg) bus_space_read_2(dev_priv->regs->bst, \
- dev_priv->regs->bsh, (reg))
-#define I915_WRITE16(reg,val) bus_space_write_2(dev_priv->regs->bst, \
- dev_priv->regs->bsh, (reg), (val))
-#define I915_READ8(reg) bus_space_read_1(dev_priv->regs->bst, \
- dev_priv->regs->bsh, (reg))
-#define I915_WRITE8(reg,val) bus_space_write_1(dev_priv->regs->bst, \
- dev_priv->regs->bsh, (reg), (val))
-
-#define POSTING_READ(reg) (void)I915_READ(reg)
-#define POSTING_READ16(reg) (void)I915_READ16(reg)
+
+#define __i915_read(x, y) \
+ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
+
+__i915_read(8, b)
+__i915_read(16, w)
+__i915_read(32, l)
+__i915_read(64, q)
+#undef __i915_read
+
+#define __i915_write(x, y) \
+ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val);
+
+__i915_write(8, b)
+__i915_write(16, w)
+__i915_write(32, l)
+__i915_write(64, q)
+#undef __i915_write
+
+#define I915_READ8(reg) i915_read8(dev_priv, (reg))
+#define I915_WRITE8(reg, val) i915_write8(dev_priv, (reg), (val))
+
+#define I915_READ16(reg) i915_read16(dev_priv, (reg))
+#define I915_WRITE16(reg, val) i915_write16(dev_priv, (reg), (val))
+#define I915_READ16_NOTRACE(reg) bus_space_read_2(dev_priv->regs->bst, \
+ dev_priv->regs->bsh, (reg))
+#define I915_WRITE16_NOTRACE(reg,val) bus_space_write_2(dev_priv->regs->bst, \
+ dev_priv->regs->bsh, (reg), (val))
+
+#define I915_READ(reg) i915_read32(dev_priv, (reg))
+#define I915_WRITE(reg, val) i915_write32(dev_priv, (reg), (val))
+#define I915_READ_NOTRACE(reg) bus_space_read_4(dev_priv->regs->bst, \
+ dev_priv->regs->bsh, (reg))
+#define I915_WRITE_NOTRACE(reg,val) bus_space_write_4(dev_priv->regs->bst, \
+ dev_priv->regs->bsh, (reg), (val))
+
+#define I915_WRITE64(reg, val) i915_write64(dev_priv, (reg), (val))
+#define I915_READ64(reg) i915_read64(dev_priv, (reg))
+
+#define POSTING_READ(reg) (void)I915_READ_NOTRACE(reg)
+#define POSTING_READ16(reg) (void)I915_READ16_NOTRACE(reg)
#define INTELDRM_VERBOSE 0
#if INTELDRM_VERBOSE > 0
diff --git a/sys/dev/pci/drm/i915/i915_trace.h b/sys/dev/pci/drm/i915/i915_trace.h
index 6b42b889088..7df9f796aa2 100644
--- a/sys/dev/pci/drm/i915/i915_trace.h
+++ b/sys/dev/pci/drm/i915/i915_trace.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_trace.h,v 1.1 2013/08/07 19:49:07 kettenis Exp $ */
+/* $OpenBSD: i915_trace.h,v 1.2 2013/09/30 06:47:48 jsg Exp $ */
/*
* Copyright (c) 2013 Mark Kettenis <kettenis@openbsd.org>
*
@@ -40,3 +40,8 @@ static inline void
trace_i915_gem_object_unbind(struct drm_i915_gem_object *obj)
{
}
+
+static inline void
+trace_i915_reg_rw(bool write, u32 reg, u64 val, int len)
+{
+}