These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / nouveau / nvkm / engine / device / base.c
index 63d8e52..bbc9824 100644 (file)
 #include "priv.h"
 #include "acpi.h"
 
-#include <core/client.h>
-#include <core/option.h>
 #include <core/notify.h>
-#include <core/parent.h>
-#include <subdev/bios.h>
-#include <subdev/fb.h>
-#include <subdev/instmem.h>
+#include <core/option.h>
 
-#include <nvif/class.h>
-#include <nvif/unpack.h>
+#include <subdev/bios.h>
 
 static DEFINE_MUTEX(nv_devices_mutex);
 static LIST_HEAD(nv_devices);
 
-struct nvkm_device *
-nvkm_device_find(u64 name)
+static struct nvkm_device *
+nvkm_device_find_locked(u64 handle)
 {
-       struct nvkm_device *device, *match = NULL;
-       mutex_lock(&nv_devices_mutex);
+       struct nvkm_device *device;
        list_for_each_entry(device, &nv_devices, head) {
-               if (device->handle == name) {
-                       match = device;
-                       break;
-               }
+               if (device->handle == handle)
+                       return device;
        }
+       return NULL;
+}
+
+struct nvkm_device *
+nvkm_device_find(u64 handle)
+{
+       struct nvkm_device *device;
+       mutex_lock(&nv_devices_mutex);
+       device = nvkm_device_find_locked(handle);
        mutex_unlock(&nv_devices_mutex);
-       return match;
+       return device;
 }
 
 int
@@ -67,280 +67,2275 @@ nvkm_device_list(u64 *name, int size)
        return nr;
 }
 
