/*
 * @file exo_io_al_qspi_common.c
 *
 * @brief This file contains abstracted function definition for QSPI interface
 *
 * @copyright Copyright 2023 Antaris, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <unistd.h>
#include "exo_io_al_qspi_common.h"
#include "exo_hal_io_al_common.h"
#include "exo_common.h"
#ifndef LINUX_TEMP_PORT
#include "exo_io_al_stm32f7xx_qspi.h"
#else
#include "exo_io_al_linux_qspi.h"
#endif

#ifndef LINUX_TEMP_PORT
#define QSPI_TX_CPLT_CB			check_qspi_dummy					///< SPI1 TX complete callback event
#define QSPI_RX_CPLT_CB			check_qspi_dummy					///< SPI1 RX complete callback event
#define QSPI_CMD_CPLT_CB		check_qspi_dummy					///< SPI1 TX RX complete callback event
#define QSPI_ABORT_CPLT_CB		check_qspi_dummy					///< SPI1 Abort complete callback event
#define QSPI_ERROR_CB			check_qspi_dummy					///< SPI1 error callback event
#else
#define QSPI_TX_CPLT_CB			linux_qspi_dummy_fn							///< SPI1 TX complete callback event
#define QSPI_RX_CPLT_CB			linux_qspi_dummy_fn							///< SPI1 RX complete callback event
#define QSPI_CMD_CPLT_CB		linux_qspi_dummy_fn							///< SPI1 TX RX complete callback event
#define QSPI_ABORT_CPLT_CB		linux_qspi_dummy_fn							///< SPI1 Abort complete callback event
#define QSPI_ERROR_CB			linux_qspi_dummy_fn							///< SPI1 error callback event
#endif

extern void *intf_inst_hdle_ptr[MAX_IO_INST_ID];



extern ioal_qspi_hdle ioal_hqspi;

#ifndef LINUX_TEMP_PORT
/**
 * @brief This is SPI interface dummy function for target
 */
void check_qspi_dummy(ioal_qspi_hdle *hqspi);
#else
/**
 * @brief This is SPI interface dummy function for linux
 */
void linux_qspi_dummy_fn(struct _ioal_qspi_hdle *hqspi);

#endif


/*
 * @brief This API initialize the callback event
 */
static void io_hal_qspi_cb_init(ioal_qspi_hdle *hqspi);



/*
 * @brief This API initialize the callback event
 */
static void io_hal_qspi_cb_init(ioal_qspi_hdle *hqspi)
{
	hqspi->qspi_tx_cplt_cb 		= QSPI_TX_CPLT_CB;
	hqspi->qspi_rx_cplt_cb 		= QSPI_RX_CPLT_CB;
	hqspi->qspi_cmd_cplt_cb 	= QSPI_CMD_CPLT_CB;
	hqspi->qspi_abort_cplt_cb 	= QSPI_ABORT_CPLT_CB;
	hqspi->qspi_error_cb 		= QSPI_ERROR_CB;

#ifndef LINUX_TEMP_PORT
	io_hal_wrpr_qspi_reg_cb(hqspi, IOHAL_STM32_QSPI_TX_CPLT_CB_ID);
	io_hal_wrpr_qspi_reg_cb(hqspi, IOHAL_STM32_QSPI_RX_CPLT_CB_ID);
	io_hal_wrpr_qspi_reg_cb(hqspi, IOHAL_STM32_QSPI_CMD_CPLT_CB_ID);
	io_hal_wrpr_qspi_reg_cb(hqspi, IOHAL_STM32_QSPI_ABORT_CB_ID);
	io_hal_wrpr_qspi_reg_cb(hqspi, IOHAL_STM32_QSPI_ERROR_CB_ID);
#endif
}





/*
 * @brief This API initialize the QSPI interface
 */
hal_ret_sts io_hal_qspi_init(ioal_qspi_hdle *ioal_hqspi, io_inst_id inst_id)
{
#ifdef LINUX_TEMP_PORT
	DEBUG_CPRINT(("\n EXO IO AL QSPI Initialise"));
	usleep(100000);
#endif
	hal_ret_sts sts = HAL_SCS;


	switch(inst_id)
	{
		case IOAL_INST_QSPI1:
			if(HAL_SCS == io_hal_wrpr_qspi_init(ioal_hqspi))
			{
				intf_inst_hdle_ptr[IOAL_INST_QSPI1] = ioal_hqspi;
				io_hal_qspi_cb_init(ioal_hqspi);
			}
			else
			{

				sts = HAL_IO_INIT_ERR;
			}
			break;


		default:
			sts = HAL_IO_INIT_INVALID_INSTANCE;
			break;

	}




#ifdef LINUX_TEMP_PORT
	DEBUG_CPRINT(("\n EXO IO AL QSPI Initialisation completed successfully"));
#endif
	return sts;
}

/**
  * @brief  This function de initializes the qspi interface
  *
  */
hal_ret_sts     io_hal_qspi_deInit   (io_inst_id inst_id)
{
	hal_ret_sts sts = HAL_SCS;
	if(HAL_SCS == io_hal_wrpr_qspi_deInit(&ioal_hqspi))
	{
		intf_inst_hdle_ptr[IOAL_INST_QSPI1] = NULL;
	}
	else
	{

		sts = HAL_IO_INIT_ERR;
	}
#ifdef LINUX_TEMP_PORT
	DEBUG_CPRINT(("\n EXO IO AL QSPI Initialisation completed successfully"));
#endif
	return sts;
}



/*
 * @brief This API transmit the data in QSPI interface with blocking mode
 */
