Skip to content

Commit 420b946

Browse files
GnurouBen Skeggs
authored andcommitted
support for platform devices
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>
1 parent 0b68168 commit 420b946

File tree

35 files changed

+305
-127
lines changed

35 files changed

+305
-127
lines changed

drivers/gpu/drm/nouveau/core/engine/device/base.c

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
131131
if (ret)
132132
return ret;
133133

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

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

451+
resource_size_t
452+
nv_device_resource_start(struct nouveau_device *device, unsigned int bar)
453+
{
454+
if (nv_device_is_pci(device)) {
455+
return pci_resource_start(device->pdev, bar);
456+
} else {
457+
struct resource *res;
458+
res = platform_get_resource(device->platformdev,
459+
IORESOURCE_MEM, bar);
460+
if (!res)
461+
return 0;
462+
return res->start;
463+
}
464+
}
465+
466+
resource_size_t
467+
nv_device_resource_len(struct nouveau_device *device, unsigned int bar)
468+
{
469+
if (nv_device_is_pci(device)) {
470+
return pci_resource_len(device->pdev, bar);
471+
} else {
472+
struct resource *res;
473+
res = platform_get_resource(device->platformdev,
474+
IORESOURCE_MEM, bar);
475+
if (!res)
476+
return 0;
477+
return resource_size(res);
478+
}
479+
}
480+
481+
dma_addr_t
482+
nv_device_map_page(struct nouveau_device *device, struct page *page)
483+
{
484+
dma_addr_t ret;
485+
486+
if (nv_device_is_pci(device)) {
487+
ret = pci_map_page(device->pdev, page, 0, PAGE_SIZE,
488+
PCI_DMA_BIDIRECTIONAL);
489+
if (pci_dma_mapping_error(device->pdev, ret))
490+
ret = 0;
491+
} else {
492+
ret = page_to_phys(page);
493+
}
494+
495+
return ret;
496+
}
497+
498+
void
499+
nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr)
500+
{
501+
if (nv_device_is_pci(device))
502+
pci_unmap_page(device->pdev, addr, PAGE_SIZE,
503+
PCI_DMA_BIDIRECTIONAL);
504+
}
505+
506+
int
507+
nv_device_get_irq(struct nouveau_device *device, bool stall)
508+
{
509+
if (nv_device_is_pci(device)) {
510+
return device->pdev->irq;
511+
} else {
512+
return platform_get_irq_byname(device->platformdev,
513+
stall ? "stall" : "nonstall");
514+
}
515+
}
516+
451517
static struct nouveau_oclass
452518
nouveau_device_oclass = {
453519
.handle = NV_ENGINE(DEVICE, 0x00),
@@ -459,8 +525,8 @@ nouveau_device_oclass = {
459525
};
460526

461527
int
462-
nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname,
463-
const char *cfg, const char *dbg,
528+
nouveau_device_create_(void *dev, enum nv_bus_type type, u64 name,
529+
const char *sname, const char *cfg, const char *dbg,
464530
int length, void **pobject)
465531
{
466532
struct nouveau_device *device;
@@ -478,7 +544,14 @@ nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname,
478544
if (ret)
479545
goto done;
480546

481-
device->pdev = pdev;
547+
switch (type) {
548+
case NOUVEAU_BUS_PCI:
549+
device->pdev = dev;
550+
break;
551+
case NOUVEAU_BUS_PLATFORM:
552+
device->platformdev = dev;
553+
break;
554+
}
482555
device->handle = name;
483556
device->cfgopt = cfg;
484557
device->dbgopt = dbg;

drivers/gpu/drm/nouveau/core/engine/falcon.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
119119
snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03x",
120120
device->chipset, falcon->addr >> 12);
121121

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

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

156-
ret = request_firmware(&fw, name, &device->pdev->dev);
156+
ret = request_firmware(&fw, name, nv_device_base(device));
157157
if (ret) {
158158
nv_error(falcon, "unable to load firmware code\n");
159159
return ret;

drivers/gpu/drm/nouveau/core/engine/fifo/base.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,
8686
}
8787

8888
/* map fifo control registers */
89-
chan->user = ioremap(pci_resource_start(device->pdev, bar) + addr +
89+
chan->user = ioremap(nv_device_resource_start(device, bar) + addr +
9090
(chan->chid * size), size);
9191
if (!chan->user)
9292
return -EFAULT;

drivers/gpu/drm/nouveau/core/engine/graph/nv20.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ nv20_graph_init(struct nouveau_object *object)
349349
nv_wr32(priv, NV10_PGRAPH_SURFACE, tmp);
350350

351351
/* begin RAM config */
352-
vramsz = pci_resource_len(nv_device(priv)->pdev, 0) - 1;
352+
vramsz = nv_device_resource_len(nv_device(priv), 0) - 1;
353353
nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200));
354354
nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204));
355355
nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0000);