-/******************************************************************************
- * nvkm_devobj (0x0080): class implementation
- *****************************************************************************/
+static const struct nvkm_device_chip
+null_chipset = {
+       .name = "NULL",
+       .bios = nvkm_bios_new,
+};
+
+static const struct nvkm_device_chip
+nv4_chipset = {
+       .name = "NV04",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv04_devinit_new,
+       .fb = nv04_fb_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv04_fifo_new,
+       .gr = nv04_gr_new,
+       .sw = nv04_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv5_chipset = {
+       .name = "NV05",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv05_devinit_new,
+       .fb = nv04_fb_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv04_fifo_new,
+       .gr = nv04_gr_new,
+       .sw = nv04_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv10_chipset = {
+       .name = "NV10",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv10_devinit_new,
+       .fb = nv10_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .gr = nv10_gr_new,
+};
+
+static const struct nvkm_device_chip
+nv11_chipset = {
+       .name = "NV11",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv10_devinit_new,
+       .fb = nv10_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv10_fifo_new,
+       .gr = nv15_gr_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv15_chipset = {
+       .name = "NV15",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv10_devinit_new,
+       .fb = nv10_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv10_fifo_new,
+       .gr = nv15_gr_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv17_chipset = {
+       .name = "NV17",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv10_devinit_new,
+       .fb = nv10_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv17_fifo_new,
+       .gr = nv17_gr_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv18_chipset = {
+       .name = "NV18",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv10_devinit_new,
+       .fb = nv10_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv17_fifo_new,
+       .gr = nv17_gr_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv1a_chipset = {
+       .name = "nForce",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv1a_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv10_fifo_new,
+       .gr = nv15_gr_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv1f_chipset = {
+       .name = "nForce2",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv1a_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv17_fifo_new,
+       .gr = nv17_gr_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv20_chipset = {
+       .name = "NV20",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv20_devinit_new,
+       .fb = nv20_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv17_fifo_new,
+       .gr = nv20_gr_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv25_chipset = {
+       .name = "NV25",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv20_devinit_new,
+       .fb = nv25_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv17_fifo_new,
+       .gr = nv25_gr_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv28_chipset = {
+       .name = "NV28",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv20_devinit_new,
+       .fb = nv25_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv17_fifo_new,
+       .gr = nv25_gr_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv2a_chipset = {
+       .name = "NV2A",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv20_devinit_new,
+       .fb = nv25_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv17_fifo_new,
+       .gr = nv2a_gr_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv30_chipset = {
+       .name = "NV30",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv20_devinit_new,
+       .fb = nv30_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv17_fifo_new,
+       .gr = nv30_gr_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv31_chipset = {
+       .name = "NV31",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv20_devinit_new,
+       .fb = nv30_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv17_fifo_new,
+       .gr = nv30_gr_new,
+       .mpeg = nv31_mpeg_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv34_chipset = {
+       .name = "NV34",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv10_devinit_new,
+       .fb = nv10_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv17_fifo_new,
+       .gr = nv34_gr_new,
+       .mpeg = nv31_mpeg_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv35_chipset = {
+       .name = "NV35",
+       .bios = nvkm_bios_new,
+       .bus = nv04_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv20_devinit_new,
+       .fb = nv35_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv17_fifo_new,
+       .gr = nv35_gr_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv36_chipset = {
+       .name = "NV36",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv04_clk_new,
+       .devinit = nv20_devinit_new,
+       .fb = nv36_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv04_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv04_pci_new,
+       .timer = nv04_timer_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv17_fifo_new,
+       .gr = nv35_gr_new,
+       .mpeg = nv31_mpeg_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv40_chipset = {
+       .name = "NV40",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv40_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv40_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv40_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv40_gr_new,
+       .mpeg = nv40_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv41_chipset = {
+       .name = "NV41",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv41_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv41_mmu_new,
+       .pci = nv40_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv40_gr_new,
+       .mpeg = nv40_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv42_chipset = {
+       .name = "NV42",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv41_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv41_mmu_new,
+       .pci = nv40_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv40_gr_new,
+       .mpeg = nv40_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv43_chipset = {
+       .name = "NV43",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv41_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv41_mmu_new,
+       .pci = nv40_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv40_gr_new,
+       .mpeg = nv40_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv44_chipset = {
+       .name = "NV44",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv44_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv44_mc_new,
+       .mmu = nv44_mmu_new,
+       .pci = nv40_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv44_gr_new,
+       .mpeg = nv44_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv45_chipset = {
+       .name = "NV45",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv40_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv04_mmu_new,
+       .pci = nv40_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv40_gr_new,
+       .mpeg = nv44_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv46_chipset = {
+       .name = "G72",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv46_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv44_mc_new,
+       .mmu = nv44_mmu_new,
+       .pci = nv46_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv44_gr_new,
+       .mpeg = nv44_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv47_chipset = {
+       .name = "G70",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv47_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv41_mmu_new,
+       .pci = nv40_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv40_gr_new,
+       .mpeg = nv44_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv49_chipset = {
+       .name = "G71",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv49_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv41_mmu_new,
+       .pci = nv40_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv40_gr_new,
+       .mpeg = nv44_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv4a_chipset = {
+       .name = "NV44A",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv44_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv44_mc_new,
+       .mmu = nv44_mmu_new,
+       .pci = nv40_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv44_gr_new,
+       .mpeg = nv44_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv4b_chipset = {
+       .name = "G73",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv49_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv04_mc_new,
+       .mmu = nv41_mmu_new,
+       .pci = nv40_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv40_gr_new,
+       .mpeg = nv44_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv4c_chipset = {
+       .name = "C61",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv46_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv44_mc_new,
+       .mmu = nv44_mmu_new,
+       .pci = nv4c_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv44_gr_new,
+       .mpeg = nv44_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv4e_chipset = {
+       .name = "C51",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv4e_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv4e_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv44_mc_new,
+       .mmu = nv44_mmu_new,
+       .pci = nv4c_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv44_gr_new,
+       .mpeg = nv44_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv50_chipset = {
+       .name = "G80",
+       .bar = nv50_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = nv50_bus_new,
+       .clk = nv50_clk_new,
+       .devinit = nv50_devinit_new,
+       .fb = nv50_fb_new,
+       .fuse = nv50_fuse_new,
+       .gpio = nv50_gpio_new,
+       .i2c = nv50_i2c_new,
+       .imem = nv50_instmem_new,
+       .mc = nv50_mc_new,
+       .mmu = nv50_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = nv46_pci_new,
+       .therm = nv50_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv50_disp_new,
+       .dma = nv50_dma_new,
+       .fifo = nv50_fifo_new,
+       .gr = nv50_gr_new,
+       .mpeg = nv50_mpeg_new,
+       .pm = nv50_pm_new,
+       .sw = nv50_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv63_chipset = {
+       .name = "C73",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv46_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv44_mc_new,
+       .mmu = nv44_mmu_new,
+       .pci = nv4c_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv44_gr_new,
+       .mpeg = nv44_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv67_chipset = {
+       .name = "C67",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv46_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv44_mc_new,
+       .mmu = nv44_mmu_new,
+       .pci = nv4c_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv44_gr_new,
+       .mpeg = nv44_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv68_chipset = {
+       .name = "C68",
+       .bios = nvkm_bios_new,
+       .bus = nv31_bus_new,
+       .clk = nv40_clk_new,
+       .devinit = nv1a_devinit_new,
+       .fb = nv46_fb_new,
+       .gpio = nv10_gpio_new,
+       .i2c = nv04_i2c_new,
+       .imem = nv40_instmem_new,
+       .mc = nv44_mc_new,
+       .mmu = nv44_mmu_new,
+       .pci = nv4c_pci_new,
+       .therm = nv40_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = nv04_disp_new,
+       .dma = nv04_dma_new,
+       .fifo = nv40_fifo_new,
+       .gr = nv44_gr_new,
+       .mpeg = nv44_mpeg_new,
+       .pm = nv40_pm_new,
+       .sw = nv10_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv84_chipset = {
+       .name = "G84",
+       .bar = g84_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = nv50_bus_new,
+       .clk = g84_clk_new,
+       .devinit = g84_devinit_new,
+       .fb = g84_fb_new,
+       .fuse = nv50_fuse_new,
+       .gpio = nv50_gpio_new,
+       .i2c = nv50_i2c_new,
+       .imem = nv50_instmem_new,
+       .mc = nv50_mc_new,
+       .mmu = nv50_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g84_pci_new,
+       .therm = g84_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .bsp = g84_bsp_new,
+       .cipher = g84_cipher_new,
+       .disp = g84_disp_new,
+       .dma = nv50_dma_new,
+       .fifo = g84_fifo_new,
+       .gr = g84_gr_new,
+       .mpeg = g84_mpeg_new,
+       .pm = g84_pm_new,
+       .sw = nv50_sw_new,
+       .vp = g84_vp_new,
+};
+
+static const struct nvkm_device_chip
+nv86_chipset = {
+       .name = "G86",
+       .bar = g84_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = nv50_bus_new,
+       .clk = g84_clk_new,
+       .devinit = g84_devinit_new,
+       .fb = g84_fb_new,
+       .fuse = nv50_fuse_new,
+       .gpio = nv50_gpio_new,
+       .i2c = nv50_i2c_new,
+       .imem = nv50_instmem_new,
+       .mc = nv50_mc_new,
+       .mmu = nv50_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g84_pci_new,
+       .therm = g84_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .bsp = g84_bsp_new,
+       .cipher = g84_cipher_new,
+       .disp = g84_disp_new,
+       .dma = nv50_dma_new,
+       .fifo = g84_fifo_new,
+       .gr = g84_gr_new,
+       .mpeg = g84_mpeg_new,
+       .pm = g84_pm_new,
+       .sw = nv50_sw_new,
+       .vp = g84_vp_new,
+};
+
+static const struct nvkm_device_chip
+nv92_chipset = {
+       .name = "G92",
+       .bar = g84_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = nv50_bus_new,
+       .clk = g84_clk_new,
+       .devinit = g84_devinit_new,
+       .fb = g84_fb_new,
+       .fuse = nv50_fuse_new,
+       .gpio = nv50_gpio_new,
+       .i2c = nv50_i2c_new,
+       .imem = nv50_instmem_new,
+       .mc = nv50_mc_new,
+       .mmu = nv50_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g84_pci_new,
+       .therm = g84_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .bsp = g84_bsp_new,
+       .cipher = g84_cipher_new,
+       .disp = g84_disp_new,
+       .dma = nv50_dma_new,
+       .fifo = g84_fifo_new,
+       .gr = g84_gr_new,
+       .mpeg = g84_mpeg_new,
+       .pm = g84_pm_new,
+       .sw = nv50_sw_new,
+       .vp = g84_vp_new,
+};
+
+static const struct nvkm_device_chip
+nv94_chipset = {
+       .name = "G94",
+       .bar = g84_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = g94_bus_new,
+       .clk = g84_clk_new,
+       .devinit = g84_devinit_new,
+       .fb = g84_fb_new,
+       .fuse = nv50_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .imem = nv50_instmem_new,
+       .mc = nv50_mc_new,
+       .mmu = nv50_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .therm = g84_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .bsp = g84_bsp_new,
+       .cipher = g84_cipher_new,
+       .disp = g94_disp_new,
+       .dma = nv50_dma_new,
+       .fifo = g84_fifo_new,
+       .gr = g84_gr_new,
+       .mpeg = g84_mpeg_new,
+       .pm = g84_pm_new,
+       .sw = nv50_sw_new,
+       .vp = g84_vp_new,
+};
+
+static const struct nvkm_device_chip
+nv96_chipset = {
+       .name = "G96",
+       .bar = g84_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = g94_bus_new,
+       .clk = g84_clk_new,
+       .devinit = g84_devinit_new,
+       .fb = g84_fb_new,
+       .fuse = nv50_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .imem = nv50_instmem_new,
+       .mc = nv50_mc_new,
+       .mmu = nv50_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .therm = g84_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .bsp = g84_bsp_new,
+       .cipher = g84_cipher_new,
+       .disp = g94_disp_new,
+       .dma = nv50_dma_new,
+       .fifo = g84_fifo_new,
+       .gr = g84_gr_new,
+       .mpeg = g84_mpeg_new,
+       .pm = g84_pm_new,
+       .sw = nv50_sw_new,
+       .vp = g84_vp_new,
+};
+
+static const struct nvkm_device_chip
+nv98_chipset = {
+       .name = "G98",
+       .bar = g84_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = g94_bus_new,
+       .clk = g84_clk_new,
+       .devinit = g98_devinit_new,
+       .fb = g84_fb_new,
+       .fuse = nv50_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .imem = nv50_instmem_new,
+       .mc = g98_mc_new,
+       .mmu = nv50_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .therm = g84_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = g94_disp_new,
+       .dma = nv50_dma_new,
+       .fifo = g84_fifo_new,
+       .gr = g84_gr_new,
+       .mspdec = g98_mspdec_new,
+       .msppp = g98_msppp_new,
+       .msvld = g98_msvld_new,
+       .pm = g84_pm_new,
+       .sec = g98_sec_new,
+       .sw = nv50_sw_new,
+};
 
-struct nvkm_devobj {
-       struct nvkm_parent base;
-       struct nvkm_object *subdev[NVDEV_SUBDEV_NR];
+static const struct nvkm_device_chip
+nva0_chipset = {
+       .name = "GT200",
+       .bar = g84_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = g94_bus_new,
+       .clk = g84_clk_new,
+       .devinit = g84_devinit_new,
+       .fb = g84_fb_new,
+       .fuse = nv50_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = nv50_i2c_new,
+       .imem = nv50_instmem_new,
+       .mc = g98_mc_new,
+       .mmu = nv50_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .therm = g84_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .bsp = g84_bsp_new,
+       .cipher = g84_cipher_new,
+       .disp = gt200_disp_new,
+       .dma = nv50_dma_new,
+       .fifo = g84_fifo_new,
+       .gr = gt200_gr_new,
+       .mpeg = g84_mpeg_new,
+       .pm = gt200_pm_new,
+       .sw = nv50_sw_new,
+       .vp = g84_vp_new,
+};
+
+static const struct nvkm_device_chip
+nva3_chipset = {
+       .name = "GT215",
+       .bar = g84_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = g94_bus_new,
+       .clk = gt215_clk_new,
+       .devinit = gt215_devinit_new,
+       .fb = gt215_fb_new,
+       .fuse = nv50_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .imem = nv50_instmem_new,
+       .mc = g98_mc_new,
+       .mmu = nv50_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gt215_pmu_new,
+       .therm = gt215_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .ce[0] = gt215_ce_new,
+       .disp = gt215_disp_new,
+       .dma = nv50_dma_new,
+       .fifo = g84_fifo_new,
+       .gr = gt215_gr_new,
+       .mpeg = g84_mpeg_new,
+       .mspdec = gt215_mspdec_new,
+       .msppp = gt215_msppp_new,
+       .msvld = gt215_msvld_new,
+       .pm = gt215_pm_new,
+       .sw = nv50_sw_new,
+};
+
+static const struct nvkm_device_chip
+nva5_chipset = {
+       .name = "GT216",
+       .bar = g84_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = g94_bus_new,
+       .clk = gt215_clk_new,
+       .devinit = gt215_devinit_new,
+       .fb = gt215_fb_new,
+       .fuse = nv50_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .imem = nv50_instmem_new,
+       .mc = g98_mc_new,
+       .mmu = nv50_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gt215_pmu_new,
+       .therm = gt215_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .ce[0] = gt215_ce_new,
+       .disp = gt215_disp_new,
+       .dma = nv50_dma_new,
+       .fifo = g84_fifo_new,
+       .gr = gt215_gr_new,
+       .mspdec = gt215_mspdec_new,
+       .msppp = gt215_msppp_new,
+       .msvld = gt215_msvld_new,
+       .pm = gt215_pm_new,
+       .sw = nv50_sw_new,
+};
+
+static const struct nvkm_device_chip
+nva8_chipset = {
+       .name = "GT218",
+       .bar = g84_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = g94_bus_new,
+       .clk = gt215_clk_new,
+       .devinit = gt215_devinit_new,
+       .fb = gt215_fb_new,
+       .fuse = nv50_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .imem = nv50_instmem_new,
+       .mc = g98_mc_new,
+       .mmu = nv50_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gt215_pmu_new,
+       .therm = gt215_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .ce[0] = gt215_ce_new,
+       .disp = gt215_disp_new,
+       .dma = nv50_dma_new,
+       .fifo = g84_fifo_new,
+       .gr = gt215_gr_new,
+       .mspdec = gt215_mspdec_new,
+       .msppp = gt215_msppp_new,
+       .msvld = gt215_msvld_new,
+       .pm = gt215_pm_new,
+       .sw = nv50_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvaa_chipset = {
+       .name = "MCP77/MCP78",
+       .bar = g84_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = g94_bus_new,
+       .clk = mcp77_clk_new,
+       .devinit = g98_devinit_new,
+       .fb = mcp77_fb_new,
+       .fuse = nv50_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .imem = nv50_instmem_new,
+       .mc = g98_mc_new,
+       .mmu = nv50_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .therm = g84_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = g94_disp_new,
+       .dma = nv50_dma_new,
+       .fifo = g84_fifo_new,
+       .gr = gt200_gr_new,
+       .mspdec = g98_mspdec_new,
+       .msppp = g98_msppp_new,
+       .msvld = g98_msvld_new,
+       .pm = g84_pm_new,
+       .sec = g98_sec_new,
+       .sw = nv50_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvac_chipset = {
+       .name = "MCP79/MCP7A",
+       .bar = g84_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = g94_bus_new,
+       .clk = mcp77_clk_new,
+       .devinit = g98_devinit_new,
+       .fb = mcp77_fb_new,
+       .fuse = nv50_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .imem = nv50_instmem_new,
+       .mc = g98_mc_new,
+       .mmu = nv50_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .therm = g84_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .disp = g94_disp_new,
+       .dma = nv50_dma_new,
+       .fifo = g84_fifo_new,
+       .gr = mcp79_gr_new,
+       .mspdec = g98_mspdec_new,
+       .msppp = g98_msppp_new,
+       .msvld = g98_msvld_new,
+       .pm = g84_pm_new,
+       .sec = g98_sec_new,
+       .sw = nv50_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvaf_chipset = {
+       .name = "MCP89",
+       .bar = g84_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = g94_bus_new,
+       .clk = gt215_clk_new,
+       .devinit = mcp89_devinit_new,
+       .fb = mcp89_fb_new,
+       .fuse = nv50_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .imem = nv50_instmem_new,
+       .mc = g98_mc_new,
+       .mmu = nv50_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gt215_pmu_new,
+       .therm = gt215_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .ce[0] = gt215_ce_new,
+       .disp = gt215_disp_new,
+       .dma = nv50_dma_new,
+       .fifo = g84_fifo_new,
+       .gr = mcp89_gr_new,
+       .mspdec = gt215_mspdec_new,
+       .msppp = gt215_msppp_new,
+       .msvld = mcp89_msvld_new,
+       .pm = gt215_pm_new,
+       .sw = nv50_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvc0_chipset = {
+       .name = "GF100",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gf100_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gf100_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .ibus = gf100_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gf100_ltc_new,
+       .mc = gf100_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = gf100_pci_new,
+       .pmu = gf100_pmu_new,
+       .therm = gt215_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .ce[0] = gf100_ce_new,
+       .ce[1] = gf100_ce_new,
+       .disp = gt215_disp_new,
+       .dma = gf100_dma_new,
+       .fifo = gf100_fifo_new,
+       .gr = gf100_gr_new,
+       .mspdec = gf100_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gf100_msvld_new,
+       .pm = gf100_pm_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvc1_chipset = {
+       .name = "GF108",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gf100_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gf100_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .ibus = gf100_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gf100_ltc_new,
+       .mc = gf100_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gf100_pmu_new,
+       .therm = gt215_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .ce[0] = gf100_ce_new,
+       .disp = gt215_disp_new,
+       .dma = gf100_dma_new,
+       .fifo = gf100_fifo_new,
+       .gr = gf108_gr_new,
+       .mspdec = gf100_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gf100_msvld_new,
+       .pm = gf108_pm_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvc3_chipset = {
+       .name = "GF106",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gf100_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gf100_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .ibus = gf100_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gf100_ltc_new,
+       .mc = gf100_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gf100_pmu_new,
+       .therm = gt215_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .ce[0] = gf100_ce_new,
+       .disp = gt215_disp_new,
+       .dma = gf100_dma_new,
+       .fifo = gf100_fifo_new,
+       .gr = gf104_gr_new,
+       .mspdec = gf100_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gf100_msvld_new,
+       .pm = gf100_pm_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvc4_chipset = {
+       .name = "GF104",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gf100_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gf100_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .ibus = gf100_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gf100_ltc_new,
+       .mc = gf100_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = gf100_pci_new,
+       .pmu = gf100_pmu_new,
+       .therm = gt215_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .ce[0] = gf100_ce_new,
+       .ce[1] = gf100_ce_new,
+       .disp = gt215_disp_new,
+       .dma = gf100_dma_new,
+       .fifo = gf100_fifo_new,
+       .gr = gf104_gr_new,
+       .mspdec = gf100_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gf100_msvld_new,
+       .pm = gf100_pm_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvc8_chipset = {
+       .name = "GF110",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gf100_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gf100_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .ibus = gf100_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gf100_ltc_new,
+       .mc = gf100_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = gf100_pci_new,
+       .pmu = gf100_pmu_new,
+       .therm = gt215_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .ce[0] = gf100_ce_new,
+       .ce[1] = gf100_ce_new,
+       .disp = gt215_disp_new,
+       .dma = gf100_dma_new,
+       .fifo = gf100_fifo_new,
+       .gr = gf110_gr_new,
+       .mspdec = gf100_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gf100_msvld_new,
+       .pm = gf100_pm_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvce_chipset = {
+       .name = "GF114",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gf100_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gf100_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .ibus = gf100_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gf100_ltc_new,
+       .mc = gf100_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = gf100_pci_new,
+       .pmu = gf100_pmu_new,
+       .therm = gt215_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .ce[0] = gf100_ce_new,
+       .ce[1] = gf100_ce_new,
+       .disp = gt215_disp_new,
+       .dma = gf100_dma_new,
+       .fifo = gf100_fifo_new,
+       .gr = gf104_gr_new,
+       .mspdec = gf100_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gf100_msvld_new,
+       .pm = gf100_pm_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvcf_chipset = {
+       .name = "GF116",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gf100_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gf100_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = g94_gpio_new,
+       .i2c = g94_i2c_new,
+       .ibus = gf100_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gf100_ltc_new,
+       .mc = gf100_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gf100_pmu_new,
+       .therm = gt215_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .ce[0] = gf100_ce_new,
+       .disp = gt215_disp_new,
+       .dma = gf100_dma_new,
+       .fifo = gf100_fifo_new,
+       .gr = gf104_gr_new,
+       .mspdec = gf100_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gf100_msvld_new,
+       .pm = gf100_pm_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvd7_chipset = {
+       .name = "GF117",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gf100_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gf100_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = gf119_gpio_new,
+       .i2c = gf117_i2c_new,
+       .ibus = gf117_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gf100_ltc_new,
+       .mc = gf100_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .therm = gf119_therm_new,
+       .timer = nv41_timer_new,
+       .ce[0] = gf100_ce_new,
+       .disp = gf119_disp_new,
+       .dma = gf119_dma_new,
+       .fifo = gf100_fifo_new,
+       .gr = gf117_gr_new,
+       .mspdec = gf100_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gf100_msvld_new,
+       .pm = gf117_pm_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvd9_chipset = {
+       .name = "GF119",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gf100_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gf100_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = gf119_gpio_new,
+       .i2c = gf119_i2c_new,
+       .ibus = gf117_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gf100_ltc_new,
+       .mc = gf100_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gf119_pmu_new,
+       .therm = gf119_therm_new,
+       .timer = nv41_timer_new,
+       .volt = nv40_volt_new,
+       .ce[0] = gf100_ce_new,
+       .disp = gf119_disp_new,
+       .dma = gf119_dma_new,
+       .fifo = gf100_fifo_new,
+       .gr = gf119_gr_new,
+       .mspdec = gf100_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gf100_msvld_new,
+       .pm = gf117_pm_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nve4_chipset = {
+       .name = "GK104",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gk104_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gk104_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gk104_i2c_new,
+       .ibus = gk104_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gk104_ltc_new,
+       .mc = gf100_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gk104_pmu_new,
+       .therm = gf119_therm_new,
+       .timer = nv41_timer_new,
+       .volt = gk104_volt_new,
+       .ce[0] = gk104_ce_new,
+       .ce[1] = gk104_ce_new,
+       .ce[2] = gk104_ce_new,
+       .disp = gk104_disp_new,
+       .dma = gf119_dma_new,
+       .fifo = gk104_fifo_new,
+       .gr = gk104_gr_new,
+       .mspdec = gk104_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gk104_msvld_new,
+       .pm = gk104_pm_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nve6_chipset = {
+       .name = "GK106",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gk104_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gk104_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gk104_i2c_new,
+       .ibus = gk104_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gk104_ltc_new,
+       .mc = gf100_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gk104_pmu_new,
+       .therm = gf119_therm_new,
+       .timer = nv41_timer_new,
+       .volt = gk104_volt_new,
+       .ce[0] = gk104_ce_new,
+       .ce[1] = gk104_ce_new,
+       .ce[2] = gk104_ce_new,
+       .disp = gk104_disp_new,
+       .dma = gf119_dma_new,
+       .fifo = gk104_fifo_new,
+       .gr = gk104_gr_new,
+       .mspdec = gk104_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gk104_msvld_new,
+       .pm = gk104_pm_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nve7_chipset = {
+       .name = "GK107",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gk104_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gk104_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gk104_i2c_new,
+       .ibus = gk104_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gk104_ltc_new,
+       .mc = gf100_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gk104_pmu_new,
+       .therm = gf119_therm_new,
+       .timer = nv41_timer_new,
+       .volt = gk104_volt_new,
+       .ce[0] = gk104_ce_new,
+       .ce[1] = gk104_ce_new,
+       .ce[2] = gk104_ce_new,
+       .disp = gk104_disp_new,
+       .dma = gf119_dma_new,
+       .fifo = gk104_fifo_new,
+       .gr = gk104_gr_new,
+       .mspdec = gk104_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gk104_msvld_new,
+       .pm = gk104_pm_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvea_chipset = {
+       .name = "GK20A",
+       .bar = gk20a_bar_new,
+       .bus = gf100_bus_new,
+       .clk = gk20a_clk_new,
+       .fb = gk20a_fb_new,
+       .fuse = gf100_fuse_new,
+       .ibus = gk20a_ibus_new,
+       .imem = gk20a_instmem_new,
+       .ltc = gk104_ltc_new,
+       .mc = gk20a_mc_new,
+       .mmu = gf100_mmu_new,
+       .pmu = gk20a_pmu_new,
+       .timer = gk20a_timer_new,
+       .volt = gk20a_volt_new,
+       .ce[2] = gk104_ce_new,
+       .dma = gf119_dma_new,
+       .fifo = gk20a_fifo_new,
+       .gr = gk20a_gr_new,
+       .pm = gk104_pm_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvf0_chipset = {
+       .name = "GK110",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gk104_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gk104_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gk104_i2c_new,
+       .ibus = gk104_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gk104_ltc_new,
+       .mc = gf100_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gk110_pmu_new,
+       .therm = gf119_therm_new,
+       .timer = nv41_timer_new,
+       .volt = gk104_volt_new,
+       .ce[0] = gk104_ce_new,
+       .ce[1] = gk104_ce_new,
+       .ce[2] = gk104_ce_new,
+       .disp = gk110_disp_new,
+       .dma = gf119_dma_new,
+       .fifo = gk104_fifo_new,
+       .gr = gk110_gr_new,
+       .mspdec = gk104_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gk104_msvld_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nvf1_chipset = {
+       .name = "GK110B",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gk104_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gk104_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gf119_i2c_new,
+       .ibus = gk104_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gk104_ltc_new,
+       .mc = gf100_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gk110_pmu_new,
+       .therm = gf119_therm_new,
+       .timer = nv41_timer_new,
+       .volt = gk104_volt_new,
+       .ce[0] = gk104_ce_new,
+       .ce[1] = gk104_ce_new,
+       .ce[2] = gk104_ce_new,
+       .disp = gk110_disp_new,
+       .dma = gf119_dma_new,
+       .fifo = gk104_fifo_new,
+       .gr = gk110b_gr_new,
+       .mspdec = gk104_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gk104_msvld_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv106_chipset = {
+       .name = "GK208B",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gk104_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gk104_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gk104_i2c_new,
+       .ibus = gk104_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gk104_ltc_new,
+       .mc = gk20a_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gk208_pmu_new,
+       .therm = gf119_therm_new,
+       .timer = nv41_timer_new,
+       .volt = gk104_volt_new,
+       .ce[0] = gk104_ce_new,
+       .ce[1] = gk104_ce_new,
+       .ce[2] = gk104_ce_new,
+       .disp = gk110_disp_new,
+       .dma = gf119_dma_new,
+       .fifo = gk208_fifo_new,
+       .gr = gk208_gr_new,
+       .mspdec = gk104_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gk104_msvld_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv108_chipset = {
+       .name = "GK208",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gk104_clk_new,
+       .devinit = gf100_devinit_new,
+       .fb = gk104_fb_new,
+       .fuse = gf100_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gk104_i2c_new,
+       .ibus = gk104_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gk104_ltc_new,
+       .mc = gk20a_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gk208_pmu_new,
+       .therm = gf119_therm_new,
+       .timer = nv41_timer_new,
+       .volt = gk104_volt_new,
+       .ce[0] = gk104_ce_new,
+       .ce[1] = gk104_ce_new,
+       .ce[2] = gk104_ce_new,
+       .disp = gk110_disp_new,
+       .dma = gf119_dma_new,
+       .fifo = gk208_fifo_new,
+       .gr = gk208_gr_new,
+       .mspdec = gk104_mspdec_new,
+       .msppp = gf100_msppp_new,
+       .msvld = gk104_msvld_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv117_chipset = {
+       .name = "GM107",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .clk = gk104_clk_new,
+       .devinit = gm107_devinit_new,
+       .fb = gm107_fb_new,
+       .fuse = gm107_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gf119_i2c_new,
+       .ibus = gk104_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gm107_ltc_new,
+       .mc = gk20a_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gm107_pmu_new,
+       .therm = gm107_therm_new,
+       .timer = gk20a_timer_new,
+       .volt = gk104_volt_new,
+       .ce[0] = gk104_ce_new,
+       .ce[2] = gk104_ce_new,
+       .disp = gm107_disp_new,
+       .dma = gf119_dma_new,
+       .fifo = gk208_fifo_new,
+       .gr = gm107_gr_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv124_chipset = {
+       .name = "GM204",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .devinit = gm204_devinit_new,
+       .fb = gm107_fb_new,
+       .fuse = gm107_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gm204_i2c_new,
+       .ibus = gk104_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gm107_ltc_new,
+       .mc = gk20a_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gm107_pmu_new,
+       .timer = gk20a_timer_new,
+       .volt = gk104_volt_new,
+       .ce[0] = gm204_ce_new,
+       .ce[1] = gm204_ce_new,
+       .ce[2] = gm204_ce_new,
+       .disp = gm204_disp_new,
+       .dma = gf119_dma_new,
+       .fifo = gm204_fifo_new,
+       .gr = gm204_gr_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv126_chipset = {
+       .name = "GM206",
+       .bar = gf100_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .devinit = gm204_devinit_new,
+       .fb = gm107_fb_new,
+       .fuse = gm107_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gm204_i2c_new,
+       .ibus = gk104_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gm107_ltc_new,
+       .mc = gk20a_mc_new,
+       .mmu = gf100_mmu_new,
+       .mxm = nv50_mxm_new,
+       .pci = g94_pci_new,
+       .pmu = gm107_pmu_new,
+       .timer = gk20a_timer_new,
+       .volt = gk104_volt_new,
+       .ce[0] = gm204_ce_new,
+       .ce[1] = gm204_ce_new,
+       .ce[2] = gm204_ce_new,
+       .disp = gm204_disp_new,
+       .dma = gf119_dma_new,
+       .fifo = gm204_fifo_new,
+       .gr = gm206_gr_new,
+       .sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv12b_chipset = {
+       .name = "GM20B",
+       .bar = gk20a_bar_new,
+       .bus = gf100_bus_new,
+       .fb = gk20a_fb_new,
+       .fuse = gm107_fuse_new,
+       .ibus = gk20a_ibus_new,
+       .imem = gk20a_instmem_new,
+       .ltc = gm107_ltc_new,
+       .mc = gk20a_mc_new,
+       .mmu = gf100_mmu_new,
+       .timer = gk20a_timer_new,
+       .ce[2] = gm204_ce_new,
+       .dma = gf119_dma_new,
+       .fifo = gm20b_fifo_new,
+       .gr = gm20b_gr_new,
+       .sw = gf100_sw_new,
 };
 
 static int
-nvkm_devobj_info(struct nvkm_object *object, void *data, u32 size)
+nvkm_device_event_ctor(struct nvkm_object *object, void *data, u32 size,
+                      struct nvkm_notify *notify)
 {
-       struct nvkm_device *device = nv_device(object);
-       struct nvkm_fb *pfb = nvkm_fb(device);
-       struct nvkm_instmem *imem = nvkm_instmem(device);
-       union {
-               struct nv_device_info_v0 v0;
-       } *args = data;
-       int ret;
-
-       nv_ioctl(object, "device info size %d\n", size);
-       if (nvif_unpack(args->v0, 0, 0, false)) {
-               nv_ioctl(object, "device info vers %d\n", args->v0.version);
-       } else
-               return ret;
+       if (!WARN_ON(size != 0)) {
+               notify->size  = 0;
+               notify->types = 1;
+               notify->index = 0;
+               return 0;
+       }
+       return -EINVAL;
+}
 
-       switch (device->chipset) {
-       case 0x01a:
-       case 0x01f:
-       case 0x04c:
-       case 0x04e:
-       case 0x063:
-       case 0x067:
-       case 0x068:
-       case 0x0aa:
-       case 0x0ac:
-       case 0x0af:
-               args->v0.platform = NV_DEVICE_INFO_V0_IGP;
-               break;
+static const struct nvkm_event_func
+nvkm_device_event_func = {
+       .ctor = nvkm_device_event_ctor,
+};
+
+struct nvkm_subdev *
+nvkm_device_subdev(struct nvkm_device *device, int index)
+{
+       struct nvkm_engine *engine;
+
+       if (device->disable_mask & (1ULL << index))
+               return NULL;
+
+       switch (index) {
+#define _(n,p,m) case NVKM_SUBDEV_##n: if (p) return (m); break
+       _(BAR    , device->bar    , &device->bar->subdev);
+       _(VBIOS  , device->bios   , &device->bios->subdev);
+       _(BUS    , device->bus    , &device->bus->subdev);
+       _(CLK    , device->clk    , &device->clk->subdev);
+       _(DEVINIT, device->devinit, &device->devinit->subdev);
+       _(FB     , device->fb     , &device->fb->subdev);
+       _(FUSE   , device->fuse   , &device->fuse->subdev);
+       _(GPIO   , device->gpio   , &device->gpio->subdev);
+       _(I2C    , device->i2c    , &device->i2c->subdev);
+       _(IBUS   , device->ibus   ,  device->ibus);
+       _(INSTMEM, device->imem   , &device->imem->subdev);
+       _(LTC    , device->ltc    , &device->ltc->subdev);
+       _(MC     , device->mc     , &device->mc->subdev);
+       _(MMU    , device->mmu    , &device->mmu->subdev);
+       _(MXM    , device->mxm    ,  device->mxm);
+       _(PCI    , device->pci    , &device->pci->subdev);
+       _(PMU    , device->pmu    , &device->pmu->subdev);
+       _(THERM  , device->therm  , &device->therm->subdev);
+       _(TIMER  , device->timer  , &device->timer->subdev);
+       _(VOLT   , device->volt   , &device->volt->subdev);
+#undef _
        default:
-               if (device->pdev) {
-                       if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP))
-                               args->v0.platform = NV_DEVICE_INFO_V0_AGP;
-                       else
-                       if (pci_is_pcie(device->pdev))
-                               args->v0.platform = NV_DEVICE_INFO_V0_PCIE;
-                       else
-                               args->v0.platform = NV_DEVICE_INFO_V0_PCI;
-               } else {
-                       args->v0.platform = NV_DEVICE_INFO_V0_SOC;
-               }
+               engine = nvkm_device_engine(device, index);
+               if (engine)
+                       return &engine->subdev;
                break;
        }
+       return NULL;
+}
 
-       switch (device->card_type) {
-       case NV_04: args->v0.family = NV_DEVICE_INFO_V0_TNT; break;
-       case NV_10:
-       case NV_11: args->v0.family = NV_DEVICE_INFO_V0_CELSIUS; break;
-       case NV_20: args->v0.family = NV_DEVICE_INFO_V0_KELVIN; break;
-       case NV_30: args->v0.family = NV_DEVICE_INFO_V0_RANKINE; break;
-       case NV_40: args->v0.family = NV_DEVICE_INFO_V0_CURIE; break;
-       case NV_50: args->v0.family = NV_DEVICE_INFO_V0_TESLA; break;
-       case NV_C0: args->v0.family = NV_DEVICE_INFO_V0_FERMI; break;
-       case NV_E0: args->v0.family = NV_DEVICE_INFO_V0_KEPLER; break;
-       case GM100: args->v0.family = NV_DEVICE_INFO_V0_MAXWELL; break;
+struct nvkm_engine *
+nvkm_device_engine(struct nvkm_device *device, int index)
+{
+       if (device->disable_mask & (1ULL << index))
+               return NULL;
+
+       switch (index) {
+#define _(n,p,m) case NVKM_ENGINE_##n: if (p) return (m); break
+       _(BSP    , device->bsp    ,  device->bsp);
+       _(CE0    , device->ce[0]  ,  device->ce[0]);
+       _(CE1    , device->ce[1]  ,  device->ce[1]);
+       _(CE2    , device->ce[2]  ,  device->ce[2]);
+       _(CIPHER , device->cipher ,  device->cipher);
+       _(DISP   , device->disp   , &device->disp->engine);
+       _(DMAOBJ , device->dma    , &device->dma->engine);
+       _(FIFO   , device->fifo   , &device->fifo->engine);
+       _(GR     , device->gr     , &device->gr->engine);
+       _(IFB    , device->ifb    ,  device->ifb);
+       _(ME     , device->me     ,  device->me);
+       _(MPEG   , device->mpeg   ,  device->mpeg);
+       _(MSENC  , device->msenc  ,  device->msenc);
+       _(MSPDEC , device->mspdec ,  device->mspdec);
+       _(MSPPP  , device->msppp  ,  device->msppp);
+       _(MSVLD  , device->msvld  ,  device->msvld);
+       _(PM     , device->pm     , &device->pm->engine);
+       _(SEC    , device->sec    ,  device->sec);
+       _(SW     , device->sw     , &device->sw->engine);
+       _(VIC    , device->vic    ,  device->vic);
+       _(VP     , device->vp     ,  device->vp);
+#undef _
        default:
-               args->v0.family = 0;
+               WARN_ON(1);
                break;
        }
+       return NULL;
+}
+
+int
+nvkm_device_fini(struct nvkm_device *device, bool suspend)
+{
+       const char *action = suspend ? "suspend" : "fini";
+       struct nvkm_subdev *subdev;
+       int ret, i;
+       s64 time;
+
+       nvdev_trace(device, "%s running...\n", action);
+       time = ktime_to_us(ktime_get());
+
+       nvkm_acpi_fini(device);
+
+       for (i = NVKM_SUBDEV_NR - 1; i >= 0; i--) {
+               if ((subdev = nvkm_device_subdev(device, i))) {
+                       ret = nvkm_subdev_fini(subdev, suspend);
+                       if (ret && suspend)
+                               goto fail;
+               }
+       }
 
-       args->v0.chipset  = device->chipset;
-       args->v0.revision = device->chiprev;
-       if (pfb && pfb->ram)
-               args->v0.ram_size = args->v0.ram_user = pfb->ram->size;
-       else
-               args->v0.ram_size = args->v0.ram_user = 0;
-       if (imem && args->v0.ram_size > 0)
-               args->v0.ram_user = args->v0.ram_user - imem->reserved;
 
+       if (device->func->fini)
+               device->func->fini(device, suspend);
+
+       time = ktime_to_us(ktime_get()) - time;
+       nvdev_trace(device, "%s completed in %lldus...\n", action, time);
        return 0;
+
+fail:
+       do {
+               if ((subdev = nvkm_device_subdev(device, i))) {
+                       int rret = nvkm_subdev_init(subdev);
+                       if (rret)
+                               nvkm_fatal(subdev, "failed restart, %d\n", ret);
+               }
+       } while (++i < NVKM_SUBDEV_NR);
+
+       nvdev_trace(device, "%s failed with %d\n", action, ret);
+       return ret;
 }
 
 static int
-nvkm_devobj_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
+nvkm_device_preinit(struct nvkm_device *device)
 {
-       switch (mthd) {
-       case NV_DEVICE_V0_INFO:
-               return nvkm_devobj_info(object, data, size);
-       default:
-               break;
+       struct nvkm_subdev *subdev;
+       int ret, i;
+       s64 time;
+
+       nvdev_trace(device, "preinit running...\n");
+       time = ktime_to_us(ktime_get());
+
+       if (device->func->preinit) {
+               ret = device->func->preinit(device);
+               if (ret)
+                       goto fail;
        }
-       return -EINVAL;
-}
 
-static u8
-nvkm_devobj_rd08(struct nvkm_object *object, u64 addr)
-{
-       return nv_rd08(object->engine, addr);
-}
+       for (i = 0; i < NVKM_SUBDEV_NR; i++) {
+               if ((subdev = nvkm_device_subdev(device, i))) {
+                       ret = nvkm_subdev_preinit(subdev);
+                       if (ret)
+                               goto fail;
+               }
+       }
 
-static u16
-nvkm_devobj_rd16(struct nvkm_object *object, u64 addr)
-{
-       return nv_rd16(object->engine, addr);
-}
+       ret = nvkm_devinit_post(device->devinit, &device->disable_mask);
+       if (ret)
+               goto fail;
 
-static u32
-nvkm_devobj_rd32(struct nvkm_object *object, u64 addr)
-{
-       return nv_rd32(object->engine, addr);
-}
+       time = ktime_to_us(ktime_get()) - time;
+       nvdev_trace(device, "preinit completed in %lldus\n", time);
+       return 0;
 
-static void
-nvkm_devobj_wr08(struct nvkm_object *object, u64 addr, u8 data)
-{
-       nv_wr08(object->engine, addr, data);
+fail:
+       nvdev_error(device, "preinit failed with %d\n", ret);
+       return ret;
 }
 
-static void
-nvkm_devobj_wr16(struct nvkm_object *object, u64 addr, u16 data)
+int
+nvkm_device_init(struct nvkm_device *device)
 {
-       nv_wr16(object->engine, addr, data);
-}
+       struct nvkm_subdev *subdev;
+       int ret, i;
+       s64 time;
 
-static void
-nvkm_devobj_wr32(struct nvkm_object *object, u64 addr, u32 data)
-{
-       nv_wr32(object->engine, addr, data);
-}
+       ret = nvkm_device_preinit(device);
+       if (ret)
+               return ret;
 
-static int
-nvkm_devobj_map(struct nvkm_object *object, u64 *addr, u32 *size)
-{
-       struct nvkm_device *device = nv_device(object);
-       *addr = nv_device_resource_start(device, 0);
-       *size = nv_device_resource_len(device, 0);
+       nvkm_device_fini(device, false);
+
+       nvdev_trace(device, "init running...\n");
+       time = ktime_to_us(ktime_get());
+
+       if (device->func->init) {
+               ret = device->func->init(device);
+               if (ret)
+                       goto fail;
+       }
+
+       for (i = 0; i < NVKM_SUBDEV_NR; i++) {
+               if ((subdev = nvkm_device_subdev(device, i))) {
+                       ret = nvkm_subdev_init(subdev);
+                       if (ret)
+                               goto fail_subdev;
+               }
+       }
+
+       nvkm_acpi_init(device);
+
+       time = ktime_to_us(ktime_get()) - time;
+       nvdev_trace(device, "init completed in %lldus\n", time);
        return 0;
+
+fail_subdev:
+       do {
+               if ((subdev = nvkm_device_subdev(device, i)))
+                       nvkm_subdev_fini(subdev, false);
+       } while (--i >= 0);
+
+fail:
+       nvdev_error(device, "init failed with %d\n", ret);
+       return ret;
 }
 
-static const u64 disable_map[] = {
-       [NVDEV_SUBDEV_VBIOS]    = NV_DEVICE_V0_DISABLE_VBIOS,
-       [NVDEV_SUBDEV_DEVINIT]  = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_GPIO]     = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_I2C]      = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_CLK  ]    = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_MXM]      = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_MC]       = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_BUS]      = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_TIMER]    = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_FB]       = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_LTC]      = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_IBUS]     = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_INSTMEM]  = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_MMU]      = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_BAR]      = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_VOLT]     = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_THERM]    = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_PMU]      = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_FUSE]     = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_ENGINE_DMAOBJ]   = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_ENGINE_PM     ]  = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_ENGINE_FIFO]     = NV_DEVICE_V0_DISABLE_FIFO,
-       [NVDEV_ENGINE_SW]       = NV_DEVICE_V0_DISABLE_FIFO,
-       [NVDEV_ENGINE_GR]       = NV_DEVICE_V0_DISABLE_GR,
-       [NVDEV_ENGINE_MPEG]     = NV_DEVICE_V0_DISABLE_MPEG,
-       [NVDEV_ENGINE_ME]       = NV_DEVICE_V0_DISABLE_ME,
-       [NVDEV_ENGINE_VP]       = NV_DEVICE_V0_DISABLE_VP,
-       [NVDEV_ENGINE_CIPHER]   = NV_DEVICE_V0_DISABLE_CIPHER,
-       [NVDEV_ENGINE_BSP]      = NV_DEVICE_V0_DISABLE_BSP,
-       [NVDEV_ENGINE_MSPPP]    = NV_DEVICE_V0_DISABLE_MSPPP,
-       [NVDEV_ENGINE_CE0]      = NV_DEVICE_V0_DISABLE_CE0,
-       [NVDEV_ENGINE_CE1]      = NV_DEVICE_V0_DISABLE_CE1,
-       [NVDEV_ENGINE_CE2]      = NV_DEVICE_V0_DISABLE_CE2,
-       [NVDEV_ENGINE_VIC]      = NV_DEVICE_V0_DISABLE_VIC,
-       [NVDEV_ENGINE_MSENC]    = NV_DEVICE_V0_DISABLE_MSENC,
-       [NVDEV_ENGINE_DISP]     = NV_DEVICE_V0_DISABLE_DISP,
-       [NVDEV_ENGINE_MSVLD]    = NV_DEVICE_V0_DISABLE_MSVLD,
-       [NVDEV_ENGINE_SEC]      = NV_DEVICE_V0_DISABLE_SEC,
-       [NVDEV_SUBDEV_NR]       = 0,
-};
-
-static void
-nvkm_devobj_dtor(struct nvkm_object *object)
+void
+nvkm_device_del(struct nvkm_device **pdevice)
 {
-       struct nvkm_devobj *devobj = (void *)object;
+       struct nvkm_device *device = *pdevice;
        int i;
+       if (device) {
+               mutex_lock(&nv_devices_mutex);
+               device->disable_mask = 0;
+               for (i = NVKM_SUBDEV_NR - 1; i >= 0; i--) {
+                       struct nvkm_subdev *subdev =
+                               nvkm_device_subdev(device, i);
+                       nvkm_subdev_del(&subdev);
+               }
 
-       for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--)
-               nvkm_object_ref(NULL, &devobj->subdev[i]);
+               nvkm_event_fini(&device->event);
 
-       nvkm_parent_destroy(&devobj->base);
-}
+               if (device->pri)
+                       iounmap(device->pri);
+               list_del(&device->head);
 
-static struct nvkm_oclass
-nvkm_devobj_oclass_super = {
-       .handle = NV_DEVICE,
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .dtor = nvkm_devobj_dtor,
-               .init = _nvkm_parent_init,
-               .fini = _nvkm_parent_fini,
-               .mthd = nvkm_devobj_mthd,
-               .map  = nvkm_devobj_map,
-               .rd08 = nvkm_devobj_rd08,
-               .rd16 = nvkm_devobj_rd16,
-               .rd32 = nvkm_devobj_rd32,
-               .wr08 = nvkm_devobj_wr08,
-               .wr16 = nvkm_devobj_wr16,
-               .wr32 = nvkm_devobj_wr32,
+               if (device->func->dtor)
+                       *pdevice = device->func->dtor(device);
+               mutex_unlock(&nv_devices_mutex);
+
+               kfree(*pdevice);
+               *pdevice = NULL;
        }
-};
+}
 
-static int
-nvkm_devobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-                struct nvkm_oclass *oclass, void *data, u32 size,
-                struct nvkm_object **pobject)
+int
+nvkm_device_ctor(const struct nvkm_device_func *func,
+                const struct nvkm_device_quirk *quirk,
+                struct device *dev, enum nvkm_device_type type, u64 handle,
+                const char *name, const char *cfg, const char *dbg,
+                bool detect, bool mmio, u64 subdev_mask,
+                struct nvkm_device *device)
 {
-       union {
-               struct nv_device_v0 v0;
-       } *args = data;
-       struct nvkm_client *client = nv_client(parent);
-       struct nvkm_device *device;
-       struct nvkm_devobj *devobj;
+       struct nvkm_subdev *subdev;
+       u64 mmio_base, mmio_size;
        u32 boot0, strap;
-       u64 disable, mmio_base, mmio_size;
        void __iomem *map;
-       int ret, i, c;
-
-       nv_ioctl(parent, "create device size %d\n", size);
-       if (nvif_unpack(args->v0, 0, 0, false)) {
-               nv_ioctl(parent, "create device v%d device %016llx "
-                                "disable %016llx debug0 %016llx\n",
-                        args->v0.version, args->v0.device,
-                        args->v0.disable, args->v0.debug0);
-       } else
-               return ret;
+       int ret = -EEXIST;
+       int i;
 
-       /* give priviledged clients register access */
-       if (client->super)
-               oclass = &nvkm_devobj_oclass_super;
+       mutex_lock(&nv_devices_mutex);
+       if (nvkm_device_find_locked(handle))
+               goto done;
 
-       /* find the device subdev that matches what the client requested */
-       device = nv_device(client->device);
-       if (args->v0.device != ~0) {
-               device = nvkm_device_find(args->v0.device);
-               if (!device)
-                       return -ENODEV;
-       }
+       device->func = func;
+       device->quirk = quirk;
+       device->dev = dev;
+       device->type = type;
+       device->handle = handle;
+       device->cfgopt = cfg;
+       device->dbgopt = dbg;
+       device->name = name;
+       list_add_tail(&device->head, &nv_devices);
+       device->debug = nvkm_dbgopt(device->dbgopt, "device");
 
-       ret = nvkm_parent_create(parent, nv_object(device), oclass, 0,
-                                nvkm_control_oclass,
-                                (1ULL << NVDEV_ENGINE_DMAOBJ) |
-                                (1ULL << NVDEV_ENGINE_FIFO) |
-                                (1ULL << NVDEV_ENGINE_DISP) |
-                                (1ULL << NVDEV_ENGINE_PM), &devobj);
-       *pobject = nv_object(devobj);
+       ret = nvkm_event_init(&nvkm_device_event_func, 1, 1, &device->event);
        if (ret)
-               return ret;
-
-       mmio_base = nv_device_resource_start(device, 0);
-       mmio_size = nv_device_resource_len(device, 0);
+               goto done;
 
-       /* translate api disable mask into internal mapping */
-       disable = args->v0.debug0;
-       for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
-               if (args->v0.disable & disable_map[i])
-                       disable |= (1ULL << i);
-       }
+       mmio_base = device->func->resource_addr(device, 0);
+       mmio_size = device->func->resource_size(device, 0);
 
        /* identify the chipset, and determine classes of subdev/engines */
-       if (!(args->v0.disable & NV_DEVICE_V0_DISABLE_IDENTIFY) &&
-           !device->card_type) {
+       if (detect) {
                map = ioremap(mmio_base, 0x102000);
-               if (map == NULL)
-                       return -ENOMEM;
+               if (ret = -ENOMEM, map == NULL)
+                       goto done;
 
                /* switch mmio to cpu's native endianness */
 #ifndef __BIG_ENDIAN
@@ -397,31 +2392,83 @@ nvkm_devobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
                        device->card_type = NV_04;
                }
 
-               switch (device->card_type) {
-               case NV_04: ret = nv04_identify(device); break;
-               case NV_10:
-               case NV_11: ret = nv10_identify(device); break;
-               case NV_20: ret = nv20_identify(device); break;
-               case NV_30: ret = nv30_identify(device); break;
-               case NV_40: ret = nv40_identify(device); break;
-               case NV_50: ret = nv50_identify(device); break;
-               case NV_C0: ret = gf100_identify(device); break;
-               case NV_E0: ret = gk104_identify(device); break;
-               case GM100: ret = gm100_identify(device); break;
+               switch (device->chipset) {
+               case 0x004: device->chip = &nv4_chipset; break;
+               case 0x005: device->chip = &nv5_chipset; break;
+               case 0x010: device->chip = &nv10_chipset; break;
+               case 0x011: device->chip = &nv11_chipset; break;
+               case 0x015: device->chip = &nv15_chipset; break;
+               case 0x017: device->chip = &nv17_chipset; break;
+               case 0x018: device->chip = &nv18_chipset; break;
+               case 0x01a: device->chip = &nv1a_chipset; break;
+               case 0x01f: device->chip = &nv1f_chipset; break;
+               case 0x020: device->chip = &nv20_chipset; break;
+               case 0x025: device->chip = &nv25_chipset; break;
+               case 0x028: device->chip = &nv28_chipset; break;
+               case 0x02a: device->chip = &nv2a_chipset; break;
+               case 0x030: device->chip = &nv30_chipset; break;
+               case 0x031: device->chip = &nv31_chipset; break;
+               case 0x034: device->chip = &nv34_chipset; break;
+               case 0x035: device->chip = &nv35_chipset; break;
+               case 0x036: device->chip = &nv36_chipset; break;
+               case 0x040: device->chip = &nv40_chipset; break;
+               case 0x041: device->chip = &nv41_chipset; break;
+               case 0x042: device->chip = &nv42_chipset; break;
+               case 0x043: device->chip = &nv43_chipset; break;
+               case 0x044: device->chip = &nv44_chipset; break;
+               case 0x045: device->chip = &nv45_chipset; break;
+               case 0x046: device->chip = &nv46_chipset; break;
+               case 0x047: device->chip = &nv47_chipset; break;
+               case 0x049: device->chip = &nv49_chipset; break;
+               case 0x04a: device->chip = &nv4a_chipset; break;
+               case 0x04b: device->chip = &nv4b_chipset; break;
+               case 0x04c: device->chip = &nv4c_chipset; break;
+               case 0x04e: device->chip = &nv4e_chipset; break;
+               case 0x050: device->chip = &nv50_chipset; break;
+               case 0x063: device->chip = &nv63_chipset; break;
+               case 0x067: device->chip = &nv67_chipset; break;
+               case 0x068: device->chip = &nv68_chipset; break;
+               case 0x084: device->chip = &nv84_chipset; break;
+               case 0x086: device->chip = &nv86_chipset; break;
+               case 0x092: device->chip = &nv92_chipset; break;
+               case 0x094: device->chip = &nv94_chipset; break;
+               case 0x096: device->chip = &nv96_chipset; break;
+               case 0x098: device->chip = &nv98_chipset; break;
+               case 0x0a0: device->chip = &nva0_chipset; break;
+               case 0x0a3: device->chip = &nva3_chipset; break;
+               case 0x0a5: device->chip = &nva5_chipset; break;
+               case 0x0a8: device->chip = &nva8_chipset; break;
+               case 0x0aa: device->chip = &nvaa_chipset; break;
+               case 0x0ac: device->chip = &nvac_chipset; break;
+               case 0x0af: device->chip = &nvaf_chipset; break;
+               case 0x0c0: device->chip = &nvc0_chipset; break;
+               case 0x0c1: device->chip = &nvc1_chipset; break;
+               case 0x0c3: device->chip = &nvc3_chipset; break;
+               case 0x0c4: device->chip = &nvc4_chipset; break;
+               case 0x0c8: device->chip = &nvc8_chipset; break;
+               case 0x0ce: device->chip = &nvce_chipset; break;
+               case 0x0cf: device->chip = &nvcf_chipset; break;
+               case 0x0d7: device->chip = &nvd7_chipset; break;
+               case 0x0d9: device->chip = &nvd9_chipset; break;
+               case 0x0e4: device->chip = &nve4_chipset; break;
+               case 0x0e6: device->chip = &nve6_chipset; break;
+               case 0x0e7: device->chip = &nve7_chipset; break;
+               case 0x0ea: device->chip = &nvea_chipset; break;
+               case 0x0f0: device->chip = &nvf0_chipset; break;
+               case 0x0f1: device->chip = &nvf1_chipset; break;
+               case 0x106: device->chip = &nv106_chipset; break;
+               case 0x108: device->chip = &nv108_chipset; break;
+               case 0x117: device->chip = &nv117_chipset; break;
+               case 0x124: device->chip = &nv124_chipset; break;
+               case 0x126: device->chip = &nv126_chipset; break;
+               case 0x12b: device->chip = &nv12b_chipset; break;
                default:
-                       ret = -EINVAL;
-                       break;
-               }
-
-               if (ret) {
-                       nv_error(device, "unknown chipset, 0x%08x\n", boot0);
-                       return ret;
+                       nvdev_error(device, "unknown chipset (%08x)\n", boot0);
+                       goto done;
                }
 
-               nv_info(device, "BOOT0  : 0x%08x\n", boot0);
-               nv_info(device, "Chipset: %s (NV%02X)\n",
-                       device->cname, device->chipset);
-               nv_info(device, "Family : NV%02X\n", device->card_type);
+               nvdev_info(device, "NVIDIA %s (%08x)\n",
+                          device->chip->name, boot0);
 
                /* determine frequency of timing crystal */
                if ( device->card_type <= NV_10 || device->chipset < 0x17 ||
@@ -436,300 +2483,89 @@ nvkm_devobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
                case 0x00400000: device->crystal = 27000; break;
                case 0x00400040: device->crystal = 25000; break;
                }
-
-               nv_debug(device, "crystal freq: %dKHz\n", device->crystal);
-       } else
-       if ( (args->v0.disable & NV_DEVICE_V0_DISABLE_IDENTIFY)) {
-               device->cname = "NULL";
-               device->oclass[NVDEV_SUBDEV_VBIOS] = &nvkm_bios_oclass;
-       }
-
-       if (!(args->v0.disable & NV_DEVICE_V0_DISABLE_MMIO) &&
-           !nv_subdev(device)->mmio) {
-               nv_subdev(device)->mmio  = ioremap(mmio_base, mmio_size);
-               if (!nv_subdev(device)->mmio) {
-                       nv_error(device, "unable to map device registers\n");
-                       return -ENOMEM;
-               }
-       }
-
-       /* ensure requested subsystems are available for use */
-       for (i = 1, c = 1; i < NVDEV_SUBDEV_NR; i++) {
-               if (!(oclass = device->oclass[i]) || (disable & (1ULL << i)))
-                       continue;
-
-               if (device->subdev[i]) {
-                       nvkm_object_ref(device->subdev[i], &devobj->subdev[i]);
-                       continue;
-               }
-
-               ret = nvkm_object_ctor(nv_object(device), NULL, oclass,
-                                      NULL, i, &devobj->subdev[i]);
-               if (ret == -ENODEV)
-                       continue;
-               if (ret)
-                       return ret;
-
-               device->subdev[i] = devobj->subdev[i];
-
-               /* note: can't init *any* subdevs until devinit has been run
-                * due to not knowing exactly what the vbios init tables will
-                * mess with.  devinit also can't be run until all of its
-                * dependencies have been created.
-                *
-                * this code delays init of any subdev until all of devinit's
-                * dependencies have been created, and then initialises each
-                * subdev in turn as they're created.
-                */
-               while (i >= NVDEV_SUBDEV_DEVINIT_LAST && c <= i) {
-                       struct nvkm_object *subdev = devobj->subdev[c++];
-                       if (subdev && !nv_iclass(subdev, NV_ENGINE_CLASS)) {
-                               ret = nvkm_object_inc(subdev);
-                               if (ret)
-                                       return ret;
-                               atomic_dec(&nv_object(device)->usecount);
-                       } else
-                       if (subdev) {
-                               nvkm_subdev_reset(subdev);
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static struct nvkm_ofuncs
-nvkm_devobj_ofuncs = {
-       .ctor = nvkm_devobj_ctor,
-       .dtor = nvkm_devobj_dtor,
-       .init = _nvkm_parent_init,
-       .fini = _nvkm_parent_fini,
-       .mthd = nvkm_devobj_mthd,
-};
-
-/******************************************************************************
- * nvkm_device: engine functions
- *****************************************************************************/
-
-struct nvkm_device *
-nv_device(void *obj)
-{
-       struct nvkm_object *device = nv_object(obj);
-       if (device->engine == NULL) {
-               while (device && device->parent)
-                       device = device->parent;
        } else {
-               device = &nv_object(obj)->engine->subdev.object;
-               if (device && device->parent)
-                       device = device->parent;
+               device->chip = &null_chipset;
        }
-#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA
-       if (unlikely(!device))
-               nv_assert("BAD CAST -> NvDevice, 0x%08x\n", nv_hclass(obj));
-#endif
-       return (void *)device;
-}
 
-static struct nvkm_oclass
-nvkm_device_sclass[] = {
-       { 0x0080, &nvkm_devobj_ofuncs },
-       {}
-};
+       if (!device->name)
+               device->name = device->chip->name;
 
-static int
-nvkm_device_event_ctor(struct nvkm_object *object, void *data, u32 size,
-                      struct nvkm_notify *notify)
-{
-       if (!WARN_ON(size != 0)) {
-               notify->size  = 0;
-               notify->types = 1;
-               notify->index = 0;
-               return 0;
-       }
-       return -EINVAL;
-}
-
-static const struct nvkm_event_func
-nvkm_device_event_func = {
-       .ctor = nvkm_device_event_ctor,
-};
-
-static int
-nvkm_device_fini(struct nvkm_object *object, bool suspend)
-{
-       struct nvkm_device *device = (void *)object;
-       struct nvkm_object *subdev;
-       int ret, i;
-
-       for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) {
-               if ((subdev = device->subdev[i])) {
-                       if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
-                               ret = nvkm_object_dec(subdev, suspend);
-                               if (ret && suspend)
-                                       goto fail;
-                       }
-               }
-       }
-
-       ret = nvkm_acpi_fini(device, suspend);
-fail:
-       for (; ret && i < NVDEV_SUBDEV_NR; i++) {
-               if ((subdev = device->subdev[i])) {
-                       if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
-                               ret = nvkm_object_inc(subdev);
-                               if (ret) {
-                                       /* XXX */
-                               }
-                       }
+       if (mmio) {
+               device->pri = ioremap(mmio_base, mmio_size);
+               if (!device->pri) {
+                       nvdev_error(device, "unable to map PRI\n");
+                       return -ENOMEM;
                }
        }
 
-       return ret;
-}
-
-static int
-nvkm_device_init(struct nvkm_object *object)
-{
-       struct nvkm_device *device = (void *)object;
-       struct nvkm_object *subdev;
-       int ret, i = 0;
-
-       ret = nvkm_acpi_init(device);
-       if (ret)
-               goto fail;
-
-       for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
-               if ((subdev = device->subdev[i])) {
-                       if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
-                               ret = nvkm_object_inc(subdev);
-                               if (ret)
-                                       goto fail;
-                       } else {
-                               nvkm_subdev_reset(subdev);
-                       }
+       mutex_init(&device->mutex);
+
+       for (i = 0; i < NVKM_SUBDEV_NR; i++) {
+#define _(s,m) case s:                                                         \
+       if (device->chip->m && (subdev_mask & (1ULL << (s)))) {                \
+               ret = device->chip->m(device, (s), &device->m);                \
+               if (ret) {                                                     \
+                       subdev = nvkm_device_subdev(device, (s));              \
+                       nvkm_subdev_del(&subdev);                              \
+                       device->m = NULL;                                      \
+                       if (ret != -ENODEV) {                                  \
+                               nvdev_error(device, "%s ctor failed, %d\n",    \
+                                           nvkm_subdev_name[s], ret);         \
+                               goto done;                                     \
+                       }                                                      \
+               }                                                              \
+       }                                                                      \
+       break
+               switch (i) {
+               _(NVKM_SUBDEV_BAR    ,     bar);
+               _(NVKM_SUBDEV_VBIOS  ,    bios);
+               _(NVKM_SUBDEV_BUS    ,     bus);
+               _(NVKM_SUBDEV_CLK    ,     clk);
+               _(NVKM_SUBDEV_DEVINIT, devinit);
+               _(NVKM_SUBDEV_FB     ,      fb);
+               _(NVKM_SUBDEV_FUSE   ,    fuse);
+               _(NVKM_SUBDEV_GPIO   ,    gpio);
+               _(NVKM_SUBDEV_I2C    ,     i2c);
+               _(NVKM_SUBDEV_IBUS   ,    ibus);
+               _(NVKM_SUBDEV_INSTMEM,    imem);
+               _(NVKM_SUBDEV_LTC    ,     ltc);
+               _(NVKM_SUBDEV_MC     ,      mc);
+               _(NVKM_SUBDEV_MMU    ,     mmu);
+               _(NVKM_SUBDEV_MXM    ,     mxm);
+               _(NVKM_SUBDEV_PCI    ,     pci);
+               _(NVKM_SUBDEV_PMU    ,     pmu);
+               _(NVKM_SUBDEV_THERM  ,   therm);
+               _(NVKM_SUBDEV_TIMER  ,   timer);
+               _(NVKM_SUBDEV_VOLT   ,    volt);
+               _(NVKM_ENGINE_BSP    ,     bsp);
+               _(NVKM_ENGINE_CE0    ,   ce[0]);
+               _(NVKM_ENGINE_CE1    ,   ce[1]);
+               _(NVKM_ENGINE_CE2    ,   ce[2]);
+               _(NVKM_ENGINE_CIPHER ,  cipher);
+               _(NVKM_ENGINE_DISP   ,    disp);
+               _(NVKM_ENGINE_DMAOBJ ,     dma);
+               _(NVKM_ENGINE_FIFO   ,    fifo);
+               _(NVKM_ENGINE_GR     ,      gr);
+               _(NVKM_ENGINE_IFB    ,     ifb);
+               _(NVKM_ENGINE_ME     ,      me);
+               _(NVKM_ENGINE_MPEG   ,    mpeg);
+               _(NVKM_ENGINE_MSENC  ,   msenc);
+               _(NVKM_ENGINE_MSPDEC ,  mspdec);
+               _(NVKM_ENGINE_MSPPP  ,   msppp);
+               _(NVKM_ENGINE_MSVLD  ,   msvld);
+               _(NVKM_ENGINE_PM     ,      pm);
+               _(NVKM_ENGINE_SEC    ,     sec);
+               _(NVKM_ENGINE_SW     ,      sw);
+               _(NVKM_ENGINE_VIC    ,     vic);
+               _(NVKM_ENGINE_VP     ,      vp);
+               default:
+                       WARN_ON(1);
+                       continue;
                }
+#undef _
        }
 
        ret = 0;
-fail:
-       for (--i; ret && i >= 0; i--) {
-               if ((subdev = device->subdev[i])) {
-                       if (!nv_iclass(subdev, NV_ENGINE_CLASS))
-                               nvkm_object_dec(subdev, false);
-               }
-       }
-
-       if (ret)
-               nvkm_acpi_fini(device, false);
-       return ret;
-}
-
-static void
-nvkm_device_dtor(struct nvkm_object *object)
-{
-       struct nvkm_device *device = (void *)object;
-
-       nvkm_event_fini(&device->event);
-
-       mutex_lock(&nv_devices_mutex);
-       list_del(&device->head);
-       mutex_unlock(&nv_devices_mutex);
-
-       if (nv_subdev(device)->mmio)
-               iounmap(nv_subdev(device)->mmio);
-
-       nvkm_engine_destroy(&device->engine);
-}
-
-resource_size_t
-nv_device_resource_start(struct nvkm_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 nvkm_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);
-       }
-}
-
-int
-nv_device_get_irq(struct nvkm_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 nvkm_oclass
-nvkm_device_oclass = {
-       .handle = NV_ENGINE(DEVICE, 0x00),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .dtor = nvkm_device_dtor,
-               .init = nvkm_device_init,
-               .fini = nvkm_device_fini,
-       },
-};
-
-int
-nvkm_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 nvkm_device *device;
-       int ret = -EEXIST;
-
-       mutex_lock(&nv_devices_mutex);
-       list_for_each_entry(device, &nv_devices, head) {
-               if (device->handle == name)
-                       goto done;
-       }
-
-       ret = nvkm_engine_create_(NULL, NULL, &nvkm_device_oclass, true,
-                                 "DEVICE", "device", length, pobject);
-       device = *pobject;
-       if (ret)
-               goto done;
-
-       switch (type) {
-       case NVKM_BUS_PCI:
-               device->pdev = dev;
-               break;
-       case NVKM_BUS_PLATFORM:
-               device->platformdev = dev;
-               break;
-       }
-       device->handle = name;
-       device->cfgopt = cfg;
-       device->dbgopt = dbg;
-       device->name = sname;
-
-       nv_subdev(device)->debug = nvkm_dbgopt(device->dbgopt, "DEVICE");
-       nv_engine(device)->sclass = nvkm_device_sclass;
-       list_add(&device->head, &nv_devices);
-
-       ret = nvkm_event_init(&nvkm_device_event_func, 1, 1, &device->event);
 done:
        mutex_unlock(&nv_devices_mutex);
        return ret;