// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright 2019 Broadcom.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/tee_drv.h>
#include <linux/uuid.h>

#include <linux/firmware/broadcom/tee_bnxt_fw.h>

#define MAX_SHM_MEM_SZ	SZ_4M

#define MAX_TEE_PARAM_ARRY_MEMB		4

enum ta_cmd {
	/*
	 * TA_CMD_BNXT_FASTBOOT - boot bnxt device by copying f/w into sram
	 *
	 *	param[0] unused
	 *	param[1] unused
	 *	param[2] unused
	 *	param[3] unused
	 *
	 * Result:
	 *	TEE_SUCCESS - Invoke command success
	 *	TEE_ERROR_ITEM_NOT_FOUND - Corrupt f/w image found on memory
	 */
	TA_CMD_BNXT_FASTBOOT = 0,

	/*
	 * TA_CMD_BNXT_COPY_COREDUMP - copy the core dump into shm
	 *
	 *	param[0] (inout memref) - Coredump buffer memory reference
	 *	param[1] (in value) - value.a: offset, data to be copied from
	 *			      value.b: size of data to be copied
	 *	param[2] unused
	 *	param[3] unused
	 *
	 * Result:
	 *	TEE_SUCCESS - Invoke command success
	 *	TEE_ERROR_BAD_PARAMETERS - Incorrect input param
	 *	TEE_ERROR_ITEM_NOT_FOUND - Corrupt core dump
	 */
	TA_CMD_BNXT_COPY_COREDUMP = 3,
};

/**
 * struct tee_bnxt_fw_private - OP-TEE bnxt private data
 * @dev:		OP-TEE based bnxt device.
 * @ctx:		OP-TEE context handler.
 * @session_id:		TA session identifier.
 */
struct tee_bnxt_fw_private {
	struct device *dev;
	struct tee_context *ctx;
	u32 session_id;
	struct tee_shm *fw_shm_pool;
};

static struct tee_bnxt_fw_private pvt_data;

static void prepare_args(int cmd,
			 struct tee_ioctl_invoke_arg *arg,
			 struct tee_param *param)
{
	memset(arg, 0, sizeof(*arg));
	memset(param, 0, MAX_TEE_PARAM_ARRY_MEMB * sizeof(*param));

	arg->func = cmd;
	arg->session = pvt_data.session_id;
	arg->num_params = MAX_TEE_PARAM_ARRY_MEMB;

	/* Fill invoke cmd params */
	switch (cmd) {
	case TA_CMD_BNXT_COPY_COREDUMP:
		param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
		param[0].u.memref.shm = pvt_data.fw_shm_pool;
		param[0].u.memref.size = MAX_SHM_MEM_SZ;
		param[0].u.memref.shm_offs = 0;
		param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
		break;
	case TA_CMD_BNXT_FASTBOOT:
	default:
		/* Nothing to do */
		break;
	}
}

/**
 * tee_bnxt_fw_load() - Load the bnxt firmware
 *		    Uses an OP-TEE call to start a secure
 *		    boot process.
 * Returns 0 on success, negative errno otherwise.
 */
int tee_bnxt_fw_load(void)
{
	int ret = 0;
	struct tee_ioctl_invoke_arg arg;
	struct tee_param param[MAX_TEE_PARAM_ARRY_MEMB];

	if (!pvt_data.ctx)
		return -ENODEV;

	prepare_args(TA_CMD_BNXT_FASTBOOT, &arg, param);

	ret = tee_client_invoke_func(pvt_data.ctx, &arg, param);
	if (ret < 0 || arg.ret != 0) {
		dev_err(pvt_data.dev,
			"TA_CMD_BNXT_FASTBOOT invoke failed TEE err: %x, ret:%x\n",
			arg.ret, ret);
		return -EINVAL;
	}

	return 0;
}
EXPORT_SYMBOL(tee_bnxt_fw_load);

/**
 * tee_bnxt_copy_coredump() - Copy coredump from the allocated memory
 *			    Uses an OP-TEE call to copy coredump
 * @buf:	destination buffer where core dump is copied into
 * @offset:	offset from the base address of core dump area
 * @size:	size of the dump
 *
 * Returns 0 on success, negative errno otherwise.
 */
