Skip to content

Commit

Permalink
support for platform devices
Browse files Browse the repository at this point in the history
Upcoming mobile Kepler GPUs (such as GK20A) use the platform bus instead
of PCI to which Nouveau is tightly dependent. This patch allows Nouveau
to handle platform devices by:

- abstracting PCI-dependent functions that were typically used for
  resource querying and page mapping,
- introducing a nv_device_is_pci() function that allows to make
  PCI-dependent code conditional,
- providing a nouveau_drm_platform_probe() function that takes a GPU
  platform device to be probed.

Core code as well as engine/subdev drivers are updated wherever possible
to make use of these functions. Some older drivers are too dependent on
PCI to be properly updated, but all newer code on which future chips may
depend should at least be runnable with platform devices.

Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Alexandre Courbot authored and Ben Skeggs committed Mar 26, 2014
1 parent 0b68168 commit 420b946
Show file tree
Hide file tree
Showing 35 changed files with 305 additions and 127 deletions.
83 changes: 78 additions & 5 deletions drivers/gpu/drm/nouveau/core/engine/device/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
if (ret)
return ret;

mmio_base = pci_resource_start(device->pdev, 0);
mmio_size = pci_resource_len(device->pdev, 0);
mmio_base = nv_device_resource_start(device, 0);
mmio_size = nv_device_resource_len(device, 0);

/* translate api disable mask into internal mapping */
disable = args->debug0;
Expand Down Expand Up @@ -448,6 +448,72 @@ nouveau_device_dtor(struct nouveau_object *object)
nouveau_engine_destroy(&device->base);
}

resource_size_t
nv_device_resource_start(struct nouveau_device *device, unsigned int bar)
{
if (nv_device_is_pci(device)) {
return pci_resource_start(device->pdev, bar);
} else {
struct resource *res;
res = platform_get_resource(device->platformdev,
IORESOURCE_MEM, bar);
if (!res)
return 0;
return res->start;
}
}

resource_size_t
nv_device_resource_len(struct nouveau_device *device, unsigned int bar)
{
if (nv_device_is_pci(device)) {
return pci_resource_len(device->pdev, bar);
} else {
struct resource *res;
res = platform_get_resource(device->platformdev,
IORESOURCE_MEM, bar);
if (!res)
return 0;
return resource_size(res);
}
}

dma_addr_t
nv_device_map_page(struct nouveau_device *device, struct page *page)
{
dma_addr_t ret;

if (nv_device_is_pci(device)) {
ret = pci_map_page(device->pdev, page, 0, PAGE_SIZE,
PCI_DMA_BIDIRECTIONAL);
if (pci_dma_mapping_error(device->pdev, ret))
ret = 0;
} else {
ret = page_to_phys(page);
}

return ret;
}

void
nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr)
{
if (nv_device_is_pci(device))
pci_unmap_page(device->pdev, addr, PAGE_SIZE,
PCI_DMA_BIDIRECTIONAL);
}

int
nv_device_get_irq(struct nouveau_device *device, bool stall)
{
if (nv_device_is_pci(device)) {
return device->pdev->irq;
} else {
return platform_get_irq_byname(device->platformdev,
stall ? "stall" : "nonstall");
}
}

