#ifndef __NVBIOS_INIT_H__
 #define __NVBIOS_INIT_H__
+
 struct nvbios_init {
        struct nvkm_subdev *subdev;
        struct nvkm_bios *bios;
 
 #ifndef __NVKM_DEVINIT_H__
 #define __NVKM_DEVINIT_H__
 #include <core/subdev.h>
+struct nvkm_devinit;
 
 struct nvkm_devinit {
+       const struct nvkm_devinit_func *func;
        struct nvkm_subdev subdev;
        bool post;
-       void (*meminit)(struct nvkm_devinit *);
-       int  (*pll_set)(struct nvkm_devinit *, u32 type, u32 freq);
-       u32  (*mmio)(struct nvkm_devinit *, u32 addr);
 };
 
-static inline struct nvkm_devinit *
-nvkm_devinit(void *obj)
-{
-       return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_DEVINIT);
-}
+u32 nvkm_devinit_mmio(struct nvkm_devinit *, u32 addr);
+int nvkm_devinit_pll_set(struct nvkm_devinit *, u32 type, u32 khz);
+void nvkm_devinit_meminit(struct nvkm_devinit *);
+u64 nvkm_devinit_disable(struct nvkm_devinit *);
 
-extern struct nvkm_oclass *nv04_devinit_oclass;
-extern struct nvkm_oclass *nv05_devinit_oclass;
-extern struct nvkm_oclass *nv10_devinit_oclass;
-extern struct nvkm_oclass *nv1a_devinit_oclass;
-extern struct nvkm_oclass *nv20_devinit_oclass;
-extern struct nvkm_oclass *nv50_devinit_oclass;
-extern struct nvkm_oclass *g84_devinit_oclass;
-extern struct nvkm_oclass *g98_devinit_oclass;
-extern struct nvkm_oclass *gt215_devinit_oclass;
-extern struct nvkm_oclass *mcp89_devinit_oclass;
-extern struct nvkm_oclass *gf100_devinit_oclass;
-extern struct nvkm_oclass *gm107_devinit_oclass;
-extern struct nvkm_oclass *gm204_devinit_oclass;
+int nv04_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
+int nv05_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
+int nv10_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
+int nv1a_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
+int nv20_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
+int nv50_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
+int g84_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
+int g98_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
+int gt215_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
+int mcp89_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
+int gf100_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
+int gm107_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
+int gm204_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
 #endif
 
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv04_devinit_new,
+       .devinit = nv04_devinit_new,
 //     .fb = nv04_fb_new,
 //     .i2c = nv04_i2c_new,
 //     .imem = nv04_instmem_new,
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv05_devinit_new,
+       .devinit = nv05_devinit_new,
 //     .fb = nv04_fb_new,
 //     .i2c = nv04_i2c_new,
 //     .imem = nv04_instmem_new,
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv10_devinit_new,
+       .devinit = nv10_devinit_new,
 //     .fb = nv10_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv10_devinit_new,
+       .devinit = nv10_devinit_new,
 //     .fb = nv10_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv10_devinit_new,
+       .devinit = nv10_devinit_new,
 //     .fb = nv10_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv10_devinit_new,
+       .devinit = nv10_devinit_new,
 //     .fb = nv10_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv10_devinit_new,
+       .devinit = nv10_devinit_new,
 //     .fb = nv10_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv1a_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv1a_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv20_devinit_new,
+       .devinit = nv20_devinit_new,
 //     .fb = nv20_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv20_devinit_new,
+       .devinit = nv20_devinit_new,
 //     .fb = nv25_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv20_devinit_new,
+       .devinit = nv20_devinit_new,
 //     .fb = nv25_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv20_devinit_new,
+       .devinit = nv20_devinit_new,
 //     .fb = nv25_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv20_devinit_new,
+       .devinit = nv20_devinit_new,
 //     .fb = nv30_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv20_devinit_new,
+       .devinit = nv20_devinit_new,
 //     .fb = nv30_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv10_devinit_new,
+       .devinit = nv10_devinit_new,
 //     .fb = nv10_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv04_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv20_devinit_new,
+       .devinit = nv20_devinit_new,
 //     .fb = nv35_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv04_clk_new,
-//     .devinit = nv20_devinit_new,
+       .devinit = nv20_devinit_new,
 //     .fb = nv36_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv40_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv41_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv41_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv41_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv44_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv40_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv46_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv47_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv49_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv44_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv49_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv46_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv4e_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv4e_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv50_bus_new,
        .clk = nv50_clk_new,
-//     .devinit = nv50_devinit_new,
+       .devinit = nv50_devinit_new,
 //     .fb = nv50_fb_new,
 //     .fuse = nv50_fuse_new,
 //     .gpio = nv50_gpio_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv46_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv46_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv31_bus_new,
        .clk = nv40_clk_new,
-//     .devinit = nv1a_devinit_new,
+       .devinit = nv1a_devinit_new,
 //     .fb = nv46_fb_new,
 //     .gpio = nv10_gpio_new,
 //     .i2c = nv04_i2c_new,
        .bios = nvkm_bios_new,
        .bus = nv50_bus_new,
        .clk = g84_clk_new,
-//     .devinit = g84_devinit_new,
+       .devinit = g84_devinit_new,
 //     .fb = g84_fb_new,
 //     .fuse = nv50_fuse_new,
 //     .gpio = nv50_gpio_new,
        .bios = nvkm_bios_new,
        .bus = nv50_bus_new,
        .clk = g84_clk_new,
-//     .devinit = g84_devinit_new,
+       .devinit = g84_devinit_new,
 //     .fb = g84_fb_new,
 //     .fuse = nv50_fuse_new,
 //     .gpio = nv50_gpio_new,
        .bios = nvkm_bios_new,
        .bus = nv50_bus_new,
        .clk = g84_clk_new,
