From: Egbert Eich Date: Tue Oct 9 16:45:13 2012 +0200 Subject: DRM/i915: On GEN2 map lower and upper mmio Register Ranges separately. Git-commit: ceb74fdfc95e571c1bb36790729098fe803cf7e2 Signed-off-by: Egbert Eich intel_gtt now maps the GTT range WC. The MMIO registers need to be mapped uncached however. On GEN2 hardware the GTT aperture is located right in the middle of the PCI BAR which also contains the MMIO registers. Mapping the full BAR in the intel driver fails however due to the different memory type. This patch maps the lower and upper MMIO range of the PCI BAR separately on GEN2 hardware and adjusts the access functions accordingly. Signed-off-by: Egbert Eich --- drivers/gpu/drm/i915/i915_dma.c | 21 ++++++++++++- drivers/gpu/drm/i915/i915_drv.c | 60 +++++++++++++++++++++++++++++++++++---- drivers/gpu/drm/i915/i915_drv.h | 23 ++++++++++++-- drivers/gpu/drm/i915/i915_reg.h | 6 ++++ 4 files changed, 98 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 67cdea7..73f6ef2 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1533,7 +1533,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) * the register BAR remains the same size for all the earlier * generations up to Ironlake. */ - if (info->gen < 5) + if (IS_GEN2(dev)) + mmio_size = I830_PTE_BASE; + else if (info->gen < 5) mmio_size = 512*1024; else mmio_size = 2*1024*1024; @@ -1544,6 +1546,16 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ret = -EIO; goto put_gmch; } + if (IS_GEN2(dev)) { + u32 start = pci_resource_start(dev->pdev, 1); + dev_priv->gen2_regs_upper = ioremap_nocache(start + mmio_size + I830_MAX_PTE_SIZE, + 512*1024 - mmio_size - I830_MAX_PTE_SIZE); + if (!dev_priv->gen2_regs_upper) { + DRM_ERROR("failed to map registers\n"); + ret = -EIO; + goto out_rmmap; + } + } else dev_priv->gen2_regs_upper = NULL; aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; dev_priv->mm.gtt_base_addr = dev_priv->mm.gtt->gma_bus_addr; @@ -1553,7 +1565,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) aperture_size); if (dev_priv->mm.gtt_mapping == NULL) { ret = -EIO; - goto out_rmmap; + goto out_rmmap1; } i915_mtrr_setup(dev_priv, dev_priv->mm.gtt_base_addr, @@ -1674,6 +1686,9 @@ out_mtrrfree: dev_priv->mm.gtt_mtrr = -1; } io_mapping_free(dev_priv->mm.gtt_mapping); +out_rmmap1: + if (dev_priv->gen2_regs_upper != NULL) + pci_iounmap(dev->pdev, dev_priv->gen2_regs_upper); out_rmmap: pci_iounmap(dev->pdev, dev_priv->regs); put_gmch: @@ -1764,6 +1779,8 @@ int i915_driver_unload(struct drm_device *dev) i915_free_hws(dev); } + if (dev_priv->gen2_regs_upper != NULL) + pci_iounmap(dev->pdev, dev_priv->gen2_regs_upper); if (dev_priv->regs != NULL) pci_iounmap(dev->pdev, dev_priv->regs); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a7837e5..f6d3931 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1145,8 +1145,15 @@ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \ } else if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \ val = read##y(dev_priv->regs + reg + 0x180000); \ - } else { \ - val = read##y(dev_priv->regs + reg); \ + } else { \ + if (dev_priv->gen2_regs_upper == NULL || reg < I830_PTE_BASE) { \ + val = read##y(dev_priv->regs + reg); \ + } else if (reg >= (I830_PTE_BASE + I830_MAX_PTE_SIZE)) { \ + val = read##y(dev_priv->gen2_regs_upper + reg - \ + I830_PTE_BASE - I830_MAX_PTE_SIZE); \ + } else { \ + printk(KERN_INFO "i915: read reg 0x%x\n", reg); \ + } \ } \ trace_i915_reg_rw(false, reg, val, sizeof(val)); \ return val; \ @@ -1158,9 +1165,9 @@ __i915_read(32, l) __i915_read(64, q) #undef __i915_read -#define __i915_write(x, y) \ +#define __i915_write(x, y) \ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \ - u32 __fifo_ret = 0; \ + u32 __fifo_ret = 0; \ trace_i915_reg_rw(true, reg, val, sizeof(val)); \ if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ @@ -1168,8 +1175,15 @@ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \ if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \ write##y(val, dev_priv->regs + reg + 0x180000); \ } else { \ - write##y(val, dev_priv->regs + reg); \ - } \ + if (dev_priv->gen2_regs_upper == NULL || reg < I830_PTE_BASE) { \ + write##y(val, dev_priv->regs + reg); \ + } else if (reg >= (I830_PTE_BASE + I830_MAX_PTE_SIZE)) { \ + write##y(val, dev_priv->gen2_regs_upper + reg - \ + I830_PTE_BASE - I830_MAX_PTE_SIZE ); \ + } else { \ + printk(KERN_INFO "i915: write reg 0x%x\n", reg); \ + } \ + } \ if (unlikely(__fifo_ret)) { \ gen6_gt_check_fifodbg(dev_priv); \ } \ @@ -1184,6 +1198,40 @@ __i915_write(32, l) __i915_write(64, q) #undef __i915_write +#define __gen2_read(x, y) \ +u##x gen2_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ + u##x val = 0; \ + if (reg < I830_PTE_BASE) { \ + val = read##y(dev_priv->regs + reg); \ + } else if (reg >= (I830_PTE_BASE + I830_MAX_PTE_SIZE)) { \ + val = read##y(dev_priv->gen2_regs_upper + reg - \ + I830_PTE_BASE - I830_MAX_PTE_SIZE); \ + } else { \ + printk(KERN_INFO "i915: read reg 0x%x\n", reg); \ + } \ + return val; \ +} + +__gen2_read(16, w) +__gen2_read(32, l) +#undef __gen2_read + +#define __gen2_write(x, y) \ +void gen2_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \ + if (reg < I830_PTE_BASE) { \ + write##y(val, dev_priv->regs + reg); \ + } else if (reg >= (I830_PTE_BASE + I830_MAX_PTE_SIZE)) { \ + write##y(val, dev_priv->gen2_regs_upper + reg - \ + I830_PTE_BASE - I830_MAX_PTE_SIZE ); \ + } else { \ + printk(KERN_INFO "i915: write reg 0x%x\n", reg); \ + } \ +} + +__gen2_write(16, w) +__gen2_write(32, l) +#undef __gen2_write + static const struct register_whitelist { uint64_t offset; uint32_t size; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index af5ceb4..369cd47 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -398,6 +398,7 @@ typedef struct drm_i915_private { int relative_constants_mode; void __iomem *regs; + void __iomem *gen2_regs_upper; struct drm_i915_gt_funcs gt; /** gt_fifo_count and the subsequent register write are synchronized @@ -1640,18 +1641,32 @@ __i915_write(32, l) __i915_write(64, q) #undef __i915_write +#define __gen2_read(x, y) \ + u##x gen2_read##x(struct drm_i915_private *dev_priv, u32 reg); + +__gen2_read(16, w) +__gen2_read(32, l) +#undef __gen2_read + +#define __gen2_write(x, y) \ + void gen2_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val); + +__gen2_write(16, w) +__gen2_write(32, l) +#undef __gen2_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) readw(dev_priv->regs + (reg)) -#define I915_WRITE16_NOTRACE(reg, val) writew(val, dev_priv->regs + (reg)) +#define I915_READ16_NOTRACE(reg) ((dev_priv->gen2_regs_upper == NULL) ? readw(dev_priv->regs + (reg)) : gen2_read16(dev_priv,reg)) +#define I915_WRITE16_NOTRACE(reg, val) ((dev_priv->gen2_regs_upper == NULL) ? writew(val, dev_priv->regs + (reg)) : gen2_write16(dev_priv, 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) readl(dev_priv->regs + (reg)) -#define I915_WRITE_NOTRACE(reg, val) writel(val, dev_priv->regs + (reg)) +#define I915_READ_NOTRACE(reg) ((dev_priv->gen2_regs_upper == NULL) ? readl(dev_priv->regs + (reg)) : gen2_read32(dev_priv,reg)) +#define I915_WRITE_NOTRACE(reg, val) ((dev_priv->gen2_regs_upper == NULL) ? writel(val, dev_priv->regs + (reg)) : gen2_write32(dev_priv, reg, val)) #define I915_WRITE64(reg, val) i915_write64(dev_priv, (reg), (val)) #define I915_READ64(reg) i915_read64(dev_priv, (reg)) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a828e90..f686fe5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -417,6 +417,12 @@ #define TILECTL_BACKSNOOP_DIS (1 << 3) /* + * GEN2 page table base address + */ +#define I830_PTE_BASE 0x10000 +#define I830_MAX_PTE_SIZE ((128 * 1024 * 1024) >> PAGE_SHIFT) + +/* * Instruction and interrupt control regs */ #define PGTBL_ER 0x02024