// SPDX-License-Identifier: GPL-2.0
/*
 * GXP firmware data manager.
 *
 * Copyright (C) 2021 Google LLC
 */

#include <linux/slab.h>

#include "gxp-config.h"
#include "gxp-debug-dump.h"
#include "gxp-firmware-data.h"
#include "gxp-host-device-structs.h"
#include "gxp-internal.h"
#include "gxp-vd.h"
#include "gxp.h"

/* A byte pattern to pre-populate the FW region with */
#define FW_DATA_DEBUG_PATTERN 0x66

/* Default application parameters */
#define DEFAULT_APP_ID 1

/*
 * Holds information about system-wide HW and memory resources given to the FWs
 * of GXP devices.
 */
struct gxp_fw_data_manager {
	/* Cached core telemetry descriptors. */
	struct gxp_core_telemetry_descriptor core_telemetry_desc;
	/*
	 * A host-view of the System configuration descriptor. This same desc
	 * is provided to all VDs and all cores. This is the R/O section.
	 */
	struct gxp_system_descriptor_ro *sys_desc_ro;
	/*
	 * A host-view of the System configuration descriptor. This same desc
	 * is provided to all VDs and all cores. This is the R/W section.
	 */
	struct gxp_system_descriptor_rw *sys_desc_rw;
};

/*
 * Here assumes sys_cfg contains gxp_system_descriptor_ro in the first page and
 * gxp_system_descriptor_rw in the second page.
 */
static void set_system_cfg_region(struct gxp_dev *gxp, void *sys_cfg)
{
	struct gxp_system_descriptor_ro *des_ro = sys_cfg;
	struct gxp_system_descriptor_rw *des_rw = sys_cfg + PAGE_SIZE;
	struct gxp_core_telemetry_descriptor *descriptor =
		&gxp->data_mgr->core_telemetry_desc;
	struct telemetry_descriptor_ro *ro;
	struct telemetry_descriptor_rw *rw;
	struct core_telemetry_descriptor *des;
	int i;

	if (gxp->debug_dump_mgr)
		des_ro->debug_dump_dev_addr = gxp->debug_dump_mgr->buf.dsp_addr;
	else
		des_ro->debug_dump_dev_addr = 0;

	for (i = 0; i < GXP_NUM_CORES; i++) {
		ro = &des_ro->telemetry_desc.per_core_loggers[i];
		rw = &des_rw->telemetry_desc.per_core_loggers[i];
		des = &descriptor->per_core_loggers[i];
		ro->host_status = des->host_status;
		ro->buffer_addr = des->buffer_addr;
		ro->buffer_size = des->buffer_size;
		rw->device_status = des->device_status;
		rw->data_available = des->watermark_level;
	}

	/* Update the global descriptors. */
	gxp->data_mgr->sys_desc_ro = des_ro;
	gxp->data_mgr->sys_desc_rw = des_rw;
}

static void _gxp_fw_data_populate_vd_cfg(struct gxp_dev *gxp,
					 struct gxp_virtual_device *vd)
{
	struct gxp_host_control_region *core_cfg;
	struct gxp_job_descriptor job;
	struct gxp_vd_descriptor *vd_desc;
	int i;

	if (!gxp_is_direct_mode(gxp))
		return;
	if (!vd->vd_cfg.vaddr || !vd->core_cfg.vaddr) {
		dev_warn(
			gxp->dev,
			"Missing VD and core CFG in image config, firmware is not bootable\n");
		return;
	}
	/* Set up VD config region. */
	vd_desc = vd->vd_cfg.vaddr;
	vd_desc->application_id = DEFAULT_APP_ID;
	vd_desc->vd_is_initialized = 0;
	/* Set up core config region. */
	job.workers_count = vd->num_cores;
	for (i = 0; i < ARRAY_SIZE(job.worker_to_fw); i++) {
		/*
		 * Kernel-initiated workloads always act like the entire VD is
		 * one giant N-core job where N is the number of cores allocated
		 * to that VD.
		 * The MCU, on the other hand, can have multiple jobs dispatched
		 * to the same VD at the same time.
		 */
		if (i < job.workers_count)
			job.worker_to_fw[i] = i;
		else
			job.worker_to_fw[i] = -1;
	}
	/* Give each VD a unique HW resources slot. */
	job.hardware_resources_slot = gxp_vd_hw_slot_id(vd);
	/* Assign the same job descriptor to all cores in this VD */
	for (i = 0; i < GXP_NUM_CORES; i++) {
		core_cfg = vd->core_cfg.vaddr +
			   vd->core_cfg.size / GXP_NUM_CORES * i;
		core_cfg->job_descriptor = job;
	}
}

