/*
 * Copyright (c) 2020 STMicroelectronics
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @brief Common part of DMAMUX drivers for stm32.
 * @note  api functions named dmamux_stm32_
 *        are calling the dma_stm32 corresponding function
 *        implemented in dma_stm32.c
 */

#include <soc.h>
#include <init.h>
#include <drivers/dma.h>
#include <drivers/clock_control.h>
#include <drivers/clock_control/stm32_clock_control.h>

#include "dmamux_stm32.h"
#include "dma_stm32.h"

#include <logging/log.h>
LOG_MODULE_REGISTER(dmamux_stm32, CONFIG_DMA_LOG_LEVEL);

#define DT_DRV_COMPAT st_stm32_dmamux

int dmamux_stm32_configure(const struct device *dev, uint32_t id,
				struct dma_config *config)
{
	/* device is the dmamux, id is the dmamux channel from 0 */
	struct dmamux_stm32_data *data = dev->data;
	const struct dmamux_stm32_config *dev_config = dev->config;

	/*
	 * request line ID for this mux channel is stored
	 * in the dma_slot parameter
	 */
	int request_id = config->dma_slot;

	if (request_id >= dev_config->req_nb + dev_config->gen_nb) {
		LOG_ERR("request ID %d is too big.", request_id);
		return -EINVAL;
	}

	/* check if this channel is valid */
	if (id >= dev_config->channel_nb) {
		LOG_ERR("channel ID %d is too big.", id);
		return -EINVAL;
	}

	/*
	 * Also configures the corresponding dma channel
	 * instance is given by the dev_dma
	 * stream is given by the index i
	 * config is directly this dma_config
	 */

	/*
	 * This dmamux channel 'id' is now used for this peripheral request
	 * It gives this mux request ID to the dma through the config.dma_slot
	 */
	if (dma_stm32_configure(data->mux_channels[id].dev_dma,
			data->mux_channels[id].dma_id, config) != 0) {
		LOG_ERR("cannot configure the dmamux.");
		return -EINVAL;
	}

	/* set the Request Line ID to this dmamux channel i */
	DMAMUX_Channel_TypeDef *dmamux =
			(DMAMUX_Channel_TypeDef *)dev_config->base;

	LL_DMAMUX_SetRequestID(dmamux, id, request_id);

	return 0;
}

int dmamux_stm32_start(const struct device *dev, uint32_t id)
{
	const struct dmamux_stm32_config *dev_config = dev->config;
	struct dmamux_stm32_data *data = dev->data;

	/* check if this channel is valid */
	if (id >= dev_config->channel_nb) {
		LOG_ERR("channel ID %d is too big.", id);
		return -EINVAL;
	}

	if (dma_stm32_start(data->mux_channels[id].dev_dma,
		data->mux_channels[id].dma_id) != 0) {
		LOG_ERR("cannot start the dmamux channel %d.", id);
		return -EINVAL;
	}

	return 0;
}

int dmamux_stm32_stop(const struct device *dev, uint32_t id)
{
	const struct dmamux_stm32_config *dev_config = dev->config;
	struct dmamux_stm32_data *data = dev->data;

	/* check if this channel is valid */
	if (id >= dev_config->channel_nb) {
		LOG_ERR("channel ID %d is too big.", id);
		return -EINVAL;
	}

	if (dma_stm32_stop(data->mux_channels[id].dev_dma,
		data->mux_channels[id].dma_id) != 0) {
		LOG_ERR("cannot stop the dmamux channel %d.", id);
		return -EINVAL;
	}

	return 0;
}

int dmamux_stm32_reload(const struct device *dev, uint32_t id,
			    uint32_t src, uint32_t dst, size_t size)
{
	const struct dmamux_stm32_config *dev_config = dev->config;
	struct dmamux_stm32_data *data = dev->data;

	/* check if this channel is valid */
	if (id >= dev_config->channel_nb) {
		LOG_ERR("channel ID %d is too big.", id);
		return -EINVAL;
	}

	if (dma_stm32_reload(data->mux_channels[id].dev_dma,
		data->mux_channels[id].dma_id,
		src, dst, size) != 0) {
		LOG_ERR("cannot reload the dmamux channel %d.", id);
		return -EINVAL;
	}

	return 0;
}

static int dmamux_stm32_init(const struct device *dev)
{
	struct dmamux_stm32_data *data = dev->data;
	const struct dmamux_stm32_config *config = dev->config;
	const struct device *clk =
		device_get_binding(STM32_CLOCK_CONTROL_NAME);

	if (clock_control_on(clk,
		(clock_control_subsys_t *) &config->pclken) != 0) {
		LOG_ERR("clock op failed\n");
		return -EIO;
	}

	int size_stream =
		sizeof(struct dmamux_stm32_channel) * config->channel_nb;
	data->mux_channels = k_malloc(size_stream);
	if (!data->mux_channels) {
		LOG_ERR("HEAP_MEM_POOL_SIZE is too small");
		return -ENOMEM;
	}
	for (int i = 0; i < config->channel_nb; i++) {
		/*
		 * associates the dmamux channel
		 * to the corresponding dma stream
		 */
		if (i < config->channel_nb / 2) {
			data->mux_channels[i].dev_dma =
				device_get_binding((const char *)"DMA_1");
			/* dma 1 channels from 1 to N */
			data->mux_channels[i].dma_id = i + 1;
		} else {
			data->mux_channels[i].dev_dma =
				device_get_binding((const char *)"DMA_2");
			data->mux_channels[i].dma_id =
			/* dma 2 channels from 1 to N */
				i - config->channel_nb / 2 + 1;
		}
	}

	return 0;
}

static const struct dma_driver_api dma_funcs = {
	.reload		 = dmamux_stm32_reload,
	.config		 = dmamux_stm32_configure,
	.start		 = dmamux_stm32_start,
	.stop		 = dmamux_stm32_stop,
};

#define DMAMUX_INIT(index) \
								\
const struct dmamux_stm32_config dmamux_stm32_config_##index = {\
	.pclken = { .bus = DT_INST_CLOCKS_CELL(index, bus),	\
		    .enr = DT_INST_CLOCKS_CELL(index, bits) },	\
	.base = DT_INST_REG_ADDR(index),			\
	.channel_nb = DT_INST_PROP(index, dma_channels),	\
	.gen_nb = DT_INST_PROP(index, dma_generators),		\
	.req_nb = DT_INST_PROP(index, dma_requests),		\
};								\
								\
static struct dmamux_stm32_data dmamux_stm32_data_##index = {	\
	.mux_channels = NULL,					\
};								\
								\
DEVICE_AND_API_INIT(dmamux_##index, DT_INST_LABEL(index),	\
		    &dmamux_stm32_init,				\
		    &dmamux_stm32_data_##index, &dmamux_stm32_config_##index,\
		    POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,\
		    &dma_funcs);

DT_INST_FOREACH_STATUS_OKAY(DMAMUX_INIT)