-//     .devinit = g84_devinit_new,
+       .devinit = g84_devinit_new,
 //     .fb = g84_fb_new,
 //     .fuse = nv50_fuse_new,
 //     .gpio = nv50_gpio_new,
        .bios = nvkm_bios_new,
        .bus = g94_bus_new,
        .clk = g84_clk_new,
-//     .devinit = g84_devinit_new,
+       .devinit = g84_devinit_new,
 //     .fb = g84_fb_new,
 //     .fuse = nv50_fuse_new,
 //     .gpio = g94_gpio_new,
        .clk = g84_clk_new,
 //     .therm = g84_therm_new,
 //     .mxm = nv50_mxm_new,
-//     .devinit = g84_devinit_new,
+       .devinit = g84_devinit_new,
 //     .mc = g94_mc_new,
        .bus = g94_bus_new,
 //     .timer = nv04_timer_new,
        .clk = g84_clk_new,
 //     .therm = g84_therm_new,
 //     .mxm = nv50_mxm_new,
-//     .devinit = g98_devinit_new,
+       .devinit = g98_devinit_new,
 //     .mc = g98_mc_new,
        .bus = g94_bus_new,
 //     .timer = nv04_timer_new,
        .bios = nvkm_bios_new,
        .bus = g94_bus_new,
        .clk = g84_clk_new,
-//     .devinit = g84_devinit_new,
+       .devinit = g84_devinit_new,
 //     .fb = g84_fb_new,
 //     .fuse = nv50_fuse_new,
 //     .gpio = g94_gpio_new,
        .bios = nvkm_bios_new,
        .bus = g94_bus_new,
        .clk = gt215_clk_new,
-//     .devinit = gt215_devinit_new,
+       .devinit = gt215_devinit_new,
 //     .fb = gt215_fb_new,
 //     .fuse = nv50_fuse_new,
 //     .gpio = g94_gpio_new,
        .bios = nvkm_bios_new,
        .bus = g94_bus_new,
        .clk = gt215_clk_new,
-//     .devinit = gt215_devinit_new,
+       .devinit = gt215_devinit_new,
 //     .fb = gt215_fb_new,
 //     .fuse = nv50_fuse_new,
 //     .gpio = g94_gpio_new,
        .bios = nvkm_bios_new,
        .bus = g94_bus_new,
        .clk = gt215_clk_new,
-//     .devinit = gt215_devinit_new,
+       .devinit = gt215_devinit_new,
 //     .fb = gt215_fb_new,
 //     .fuse = nv50_fuse_new,
 //     .gpio = g94_gpio_new,
        .bios = nvkm_bios_new,
        .bus = g94_bus_new,
        .clk = mcp77_clk_new,
-//     .devinit = g98_devinit_new,
+       .devinit = g98_devinit_new,
 //     .fb = mcp77_fb_new,
 //     .fuse = nv50_fuse_new,
 //     .gpio = g94_gpio_new,
        .bios = nvkm_bios_new,
        .bus = g94_bus_new,
        .clk = mcp77_clk_new,
-//     .devinit = g98_devinit_new,
+       .devinit = g98_devinit_new,
 //     .fb = mcp77_fb_new,
 //     .fuse = nv50_fuse_new,
 //     .gpio = g94_gpio_new,
        .bios = nvkm_bios_new,
        .bus = g94_bus_new,
        .clk = gt215_clk_new,
-//     .devinit = mcp89_devinit_new,
+       .devinit = mcp89_devinit_new,
 //     .fb = mcp89_fb_new,
 //     .fuse = nv50_fuse_new,
 //     .gpio = g94_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gf100_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gf100_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = g94_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gf100_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gf100_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = g94_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gf100_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gf100_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = g94_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gf100_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gf100_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = g94_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gf100_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gf100_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = g94_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gf100_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gf100_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = g94_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gf100_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gf100_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = g94_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gf100_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gf100_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = gf110_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gf100_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gf100_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = gf110_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gk104_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gk104_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = gk104_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gk104_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gk104_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = gk104_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gk104_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gk104_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = gk104_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gk104_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gk104_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = gk104_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gk104_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gk104_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = gk104_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gk104_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gk104_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = gk104_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gk104_clk_new,
-//     .devinit = gf100_devinit_new,
+       .devinit = gf100_devinit_new,
 //     .fb = gk104_fb_new,
 //     .fuse = gf100_fuse_new,
 //     .gpio = gk104_gpio_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
        .clk = gk104_clk_new,
-//     .devinit = gm107_devinit_new,
+       .devinit = gm107_devinit_new,
 //     .fb = gm107_fb_new,
 //     .fuse = gm107_fuse_new,
 //     .gpio = gk104_gpio_new,
        .bar = gf100_bar_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
-//     .devinit = gm204_devinit_new,
+       .devinit = gm204_devinit_new,
 //     .fb = gm107_fb_new,
 //     .fuse = gm107_fuse_new,
 //     .gpio = gk104_gpio_new,
        .bar = gf100_bar_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