drivers/gpu/drm/nouveau/core/engine/graph/nv40.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ nv40_graph_init(struct nouveau_object *object)
484484
engine->tile_prog(engine, i);
485485

486486
/* begin RAM config */
487-
vramsz = pci_resource_len(nv_device(priv)->pdev, 0) - 1;
487+
vramsz = nv_device_resource_len(nv_device(priv), 0) - 1;
488488
switch (nv_device(priv)->chipset) {
489489
case 0x40:
490490
nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200));

drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,10 +1091,10 @@ nvc0_graph_ctor_fw(struct nvc0_graph_priv *priv, const char *fwname,
10911091
int ret;
10921092

10931093
snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname);
1094-
ret = request_firmware(&fw, f, &device->pdev->dev);
1094+
ret = request_firmware(&fw, f, nv_device_base(device));
10951095
if (ret) {
10961096
snprintf(f, sizeof(f), "nouveau/%s", fwname);
1097-
ret = request_firmware(&fw, f, &device->pdev->dev);
1097+
ret = request_firmware(&fw, f, nv_device_base(device));
10981098
if (ret) {
10991099
nv_error(priv, "failed to load %s\n", fwname);
11001100
return ret;

drivers/gpu/drm/nouveau/core/engine/xtensa.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ _nouveau_xtensa_init(struct nouveau_object *object)
112112
snprintf(name, sizeof(name), "nouveau/nv84_xuc%03x",
113113
xtensa->addr >> 12);
114114

115-
ret = request_firmware(&fw, name, &device->pdev->dev);
115+
ret = request_firmware(&fw, name, nv_device_base(device));
116116
if (ret) {
117117
nv_warn(xtensa, "unable to load firmware %s\n", name);
118118
return ret;

drivers/gpu/drm/nouveau/core/include/core/device.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ struct nouveau_device {
6666
struct list_head head;
6767

6868
struct pci_dev *pdev;
69+
struct platform_device *platformdev;
6970
u64 handle;
7071

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

146+
static inline bool
147+
nv_device_is_pci(struct nouveau_device *device)
148+
{
149+
return device->pdev != NULL;
150+
}
151+
152+
static inline struct device *
153+
nv_device_base(struct nouveau_device *device)
154+
{
155+
return nv_device_is_pci(device) ? &device->pdev->dev :
156+
&device->platformdev->dev;
157+
}
158+
159+
resource_size_t
160+
nv_device_resource_start(struct nouveau_device *device, unsigned int bar);
161+
162+
resource_size_t
163+
nv_device_resource_len(struct nouveau_device *device, unsigned int bar);
164+
165+
dma_addr_t
166+
nv_device_map_page(struct nouveau_device *device, struct page *page);
167+
168+
void
169+
nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr);
170+
171+
int
172+
nv_device_get_irq(struct nouveau_device *device, bool stall);
173+
145174
#endif

drivers/gpu/drm/nouveau/core/include/engine/device.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,20 @@
33

44
#include <core/device.h>
55

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

9-
int nouveau_device_create_(struct pci_dev *, u64 name, const char *sname,
10-
const char *cfg, const char *dbg, int, void **);
8+
enum nv_bus_type {
9+
NOUVEAU_BUS_PCI,
10+
NOUVEAU_BUS_PLATFORM,
11+
};
12+
13+
#define nouveau_device_create(p,t,n,s,c,d,u) \
14+
nouveau_device_create_((void *)(p), (t), (n), (s), (c), (d), \
15+
sizeof(**u), (void **)u)
16+
17+
int nouveau_device_create_(void *, enum nv_bus_type type, u64 name,
18+
const char *sname, const char *cfg, const char *dbg,
19+
int, void **);
1120

1221
int nv04_identify(struct nouveau_device *);
1322
int nv10_identify(struct nouveau_device *);

drivers/gpu/drm/nouveau/core/include/subdev/mc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ struct nouveau_mc_intr {
1212
struct nouveau_mc {
1313
struct nouveau_subdev base;
1414
bool use_msi;
15+
unsigned int irq;
1516
};
1617

1718
static inline struct nouveau_mc *

0 commit comments

Comments
 (0)