static struct nouveau_oclass
nouveau_device_oclass = {
.handle = NV_ENGINE(DEVICE, 0x00),
Expand All @@ -459,8 +525,8 @@ nouveau_device_oclass = {
};

int
nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname,
const char *cfg, const char *dbg,
nouveau_device_create_(void *dev, enum nv_bus_type type, u64 name,
const char *sname, const char *cfg, const char *dbg,
int length, void **pobject)
{
struct nouveau_device *device;
Expand All @@ -478,7 +544,14 @@ nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname,
if (ret)
goto done;

device->pdev = pdev;
switch (type) {
case NOUVEAU_BUS_PCI:
device->pdev = dev;
break;
case NOUVEAU_BUS_PLATFORM:
device->platformdev = dev;
break;
}
device->handle = name;
device->cfgopt = cfg;
device->dbgopt = dbg;
Expand Down
6 changes: 3 additions & 3 deletions drivers/gpu/drm/nouveau/core/engine/falcon.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03x",
device->chipset, falcon->addr >> 12);

ret = request_firmware(&fw, name, &device->pdev->dev);
ret = request_firmware(&fw, name, nv_device_base(device));
if (ret == 0) {
falcon->code.data = vmemdup(fw->data, fw->size);
falcon->code.size = fw->size;
Expand All @@ -138,7 +138,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03xd",
device->chipset, falcon->addr >> 12);

ret = request_firmware(&fw, name, &device->pdev->dev);
ret = request_firmware(&fw, name, nv_device_base(device));
if (ret) {
nv_error(falcon, "unable to load firmware data\n");
return ret;
Expand All @@ -153,7 +153,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03xc",
device->chipset, falcon->addr >> 12);

ret = request_firmware(&fw, name, &device->pdev->dev);
ret = request_firmware(&fw, name, nv_device_base(device));
if (ret) {
nv_error(falcon, "unable to load firmware code\n");
return ret;
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/core/engine/fifo/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,
}

/* map fifo control registers */
chan->user = ioremap(pci_resource_start(device->pdev, bar) + addr +
chan->user = ioremap(nv_device_resource_start(device, bar) + addr +
(chan->chid * size), size);
if (!chan->user)
return -EFAULT;
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ nv20_graph_init(struct nouveau_object *object)
nv_wr32(priv, NV10_PGRAPH_SURFACE, tmp);

/* begin RAM config */
vramsz = pci_resource_len(nv_device(priv)->pdev, 0) - 1;
vramsz = nv_device_resource_len(nv_device(priv), 0) - 1;
nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200));
nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204));
nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0000);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ nv40_graph_init(struct nouveau_object *object)
engine->tile_prog(engine, i);

/* begin RAM config */
vramsz = pci_resource_len(nv_device(priv)->pdev, 0) - 1;
vramsz = nv_device_resource_len(nv_device(priv), 0) - 1;
switch (nv_device(priv)->chipset) {
case 0x40:
nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200));
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
Original file line number Diff line number Diff line change
Expand Up @@ -1091,10 +1091,10 @@ nvc0_graph_ctor_fw(struct nvc0_graph_priv *priv, const char *fwname,
int ret;

snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname);
ret = request_firmware(&fw, f, &device->pdev->dev);
ret = request_firmware(&fw, f, nv_device_base(device));
if (ret) {
snprintf(f, sizeof(f), "nouveau/%s", fwname);
ret = request_firmware(&fw, f, &device->pdev->dev);
ret = request_firmware(&fw, f, nv_device_base(device));
if (ret) {
nv_error(priv, "failed to load %s\n", fwname);
return ret;
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/core/engine/xtensa.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ _nouveau_xtensa_init(struct nouveau_object *object)
snprintf(name, sizeof(name), "nouveau/nv84_xuc%03x",
xtensa->addr >> 12);

ret = request_firmware(&fw, name, &device->pdev->dev);
ret = request_firmware(&fw, name, nv_device_base(device));
if (ret) {
nv_warn(xtensa, "unable to load firmware %s\n", name);
return ret;
Expand Down
29 changes: 29 additions & 0 deletions drivers/gpu/drm/nouveau/core/include/core/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ struct nouveau_device {
struct list_head head;

struct pci_dev *pdev;
struct platform_device *platformdev;
u64 handle;

const char *cfgopt;
Expand Down Expand Up @@ -142,4 +143,32 @@ nv_device_match(struct nouveau_object *object, u16 dev, u16 ven, u16 sub)
device->pdev->subsystem_device == sub;
}

static inline bool
nv_device_is_pci(struct nouveau_device *device)
{
return device->pdev != NULL;
}

static inline struct device *
nv_device_base(struct nouveau_device *device)
{
return nv_device_is_pci(device) ? &device->pdev->dev :
&device->platformdev->dev;
}

resource_size_t
nv_device_resource_start(struct nouveau_device *device, unsigned int bar);

resource_size_t
nv_device_resource_len(struct nouveau_device *device, unsigned int bar);

dma_addr_t
nv_device_map_page(struct nouveau_device *device, struct page *page);

void
nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr);

int
nv_device_get_irq(struct nouveau_device *device, bool stall);

#endif
17 changes: 13 additions & 4 deletions drivers/gpu/drm/nouveau/core/include/engine/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,20 @@

#include <core/device.h>

#define nouveau_device_create(p,n,s,c,d,u) \
nouveau_device_create_((p), (n), (s), (c), (d), sizeof(**u), (void **)u)
struct platform_device;

int nouveau_device_create_(struct pci_dev *, u64 name, const char *sname,
const char *cfg, const char *dbg, int, void **);
enum nv_bus_type {
NOUVEAU_BUS_PCI,
NOUVEAU_BUS_PLATFORM,
};

#define nouveau_device_create(p,t,n,s,c,d,u) \
nouveau_device_create_((void *)(p), (t), (n), (s), (c), (d), \
sizeof(**u), (void **)u)

int nouveau_device_create_(void *, enum nv_bus_type type, u64 name,
const char *sname, const char *cfg, const char *dbg,
int, void **);

int nv04_identify(struct nouveau_device *);
int nv10_identify(struct nouveau_device *);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/core/include/subdev/mc.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct nouveau_mc_intr {
struct nouveau_mc {
struct nouveau_subdev base;
bool use_msi;
unsigned int irq;
};

static inline struct nouveau_mc *
Expand Down
12 changes: 1 addition & 11 deletions drivers/gpu/drm/nouveau/core/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/printk.h>
#include <linux/bitops.h>
#include <linux/firmware.h>
Expand All @@ -23,17 +24,6 @@

#include <asm/unaligned.h>

static inline int
ffsll(u64 mask)
{
int i;
for (i = 0; i < 64; i++) {
if (mask & (1ULL << i))
return i + 1;
}
return 0;
}

#ifndef ioread32_native
#ifdef __BIG_ENDIAN
#define ioread16_native ioread16be
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/nouveau/core/subdev/bar/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ nouveau_bar_create_(struct nouveau_object *parent,
if (ret)
return ret;

bar->iomem = ioremap(pci_resource_start(device->pdev, 3),
pci_resource_len(device->pdev, 3));
bar->iomem = ioremap(nv_device_resource_start(device, 3),
nv_device_resource_len(device, 3));
return 0;
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,

/* BAR3 */
start = 0x0100000000ULL;
limit = start + pci_resource_len(device->pdev, 3);
limit = start + nv_device_resource_len(device, 3);

ret = nouveau_vm_new(device, start, limit, start, &vm);
if (ret)
Expand Down Expand Up @@ -173,7 +173,7 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,

/* BAR1 */
start = 0x0000000000ULL;
limit = start + pci_resource_len(device->pdev, 1);
limit = start + nv_device_resource_len(device, 1);

ret = nouveau_vm_new(device, start, limit--, start, &vm);
if (ret)
Expand Down
15 changes: 7 additions & 8 deletions drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_object **pobject)
{
struct nouveau_device *device = nv_device(parent);
struct pci_dev *pdev = device->pdev;
struct nvc0_bar_priv *priv;
struct nouveau_gpuobj *mem;
struct nouveau_vm *vm;
Expand All @@ -107,14 +106,14 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret)
return ret;

ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 3), 0, &vm);
ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 3), 0, &vm);
if (ret)
return ret;

atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]);

ret = nouveau_gpuobj_new(nv_object(priv), NULL,
(pci_resource_len(pdev, 3) >> 12) * 8,
(nv_device_resource_len(device, 3) >> 12) * 8,
0x1000, NVOBJ_FLAG_ZERO_ALLOC,
&vm->pgt[0].obj[0]);
vm->pgt[0].refcount[0] = 1;
Expand All @@ -128,8 +127,8 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,

nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr));
nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr));
nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 3) - 1));
nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 3) - 1));
nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 3) - 1));
nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 3) - 1));

/* BAR1 */
ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0,
Expand All @@ -143,7 +142,7 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret)
return ret;

ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 1), 0, &vm);
ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 1), 0, &vm);
if (ret)
return ret;

Expand All @@ -156,8 +155,8 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,

nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr));
nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr));
nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 1) - 1));
nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 1) - 1));
nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 1) - 1));
nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 1) - 1));

priv->base.alloc = nouveau_bar_alloc;
priv->base.kmap = nvc0_bar_kmap;
Expand Down
8 changes: 5 additions & 3 deletions drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
*
*/

#include <core/device.h>

#define NV04_PFB_BOOT_0 0x00100000
# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003
# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000
Expand Down Expand Up @@ -60,10 +62,10 @@
# define NV10_PFB_REFCTRL_VALID_1 (1 << 31)

static inline struct io_mapping *
fbmem_init(struct pci_dev *pdev)
fbmem_init(struct nouveau_device *dev)
{
return io_mapping_create_wc(pci_resource_start(pdev, 1),
pci_resource_len(pdev, 1));
return io_mapping_create_wc(nv_device_resource_start(dev, 1),
nv_device_resource_len(dev, 1));
}

static inline void
Expand Down
Loading

0 comments on commit 420b946

Please sign in to comment.