int tee_bnxt_copy_coredump(void *buf, u32 offset, u32 size)
{
	struct tee_ioctl_invoke_arg arg;
	struct tee_param param[MAX_TEE_PARAM_ARRY_MEMB];
	void *core_data;
	u32 rbytes = size;
	u32 nbytes = 0;
	int ret = 0;

	if (!pvt_data.ctx)
		return -ENODEV;

	prepare_args(TA_CMD_BNXT_COPY_COREDUMP, &arg, param);

	while (rbytes)  {
		nbytes = rbytes;

		nbytes = min_t(u32, rbytes, param[0].u.memref.size);

		/* Fill additional invoke cmd params */
		param[1].u.value.a = offset;
		param[1].u.value.b = nbytes;

		ret = tee_client_invoke_func(pvt_data.ctx, &arg, param);
		if (ret < 0 || arg.ret != 0) {
			dev_err(pvt_data.dev,
				"TA_CMD_BNXT_COPY_COREDUMP invoke failed TEE err: %x, ret:%x\n",
				arg.ret, ret);
			return -EINVAL;
		}

		core_data = tee_shm_get_va(pvt_data.fw_shm_pool, 0);
		if (IS_ERR(core_data)) {
			dev_err(pvt_data.dev, "tee_shm_get_va failed\n");
			return PTR_ERR(core_data);
		}

		memcpy(buf, core_data, nbytes);

		rbytes -= nbytes;
		buf += nbytes;
		offset += nbytes;
	}

	return 0;
}
EXPORT_SYMBOL(tee_bnxt_copy_coredump);

static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
{
	return (ver->impl_id == TEE_IMPL_ID_OPTEE);
}

static int tee_bnxt_fw_probe(struct device *dev)
{
	struct tee_client_device *bnxt_device = to_tee_client_device(dev);
	int ret, err = -ENODEV;
	struct tee_ioctl_open_session_arg sess_arg;
	struct tee_shm *fw_shm_pool;

	memset(&sess_arg, 0, sizeof(sess_arg));

	/* Open context with TEE driver */
	pvt_data.ctx = tee_client_open_context(NULL, optee_ctx_match, NULL,
					       NULL);
	if (IS_ERR(pvt_data.ctx))
		return -ENODEV;

	/* Open session with Bnxt load Trusted App */
	memcpy(sess_arg.uuid, bnxt_device->id.uuid.b, TEE_IOCTL_UUID_LEN);
	sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
	sess_arg.num_params = 0;

	ret = tee_client_open_session(pvt_data.ctx, &sess_arg, NULL);
	if (ret < 0 || sess_arg.ret != 0) {
		dev_err(dev, "tee_client_open_session failed, err: %x\n",
			sess_arg.ret);
		err = -EINVAL;
		goto out_ctx;
	}
	pvt_data.session_id = sess_arg.session;

	pvt_data.dev = dev;

	fw_shm_pool = tee_shm_alloc(pvt_data.ctx, MAX_SHM_MEM_SZ,
				    TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
	if (IS_ERR(fw_shm_pool)) {
		dev_err(pvt_data.dev, "tee_shm_alloc failed\n");
		err = PTR_ERR(fw_shm_pool);
		goto out_sess;
	}

	pvt_data.fw_shm_pool = fw_shm_pool;

	return 0;

out_sess:
	tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
out_ctx:
	tee_client_close_context(pvt_data.ctx);

	return err;
}

static int tee_bnxt_fw_remove(struct device *dev)
{
	tee_shm_free(pvt_data.fw_shm_pool);
	tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
	tee_client_close_context(pvt_data.ctx);
	pvt_data.ctx = NULL;

	return 0;
}

static const struct tee_client_device_id tee_bnxt_fw_id_table[] = {
	{UUID_INIT(0x6272636D, 0x2019, 0x0716,
		    0x42, 0x43, 0x4D, 0x5F, 0x53, 0x43, 0x48, 0x49)},
	{}
};

MODULE_DEVICE_TABLE(tee, tee_bnxt_fw_id_table);

static struct tee_client_driver tee_bnxt_fw_driver = {
	.id_table	= tee_bnxt_fw_id_table,
	.driver		= {
		.name		= KBUILD_MODNAME,
		.bus		= &tee_bus_type,
		.probe		= tee_bnxt_fw_probe,
		.remove		= tee_bnxt_fw_remove,
	},
};

static int __init tee_bnxt_fw_mod_init(void)
{
	return driver_register(&tee_bnxt_fw_driver.driver);
}

static void __exit tee_bnxt_fw_mod_exit(void)
{
	driver_unregister(&tee_bnxt_fw_driver.driver);
}

module_init(tee_bnxt_fw_mod_init);
module_exit(tee_bnxt_fw_mod_exit);

MODULE_AUTHOR("Vikas Gupta <vikas.gupta@broadcom.com>");
MODULE_DESCRIPTION("Broadcom bnxt firmware manager");
MODULE_LICENSE("GPL v2");
