void nvhost_vic03_deinit(struct platform_device *dev)
{
	struct vic03 *v = get_vic03(dev);
	struct nvhost_device_data *pdata = nvhost_get_devdata(dev);

	DEFINE_DMA_ATTRS(attrs);
	dma_set_attr(DMA_ATTR_READ_ONLY, &attrs);

	if (!v)
		return;

	if (pdata->scaling_init)
		nvhost_scale_hw_deinit(dev);

	if (v->ucode.mapped) {
		dma_free_attrs(&dev->dev,
			v->ucode.size, v->ucode.mapped,
			v->ucode.dma_addr, &attrs);
		v->ucode.mapped = NULL;
		v->ucode.dma_addr = 0;
	}

	/* zap, free */
	set_vic03(dev, NULL);
	kfree(v);
}
int nvhost_vic_finalize_poweron(struct platform_device *pdev)
{
	struct nvhost_device_data *pdata = nvhost_get_devdata(pdev);
	int err;

	nvhost_dbg_fn("");

	host1x_writel(pdev, flcn_slcg_override_high_a_r(), 0);
	host1x_writel(pdev, flcn_cg_r(),
		     flcn_cg_idle_cg_dly_cnt_f(4) |
		     flcn_cg_idle_cg_en_f(1) |
		     flcn_cg_wakeup_dly_cnt_f(4));

	err = nvhost_flcn_boot(pdev);
	if (err)
		return err;

	if (pdata->scaling_init) {
		err = nvhost_scale_hw_init(pdev);
		if (err)
			dev_warn(&pdev->dev, "failed to initialize scaling (%d)",
				 err);
	}

	return 0;
}
int nvhost_flcn_init(struct platform_device *dev)
{
	int err = 0;
	struct nvhost_device_data *pdata = nvhost_get_devdata(dev);
	struct flcn *v = get_flcn(dev);

	nvhost_dbg_fn("in dev:%p v:%p", dev, v);

	v = kzalloc(sizeof(*v), GFP_KERNEL);
	if (!v) {
		dev_err(&dev->dev, "couldn't alloc flcn support");
		err = -ENOMEM;
		goto clean_up;
	}
	set_flcn(dev, v);
	nvhost_dbg_fn("primed dev:%p v:%p", dev, v);

	err = flcn_read_ucode(dev, pdata->firmware_name);
	if (err || !v->valid)
		goto clean_up;

	nvhost_module_busy(dev);
	err = nvhost_flcn_boot(dev);
	nvhost_module_idle(dev);

	return 0;

 clean_up:
	nvhost_err(&dev->dev, "failed");
	return err;
}
int nvhost_vic03_init(struct platform_device *dev)
{
	int err = 0;
	struct nvhost_device_data *pdata = nvhost_get_devdata(dev);
	struct vic03 *v = get_vic03(dev);
	char *fw_name;

	nvhost_dbg_fn("in dev:%p v:%p", dev, v);

	fw_name = vic_get_fw_name(dev);
	if (!fw_name) {
		dev_err(&dev->dev, "couldn't determine firmware name");
		return -EINVAL;
	}

	if (!v) {
		nvhost_dbg_fn("allocating vic03 support");
		v = kzalloc(sizeof(*v), GFP_KERNEL);
		if (!v) {
			dev_err(&dev->dev, "couldn't alloc vic03 support");
			err = -ENOMEM;
			goto clean_up;
		}
		set_vic03(dev, v);
		v->is_booted = false;
	}
	nvhost_dbg_fn("primed dev:%p v:%p", dev, v);

	v->host = nvhost_get_host(dev);

	if (!v->ucode.valid)
		err = vic03_read_ucode(dev, fw_name);
	if (err)
		goto clean_up;

	kfree(fw_name);
	fw_name = NULL;

	nvhost_module_busy(dev);
	err = vic03_boot(dev);
	nvhost_module_idle(dev);

	if (pdata->scaling_init)
		nvhost_scale_hw_init(dev);

	return 0;

 clean_up:
	kfree(fw_name);
	nvhost_err(&dev->dev, "failed");

	return err;
}
int nvhost_vic03_prepare_poweroff(struct platform_device *dev)
{
	struct nvhost_device_data *pdata = nvhost_get_devdata(dev);
	struct vic03 *v;
	struct nvhost_channel *ch = pdata->channel;

	if (ch) {
		mutex_lock(&ch->submitlock);
		ch->cur_ctx = NULL;
		mutex_unlock(&ch->submitlock);
	}

	v = get_vic03(pdata->pdev);
	if (v)
		v->is_booted = false;

	return 0;
}
int nvhost_vic_prepare_poweroff(struct platform_device *dev)
{
	struct nvhost_device_data *pdata = nvhost_get_devdata(dev);
	struct flcn *v;
	struct nvhost_channel *ch = pdata->channels[0];

	nvhost_dbg_fn("");

	if (pdata->scaling_deinit)
		nvhost_scale_hw_deinit(dev);

	if (ch && ch->dev) {
		mutex_lock(&ch->submitlock);
		ch->cur_ctx = NULL;
		mutex_unlock(&ch->submitlock);
	}

	v = get_flcn(pdata->pdev);

	return 0;
}
static struct nvhost_hwctx *vic03_alloc_hwctx(struct nvhost_hwctx_handler *h,
		struct nvhost_channel *ch)
{
	struct host1x_hwctx_handler *p = to_host1x_hwctx_handler(h);

