}
 
 static void
-gf100_gr_init_fw(struct gf100_gr *gr, u32 fuc_base,
+gf100_gr_init_fw(struct nvkm_falcon *falcon,
                 struct gf100_gr_fuc *code, struct gf100_gr_fuc *data)
 {
-       struct nvkm_device *device = gr->base.engine.subdev.device;
-       int i;
-
-       nvkm_wr32(device, fuc_base + 0x01c0, 0x01000000);
-       for (i = 0; i < data->size / 4; i++)
-               nvkm_wr32(device, fuc_base + 0x01c4, data->data[i]);
-
-       nvkm_wr32(device, fuc_base + 0x0180, 0x01000000);
-       for (i = 0; i < code->size / 4; i++) {
-               if ((i & 0x3f) == 0)
-                       nvkm_wr32(device, fuc_base + 0x0188, i >> 6);
-               nvkm_wr32(device, fuc_base + 0x0184, code->data[i]);
-       }
-
-       /* code must be padded to 0x40 words */
-       for (; i & 0x3f; i++)
-               nvkm_wr32(device, fuc_base + 0x0184, 0);
+       nvkm_falcon_load_dmem(falcon, data->data, 0x0, data->size, 0);
+       nvkm_falcon_load_imem(falcon, code->data, 0x0, code->size, 0, 0, false);
 }
 
 static void
        if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS))
                ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_FECS);
        else
-               gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c, &gr->fuc409d);
+               gf100_gr_init_fw(gr->fecs, &gr->fuc409c, &gr->fuc409d);
        if (ret)
                return ret;
 
        if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS))
                ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_GPCCS);
        else
-               gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac, &gr->fuc41ad);
+               gf100_gr_init_fw(gr->gpccs, &gr->fuc41ac, &gr->fuc41ad);
        if (ret)
                return ret;
 
        nvkm_wr32(device, 0x41a10c, 0x00000000);
        nvkm_wr32(device, 0x40910c, 0x00000000);
 
-       if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS))
-               nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_GPCCS);
-       else
-               nvkm_wr32(device, 0x41a100, 0x00000002);
-       if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS))
-               nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_FECS);
-       else
-               nvkm_wr32(device, 0x409100, 0x00000002);
+       nvkm_falcon_start(gr->gpccs);
+       nvkm_falcon_start(gr->fecs);
+
        if (nvkm_msec(device, 2000,
                if (nvkm_rd32(device, 0x409800) & 0x00000001)
                        break;
        const struct gf100_grctx_func *grctx = gr->func->grctx;
        struct nvkm_subdev *subdev = &gr->base.engine.subdev;
        struct nvkm_device *device = subdev->device;
-       int i;
 
        if (!gr->func->fecs.ucode) {
                return -ENOSYS;
 
        /* load HUB microcode */
        nvkm_mc_unk260(device, 0);
-       nvkm_wr32(device, 0x4091c0, 0x01000000);
-       for (i = 0; i < gr->func->fecs.ucode->data.size / 4; i++)
-               nvkm_wr32(device, 0x4091c4, gr->func->fecs.ucode->data.data[i]);
-
-       nvkm_wr32(device, 0x409180, 0x01000000);
-       for (i = 0; i < gr->func->fecs.ucode->code.size / 4; i++) {
-               if ((i & 0x3f) == 0)
-                       nvkm_wr32(device, 0x409188, i >> 6);
-               nvkm_wr32(device, 0x409184, gr->func->fecs.ucode->code.data[i]);
-       }
+       nvkm_falcon_load_dmem(gr->fecs, gr->func->fecs.ucode->data.data, 0x0,
+                             gr->func->fecs.ucode->data.size, 0);
+       nvkm_falcon_load_imem(gr->fecs, gr->func->fecs.ucode->code.data, 0x0,
+                             gr->func->fecs.ucode->code.size, 0, 0, false);
 
        /* load GPC microcode */
-       nvkm_wr32(device, 0x41a1c0, 0x01000000);
-       for (i = 0; i < gr->func->gpccs.ucode->data.size / 4; i++)
-               nvkm_wr32(device, 0x41a1c4, gr->func->gpccs.ucode->data.data[i]);
-
-       nvkm_wr32(device, 0x41a180, 0x01000000);
-       for (i = 0; i < gr->func->gpccs.ucode->code.size / 4; i++) {
-               if ((i & 0x3f) == 0)
-                       nvkm_wr32(device, 0x41a188, i >> 6);
-               nvkm_wr32(device, 0x41a184, gr->func->gpccs.ucode->code.data[i]);
-       }
+       nvkm_falcon_load_dmem(gr->gpccs, gr->func->gpccs.ucode->data.data, 0x0,
+                             gr->func->gpccs.ucode->data.size, 0);
+       nvkm_falcon_load_imem(gr->gpccs, gr->func->gpccs.ucode->code.data, 0x0,
+                             gr->func->gpccs.ucode->code.size, 0, 0, false);
        nvkm_mc_unk260(device, 1);
 
        /* load register lists */
 gf100_gr_init_(struct nvkm_gr *base)
 {
        struct gf100_gr *gr = gf100_gr(base);
+       struct nvkm_subdev *subdev = &base->engine.subdev;
+       u32 ret;
+
        nvkm_pmu_pgob(gr->base.engine.subdev.device->pmu, false);
+
+       ret = nvkm_falcon_get(gr->fecs, subdev);
+       if (ret)
+               return ret;
+
+       ret = nvkm_falcon_get(gr->gpccs, subdev);
+       if (ret)
+               return ret;
+
        return gr->func->init(gr);
 }
 
+static int
+gf100_gr_fini_(struct nvkm_gr *base, bool suspend)
+{
+       struct gf100_gr *gr = gf100_gr(base);
+       struct nvkm_subdev *subdev = &gr->base.engine.subdev;
+       nvkm_falcon_put(gr->gpccs, subdev);
+       nvkm_falcon_put(gr->fecs, subdev);
+       return 0;
+}
+
 void
 gf100_gr_dtor_fw(struct gf100_gr_fuc *fuc)
 {
                gr->func->dtor(gr);
        kfree(gr->data);
 
+       nvkm_falcon_del(&gr->gpccs);
+       nvkm_falcon_del(&gr->fecs);
+
        gf100_gr_dtor_fw(&gr->fuc409c);
        gf100_gr_dtor_fw(&gr->fuc409d);
        gf100_gr_dtor_fw(&gr->fuc41ac);
        .dtor = gf100_gr_dtor,
        .oneinit = gf100_gr_oneinit,
        .init = gf100_gr_init_,
+       .fini = gf100_gr_fini_,
        .intr = gf100_gr_intr,
        .units = gf100_gr_units,
        .chan_new = gf100_gr_chan_new,
 gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device,
              int index, struct gf100_gr *gr)
 {
+       struct nvkm_subdev *subdev = &gr->base.engine.subdev;
        int ret;
 
        gr->func = func;
        if (ret)
                return ret;
 
-       return 0;
+       ret = nvkm_falcon_v1_new(subdev, "FECS", 0x409000, &gr->fecs);
+       if (ret)
+               return ret;
+
+       return nvkm_falcon_v1_new(subdev, "GPCCS", 0x41a000, &gr->gpccs);
 }
 
 int