/*
 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include "priv.h"

#include <core/memory.h>
#include <subdev/acr.h>

#include <nvfw/flcn.h>
#include <nvfw/pmu.h>

static int
gm20b_pmu_acr_bootstrap_falcon_cb(void *priv, struct nvfw_falcon_msg *hdr)
{
	struct nv_pmu_acr_bootstrap_falcon_msg *msg =
		container_of(hdr, typeof(*msg), msg.hdr);
	return msg->falcon_id;
}

int
gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *falcon,
			       enum nvkm_acr_lsf_id id)
{
	struct nvkm_pmu *pmu = container_of(falcon, typeof(*pmu), falcon);
	struct nv_pmu_acr_bootstrap_falcon_cmd cmd = {
		.cmd.hdr.unit_id = NV_PMU_UNIT_ACR,
		.cmd.hdr.size = sizeof(cmd),
		.cmd.cmd_type = NV_PMU_ACR_CMD_BOOTSTRAP_FALCON,
		.flags = NV_PMU_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES,
		.falcon_id = id,
	};
	int ret;

	ret = nvkm_falcon_cmdq_send(pmu->hpq, &cmd.cmd.hdr,
				    gm20b_pmu_acr_bootstrap_falcon_cb,
				    &pmu->subdev, msecs_to_jiffies(1000));
	if (ret >= 0) {
		if (ret != cmd.falcon_id)
			ret = -EIO;
		else
			ret = 0;
	}

	return ret;
}

void
gm20b_pmu_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust)
{
	struct loader_config hdr;
	u64 addr;

	nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr));
	addr = ((u64)hdr.code_dma_base1 << 40 | hdr.code_dma_base << 8);
	hdr.code_dma_base  = lower_32_bits((addr + adjust) >> 8);
	hdr.code_dma_base1 = upper_32_bits((addr + adjust) >> 8);
	addr = ((u64)hdr.data_dma_base1 << 40 | hdr.data_dma_base << 8);
	hdr.data_dma_base  = lower_32_bits((addr + adjust) >> 8);
	hdr.data_dma_base1 = upper_32_bits((addr + adjust) >> 8);
	addr = ((u64)hdr.overlay_dma_base1 << 40 | hdr.overlay_dma_base << 8);
	hdr.overlay_dma_base  = lower_32_bits((addr + adjust) << 8);
	hdr.overlay_dma_base1 = upper_32_bits((addr + adjust) << 8);
	nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr));

	loader_config_dump(&acr->subdev, &hdr);
}

void
gm20b_pmu_acr_bld_write(struct nvkm_acr *acr, u32 bld,
			struct nvkm_acr_lsfw *lsfw)
{
	const u64 base = lsfw->offset.img + lsfw->app_start_offset;
	const u64 code = (base + lsfw->app_resident_code_offset) >> 8;
	const u64 data = (base + lsfw->app_resident_data_offset) >> 8;
	const struct loader_config hdr = {
		.dma_idx = FALCON_DMAIDX_UCODE,
		.code_dma_base = lower_32_bits(code),
		.code_size_total = lsfw->app_size,
		.code_size_to_load = lsfw->app_resident_code_size,
		.code_entry_point = lsfw->app_imem_entry,
		.data_dma_base = lower_32_bits(data),
		.data_size = lsfw->app_resident_data_size,
		.overlay_dma_base = lower_32_bits(code),
		.argc = 1,
		.argv = lsfw->falcon->data.limit - sizeof(struct nv_pmu_args),
		.code_dma_base1 = upper_32_bits(code),
		.data_dma_base1 = upper_32_bits(data),
		.overlay_dma_base1 = upper_32_bits(code),
	};

	nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr));
}

static const struct nvkm_acr_lsf_func
gm20b_pmu_acr = {
	.flags = NVKM_ACR_LSF_DMACTL_REQ_CTX,
	.bld_size = sizeof(struct loader_config),
	.bld_write = gm20b_pmu_acr_bld_write,
	.bld_patch = gm20b_pmu_acr_bld_patch,
	.bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_PMU) |
			     BIT_ULL(NVKM_ACR_LSF_FECS) |
			     BIT_ULL(NVKM_ACR_LSF_GPCCS),
	.bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon,
};

static int
gm20b_pmu_acr_init_wpr_callback(void *priv, struct nvfw_falcon_msg *hdr)
{
	struct nv_pmu_acr_init_wpr_region_msg *msg =
		container_of(hdr, typeof(*msg), msg.hdr);
	struct nvkm_pmu *pmu = priv;
	struct nvkm_subdev *subdev = &pmu->subdev;

	if (msg->error_code) {
		nvkm_error(subdev, "ACR WPR init failure: %d\n",
			   msg->error_code);
		return -EINVAL;
	}

	nvkm_debug(subdev, "ACR WPR init complete\n");
	complete_all(&pmu->wpr_ready);
	return 0;
}

static int
gm20b_pmu_acr_init_wpr(struct nvkm_pmu *pmu)
{
	struct nv_pmu_acr_init_wpr_region_cmd cmd = {
		.cmd.hdr.unit_id = NV_PMU_UNIT_ACR,
		.cmd.hdr.size = sizeof(cmd),
		.cmd.cmd_type = NV_PMU_ACR_CMD_INIT_WPR_REGION,
		.region_id = 1,
		.wpr_offset = 0,
	};

	return nvkm_falcon_cmdq_send(pmu->hpq, &cmd.cmd.hdr,
				     gm20b_pmu_acr_init_wpr_callback, pmu, 0);
}

static int
gm20b_pmu_initmsg(struct nvkm_pmu *pmu)
{
	struct nv_pmu_init_msg msg;
	int ret;

	ret = nvkm_falcon_msgq_recv_initmsg(pmu->msgq, &msg, sizeof(msg));
	if (ret)
		return ret;

	if (msg.hdr.unit_id != NV_PMU_UNIT_INIT ||
	    msg.msg_type != NV_PMU_INIT_MSG_INIT)
		return -EINVAL;

	nvkm_falcon_cmdq_init(pmu->hpq, msg.queue_info[0].index,
					msg.queue_info[0].offset,
					msg.queue_info[0].size);
	nvkm_falcon_cmdq_init(pmu->lpq, msg.queue_info[1].index,
					msg.queue_info[1].offset,
					msg.queue_info[1].size);
	nvkm_falcon_msgq_init(pmu->msgq, msg.queue_info[4].index,
					 msg.queue_info[4].offset,
					 msg.queue_info[4].size);
	return gm20b_pmu_acr_init_wpr(pmu);
}

static void
gm20b_pmu_recv(struct nvkm_pmu *pmu)
{
	if (!pmu->initmsg_received) {
		int ret = pmu->func->initmsg(pmu);
		if (ret) {
			nvkm_error(&pmu->subdev, "error parsing init message: %d\n", ret);
			return;
		}

		pmu->initmsg_received = true;
	}

	nvkm_falcon_msgq_recv(pmu->msgq);
}

static void
gm20b_pmu_fini(struct nvkm_pmu *pmu)
{
	/*TODO: shutdown RTOS. */

	flush_work(&pmu->recv.work);
	nvkm_falcon_cmdq_fini(pmu->lpq);
	nvkm_falcon_cmdq_fini(pmu->hpq);

	reinit_completion(&pmu->wpr_ready);

	nvkm_falcon_put(&pmu->falcon, &pmu->subdev);
}