-//     .devinit = gm204_devinit_new,
+       .devinit = gm204_devinit_new,
 //     .fb = gm107_fb_new,
 //     .fuse = gm107_fuse_new,
 //     .gpio = gk104_gpio_new,
 
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = >215_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gf100_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gf100_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = >215_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gf100_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gf100_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = >215_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gf106_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gf100_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = >215_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gf100_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gf100_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = >215_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gf106_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gf100_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = >215_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gf106_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gf100_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = >215_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gf100_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gf100_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &gf110_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gf106_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gf100_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &gf110_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gf106_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gf100_fb_oclass;
 
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &gf110_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gf106_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gk104_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &gf110_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gf106_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gk104_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &gf110_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gf106_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gk104_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &gf110_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gf106_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gk104_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &gf110_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gf106_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gk104_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &gf110_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gk20a_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gk104_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &gf110_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gf100_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gk20a_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gk104_fb_oclass;
 
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gm107_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &gm107_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gm107_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gk20a_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &gk20a_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gm107_fb_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &gm107_therm_oclass;
 #endif
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gm204_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gk20a_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &gk20a_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gm107_fb_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &gm107_therm_oclass;
 #endif
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gm204_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gk20a_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &gk20a_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gm107_fb_oclass;
 
        switch (device->chipset) {
        case 0x04:
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv04_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv04_fb_oclass;
                break;
        case 0x05:
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv05_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv04_fb_oclass;
 
        case 0x10:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
        case 0x15:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
        case 0x16:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
        case 0x1a:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv1a_fb_oclass;
        case 0x11:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
        case 0x17:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
        case 0x1f:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv1a_fb_oclass;
        case 0x18:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
 
        case 0x20:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv20_fb_oclass;
        case 0x25:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
        case 0x28:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
        case 0x2a:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
 
        case 0x30:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv30_fb_oclass;
        case 0x35:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv35_fb_oclass;
        case 0x31:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv30_fb_oclass;
        case 0x36:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv36_fb_oclass;
        case 0x34:
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
 
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv40_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv40_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv47_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv49_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv49_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv44_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv44_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv4e_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv4e_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
 
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &nv50_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv50_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &nv50_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &g84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  g84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  g84_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &nv50_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &g84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  g84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  g84_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &nv50_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &g84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  g84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  g84_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &nv50_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &g84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  g84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  g94_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  g84_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &nv50_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &g84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  g84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  g94_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  g84_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &nv50_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &g84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  g98_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  g98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  g84_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &nv50_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &g84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  g84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  g98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  g84_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &nv50_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &g84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  g98_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  g98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  mcp77_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &nv50_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &g84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  g98_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  g98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  mcp77_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &nv50_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = >215_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gt215_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  g98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gt215_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &nv50_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = >215_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gt215_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  g98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gt215_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &nv50_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = >215_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gt215_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  g98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  gt215_fb_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &nv50_fuse_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = >215_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] =  mcp89_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  g98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  mcp89_fb_oclass;
 
        struct nvkm_devinit *devinit = device->devinit;
        u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000;
        if (pclk)
-               devinit->pll_set(devinit, PLL_VPLL0 + head, pclk);
+               nvkm_devinit_pll_set(devinit, PLL_VPLL0 + head, pclk);
        nvkm_wr32(device, 0x612200 + (head * 0x800), 0x00000000);
 }
 
 
        struct nvkm_devinit *devinit = device->devinit;
        u32 pclk = nvkm_rd32(device, 0x610ad0 + (head * 0x540)) & 0x3fffff;
        if (pclk)
-               devinit->pll_set(devinit, PLL_VPLL0 + head, pclk);
+               nvkm_devinit_pll_set(devinit, PLL_VPLL0 + head, pclk);
 }
 
 static void
 
        if (reg & ~0x00fffffc)
                warn("unknown bits in register 0x%08x\n", reg);
 
-       if (devinit->mmio)
-               reg = devinit->mmio(devinit, reg);
-       return reg;
+       return nvkm_devinit_mmio(devinit, reg);
 }
 
 static u32
 init_prog_pll(struct nvbios_init *init, u32 id, u32 freq)
 {
        struct nvkm_devinit *devinit = init->bios->subdev.device->devinit;
-       if (devinit->pll_set && init_exec(init)) {
-               int ret = devinit->pll_set(devinit, id, freq);
+       if (init_exec(init)) {
+               int ret = nvkm_devinit_pll_set(devinit, id, freq);
                if (ret)
                        warn("failed to prog pll 0x%08x to %dkHz\n", id, freq);
        }
        init->offset += 1;
 
        init_exec_force(init, true);
-       if (init_exec(init) && devinit->meminit)
-               devinit->meminit(devinit);
+       if (init_exec(init))
+               nvkm_devinit_meminit(devinit);
        init_exec_force(init, false);
 }
 
 
 #include <core/option.h>
 #include <subdev/vga.h>
 
+u32
+nvkm_devinit_mmio(struct nvkm_devinit *init, u32 addr)
+{
+       if (init->func->mmio)
+               addr = init->func->mmio(init, addr);
+       return addr;
+}
+
 int
-_nvkm_devinit_fini(struct nvkm_object *object, bool suspend)
+nvkm_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 khz)
+{
+       return init->func->pll_set(init, type, khz);
+}
+
+void
+nvkm_devinit_meminit(struct nvkm_devinit *init)
+{
+       if (init->func->meminit)
+               init->func->meminit(init);
+}
+
+u64
+nvkm_devinit_disable(struct nvkm_devinit *init)
 {
-       struct nvkm_devinit *init = (void *)object;
+       if (init->func->disable)
+               return init->func->disable(init);
+       return 0;
+}
 
+static int
+nvkm_devinit_fini(struct nvkm_subdev *subdev, bool suspend)
+{
+       struct nvkm_devinit *init = nvkm_devinit(subdev);
        /* force full reinit on resume */
        if (suspend)
                init->post = true;
+       return 0;
+}
 
-       /* unlock the extended vga crtc regs */
-       nvkm_lockvgac(init->subdev.device, false);
+static int
+nvkm_devinit_preinit(struct nvkm_subdev *subdev)
+{
+       struct nvkm_devinit *init = nvkm_devinit(subdev);
+
+       if (init->func->preinit)
+               init->func->preinit(init);
 
-       return nvkm_subdev_fini_old(&init->subdev, suspend);
+       /* unlock the extended vga crtc regs */
+       nvkm_lockvgac(subdev->device, false);
+       return 0;
 }
 
