/*
 * Copyright 2020 Google LLC
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * This driver creates fake eSPI buses which can contain emulated devices
 * (mainly host), implemented by a separate emulation driver.
 * The API between this driver/controller and device emulators attached
 * to its bus is defined by struct emul_espi_device_api.
 */

#define DT_DRV_COMPAT zephyr_espi_emul_controller

#define LOG_LEVEL CONFIG_ESPI_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(espi_emul_ctlr);

#include <zephyr/device.h>
#include <zephyr/drivers/emul.h>
#include <zephyr/drivers/espi.h>
#include <zephyr/drivers/espi_emul.h>
#include "espi_utils.h"

/** Working data for the controller */
struct espi_emul_data {
	/* List of struct espi_emul associated with the device */
	sys_slist_t emuls;
	/* eSPI host configuration */
	struct espi_cfg cfg;
	/** List of eSPI callbacks */
	sys_slist_t callbacks;
};

static struct espi_emul *espi_emul_find(const struct device *dev,
					unsigned int chipsel)
{
	struct espi_emul_data *data = dev->data;
	sys_snode_t *node;

	SYS_SLIST_FOR_EACH_NODE(&data->emuls, node) {
		struct espi_emul *emul;

		emul = CONTAINER_OF(node, struct espi_emul, node);
		if (emul->chipsel == chipsel) {
			return emul;
		}
	}

	return NULL;
}

static int espi_emul_config(const struct device *dev, struct espi_cfg *cfg)
{
	struct espi_emul_data *data = dev->data;

	__ASSERT_NO_MSG(cfg);

	data->cfg = *cfg;

	return 0;
}


static int emul_espi_trigger_event(const struct device *dev,
				   struct espi_event *evt)
{
	struct espi_emul_data *data = dev->data;

	if (((evt->evt_type & ESPI_BUS_EVENT_VWIRE_RECEIVED) &&
	     !(data->cfg.channel_caps & ESPI_CHANNEL_VWIRE)) ||
	    ((evt->evt_type & ESPI_BUS_EVENT_OOB_RECEIVED) &&
	     !(data->cfg.channel_caps & ESPI_CHANNEL_OOB)) ||
	    ((evt->evt_type & ESPI_BUS_PERIPHERAL_NOTIFICATION)
	     && !(data->cfg.channel_caps & ESPI_CHANNEL_PERIPHERAL))) {
		return -EIO;
	}

	espi_send_callbacks(&data->callbacks, dev, *evt);

	return 0;
}

static bool espi_emul_get_channel_status(const struct device *dev, enum espi_channel ch)
{
	struct espi_emul_data *data = dev->data;

	return (data->cfg.channel_caps & ch);
}

static int espi_emul_read_lpc_request(const struct device *dev,
				      enum lpc_peripheral_opcode op,
				      uint32_t *data)
{
	const struct emul_espi_device_api *api;
	struct espi_emul *emul;
	struct espi_emul_data *emul_data = dev->data;

	if (!(emul_data->cfg.channel_caps & ESPI_CHANNEL_VWIRE)) {
		LOG_ERR("bad channel vwire");
		return -EINVAL;
	}

	emul = espi_emul_find(dev, EMUL_ESPI_HOST_CHIPSEL);
	if (!emul) {
		LOG_ERR("espi_emul not found");
		return -ENOTSUP;
	}

	__ASSERT_NO_MSG(emul->api);
	api = emul->api;

	switch (op) {
#ifdef CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION
	case EACPI_GET_SHARED_MEMORY:
		__ASSERT_NO_MSG(api->get_acpi_shm);
		*data = (uint32_t)api->get_acpi_shm(emul);
		break;
#endif
	default:
		return -EINVAL;
	}
	return 0;
}

static int espi_emul_write_lpc_request(const struct device *dev, enum lpc_peripheral_opcode op,
				       uint32_t *data)
{
	ARG_UNUSED(dev);

	return -EINVAL;
}

