#define __NVKM_SEC2_H__
 #define nvkm_sec2(p) container_of((p), struct nvkm_sec2, engine)
 #include <core/engine.h>
+#include <core/falcon.h>
 
 struct nvkm_sec2 {
        const struct nvkm_sec2_func *func;
        struct nvkm_engine engine;
+       struct nvkm_falcon falcon;
        u32 addr;
 
-       struct nvkm_falcon *falcon;
        struct nvkm_msgqueue *queue;
        struct work_struct work;
 };
 
 #include <core/firmware.h>
 #include <core/msgqueue.h>
 #include <subdev/top.h>
-#include <engine/falcon.h>
 
 static void
 nvkm_sec2_intr(struct nvkm_engine *engine)
        nvkm_msgqueue_recv(sec2->queue);
 }
 
-
-static int
-nvkm_sec2_oneinit(struct nvkm_engine *engine)
-{
-       struct nvkm_sec2 *sec2 = nvkm_sec2(engine);
-       struct nvkm_subdev *subdev = &sec2->engine.subdev;
-
-       if (!sec2->addr) {
-               sec2->addr = nvkm_top_addr(subdev->device, subdev->index);
-               if (WARN_ON(!sec2->addr))
-                       return -EINVAL;
-       }
-
-       return nvkm_falcon_v1_new(subdev, "SEC2", sec2->addr, &sec2->falcon);
-}
-
 static int
 nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend)
 {
 {
        struct nvkm_sec2 *sec2 = nvkm_sec2(engine);
        nvkm_msgqueue_del(&sec2->queue);
-       nvkm_falcon_del(&sec2->falcon);
+       nvkm_falcon_dtor(&sec2->falcon);
        return sec2;
 }
 
 static const struct nvkm_engine_func
 nvkm_sec2 = {
        .dtor = nvkm_sec2_dtor,
-       .oneinit = nvkm_sec2_oneinit,
        .fini = nvkm_sec2_fini,
        .intr = nvkm_sec2_intr,
 };
 
        sec2->func = fwif->func;
 
+       ret = nvkm_falcon_ctor(sec2->func->flcn, &sec2->engine.subdev,
+                              nvkm_subdev_name[index], addr, &sec2->falcon);
+       if (ret)
+               return ret;
+
        INIT_WORK(&sec2->work, nvkm_sec2_recv);
        return 0;
 };
 
 gp102_sec2_acr_0 = {
 };
 
+
+static const struct nvkm_falcon_func
+gp102_sec2_flcn = {
+       .load_imem = nvkm_falcon_v1_load_imem,
+       .load_dmem = nvkm_falcon_v1_load_dmem,
+       .read_dmem = nvkm_falcon_v1_read_dmem,
+       .bind_context = nvkm_falcon_v1_bind_context,
+       .wait_for_halt = nvkm_falcon_v1_wait_for_halt,
+       .clear_interrupt = nvkm_falcon_v1_clear_interrupt,
+       .set_start_addr = nvkm_falcon_v1_set_start_addr,
+       .start = nvkm_falcon_v1_start,
+       .enable = nvkm_falcon_v1_enable,
+       .disable = nvkm_falcon_v1_disable,
+};
+
 const struct nvkm_sec2_func
 gp102_sec2 = {
+       .flcn = &gp102_sec2_flcn,
 };
 
 MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin");
                const struct nvkm_sec2_fwif *fwif)
 {
        return nvkm_acr_lsfw_load_sig_image_desc_v1(&sec2->engine.subdev,
-                                                   sec2->falcon,
+                                                   &sec2->falcon,
                                                    NVKM_ACR_LSF_SEC2, "sec2/",
                                                    ver, fwif->acr);
 }
 
 #include <engine/sec2.h>
 
 struct nvkm_sec2_func {
+       const struct nvkm_falcon_func *flcn;
 };
 
 struct nvkm_sec2_fwif {
 
  */
 #include "priv.h"
 
+static const struct nvkm_falcon_func
+tu102_sec2_flcn = {
+       .load_imem = nvkm_falcon_v1_load_imem,
+       .load_dmem = nvkm_falcon_v1_load_dmem,
+       .read_dmem = nvkm_falcon_v1_read_dmem,
+       .bind_context = nvkm_falcon_v1_bind_context,
+       .wait_for_halt = nvkm_falcon_v1_wait_for_halt,
+       .clear_interrupt = nvkm_falcon_v1_clear_interrupt,
+       .set_start_addr = nvkm_falcon_v1_set_start_addr,
+       .start = nvkm_falcon_v1_start,
+       .enable = nvkm_falcon_v1_enable,
+       .disable = nvkm_falcon_v1_disable,
+};
+
 static const struct nvkm_sec2_func
 tu102_sec2 = {
+       .flcn = &tu102_sec2_flcn,
 };
 
 static int
 
        /* For some reason we should not add app_resident_code_offset here */
        addr_code = base;
        addr_data = base + pdesc->app_resident_data_offset;
-       addr_args = sec->falcon->data.limit;
+       addr_args = sec->falcon.data.limit;
        addr_args -= NVKM_MSGQUEUE_CMDLINE_SIZE;
 
        desc->dma_idx = FALCON_SEC2_DMAIDX_UCODE;
 
        /* For some reason we should not add app_resident_code_offset here */
        addr_code = base;
        addr_data = base + pdesc->app_resident_data_offset;
-       addr_args = sec->falcon->data.limit;
+       addr_args = sec->falcon.data.limit;
        addr_args -= NVKM_MSGQUEUE_CMDLINE_SIZE;
 
        desc->ctx_dma = FALCON_SEC2_DMAIDX_UCODE;
 
        case NVKM_SECBOOT_FALCON_SEC2:
                /* we must keep SEC2 alive forever since ACR will run on it */
                nvkm_engine_ref(&subdev->device->sec2->engine);
-               sb->boot_falcon = subdev->device->sec2->falcon;
+               sb->boot_falcon = &subdev->device->sec2->falcon;
                sb->halt_falcon = &subdev->device->pmu->falcon;
                break;
        default:
 
                return ver;
 
        /* Allocate the PMU queue corresponding to the FW version */
-       ret = nvkm_msgqueue_new(img->ucode_desc.app_version, sec->falcon,
+       ret = nvkm_msgqueue_new(img->ucode_desc.app_version, &sec->falcon,
                                sb, &sec->queue);
        if (ret)
                return ret;
        const u32 addr_args = 0x01000000;
        int ret;
 
-       ret = acr_ls_msgqueue_post_run(sec->queue, sec->falcon, addr_args);
+       ret = acr_ls_msgqueue_post_run(sec->queue, &sec->falcon, addr_args);
        if (ret)
                return ret;