-int
-_nvkm_devinit_init(struct nvkm_object *object)
+static int
+nvkm_devinit_init(struct nvkm_subdev *subdev)
 {
-       struct nvkm_devinit_impl *impl = (void *)object->oclass;
-       struct nvkm_devinit *init = (void *)object;
+       struct nvkm_devinit *init = nvkm_devinit(subdev);
        int ret;
 
-       ret = nvkm_subdev_init_old(&init->subdev);
+       ret = init->func->post(init, init->post);
        if (ret)
                return ret;
 
-       ret = impl->post(&init->subdev, init->post);
-       if (ret)
-               return ret;
+       if (init->func->init)
+               init->func->init(init);
 
-       if (impl->disable)
-               nv_device(init)->disable_mask |= impl->disable(init);
+       if (init->func->disable)
+               subdev->device->disable_mask |= init->func->disable(init);
        return 0;
 }
 
-void
-_nvkm_devinit_dtor(struct nvkm_object *object)
+static void *
+nvkm_devinit_dtor(struct nvkm_subdev *subdev)
 {
-       struct nvkm_devinit *init = (void *)object;
+       struct nvkm_devinit *init = nvkm_devinit(subdev);
+       void *data = init;
 
-       /* lock crtc regs */
-       nvkm_lockvgac(init->subdev.device, true);
+       if (init->func->dtor)
+               data = init->func->dtor(init);
 
-       nvkm_subdev_destroy(&init->subdev);
+       /* lock crtc regs */
+       nvkm_lockvgac(subdev->device, true);
+       return data;
 }
 
-int
-nvkm_devinit_create_(struct nvkm_object *parent, struct nvkm_object *engine,
-                    struct nvkm_oclass *oclass, int size, void **pobject)
-{
-       struct nvkm_devinit_impl *impl = (void *)oclass;
-       struct nvkm_device *device = nv_device(parent);
-       struct nvkm_devinit *init;
-       int ret;
-
-       ret = nvkm_subdev_create_(parent, engine, oclass, 0, "DEVINIT",
-                                 "init", size, pobject);
-       init = *pobject;
-       if (ret)
-               return ret;
+static const struct nvkm_subdev_func
+nvkm_devinit = {
+       .dtor = nvkm_devinit_dtor,
+       .preinit = nvkm_devinit_preinit,
+       .init = nvkm_devinit_init,
+       .fini = nvkm_devinit_fini,
+};
 
+void
+nvkm_devinit_ctor(const struct nvkm_devinit_func *func,
+                 struct nvkm_device *device, int index,
+                 struct nvkm_devinit *init)
+{
+       nvkm_subdev_ctor(&nvkm_devinit, device, index, 0, &init->subdev);
+       init->func = func;
        init->post = nvkm_boolopt(device->cfgopt, "NvForcePost", false);
-       init->meminit = impl->meminit;
-       init->pll_set = impl->pll_set;
-       init->mmio    = impl->mmio;
-       return 0;
 }
 
        return disable;
 }
 
-struct nvkm_oclass *
-g84_devinit_oclass = &(struct nvkm_devinit_impl) {
-       .base.handle = NV_SUBDEV(DEVINIT, 0x84),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv50_devinit_ctor,
-               .dtor = _nvkm_devinit_dtor,
-               .init = nv50_devinit_init,
-               .fini = _nvkm_devinit_fini,
-       },
+static const struct nvkm_devinit_func
+g84_devinit = {
+       .preinit = nv50_devinit_preinit,
+       .init = nv50_devinit_init,
+       .post = nv04_devinit_post,
        .pll_set = nv50_devinit_pll_set,
        .disable = g84_devinit_disable,
-       .post = nvbios_init,
-}.base;
+};
+
+int
+g84_devinit_new(struct nvkm_device *device, int index,
+               struct nvkm_devinit **pinit)
+{
+       return nv50_devinit_new_(&g84_devinit, device, index, pinit);
+}
 
        return disable;
 }
 
-struct nvkm_oclass *
-g98_devinit_oclass = &(struct nvkm_devinit_impl) {
-       .base.handle = NV_SUBDEV(DEVINIT, 0x98),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv50_devinit_ctor,
-               .dtor = _nvkm_devinit_dtor,
-               .init = nv50_devinit_init,
-               .fini = _nvkm_devinit_fini,
-       },
+static const struct nvkm_devinit_func
+g98_devinit = {
+       .preinit = nv50_devinit_preinit,
+       .init = nv50_devinit_init,
+       .post = nv04_devinit_post,
        .pll_set = nv50_devinit_pll_set,
        .disable = g98_devinit_disable,
-       .post = nvbios_init,
-}.base;
+};
+
+int
+g98_devinit_new(struct nvkm_device *device, int index,
+               struct nvkm_devinit **pinit)
+{
+       return nv50_devinit_new_(&g98_devinit, device, index, pinit);
+}
 
        return disable;
 }
 
+static const struct nvkm_devinit_func
+gf100_devinit = {
+       .preinit = nv50_devinit_preinit,
+       .init = nv50_devinit_init,
+       .post = nv04_devinit_post,
+       .pll_set = gf100_devinit_pll_set,
+       .disable = gf100_devinit_disable,
+};
+
 int