int gxp_fw_data_init(struct gxp_dev *gxp)
{
	struct gxp_fw_data_manager *mgr;
	void *virt;

	mgr = devm_kzalloc(gxp->dev, sizeof(*mgr), GFP_KERNEL);
	if (!mgr)
		return -ENOMEM;

	if (gxp_is_direct_mode(gxp)) {
		virt = memremap(gxp->fwdatabuf.paddr, gxp->fwdatabuf.size, MEMREMAP_WC);
		if (IS_ERR_OR_NULL(virt)) {
			dev_err(gxp->dev, "Failed to map fw data region\n");
			return -ENODEV;
		}
		gxp->fwdatabuf.vaddr = virt;

		/* Populate the region with a pre-defined pattern. */
		memset(virt, FW_DATA_DEBUG_PATTERN, gxp->fwdatabuf.size);
	}
	gxp->data_mgr = mgr;

	return 0;
}

void gxp_fw_data_destroy(struct gxp_dev *gxp)
{
	struct gxp_fw_data_manager *mgr = gxp->data_mgr;

	if (gxp->fwdatabuf.vaddr)
		memunmap(gxp->fwdatabuf.vaddr);

	devm_kfree(gxp->dev, mgr);
	gxp->data_mgr = NULL;
}

void gxp_fw_data_populate_vd_cfg(struct gxp_dev *gxp, struct gxp_virtual_device *vd)
{
	_gxp_fw_data_populate_vd_cfg(gxp, vd);
}

int gxp_fw_data_set_core_telemetry_descriptors(struct gxp_dev *gxp, u32 host_status,
					       struct gxp_coherent_buf *buffers,
					       u32 per_buffer_size)
{
	struct gxp_core_telemetry_descriptor *descriptor = &gxp->data_mgr->core_telemetry_desc;
	struct core_telemetry_descriptor *core_descriptors = descriptor->per_core_loggers;
	uint core;
	bool enable;

	enable = (host_status & GXP_CORE_TELEMETRY_HOST_STATUS_ENABLED);

	if (enable) {
		/* Validate that the provided IOVAs are addressable (i.e. 32-bit) */
		for (core = 0; core < GXP_NUM_CORES; core++) {
			if (buffers && buffers[core].dsp_addr > U32_MAX &&
			    buffers[core].size == per_buffer_size)
				return -EINVAL;
		}

		for (core = 0; core < GXP_NUM_CORES; core++) {
			core_descriptors[core].host_status = host_status;
			core_descriptors[core].buffer_addr =
				(u32)buffers[core].dsp_addr;
			core_descriptors[core].buffer_size = per_buffer_size;
		}
	} else {
		for (core = 0; core < GXP_NUM_CORES; core++) {
			core_descriptors[core].host_status = host_status;
			core_descriptors[core].buffer_addr = 0;
			core_descriptors[core].buffer_size = 0;
		}
	}

	return 0;
}

u32 gxp_fw_data_get_core_telemetry_device_status(struct gxp_dev *gxp, uint core)
{
	struct gxp_system_descriptor_rw *des_rw = gxp->data_mgr->sys_desc_rw;

	if (core >= GXP_NUM_CORES)
		return 0;

	return des_rw->telemetry_desc.per_core_loggers[core].device_status;
}

struct gxp_mapped_resource gxp_fw_data_resource(struct gxp_dev *gxp)
{
	/*
	 * For direct mode, the config regions are programmed by host (us); for
	 * MCU mode, the config regions are programmed by MCU.
	 */
	if (gxp_is_direct_mode(gxp)) {
		return gxp->fwdatabuf;
	} else {
		return gxp->shared_buf;
	}
}

void *gxp_fw_data_system_cfg(struct gxp_dev *gxp)
{
	struct gxp_mapped_resource res = gxp_fw_data_resource(gxp);

	/* Use the end of the shared region for system cfg. */
	return res.vaddr + res.size - GXP_FW_DATA_SYSCFG_SIZE;
}

void gxp_fw_data_populate_system_config(struct gxp_dev *gxp)
{
	set_system_cfg_region(gxp, gxp_fw_data_system_cfg(gxp));
}
