drm/nouveau: have non-core mmio accesses go through device object

Adds an extra layer of indirection to each register access, but it's not
too bad, and will also go away as pieces are ported.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Ben Skeggs 2012-07-09 14:14:48 +10:00
parent 9458029940
commit 586c55f6ad
5 changed files with 99 additions and 109 deletions

View file

@ -80,7 +80,7 @@ nouveau-y += core/engine/mpeg/nv50.o
nouveau-y += core/engine/ppp/nv98.o nouveau-y += core/engine/ppp/nv98.o
nouveau-y += core/engine/vp/nv84.o nouveau-y += core/engine/vp/nv84.o
nouveau-y += nouveau_drm.o \ nouveau-y += nouveau_drm.o nouveau_compat.o \
nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nouveau_gpuobj.o nouveau_irq.o nouveau_notifier.o \ nouveau_gpuobj.o nouveau_irq.o nouveau_notifier.o \
nouveau_sgdma.o nouveau_dma.o nouveau_util.o \ nouveau_sgdma.o nouveau_dma.o nouveau_util.o \

View file

@ -0,0 +1,40 @@
#include "nouveau_drm.h"
#include "nouveau_compat.h"
void *nouveau_newpriv(struct drm_device *);
u8
_nv_rd08(struct drm_device *dev, u32 reg)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
return nv_ro08(drm->device, reg);
}
void
_nv_wr08(struct drm_device *dev, u32 reg, u8 val)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
nv_wo08(drm->device, reg, val);
}
u32
_nv_rd32(struct drm_device *dev, u32 reg)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
return nv_ro32(drm->device, reg);
}
void
_nv_wr32(struct drm_device *dev, u32 reg, u32 val)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
nv_wo32(drm->device, reg, val);
}
u32
_nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val)
{
u32 tmp = _nv_rd32(dev, reg);
_nv_wr32(dev, reg, (tmp & ~mask) | val);
return tmp;
}

View file

@ -0,0 +1,10 @@
#ifndef __NOUVEAU_COMPAT_H__
#define __NOUVEAU_COMPAT_H__
u8 _nv_rd08(struct drm_device *, u32);
void _nv_wr08(struct drm_device *, u32, u8);
u32 _nv_rd32(struct drm_device *, u32);
void _nv_wr32(struct drm_device *, u32, u32);
u32 _nv_mask(struct drm_device *, u32, u32, u32);
#endif

View file

@ -673,8 +673,6 @@ struct drm_nouveau_private {
int flags; int flags;
u32 crystal; u32 crystal;
void __iomem *mmio;
spinlock_t ramin_lock; spinlock_t ramin_lock;
void __iomem *ramin; void __iomem *ramin;
u32 ramin_size; u32 ramin_size;
@ -1428,36 +1426,12 @@ static inline void nvchan_wr32(struct nouveau_channel *chan,
} }
/* register access */ /* register access */
static inline u32 nv_rd32(struct drm_device *dev, unsigned reg) #include "nouveau_compat.h"
{ #define nv_rd08 _nv_rd08
struct drm_nouveau_private *dev_priv = dev->dev_private; #define nv_wr08 _nv_wr08
return ioread32_native(dev_priv->mmio + reg); #define nv_rd32 _nv_rd32
} #define nv_wr32 _nv_wr32
#define nv_mask _nv_mask
static inline void nv_wr32(struct drm_device *dev, unsigned reg, u32 val)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
iowrite32_native(val, dev_priv->mmio + reg);
}
static inline u32 nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val)
{
u32 tmp = nv_rd32(dev, reg);
nv_wr32(dev, reg, (tmp & ~mask) | val);
return tmp;
}
static inline u8 nv_rd08(struct drm_device *dev, unsigned reg)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
return ioread8(dev_priv->mmio + reg);
}
static inline void nv_wr08(struct drm_device *dev, unsigned reg, u8 val)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
iowrite8(val, dev_priv->mmio + reg);
}
#define nv_wait(dev, reg, mask, val) \ #define nv_wait(dev, reg, mask, val) \
nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val)) nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val))

View file