-gf100_devinit_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-                  struct nvkm_oclass *oclass, void *data, u32 size,
-                  struct nvkm_object **pobject)
+gf100_devinit_new(struct nvkm_device *device, int index,
+               struct nvkm_devinit **pinit)
 {
-       struct nvkm_devinit_impl *impl = (void *)oclass;
-       struct nv50_devinit *init;
-       u64 disable;
-       int ret;
-
-       ret = nvkm_devinit_create(parent, engine, oclass, &init);
-       *pobject = nv_object(init);
-       if (ret)
-               return ret;
-
-       disable = impl->disable(&init->base);
-       if (disable & (1ULL << NVDEV_ENGINE_DISP))
-               init->base.post = true;
-
-       return 0;
+       return nv50_devinit_new_(&gf100_devinit, device, index, pinit);
 }
-
-struct nvkm_oclass *
-gf100_devinit_oclass = &(struct nvkm_devinit_impl) {
-       .base.handle = NV_SUBDEV(DEVINIT, 0xc0),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = gf100_devinit_ctor,
-               .dtor = _nvkm_devinit_dtor,
-               .init = nv50_devinit_init,
-               .fini = _nvkm_devinit_fini,
-       },
-       .pll_set = gf100_devinit_pll_set,
-       .disable = gf100_devinit_disable,
-       .post = nvbios_init,
-}.base;
 
        return disable;
 }
 
-struct nvkm_oclass *
-gm107_devinit_oclass = &(struct nvkm_devinit_impl) {
-       .base.handle = NV_SUBDEV(DEVINIT, 0x07),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = gf100_devinit_ctor,
-               .dtor = _nvkm_devinit_dtor,
-               .init = nv50_devinit_init,
-               .fini = _nvkm_devinit_fini,
-       },
+static const struct nvkm_devinit_func
+gm107_devinit = {
+       .preinit = nv50_devinit_preinit,
+       .init = nv50_devinit_init,
+       .post = nv04_devinit_post,
        .pll_set = gf100_devinit_pll_set,
        .disable = gm107_devinit_disable,
-       .post = nvbios_init,
-}.base;
+};
+
+int
+gm107_devinit_new(struct nvkm_device *device, int index,
+               struct nvkm_devinit **pinit)
+{
+       return nv50_devinit_new_(&gm107_devinit, device, index, pinit);
+}
 
 }
 
 static int
-gm204_devinit_post(struct nvkm_subdev *subdev, bool post)
+gm204_devinit_post(struct nvkm_devinit *base, bool post)
 {
-       struct nv50_devinit *init = (void *)nvkm_devinit(subdev);
+       struct nv50_devinit *init = nv50_devinit(base);
+       struct nvkm_subdev *subdev = &init->base.subdev;
        struct nvkm_device *device = subdev->device;
        struct nvkm_bios *bios = device->bios;
        struct bit_entry bit_I;
        return pmu_load(init, 0x01, post, NULL, NULL);
 }
 
-struct nvkm_oclass *
-gm204_devinit_oclass = &(struct nvkm_devinit_impl) {
-       .base.handle = NV_SUBDEV(DEVINIT, 0x07),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = gf100_devinit_ctor,
-               .dtor = _nvkm_devinit_dtor,
-               .init = nv50_devinit_init,
-               .fini = _nvkm_devinit_fini,
-       },
+static const struct nvkm_devinit_func
+gm204_devinit = {
+       .preinit = nv50_devinit_preinit,
+       .init = nv50_devinit_init,
+       .post = gm204_devinit_post,
        .pll_set = gf100_devinit_pll_set,
        .disable = gm107_devinit_disable,
-       .post = gm204_devinit_post,
-}.base;
+};
+
+int
+gm204_devinit_new(struct nvkm_device *device, int index,
+               struct nvkm_devinit **pinit)
+{
+       return nv50_devinit_new_(&gm204_devinit, device, index, pinit);
+}
 
 };
 
 static u32
-gt215_devinit_mmio(struct nvkm_devinit *obj, u32 addr)
+gt215_devinit_mmio(struct nvkm_devinit *base, u32 addr)
 {
-       struct nv50_devinit *init = container_of(obj, typeof(*init), base);
+       struct nv50_devinit *init = nv50_devinit(base);
        struct nvkm_device *device = init->base.subdev.device;
        u32 *mmio = gt215_devinit_mmio_part;
 
        return addr;
 }
 
-struct nvkm_oclass *
-gt215_devinit_oclass = &(struct nvkm_devinit_impl) {
-       .base.handle = NV_SUBDEV(DEVINIT, 0xa3),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv50_devinit_ctor,
-               .dtor = _nvkm_devinit_dtor,
-               .init = nv50_devinit_init,
-               .fini = _nvkm_devinit_fini,
-       },
+static const struct nvkm_devinit_func
+gt215_devinit = {
+       .preinit = nv50_devinit_preinit,
+       .init = nv50_devinit_init,
+       .post = nv04_devinit_post,
+       .mmio = gt215_devinit_mmio,
        .pll_set = gt215_devinit_pll_set,
        .disable = gt215_devinit_disable,
-       .mmio    = gt215_devinit_mmio,
-       .post = nvbios_init,
-}.base;
+};
+
+int
+gt215_devinit_new(struct nvkm_device *device, int index,
+               struct nvkm_devinit **pinit)
+{
+       return nv50_devinit_new_(>215_devinit, device, index, pinit);
+}
 
        return disable;
 }
 
-struct nvkm_oclass *
-mcp89_devinit_oclass = &(struct nvkm_devinit_impl) {
-       .base.handle = NV_SUBDEV(DEVINIT, 0xaf),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv50_devinit_ctor,
-               .dtor = _nvkm_devinit_dtor,
-               .init = nv50_devinit_init,
-               .fini = _nvkm_devinit_fini,
-       },
+static const struct nvkm_devinit_func
+mcp89_devinit = {
+       .preinit = nv50_devinit_preinit,
+       .init = nv50_devinit_init,
+       .post = nv04_devinit_post,
        .pll_set = gt215_devinit_pll_set,
        .disable = mcp89_devinit_disable,
-       .post = nvbios_init,
-}.base;
+};
+
+int
+mcp89_devinit_new(struct nvkm_device *device, int index,
+               struct nvkm_devinit **pinit)
+{
+       return nv50_devinit_new_(&mcp89_devinit, device, index, pinit);
+}
 
 }
 
 int