static int
gm20b_pmu_init(struct nvkm_pmu *pmu)
{
	struct nvkm_falcon *falcon = &pmu->falcon;
	struct nv_pmu_args args = { .secure_mode = true };
	u32 addr_args = falcon->data.limit - sizeof(args);
	int ret;

	ret = nvkm_falcon_get(&pmu->falcon, &pmu->subdev);
	if (ret)
		return ret;

	pmu->initmsg_received = false;

	nvkm_falcon_pio_wr(falcon, (u8 *)&args, 0, 0, DMEM, addr_args, sizeof(args), 0, false);
	nvkm_falcon_start(falcon);
	return 0;
}

const struct nvkm_pmu_func
gm20b_pmu = {
	.flcn = &gm200_pmu_flcn,
	.init = gm20b_pmu_init,
	.fini = gm20b_pmu_fini,
	.intr = gt215_pmu_intr,
	.recv = gm20b_pmu_recv,
	.initmsg = gm20b_pmu_initmsg,
	.reset = gf100_pmu_reset,
};

#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
MODULE_FIRMWARE("nvidia/gm20b/pmu/desc.bin");
MODULE_FIRMWARE("nvidia/gm20b/pmu/image.bin");
MODULE_FIRMWARE("nvidia/gm20b/pmu/sig.bin");
#endif

int
gm20b_pmu_load(struct nvkm_pmu *pmu, int ver, const struct nvkm_pmu_fwif *fwif)
{
	return nvkm_acr_lsfw_load_sig_image_desc(&pmu->subdev, &pmu->falcon,
						 NVKM_ACR_LSF_PMU, "pmu/",
						 ver, fwif->acr);
}

static const struct nvkm_pmu_fwif
gm20b_pmu_fwif[] = {
	{  0, gm20b_pmu_load, &gm20b_pmu, &gm20b_pmu_acr },
	{ -1, gm200_pmu_nofw, &gm20b_pmu },
	{}
};

int
gm20b_pmu_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
	      struct nvkm_pmu **ppmu)
{
	return nvkm_pmu_new_(gm20b_pmu_fwif, device, type, inst, ppmu);
}