	struct vic03 *v = get_vic03(ch->dev);
	struct host1x_hwctx *ctx;
	u32 *ptr;
	u32 syncpt = nvhost_get_devdata(ch->dev)->syncpts[0];
	u32 nvhost_vic03_restore_size = 10; /* number of words written below */

	nvhost_dbg_fn("");

	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
	if (!ctx)
		return NULL;

	ctx->restore_size = nvhost_vic03_restore_size;

	ctx->cpuva = dma_alloc_writecombine(&ch->dev->dev,
						ctx->restore_size * 4,
						&ctx->iova,
						GFP_KERNEL);
	if (!ctx->cpuva) {
		dev_err(&ch->dev->dev, "memory allocation failed\n");
		goto fail;
	}

	ptr = ctx->cpuva;

	/* set app id, fce ucode size, offset */
	ptr[0] = nvhost_opcode_incr(VIC_UCLASS_METHOD_OFFSET, 2);
	ptr[1] = NVA0B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID  >> 2;
	ptr[2] = 1;

	ptr[3] = nvhost_opcode_incr(VIC_UCLASS_METHOD_OFFSET, 2);
	ptr[4] = NVA0B6_VIDEO_COMPOSITOR_SET_FCE_UCODE_SIZE >> 2;
	ptr[5] = v->ucode.fce.size;

	ptr[6] = nvhost_opcode_incr(VIC_UCLASS_METHOD_OFFSET, 2);
	ptr[7] = NVA0B6_VIDEO_COMPOSITOR_SET_FCE_UCODE_OFFSET >> 2;
	ptr[8] = (v->ucode.dma_addr + v->ucode.fce.data_offset) >> 8;

	/* syncpt increment to track restore gather. */
	ptr[9] = nvhost_opcode_imm_incr_syncpt(
			host1x_uclass_incr_syncpt_cond_op_done_v(),
			syncpt);

	kref_init(&ctx->hwctx.ref);
	ctx->hwctx.h = &p->h;
	ctx->hwctx.channel = ch;
	ctx->hwctx.valid = true; /* this is a preconditioning sequence... */
	ctx->hwctx.save_incrs = 0;
	ctx->hwctx.save_slots = 0;

	ctx->hwctx.restore_incrs = 1;

	return &ctx->hwctx;

 fail:
	kfree(ctx);
	return NULL;
}