-nv04_devinit_fini(struct nvkm_object *object, bool suspend)
+nv04_devinit_post(struct nvkm_devinit *init, bool execute)
 {
-       struct nv04_devinit *init = (void *)object;
-       struct nvkm_device *device = init->base.subdev.device;
-       int ret;
+       return nvbios_init(&init->subdev, execute);
+}
+
+void
+nv04_devinit_preinit(struct nvkm_devinit *base)
+{
+       struct nv04_devinit *init = nv04_devinit(base);
+       struct nvkm_subdev *subdev = &init->base.subdev;
+       struct nvkm_device *device = subdev->device;
 
        /* make i2c busses accessible */
        nvkm_mask(device, 0x000200, 0x00000001, 0x00000001);
 
-       ret = nvkm_devinit_fini(&init->base, suspend);
-       if (ret)
-               return ret;
-
        /* unslave crtcs */
        if (init->owner < 0)
                init->owner = nvkm_rdvgaowner(device);
        nvkm_wrvgaowner(device, 0);
-       return 0;
-}
-
-int
-nv04_devinit_init(struct nvkm_object *object)
-{
-       struct nv04_devinit *init = (void *)object;
-       struct nvkm_subdev *subdev = &init->base.subdev;
-       struct nvkm_device *device = subdev->device;
 
        if (!init->base.post) {
                u32 htotal = nvkm_rdvgac(device, 0, 0x06);
                        init->base.post = true;
                }
        }
-
-       return nvkm_devinit_init(&init->base);
 }
 
-void
-nv04_devinit_dtor(struct nvkm_object *object)
+void *
+nv04_devinit_dtor(struct nvkm_devinit *base)
 {
-       struct nv04_devinit *init = (void *)object;
-
+       struct nv04_devinit *init = nv04_devinit(base);
        /* restore vga owner saved at first init */
        nvkm_wrvgaowner(init->base.subdev.device, init->owner);
-
-       nvkm_devinit_destroy(&init->base);
+       return init;
 }
 
 int
-nv04_devinit_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-                 struct nvkm_oclass *oclass, void *data, u32 size,
-                 struct nvkm_object **pobject)
+nv04_devinit_new_(const struct nvkm_devinit_func *func,
+                 struct nvkm_device *device, int index,
+                 struct nvkm_devinit **pinit)
 {
        struct nv04_devinit *init;
-       int ret;
 
-       ret = nvkm_devinit_create(parent, engine, oclass, &init);
-       *pobject = nv_object(init);
-       if (ret)
-               return ret;
+       if (!(init = kzalloc(sizeof(*init), GFP_KERNEL)))
+               return -ENOMEM;
+       *pinit = &init->base;
 
+       nvkm_devinit_ctor(func, device, index, &init->base);
        init->owner = -1;
        return 0;
 }
 
-struct nvkm_oclass *
-nv04_devinit_oclass = &(struct nvkm_devinit_impl) {
-       .base.handle = NV_SUBDEV(DEVINIT, 0x04),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv04_devinit_ctor,
-               .dtor = nv04_devinit_dtor,
-               .init = nv04_devinit_init,
-               .fini = nv04_devinit_fini,
-       },
+static const struct nvkm_devinit_func
+nv04_devinit = {
+       .dtor = nv04_devinit_dtor,
+       .preinit = nv04_devinit_preinit,
+       .post = nv04_devinit_post,
        .meminit = nv04_devinit_meminit,
        .pll_set = nv04_devinit_pll_set,
-       .post = nvbios_init,
-}.base;
+};
+
+int
+nv04_devinit_new(struct nvkm_device *device, int index,
+                struct nvkm_devinit **pinit)
+{
+       return nv04_devinit_new_(&nv04_devinit, device, index, pinit);
+}
 
-#ifndef __NVKM_DEVINIT_NV04_H__
-#define __NVKM_DEVINIT_NV04_H__
+#ifndef __NV04_DEVINIT_H__
+#define __NV04_DEVINIT_H__
+#define nv04_devinit(p) container_of((p), struct nv04_devinit, base)
 #include "priv.h"
 struct nvkm_pll_vals;
 
        int owner;
 };
 
-int  nv04_devinit_ctor(struct nvkm_object *, struct nvkm_object *,
-                      struct nvkm_oclass *, void *, u32,
-                      struct nvkm_object **);
-void nv04_devinit_dtor(struct nvkm_object *);
-int  nv04_devinit_init(struct nvkm_object *);
-int  nv04_devinit_fini(struct nvkm_object *, bool);
+int nv04_devinit_new_(const struct nvkm_devinit_func *, struct nvkm_device *,
+                     int, struct nvkm_devinit **);
+void *nv04_devinit_dtor(struct nvkm_devinit *);
+void nv04_devinit_preinit(struct nvkm_devinit *);
+void nv04_devinit_fini(struct nvkm_devinit *);
 int  nv04_devinit_pll_set(struct nvkm_devinit *, u32, u32);
 
 void setPLL_single(struct nvkm_devinit *, u32, struct nvkm_pll_vals *);
 
        fbmem_fini(fb);
 }
 
