/******************************************************************************/
/**
 * @file otsu_mem.c
 *
 * @brief This file contains functions that provides demonstration of
 *        usage of otsu memory layout configure APIs
 *
 * The functions provided in the file provides demonstration on
 * usage of otsu memory layout manager APIs
 *
 * @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 headers of the module                      */
/******************************************************************************/


#include "otsu_mem_def.h"
#include "otsu_tctm_msg_def.h"
#include <stddef.h>
#include "exo_types.h"


/******************************************************************************/
/*                  Definition of local macros                 				  */
/******************************************************************************/


#define FMC_NOR_FLASH_OSAL 0x60000000

/* SDRAM location after 1 MB */
#define BL_FALLBACK2_EXT_NOR_LOC_C			   (uint32_t)0xC0100000
/* SDRAM location after 2 MB */
#define BL_FALLBACK3_EXT_NOR_LOC_FATORY_CODE_D (uint32_t)0xC0200000

#define OTSU_FIRMWARE_STORAGE_MEM (1024*1024)

/* External NOR FLASH address */
#define EXT_STORAGE_FLASH_MEM_ADDRS   (uint32_t) (FMC_NOR_FLASH_OSAL )
//#define EXT_STORAGE_FLASH_MEM_ADDRS   (uint32_t) (OTSU_MEM_OFFSET_FOR_FTM_COPY)

/* Internal execution FLASH address */
#define INT_EXECUTION_FLASH_MEM_ADDRS (uint32_t) 0x8010000
/* Internal previous version software storage FLASH address */
#define INT_PRV_SFT_STORAGE_MEM_ADDRS (uint32_t) 0x8110000
/* External NOR Flash current version storage address */
#define EXT_PRV_SFT_BCKUP_MEM_ADDRS   (uint32_t) (BL_FALLBACK3_EXT_NOR_LOC_FATORY_CODE_D)

#define OTSU_MEM_OFFSET_FOR_FACTORY_COPY (uint32_t)(FMC_NOR_FLASH_OSAL + (1024*1024))

#define TOTAL_OTSU_MEM_REGION   5


/* Allocated SDRAM for OTSU module  1mb*/
static uint8_t ftm_file_dwnlod_storage[OTSU_FIRMWARE_STORAGE_MEM] PLACE_IN_EXT_RAM_MEM;



#ifdef COREBOARD
/* Use FMC flash in coreboard */
#define PLACE_IN_EXT_FLASH_OTSU __attribute__((aligned(4))) __attribute__ ((section (".ext_fmcflash_firmware")))

#else
/* Use QSPI flash in discovery */
#define PLACE_IN_EXT_FLASH_OTSU __attribute__((aligned(4))) __attribute__ ((section (".ext_qspiflash_firmware")))

#endif



/* Allocated FMC flash for OTSU module  1mb*/
static uint8_t PLACE_IN_EXT_FLASH_OTSU ext_mem_norflash_otsu_bank1[OTSU_FIRMWARE_STORAGE_MEM];

/* Allocated for FMC flash OTSU module 1mb */
static uint8_t PLACE_IN_EXT_FLASH_OTSU ext_mem_norflash_otsu_bank2[OTSU_FIRMWARE_STORAGE_MEM];


/******************************************************************************/
/*                       Definition of local variables                        */
/******************************************************************************/


static s_otsu_mem_RegionInfo PLACE_IN_EXT_RAM_MEM ostu_mem_region_info[TOTAL_OTSU_MEM_REGION+1];  // required 110KB

/******************************************************************************/
/*                  Declaration of local function prototypes                  */
/******************************************************************************/



/**
* @brief This function used to configure all memory regions like internal flash,
* external flash, sdram.
*
* @param[in]  s_otsu_storageRegion : pointer to structure that will contain all memory information
*
* @return memory address
* @retval allocated address
*/
static void otsu_mem_configure_all(s_otsu_storageRegion *region_info);


/******************************************************************************/
/*                       Definition of local functions                        */
/******************************************************************************/