static int espi_emul_send_vwire(const struct device *dev, enum espi_vwire_signal vw, uint8_t level)
{
	const struct emul_espi_device_api *api;
	struct espi_emul *emul;
	struct espi_emul_data *data = dev->data;

	if (!(data->cfg.channel_caps & ESPI_CHANNEL_VWIRE)) {
		return -EIO;
	}

	emul = espi_emul_find(dev, EMUL_ESPI_HOST_CHIPSEL);
	if (!emul) {
		LOG_DBG("espi_emul not found");
		return -EIO;
	}

	__ASSERT_NO_MSG(emul->api);
	__ASSERT_NO_MSG(emul->api->set_vw);
	api = emul->api;

	return api->set_vw(emul, vw, level);
}

static int espi_emul_receive_vwire(const struct device *dev, enum espi_vwire_signal vw, uint8_t *level)
{
	const struct emul_espi_device_api *api;
	struct espi_emul *emul;
	struct espi_emul_data *data = dev->data;

	if (!(data->cfg.channel_caps & ESPI_CHANNEL_VWIRE)) {
		return -EIO;
	}

	emul = espi_emul_find(dev, EMUL_ESPI_HOST_CHIPSEL);
	if (!emul) {
		LOG_INF("espi_emul not found");
		return -EIO;
	}

	__ASSERT_NO_MSG(emul->api);
	__ASSERT_NO_MSG(emul->api->get_vw);
	api = emul->api;

	return api->get_vw(emul, vw, level);
}

static int espi_emul_manage_callback(const struct device *dev, struct espi_callback *callback, bool set)
{
	struct espi_emul_data *data = dev->data;

	return espi_manage_callback(&data->callbacks, callback, set);
}

/**
 * Set up a new emulator and add it to the list
 *
 * @param dev eSPI emulation controller device
 */
static int espi_emul_init(const struct device *dev)
{
	struct espi_emul_data *data = dev->data;
	const struct emul_list_for_bus *list = dev->config;

	sys_slist_init(&data->emuls);

	return emul_init_for_bus_from_list(dev, list);
}

int espi_emul_register(const struct device *dev, const char *name,
		       struct espi_emul *emul)
{
	struct espi_emul_data *data = dev->data;

	sys_slist_append(&data->emuls, &emul->node);

	LOG_INF("Register emulator '%s' at cs %u\n", name, emul->chipsel);

	return 0;
}

/* Device instantiation */
static struct emul_espi_driver_api emul_espi_driver_api = {
	.espi_api = {
		.config = espi_emul_config,
		.get_channel_status = espi_emul_get_channel_status,
		.read_lpc_request = espi_emul_read_lpc_request,
		.write_lpc_request = espi_emul_write_lpc_request,
		.send_vwire = espi_emul_send_vwire,
		.receive_vwire = espi_emul_receive_vwire,
		.manage_callback = espi_emul_manage_callback
	},
	.trigger_event = emul_espi_trigger_event,
	.find_emul = espi_emul_find,
};


#define EMUL_LINK_AND_COMMA(node_id) {	    \
		.label = DT_LABEL(node_id), \
},

#define ESPI_EMUL_INIT(n)					      \
	static const struct emul_link_for_bus emuls_##n[] = {	      \
		DT_FOREACH_CHILD(DT_DRV_INST(n), EMUL_LINK_AND_COMMA) \
	};							      \
	static struct emul_list_for_bus espi_emul_cfg_##n = {	      \
		.children = emuls_##n,				      \
		.num_children = ARRAY_SIZE(emuls_##n),		      \
	};							      \
	static struct espi_emul_data espi_emul_data_##n;	      \
	DEVICE_DT_INST_DEFINE(n,				      \
			      &espi_emul_init,			      \
			      NULL,				      \
			      &espi_emul_data_##n,		      \
			      &espi_emul_cfg_##n,		      \
			      POST_KERNEL,			      \
			      CONFIG_ESPI_INIT_PRIORITY,	      \
			      &emul_espi_driver_api);


DT_INST_FOREACH_STATUS_OKAY(ESPI_EMUL_INIT)