-struct nvkm_oclass *
-nv05_devinit_oclass = &(struct nvkm_devinit_impl) {
-       .base.handle = NV_SUBDEV(DEVINIT, 0x05),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv04_devinit_ctor,
-               .dtor = nv04_devinit_dtor,
-               .init = nv04_devinit_init,
-               .fini = nv04_devinit_fini,
-       },
+static const struct nvkm_devinit_func
+nv05_devinit = {
+       .dtor = nv04_devinit_dtor,
+       .preinit = nv04_devinit_preinit,
+       .post = nv04_devinit_post,
        .meminit = nv05_devinit_meminit,
        .pll_set = nv04_devinit_pll_set,
-       .post = nvbios_init,
-}.base;
+};
+
+int
+nv05_devinit_new(struct nvkm_device *device, int index,
+                struct nvkm_devinit **pinit)
+{
+       return nv04_devinit_new_(&nv05_devinit, device, index, pinit);
+}
 
        fbmem_fini(fb);
 }
 
-struct nvkm_oclass *
-nv10_devinit_oclass = &(struct nvkm_devinit_impl) {
-       .base.handle = NV_SUBDEV(DEVINIT, 0x10),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv04_devinit_ctor,
-               .dtor = nv04_devinit_dtor,
-               .init = nv04_devinit_init,
-               .fini = nv04_devinit_fini,
-       },
+static const struct nvkm_devinit_func
+nv10_devinit = {
+       .dtor = nv04_devinit_dtor,
+       .preinit = nv04_devinit_preinit,
+       .post = nv04_devinit_post,
        .meminit = nv10_devinit_meminit,
        .pll_set = nv04_devinit_pll_set,
-       .post = nvbios_init,
-}.base;
+};
+
+int
+nv10_devinit_new(struct nvkm_device *device, int index,
+                struct nvkm_devinit **pinit)
+{
+       return nv04_devinit_new_(&nv10_devinit, device, index, pinit);
+}
 
 #include <subdev/bios.h>
 #include <subdev/bios/init.h>
 
-struct nvkm_oclass *
-nv1a_devinit_oclass = &(struct nvkm_devinit_impl) {
-       .base.handle = NV_SUBDEV(DEVINIT, 0x1a),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv04_devinit_ctor,
-               .dtor = nv04_devinit_dtor,
-               .init = nv04_devinit_init,
-               .fini = nv04_devinit_fini,
-       },
+static const struct nvkm_devinit_func
+nv1a_devinit = {
+       .dtor = nv04_devinit_dtor,
+       .preinit = nv04_devinit_preinit,
+       .post = nv04_devinit_post,
        .pll_set = nv04_devinit_pll_set,
-       .post = nvbios_init,
-}.base;
+};
+
+int
+nv1a_devinit_new(struct nvkm_device *device, int index,
+                struct nvkm_devinit **pinit)
+{
+       return nv04_devinit_new_(&nv1a_devinit, device, index, pinit);
+}
 
        struct io_mapping *fb;
 
        /* Map the framebuffer aperture */
-       fb = fbmem_init(nv_device(init));
+       fb = fbmem_init(device);
        if (!fb) {
                nvkm_error(subdev, "failed to map fb\n");
                return;
        fbmem_fini(fb);
 }
 
-struct nvkm_oclass *
-nv20_devinit_oclass = &(struct nvkm_devinit_impl) {
-       .base.handle = NV_SUBDEV(DEVINIT, 0x20),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv04_devinit_ctor,
-               .dtor = nv04_devinit_dtor,
-               .init = nv04_devinit_init,
-               .fini = nv04_devinit_fini,
-       },
+static const struct nvkm_devinit_func
+nv20_devinit = {
+       .dtor = nv04_devinit_dtor,
+       .preinit = nv04_devinit_preinit,
+       .post = nv04_devinit_post,
        .meminit = nv20_devinit_meminit,
        .pll_set = nv04_devinit_pll_set,
-       .post = nvbios_init,
-}.base;
+};
+
+int
+nv20_devinit_new(struct nvkm_device *device, int index,
+                struct nvkm_devinit **pinit)
+{
+       return nv04_devinit_new_(&nv20_devinit, device, index, pinit);
+}
 
        return disable;
 }
 