hal_ret_sts io_hal_qspi_transmit(ioal_qspi_hdle *hqspi, uint8 *pdata, uint32 timeout)
{
	hal_ret_sts ret_sts = HAL_MAX_ERR;
	hqspi->intf_gen_info.state = IO_BUSY_STATE;
	if(HAL_SCS == io_hal_wrpr_qspi_transmit(hqspi,pdata,timeout))
	{
		ret_sts = HAL_SCS;
		hqspi->intf_gen_info.state = IO_FREE_STATE;
	}
	else
	{
		ret_sts = HAL_IO_TX_ERR;
		hqspi->intf_gen_info.state = IO_FREE_STATE;
	}
	return ret_sts;
}

/*
 * @brief This API receive the data from QSPI interface with blocking mode
 */
hal_ret_sts io_hal_qspi_receive(ioal_qspi_hdle *hqspi, uint8 *pdata, uint32 timeout)
{
	hal_ret_sts ret_sts = HAL_MAX_ERR;
	hqspi->intf_gen_info.state = IO_BUSY_STATE;
	if(HAL_SCS == io_hal_wrpr_qspi_receive(hqspi,pdata,timeout))
	{
		ret_sts = HAL_SCS;
		hqspi->intf_gen_info.state = IO_FREE_STATE;
	}
	else
	{
		ret_sts = HAL_IO_RX_ERR;
		hqspi->intf_gen_info.state = IO_FREE_STATE;
	}
	return ret_sts;
}

/*
 * @brief This API set the command configuration
 */
hal_ret_sts io_hal_qspi_command(ioal_qspi_hdle *hqspi, ioal_qspi_CommandTypeDef *cmd, uint32 timeout)
{
	hal_ret_sts ret_sts = HAL_MAX_ERR;
	hqspi->intf_gen_info.state = IO_BUSY_STATE;
	if(HAL_SCS == io_hal_wrpr_qspi_command(hqspi, cmd, timeout))
	{
		ret_sts = HAL_SCS;
		hqspi->intf_gen_info.state = IO_FREE_STATE;
	}
	else
	{
		ret_sts = HAL_IO_RX_ERR;
		hqspi->intf_gen_info.state = IO_FREE_STATE;
	}
	return ret_sts;
}


/*
 * @brief This API enable the auto polling mode
 */
hal_ret_sts     io_hal_qspi_auto_polling(ioal_qspi_hdle *hqspi, ioal_qspi_CommandTypeDef *cmd, ioal_qspi_AutoPollingTypeDef *cfg, uint32 timeout)
{
	hal_ret_sts ret_sts = HAL_MAX_ERR;
	hqspi->intf_gen_info.state = IO_BUSY_STATE;
	if(HAL_SCS == io_hal_wrpr_qspi_auto_polling(hqspi, cmd, cfg, timeout))
	{
		ret_sts = HAL_SCS;
		hqspi->intf_gen_info.state = IO_FREE_STATE;
	}
	else
	{
		ret_sts = HAL_IO_RX_ERR;
		hqspi->intf_gen_info.state = IO_FREE_STATE;
	}
	return ret_sts;

}



/*
 * @brief This API enable the memory mapped mode
 */
hal_ret_sts     io_hal_qspi_memory_mapped(ioal_qspi_hdle *hqspi, ioal_qspi_CommandTypeDef *cmd, ioal_qspi_MemoryMappedTypeDef *cfg)
{
	hal_ret_sts ret_sts = HAL_MAX_ERR;
	hqspi->intf_gen_info.state = IO_BUSY_STATE;
	if(HAL_SCS == io_hal_wrpr_qspi_memory_mapped(hqspi, cmd, cfg))
	{
		ret_sts = HAL_SCS;
		hqspi->intf_gen_info.state = IO_FREE_STATE;
	}
	else
	{
		ret_sts = HAL_IO_RX_ERR;
		hqspi->intf_gen_info.state = IO_FREE_STATE;
	}
	return ret_sts;
}

/*
 * @brief This API Re-initialize the QSPI interface
 */
hal_ret_sts    io_hal_qspi_reinit(io_inst_id inst_id)
{
#ifdef LINUX_TEMP_PORT
	DEBUG_CPRINT(("\n EXO IO AL QSPI Re-Initialise"));
	usleep(100000);
#endif
	hal_ret_sts sts = HAL_SCS;
	ioal_qspi_hdle ioal_hqspi;

	switch(inst_id)
	{
		case IOAL_INST_QSPI1:
			if(HAL_SCS == io_hal_qspi_deInit(inst_id))
			{
				if(HAL_SCS == io_hal_wrpr_qspi_init(&ioal_hqspi))
				{
					intf_inst_hdle_ptr[IOAL_INST_QSPI1] = &ioal_hqspi;
					io_hal_qspi_cb_init(&ioal_hqspi);
				}
				else
				{
					sts = HAL_IO_INIT_ERR;
				}
			}
			else
			{
				sts = HAL_IO_INIT_ERR;
			}

		   break;


		default:
			sts = HAL_IO_INIT_INVALID_INSTANCE;
			break;

	}

#ifdef LINUX_TEMP_PORT
	DEBUG_CPRINT(("\n EXO IO AL QSPI Re-Initialisation completed successfully"));
#endif
	return sts;
}

#ifndef LINUX_TEMP_PORT
/**
 * @brief This is QSPI interface dummy function for target
 */
void check_qspi_dummy(ioal_qspi_hdle *hqspi)
{
	return;
}

#else
/**
 * @brief This is QSPI interface dummy function for linux
 */
void linux_qspi_dummy_fn(struct _ioal_qspi_hdle *hqspi)
{
}

#endif