@ -1037,7 +1037,6 @@ nouveau_newpriv(struct drm_device *dev)
int nouveau_load(struct drm_device *dev, unsigned long flags) int nouveau_load(struct drm_device *dev, unsigned long flags)
{ {
struct drm_nouveau_private *dev_priv; struct drm_nouveau_private *dev_priv;
unsigned long long offset, length;
uint32_t reg0 = ~0, strap; uint32_t reg0 = ~0, strap;
int ret; int ret;
@ -1050,65 +1049,50 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
dev->dev_private = dev_priv; dev->dev_private = dev_priv;
dev_priv->dev = dev; dev_priv->dev = dev;
pci_set_master(dev->pdev);
dev_priv->flags = flags & NOUVEAU_FLAGS; dev_priv->flags = flags & NOUVEAU_FLAGS;
NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
dev->pci_vendor, dev->pci_device, dev->pdev->class); dev->pci_vendor, dev->pci_device, dev->pdev->class);
/* first up, map the start of mmio and determine the chipset */ /* determine chipset and derive architecture from it */
dev_priv->mmio = ioremap(pci_resource_start(dev->pdev, 0), PAGE_SIZE); reg0 = nv_rd32(dev, NV03_PMC_BOOT_0);
if (dev_priv->mmio) { if ((reg0 & 0x0f000000) > 0) {
#ifdef __BIG_ENDIAN dev_priv->chipset = (reg0 & 0xff00000) >> 20;
/* put the card into big-endian mode if it's not */ switch (dev_priv->chipset & 0xf0) {
if (nv_rd32(dev, NV03_PMC_BOOT_1) != 0x01000001) case 0x10:
nv_wr32(dev, NV03_PMC_BOOT_1, 0x01000001); case 0x20:
DRM_MEMORYBARRIER(); case 0x30:
#endif dev_priv->card_type = dev_priv->chipset & 0xf0;
break;
/* determine chipset and derive architecture from it */ case 0x40:
reg0 = nv_rd32(dev, NV03_PMC_BOOT_0); case 0x60:
if ((reg0 & 0x0f000000) > 0) { dev_priv->card_type = NV_40;
dev_priv->chipset = (reg0 & 0xff00000) >> 20; break;
switch (dev_priv->chipset & 0xf0) { case 0x50:
case 0x10: case 0x80:
case 0x20: case 0x90:
case 0x30: case 0xa0:
dev_priv->card_type = dev_priv->chipset & 0xf0; dev_priv->card_type = NV_50;
break; break;
case 0x40: case 0xc0:
case 0x60: dev_priv->card_type = NV_C0;
dev_priv->card_type = NV_40; break;
break; case 0xd0:
case 0x50: dev_priv->card_type = NV_D0;
case 0x80: break;
case 0x90: case 0xe0:
case 0xa0: dev_priv->card_type = NV_E0;
dev_priv->card_type = NV_50; break;
break; default:
case 0xc0: break;
dev_priv->card_type = NV_C0;
break;
case 0xd0:
dev_priv->card_type = NV_D0;
break;
case 0xe0:
dev_priv->card_type = NV_E0;
break;
default:
break;
}
} else
if ((reg0 & 0xff00fff0) == 0x20004000) {
if (reg0 & 0x00f00000)
dev_priv->chipset = 0x05;
else
dev_priv->chipset = 0x04;
dev_priv->card_type = NV_04;
} }
} else
iounmap(dev_priv->mmio); if ((reg0 & 0xff00fff0) == 0x20004000) {
if (reg0 & 0x00f00000)
dev_priv->chipset = 0x05;
else
dev_priv->chipset = 0x04;
dev_priv->card_type = NV_04;
} }
if (!dev_priv->card_type) { if (!dev_priv->card_type) {
@ -1120,21 +1104,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
NV_INFO(dev, "Detected an NV%02x generation card (0x%08x)\n", NV_INFO(dev, "Detected an NV%02x generation card (0x%08x)\n",
dev_priv->card_type, reg0); dev_priv->card_type, reg0);
/* map the mmio regs, limiting the amount to preserve vmap space */
offset = pci_resource_start(dev->pdev, 0);
length = pci_resource_len(dev->pdev, 0);
if (dev_priv->card_type < NV_E0)
length = min(length, (unsigned long long)0x00800000);
dev_priv->mmio = ioremap(offset, length);
if (!dev_priv->mmio) {
NV_ERROR(dev, "Unable to initialize the mmio mapping. "
"Please report your setup to " DRIVER_EMAIL "\n");
ret = -EINVAL;
goto err_priv;
}
NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", offset);
/* determine frequency of timing crystal */ /* determine frequency of timing crystal */
strap = nv_rd32(dev, 0x101000); strap = nv_rd32(dev, 0x101000);
if ( dev_priv->chipset < 0x17 || if ( dev_priv->chipset < 0x17 ||
@ -1174,7 +1143,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
ret = nouveau_remove_conflicting_drivers(dev); ret = nouveau_remove_conflicting_drivers(dev);
if (ret) if (ret)
goto err_mmio; goto err_priv;
/* Map PRAMIN BAR, or on older cards, the aperture within BAR0 */ /* Map PRAMIN BAR, or on older cards, the aperture within BAR0 */
if (dev_priv->card_type >= NV_40) { if (dev_priv->card_type >= NV_40) {
@ -1189,16 +1158,16 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
if (!dev_priv->ramin) { if (!dev_priv->ramin) {
NV_ERROR(dev, "Failed to map PRAMIN BAR\n"); NV_ERROR(dev, "Failed to map PRAMIN BAR\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_mmio; goto err_priv;
} }
} else { } else {
dev_priv->ramin_size = 1 * 1024 * 1024; dev_priv->ramin_size = 1 * 1024 * 1024;
dev_priv->ramin = ioremap(offset + NV_RAMIN, dev_priv->ramin = ioremap(pci_resource_start(dev->pdev, 0),
dev_priv->ramin_size); dev_priv->ramin_size);
if (!dev_priv->ramin) { if (!dev_priv->ramin) {
NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n"); NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_mmio; goto err_priv;
} }
} }
@ -1219,8 +1188,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
err_ramin: err_ramin:
iounmap(dev_priv->ramin); iounmap(dev_priv->ramin);
err_mmio:
iounmap(dev_priv->mmio);
err_priv: err_priv:
dev->dev_private = dev_priv->newpriv; dev->dev_private = dev_priv->newpriv;
kfree(dev_priv); kfree(dev_priv);
@ -1239,7 +1206,6 @@ int nouveau_unload(struct drm_device *dev)
nouveau_card_takedown(dev); nouveau_card_takedown(dev);
iounmap(dev_priv->mmio);
iounmap(dev_priv->ramin); iounmap(dev_priv->ramin);
dev->dev_private = dev_priv->newpriv; dev->dev_private = dev_priv->newpriv;