-int
-nv50_devinit_init(struct nvkm_object *object)
+void
+nv50_devinit_preinit(struct nvkm_devinit *base)
 {
-       struct nv50_devinit *init = (void *)object;
+       struct nv50_devinit *init = nv50_devinit(base);
        struct nvkm_subdev *subdev = &init->base.subdev;
        struct nvkm_device *device = subdev->device;
-       struct nvkm_bios *bios = device->bios;
        struct nvkm_subdev *ibus = device->ibus;
-       struct nvbios_outp info;
-       struct dcb_output outp;
-       u8  ver = 0xff, hdr, cnt, len;
-       int ret, i = 0;
 
+       /* our heuristics can't detect whether the board has had its
+        * devinit scripts executed or not if the display engine is
+        * missing, assume it's a secondary gpu which requires post
+        */
+       if (!init->base.post) {
+               u64 disable = nvkm_devinit_disable(&init->base);
+               if (disable & (1ULL << NVDEV_ENGINE_DISP))
+                       init->base.post = true;
+       }
+
+       /* magic to detect whether or not x86 vbios code has executed
+        * the devinit scripts to initialise the board
+        */
        if (!init->base.post) {
                if (!nvkm_rdvgac(device, 0, 0x00) &&
                    !nvkm_rdvgac(device, 0, 0x1a)) {
         */
        if (init->base.post && ibus)
                nvkm_object_init(&ibus->object);
+}
 
-       ret = nvkm_devinit_init(&init->base);
-       if (ret)
-               return ret;
+void
+nv50_devinit_init(struct nvkm_devinit *base)
+{
+       struct nv50_devinit *init = nv50_devinit(base);
+       struct nvkm_subdev *subdev = &init->base.subdev;
+       struct nvkm_device *device = subdev->device;
+       struct nvkm_bios *bios = device->bios;
+       struct nvbios_outp info;
+       struct dcb_output outp;
+       u8  ver = 0xff, hdr, cnt, len;
+       int i = 0;
 
        /* if we ran the init tables, we have to execute the first script
         * pointer of each dcb entry's display encoder table in order
                if (nvbios_outp_match(bios, outp.hasht, outp.hashm,
                                      &ver, &hdr, &cnt, &len, &info)) {
                        struct nvbios_init exec = {
-                               .subdev = nv_subdev(init),
+                               .subdev = subdev,
                                .bios = bios,
                                .offset = info.script[0],
                                .outp = &outp,
                }
                i++;
        }
-
-       return 0;
 }
 
 int
-nv50_devinit_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-                 struct nvkm_oclass *oclass, void *data, u32 size,
-                 struct nvkm_object **pobject)
+nv50_devinit_new_(const struct nvkm_devinit_func *func,
+                 struct nvkm_device *device, int index,
+                 struct nvkm_devinit **pinit)
 {
        struct nv50_devinit *init;
-       int ret;
 
-       ret = nvkm_devinit_create(parent, engine, oclass, &init);
-       *pobject = nv_object(init);
-       if (ret)
-               return ret;
+       if (!(init = kzalloc(sizeof(*init), GFP_KERNEL)))
+               return -ENOMEM;
+       *pinit = &init->base;
 
+       nvkm_devinit_ctor(func, device, index, &init->base);
        return 0;
 }
 
-struct nvkm_oclass *
-nv50_devinit_oclass = &(struct nvkm_devinit_impl) {
-       .base.handle = NV_SUBDEV(DEVINIT, 0x50),
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv50_devinit_ctor,
-               .dtor = _nvkm_devinit_dtor,
-               .init = nv50_devinit_init,
-               .fini = _nvkm_devinit_fini,
-       },
+static const struct nvkm_devinit_func
+nv50_devinit = {
+       .preinit = nv50_devinit_preinit,
+       .init = nv50_devinit_init,
+       .post = nv04_devinit_post,
        .pll_set = nv50_devinit_pll_set,
        .disable = nv50_devinit_disable,
-       .post = nvbios_init,
-}.base;
+};
+
+int
+nv50_devinit_new(struct nvkm_device *device, int index,
+                struct nvkm_devinit **pinit)
+{
+       return nv50_devinit_new_(&nv50_devinit, device, index, pinit);
+}
 
-#ifndef __NVKM_DEVINIT_NV50_H__
-#define __NVKM_DEVINIT_NV50_H__
+#ifndef __NV50_DEVINIT_H__
+#define __NV50_DEVINIT_H__
+#define nv50_devinit(p) container_of((p), struct nv50_devinit, base)
 #include "priv.h"
 
 struct nv50_devinit {
        u32 r001540;
 };
 
-int  nv50_devinit_ctor(struct nvkm_object *, struct nvkm_object *,
-                      struct nvkm_oclass *, void *, u32,
-                      struct nvkm_object **);
-int  nv50_devinit_init(struct nvkm_object *);
+int nv50_devinit_new_(const struct nvkm_devinit_func *, struct nvkm_device *,
+                     int, struct nvkm_devinit **);
+void nv50_devinit_preinit(struct nvkm_devinit *);
+void nv50_devinit_init(struct nvkm_devinit *);
 int  nv50_devinit_pll_set(struct nvkm_devinit *, u32, u32);
 
 int  gt215_devinit_pll_set(struct nvkm_devinit *, u32, u32);
 
 #ifndef __NVKM_DEVINIT_PRIV_H__
 #define __NVKM_DEVINIT_PRIV_H__
+#define nvkm_devinit(p) container_of((p), struct nvkm_devinit, subdev)
 #include <subdev/devinit.h>
 
-struct nvkm_devinit_impl {
-       struct nvkm_oclass base;
+struct nvkm_devinit_func {
+       void *(*dtor)(struct nvkm_devinit *);
+       void (*preinit)(struct nvkm_devinit *);
+       void (*init)(struct nvkm_devinit *);
+       int  (*post)(struct nvkm_devinit *, bool post);
+       u32  (*mmio)(struct nvkm_devinit *, u32);
        void (*meminit)(struct nvkm_devinit *);
        int  (*pll_set)(struct nvkm_devinit *, u32 type, u32 freq);
        u64  (*disable)(struct nvkm_devinit *);
-       u32  (*mmio)(struct nvkm_devinit *, u32);
-       int  (*post)(struct nvkm_subdev *, bool);
 };
 
-#define nvkm_devinit_create(p,e,o,d)                                        \
-       nvkm_devinit_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nvkm_devinit_destroy(p) ({                                          \
-       struct nvkm_devinit *d = (p);                                       \
-       _nvkm_devinit_dtor(nv_object(d));                                   \
-})
-#define nvkm_devinit_init(p) ({                                             \
-       struct nvkm_devinit *d = (p);                                       \
-       _nvkm_devinit_init(nv_object(d));                                   \
-})
-#define nvkm_devinit_fini(p,s) ({                                           \
-       struct nvkm_devinit *d = (p);                                       \
-       _nvkm_devinit_fini(nv_object(d), (s));                              \
-})
+void nvkm_devinit_ctor(const struct nvkm_devinit_func *, struct nvkm_device *,
+                      int index, struct nvkm_devinit *);
 
-int nvkm_devinit_create_(struct nvkm_object *, struct nvkm_object *,
-                           struct nvkm_oclass *, int, void **);
-void _nvkm_devinit_dtor(struct nvkm_object *);
-int _nvkm_devinit_init(struct nvkm_object *);
-int _nvkm_devinit_fini(struct nvkm_object *, bool suspend);
+int nv04_devinit_post(struct nvkm_devinit *, bool);
 #endif