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;
        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),
 };
 
 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;
        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;
 
                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;
                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;
                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;
 
        }
 
        /* 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;
 
        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);
 
                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));
 
        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;
 
                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;
 
        struct list_head head;
 
        struct pci_dev *pdev;
+       struct platform_device *platformdev;
        u64 handle;
 
        const char *cfgopt;
               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
 
 
 #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 *);
 
 struct nouveau_mc {
        struct nouveau_subdev base;
        bool use_msi;
+       unsigned int irq;
 };
 
 static inline struct nouveau_mc *
 
 #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>
 
 #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
 
        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;
 }
 
 
 
        /* 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)
 
        /* 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)
 
              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;
        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;
 
        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,
        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;
 
 
        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;
 
  *
  */
 
+#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
 #      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
 
        int i;
 
        /* Map the framebuffer aperture */
-       fb = fbmem_init(nv_device(priv)->pdev);
+       fb = fbmem_init(nv_device(priv));
        if (!fb) {
                nv_error(priv, "failed to map fb\n");
                return;
 
        int i, v;
 
        /* Map the framebuffer aperture */
-       fb = fbmem_init(nv_device(priv)->pdev);
+       fb = fbmem_init(nv_device(priv));
        if (!fb) {
                nv_error(priv, "failed to map fb\n");
                return;
 
                mem_width_count = 2;
 
        /* Map the framebuffer aperture */
-       fb = fbmem_init(nv_device(priv)->pdev);
+       fb = fbmem_init(nv_device(priv));
        if (!fb) {
                nv_error(priv, "failed to map fb\n");
                return;
 
        struct io_mapping *fb;
 
        /* Map the framebuffer aperture */
-       fb = fbmem_init(nv_device(priv)->pdev);
+       fb = fbmem_init(nv_device(priv));
        if (!fb) {
                nv_error(priv, "failed to map fb\n");
                return;
 
 
        priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
        if (priv->r100c08_page) {
-               priv->r100c08 = pci_map_page(device->pdev, priv->r100c08_page,
-                                            0, PAGE_SIZE,
-                                            PCI_DMA_BIDIRECTIONAL);
-               if (pci_dma_mapping_error(device->pdev, priv->r100c08))
+               priv->r100c08 = nv_device_map_page(device, priv->r100c08_page);
+               if (!priv->r100c08)
                        nv_warn(priv, "failed 0x100c08 page map\n");
        } else {
                nv_warn(priv, "failed 0x100c08 page alloc\n");
        struct nv50_fb_priv *priv = (void *)object;
 
        if (priv->r100c08_page) {
-               pci_unmap_page(device->pdev, priv->r100c08, PAGE_SIZE,
-                              PCI_DMA_BIDIRECTIONAL);
+               nv_device_unmap_page(device, priv->r100c08);
                __free_page(priv->r100c08_page);
        }
 
 
        struct nvc0_fb_priv *priv = (void *)object;
 
        if (priv->r100c10_page) {
-               pci_unmap_page(device->pdev, priv->r100c10, PAGE_SIZE,
-                              PCI_DMA_BIDIRECTIONAL);
+               nv_device_unmap_page(device, priv->r100c10);
                __free_page(priv->r100c10_page);
        }
 
 
        priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
        if (priv->r100c10_page) {
-               priv->r100c10 = pci_map_page(device->pdev, priv->r100c10_page,
-                                            0, PAGE_SIZE,
-                                            PCI_DMA_BIDIRECTIONAL);
-               if (pci_dma_mapping_error(device->pdev, priv->r100c10))
+               priv->r100c10 = nv_device_map_page(device, priv->r100c10_page);
+               if (!priv->r100c10)
                        return -EFAULT;
        }
 
 
        snprintf(port->adapter.name, sizeof(port->adapter.name),
                 "nouveau-%s-%d", device->name, index);
        port->adapter.owner = THIS_MODULE;
-       port->adapter.dev.parent = &device->pdev->dev;
+       port->adapter.dev.parent = nv_device_base(device);
        port->index = index;
        port->func = func;
        i2c_set_adapdata(&port->adapter, i2c);
 
                  struct nouveau_object **pobject)
 {
        struct nouveau_device *device = nv_device(parent);
-       struct pci_dev *pdev = device->pdev;
        struct nv04_instmem_priv *priv;
        int ret, bar, vs;
 
                return ret;
 
        /* map bar */
-       if (pci_resource_len(pdev, 2))
+       if (nv_device_resource_len(device, 2))
                bar = 2;
        else
                bar = 3;
 
-       priv->iomem = ioremap(pci_resource_start(pdev, bar),
-                             pci_resource_len(pdev, bar));
+       priv->iomem = ioremap(nv_device_resource_start(device, bar),
+                             nv_device_resource_len(device, bar));
        if (!priv->iomem) {
                nv_error(priv, "unable to map PRAMIN BAR\n");
                return -EFAULT;
 
 {
        struct nouveau_device *device = nv_device(object);
        struct nouveau_mc *pmc = (void *)object;
-       free_irq(device->pdev->irq, pmc);
+       free_irq(pmc->irq, pmc);
        if (pmc->use_msi)
                pci_disable_msi(device->pdev);
        nouveau_subdev_destroy(&pmc->base);
        if (ret)
                return ret;
 
-       switch (device->pdev->device & 0x0ff0) {
-       case 0x00f0:
-       case 0x02e0:
-               /* BR02? NFI how these would be handled yet exactly */
-               break;
-       default:
-               switch (device->chipset) {
-               case 0xaa: break; /* reported broken, nv also disable it */
-               default:
-                       pmc->use_msi = true;
+       if (nv_device_is_pci(device))
+               switch (device->pdev->device & 0x0ff0) {
+               case 0x00f0:
+               case 0x02e0:
+                       /* BR02? NFI how these would be handled yet exactly */
                        break;
+               default:
+                       switch (device->chipset) {
+                       case 0xaa:
+                               /* reported broken, nv also disable it */
+                               break;
+                       default:
+                               pmc->use_msi = true;
+                               break;
                }
-       }
 
-       pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI", pmc->use_msi);
-       if (pmc->use_msi && oclass->msi_rearm) {
-               pmc->use_msi = pci_enable_msi(device->pdev) == 0;
-               if (pmc->use_msi) {
-                       nv_info(pmc, "MSI interrupts enabled\n");
-                       oclass->msi_rearm(pmc);
+               pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI",
+                                              pmc->use_msi);
+
+               if (pmc->use_msi && oclass->msi_rearm) {
+                       pmc->use_msi = pci_enable_msi(device->pdev) == 0;
+                       if (pmc->use_msi) {
+                               nv_info(pmc, "MSI interrupts enabled\n");
+                               oclass->msi_rearm(pmc);
+                       }
+               } else {
+                       pmc->use_msi = false;
                }
-       } else {
-               pmc->use_msi = false;
        }
 
-       ret = request_irq(device->pdev->irq, nouveau_mc_intr,
-                         IRQF_SHARED, "nouveau", pmc);
+       ret = nv_device_get_irq(device, true);
+       if (ret < 0)
+               return ret;
+       pmc->irq = ret;
+
+       ret = request_irq(pmc->irq, nouveau_mc_intr, IRQF_SHARED, "nouveau",
+                         pmc);
+
        if (ret < 0)
                return ret;
 
 
        acpi_handle handle;
        int rev;
 
-       handle = ACPI_HANDLE(&device->pdev->dev);
+       handle = ACPI_HANDLE(nv_device_base(device));
        if (!handle)
                return false;
 
 
                getparam->value = device->chipset;
                break;
        case NOUVEAU_GETPARAM_PCI_VENDOR:
-               getparam->value = dev->pdev->vendor;
+               if (nv_device_is_pci(device))
+                       getparam->value = dev->pdev->vendor;
+               else
+                       getparam->value = 0;
                break;
        case NOUVEAU_GETPARAM_PCI_DEVICE:
-               getparam->value = dev->pdev->device;
+               if (nv_device_is_pci(device))
+                       getparam->value = dev->pdev->device;
+               else
+                       getparam->value = 0;
                break;
        case NOUVEAU_GETPARAM_BUS_TYPE:
+               if (!nv_device_is_pci(device))
+                       getparam->value = 3;
+               else
                if (drm_pci_device_is_agp(dev))
                        getparam->value = 0;
                else
 
 {
        struct drm_device *dev = drm->dev;
 
-       if (!drm_pci_device_is_agp(dev) || !dev->agp)
+       if (!dev->pdev || !drm_pci_device_is_agp(dev) || !dev->agp)
                return false;
 
        if (drm->agp.stat == UNKNOWN) {
 
        struct nvbios *bios = &drm->vbios;
        int ret;
 
+       /* only relevant for PCI devices */
+       if (!dev->pdev)
+               return 0;
+
        if (!NVInitVBIOS(dev))
                return -ENODEV;
 
 
                /* fallthrough, tiled memory */
        case TTM_PL_VRAM:
                mem->bus.offset = mem->start << PAGE_SHIFT;
-               mem->bus.base = pci_resource_start(dev->pdev, 1);
+               mem->bus.base = nv_device_resource_start(nouveau_dev(dev), 1);
                mem->bus.is_iomem = true;
                if (nv_device(drm->device)->card_type >= NV_50) {
                        struct nouveau_bar *bar = nouveau_bar(drm->device);
        struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
        struct nouveau_bo *nvbo = nouveau_bo(bo);
        struct nouveau_device *device = nv_device(drm->device);
-       u32 mappable = pci_resource_len(device->pdev, 1) >> PAGE_SHIFT;
+       u32 mappable = nv_device_resource_len(device, 1) >> PAGE_SHIFT;
        int ret;
 
        /* as long as the bo isn't in vram, and isn't tiled, we've got
 {
        struct ttm_dma_tt *ttm_dma = (void *)ttm;
        struct nouveau_drm *drm;
+       struct nouveau_device *device;
        struct drm_device *dev;
        unsigned i;
        int r;
        }
 
        drm = nouveau_bdev(ttm->bdev);
+       device = nv_device(drm->device);
        dev = drm->dev;
 
 #if __OS_HAS_AGP
        }
 
        for (i = 0; i < ttm->num_pages; i++) {
-               ttm_dma->dma_address[i] = pci_map_page(dev->pdev, ttm->pages[i],
-                                                  0, PAGE_SIZE,
-                                                  PCI_DMA_BIDIRECTIONAL);
-               if (pci_dma_mapping_error(dev->pdev, ttm_dma->dma_address[i])) {
+               ttm_dma->dma_address[i] = nv_device_map_page(device,
+                                                            ttm->pages[i]);
+               if (!ttm_dma->dma_address[i]) {
                        while (--i) {
-                               pci_unmap_page(dev->pdev, ttm_dma->dma_address[i],
-                                              PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+                               nv_device_unmap_page(device,
+                                                    ttm_dma->dma_address[i]);
                                ttm_dma->dma_address[i] = 0;
                        }
                        ttm_pool_unpopulate(ttm);
 {
        struct ttm_dma_tt *ttm_dma = (void *)ttm;
        struct nouveau_drm *drm;
+       struct nouveau_device *device;
        struct drm_device *dev;
        unsigned i;
        bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
                return;
 
        drm = nouveau_bdev(ttm->bdev);
+       device = nv_device(drm->device);
        dev = drm->dev;
 
 #if __OS_HAS_AGP
 
        for (i = 0; i < ttm->num_pages; i++) {
                if (ttm_dma->dma_address[i]) {
-                       pci_unmap_page(dev->pdev, ttm_dma->dma_address[i],
-                                      PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+                       nv_device_unmap_page(device, ttm_dma->dma_address[i]);
                }
        }
 
 
                         * nfi why this exists, it came from the -nv ddx.
                         */
                        args.flags = NV_DMA_TARGET_PCI | NV_DMA_ACCESS_RDWR;
-                       args.start = pci_resource_start(device->pdev, 1);
+                       args.start = nv_device_resource_start(device, 1);
                        args.limit = args.start + limit;
                } else {
                        args.flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR;
 
 nouveau_display_create(struct drm_device *dev)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
+       struct nouveau_device *device = nouveau_dev(dev);
        struct nouveau_display *disp;
        int ret, gen;
 
        }
 
        dev->mode_config.funcs = &nouveau_mode_config_funcs;
-       dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1);
+       dev->mode_config.fb_base = nv_device_resource_start(device, 1);
 
        dev->mode_config.min_width = 0;
        dev->mode_config.min_height = 0;
 
 static struct drm_driver driver;
 
 static u64
-nouveau_name(struct pci_dev *pdev)
+nouveau_pci_name(struct pci_dev *pdev)
 {
        u64 name = (u64)pci_domain_nr(pdev->bus) << 32;
        name |= pdev->bus->number << 16;
        return name | PCI_FUNC(pdev->devfn);
 }
 
+static u64
+nouveau_platform_name(struct platform_device *platformdev)
+{
+       return platformdev->id;
+}
+
+static u64
+nouveau_name(struct drm_device *dev)
+{
+       if (dev->pdev)
+               return nouveau_pci_name(dev->pdev);
+       else
+               return nouveau_platform_name(dev->platformdev);
+}
+
 static int
-nouveau_cli_create(struct pci_dev *pdev, const char *name,
+nouveau_cli_create(u64 name, const char *sname,
                   int size, void **pcli)
 {
        struct nouveau_cli *cli;
        int ret;
 
        *pcli = NULL;
-       ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config,
+       ret = nouveau_client_create_(sname, name, nouveau_config,
                                     nouveau_debug, size, pcli);
        cli = *pcli;
        if (ret) {
        remove_conflicting_framebuffers(aper, "nouveaufb", boot);
        kfree(aper);
 
-       ret = nouveau_device_create(pdev, nouveau_name(pdev), pci_name(pdev),
+       ret = nouveau_device_create(pdev, NOUVEAU_BUS_PCI,
+                                   nouveau_pci_name(pdev), pci_name(pdev),
                                    nouveau_config, nouveau_debug, &device);
        if (ret)
                return ret;
 {
        struct pci_dev *pdev = drm->dev->pdev;
 
+       if (!pdev) {
+               DRM_INFO("not a PCI device; no HDMI");
+               drm->hdmi_device = NULL;
+               return;
+       }
+
        /* subfunction one is a hdmi audio device? */
        drm->hdmi_device = pci_get_bus_and_slot((unsigned int)pdev->bus->number,
                                                PCI_DEVFN(PCI_SLOT(pdev->devfn), 1));
        struct nouveau_drm *drm;
        int ret;
 
-       ret = nouveau_cli_create(pdev, "DRM", sizeof(*drm), (void**)&drm);
+       ret = nouveau_cli_create(nouveau_name(dev), "DRM", sizeof(*drm),
+                                (void **)&drm);
        if (ret)
                return ret;
 
        /* make sure AGP controller is in a consistent state before we
         * (possibly) execute vbios init tables (see nouveau_agp.h)
         */
-       if (drm_pci_device_is_agp(dev) && dev->agp) {
+       if (pdev && drm_pci_device_is_agp(dev) && dev->agp) {
                /* dummy device object, doesn't init anything, but allows
                 * agp code access to registers
                 */
 static int
 nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
 {
-       struct pci_dev *pdev = dev->pdev;
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_cli *cli;
        char name[32], tmpname[TASK_COMM_LEN];
        get_task_comm(tmpname, current);
        snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid));
 
-       ret = nouveau_cli_create(pdev, name, sizeof(*cli), (void **)&cli);
+       ret = nouveau_cli_create(nouveau_name(dev), name, sizeof(*cli),
+                       (void **)&cli);
+
        if (ret)
                goto out_suspend;
 
        .driver.pm = &nouveau_pm_ops,
 };
 
+int nouveau_drm_platform_probe(struct platform_device *pdev)
+{
+       struct nouveau_device *device;
+       int ret;
+
+       ret = nouveau_device_create(pdev, NOUVEAU_BUS_PLATFORM,
+                                   nouveau_platform_name(pdev),
+                                   dev_name(&pdev->dev), nouveau_config,
+                                   nouveau_debug, &device);
+
+       ret = drm_platform_init(&driver, pdev);
+       if (ret) {
+               nouveau_object_ref(NULL, (struct nouveau_object **)&device);
+               return ret;
+       }
+
+       return ret;
+}
+
 static int __init
 nouveau_drm_init(void)
 {
 
 static inline struct drm_device *
 drm_device(struct device *d)
 {
-       return pci_get_drvdata(to_pci_dev(d));
+       return dev_get_drvdata(d);
 }
 
 #define snappendf(p,r,f,a...) do {                                             \
 {
        struct nouveau_sysfs *sysfs = nouveau_sysfs(dev);
        struct nouveau_drm *drm = nouveau_drm(dev);
+       struct nouveau_device *device = nv_device(drm->device);
 
        if (sysfs->ctrl) {
-               device_remove_file(&dev->pdev->dev, &dev_attr_pstate);
+               device_remove_file(nv_device_base(device), &dev_attr_pstate);
                nouveau_object_del(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL);
        }
 
 nouveau_sysfs_init(struct drm_device *dev)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
+       struct nouveau_device *device = nv_device(drm->device);
        struct nouveau_sysfs *sysfs;
        int ret;
 
        ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL,
                                 NV_CONTROL_CLASS, NULL, 0, &sysfs->ctrl);
        if (ret == 0)
-               device_create_file(&dev->pdev->dev, &dev_attr_pstate);
+               device_create_file(nv_device_base(device), &dev_attr_pstate);
 
        return 0;
 }
 
 nouveau_ttm_init(struct nouveau_drm *drm)
 {
        struct drm_device *dev = drm->dev;
+       struct nouveau_device *device = nv_device(drm->device);
        u32 bits;
        int ret;
 
        bits = nouveau_vmmgr(drm->device)->dma_bits;
-       if ( drm->agp.stat == ENABLED ||
-           !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits)))
-               bits = 32;
-
-       ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits));
-       if (ret)
-               return ret;
-
-       ret = pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(bits));
-       if (ret)
-               pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(32));
+       if (nv_device_is_pci(device)) {
+               if (drm->agp.stat == ENABLED ||
+                    !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits)))
+                       bits = 32;
+
+               ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits));
+               if (ret)
+                       return ret;
+
+               ret = pci_set_consistent_dma_mask(dev->pdev,
+                                                 DMA_BIT_MASK(bits));
+               if (ret)
+                       pci_set_consistent_dma_mask(dev->pdev,
+                                                   DMA_BIT_MASK(32));
+       }
 
        ret = nouveau_ttm_global_init(drm);
        if (ret)
                return ret;
        }
 
-       drm->ttm.mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 1),
-                                        pci_resource_len(dev->pdev, 1));
+       drm->ttm.mtrr = arch_phys_wc_add(nv_device_resource_start(device, 1),
+                                        nv_device_resource_len(device, 1));
 
        /* GART init */
        if (drm->agp.stat != ENABLED) {
 
 {
        struct drm_device *dev = drm->dev;
        bool runtime = false;
+
+       /* only relevant for PCI devices */
+       if (!dev->pdev)
+               return;
+
        vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
 
        if (nouveau_runtime_pm == 1)