/**
* @brief This function used to configure all memory regions like internal flash,
* external flash, sdram.
*/
static void otsu_mem_configure_all(s_otsu_storageRegion *region_info)
{
	uint8_t memory_cnt =0;
	while(region_info->pucStartAddress != NULL)
	{
		ostu_mem_region_info[memory_cnt].memoryStartAddress = region_info->pucStartAddress;
		ostu_mem_region_info[memory_cnt].memoryEndAddress = (uint8_t*)((region_info->pucStartAddress + region_info->xSizeInBytes)-1);
		ostu_mem_region_info[memory_cnt].current_free_address = region_info->pucStartAddress;
		ostu_mem_region_info[memory_cnt].freeBytes = ((uint32_t)ostu_mem_region_info[memory_cnt].memoryEndAddress) - ((uint32_t)ostu_mem_region_info[memory_cnt].memoryStartAddress) +1;
		ostu_mem_region_info[memory_cnt].memory_length = ostu_mem_region_info[memory_cnt].freeBytes;

		memory_cnt++;
		region_info++;
	}
	ostu_mem_region_info[memory_cnt].memoryStartAddress = NULL;
	ostu_mem_region_info[memory_cnt].memoryEndAddress = NULL;
	ostu_mem_region_info[memory_cnt].current_free_address = NULL;
	ostu_mem_region_info[memory_cnt].freeBytes = 0;
}

/******************************************************************************/
/*                      Definition of global functions                        */
/******************************************************************************/



/**
* @brief This function will return the download address to be allocated for file transfer
*/
uint32_t otsu_get_ftm_download_address()
{
	return (uint32_t)(ostu_mem_region_info[otsu_ftm_dwnld_mem].memoryStartAddress);
}

/**
* @brief This function will return the storage addrewss to be used to move firmware stored in sdram to
* external flash
*/
uint32_t otsu_get_fw_storage_address()
{
	return (uint32_t)(ostu_mem_region_info[otsu_storage_mem].memoryStartAddress);
}

/**
* @brief This function will return the firmware execution address
*/
uint32_t get_fw_execution_address()
{
	return (uint32_t)(ostu_mem_region_info[otsu_execution_mem].memoryStartAddress);
}


/**
* @brief This function will return the backup firmware stored in internal flash
*/
uint32_t get_previous_fwstored_address()
{
	return (uint32_t)(ostu_mem_region_info[otsu_previous_sft_mem].memoryStartAddress);
}


/**
* @brief This function will return the backup firmware stored in external flash
* this is the factory firmware copy
*/
uint32_t get_factory_fwstored_address()
{
	return (uint32_t)(ostu_mem_region_info[otsu_factory_sft_mem].memoryStartAddress);
}




/**
* @brief This function used to configure different memory regions like internal flash,
* external flash, sdram.
*/
void otsu_mem_configure(e_otsu_mem_type_def mem_type, uint32_t mem_address_set, uint32_t size)
{
	s_otsu_storageRegion memory_details;

		memory_details.pucStartAddress = (uint8_t*)mem_address_set;
		memory_details.xSizeInBytes = size;
		memory_details.mem_type = mem_type;
		ostu_mem_region_info[mem_type].memoryStartAddress = memory_details.pucStartAddress;
		ostu_mem_region_info[mem_type].memoryEndAddress = (uint8_t*)((memory_details.pucStartAddress + memory_details.xSizeInBytes)-1);
		ostu_mem_region_info[mem_type].current_free_address = memory_details.pucStartAddress;
		ostu_mem_region_info[mem_type].freeBytes = ((uint32_t)ostu_mem_region_info[mem_type].memoryEndAddress) - ((uint32_t)ostu_mem_region_info[mem_type].memoryStartAddress) +1;
		ostu_mem_region_info[mem_type].memory_length = ostu_mem_region_info[mem_type].freeBytes;
}

/**
* @brief This function used to initialize the memories that used for OTSU to
* manage different firmwares
*
*/
void otsu_mem_init(void)
{
	/*
	 * memory allocated for fw loading
	 */
	s_otsu_storageRegion memory_details[]=
	{
			{
					ftm_file_dwnlod_storage,(1024 *1024),otsu_ftm_dwnld_mem //in bytes
			},
			{
					ext_mem_norflash_otsu_bank1,(1024 *1024),otsu_storage_mem //in bytes
			},
			{
					(uint8_t*)INT_EXECUTION_FLASH_MEM_ADDRS,(900 *1024),otsu_execution_mem //in bytes
			},
			{
					(uint8_t*)INT_PRV_SFT_STORAGE_MEM_ADDRS,(900 *1024),otsu_previous_sft_mem //in bytes
			},
			{
					ext_mem_norflash_otsu_bank2,(1024 *1024),otsu_factory_sft_mem //in bytes
			},
			{
					(uint8_t*)NULL,0,otsu_mem_none //in bytes
			}
	};

	otsu_mem_configure_all(memory_details);
}
