/**
 * @file   rtic_secdrv.c
 * @brief  RTIC functions and ISR thread
 *
 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
 *
 * This software is proprietary of Samsung Electronics.
 * No part of this software, either material or conceptual may be copied
 * or distributed, transmitted, transcribed, stored in a retrieval system
 * or translated into any human or computer language in any form by any means,
 * electronic, mechanical, manual or otherwise, or disclosed to third parties
 * without the express written permission of Samsung Electronics.
 */

#include "drStd.h"
#include "DrApi/DrApiMm.h"
#if TBASE_API_LEVEL >= 5
#include "DrApi/DrApiMmExt.h"
#include "DrApi/DrApiError.h"
#endif
#include "DrApi/DrApiThread.h"
#include "DrApi/DrApiIpcMsg.h"
#include "DrApi/DrApiLogging.h"
#include "DrApi/DrApiMcSystem.h"
#include "drLog.h"
/* RTIC dedicated headers */
//#include "secdrv_common.h"
#include "drMobicore.h"
#include "rtic_secdrv.h"
#include "rtic_sfr.h"
#include "rtic_err.h"

#if defined(USE_INTERRUPT)
#include "drCommon.h"
DECLARE_STACK(RTIC_thread_stack, 4096);
#endif

#define DE_DEBUG

#if TBASE_API_LEVEL >= 5
addr_t rtic_sfr_base_va, rtic_clk_base_va;
#endif

//=====================================================================
// example code of Wrapper functin for TIMA-PKM
//=====================================================================

/* print byte string to hexa values */
void print_byte_to_hex(uint8_t *byte_array, size_t byte_length)
{
	int i;
	for(i = 0; i < byte_length; i++) {
		if ((0 != i) && (0 == (i % 32)))
			dbgSN(" ");
		dbgSH(" 0x", byte_array[i]);
	}
	dbgSN("\n");
}

uint32_t rtic_wrapper_test(void)
{
	uint32_t ret = RV_SUCCESS;
	uint32_t test_cnt;
	uint8_t hashval[20];// byte array to store result hash value

	/* call RTIC init */
	/* this function can be called along with TIMA enabling */
	ret = rtic_init();
	if (ret != RV_SUCCESS)
		return ret;

	for (test_cnt = 0; test_cnt < 10000; test_cnt++) {
		
		/* parameters: start_addr, length, result_buffer */
		ret = rtic_get_hash(0x040008000, 0x32768, hashval);
		if (ret != RV_SUCCESS)
			return ret;

		print_byte_to_hex(hashval, 20);

	}

	/* call RTIC exit */
	/* this function can be called along with TIMA disabling */
	ret = rtic_stop();
	if (ret != RV_SUCCESS)
		return ret;

	return ret;
}


//=====================================================================
// Wrapper functin for TIMA-PKM
//=====================================================================
uint32_t rtic_get_hash(uint32_t start_addr, uint32_t length, uint8_t *hashval)
{
	uint32_t ret = RV_SUCCESS;
	/* RTIC clock enable */
	/*Moved write to rtic_set_mem for 2 clock handling*/
	ret = rtic_set_mem(0, start_addr, length);
	if (ret != RV_SUCCESS) {
		ERR_LOG("[RTIC] Driver:: memory setting was failed");
		return ret;
	}

	ret = rtic_hashonce();
	if (ret != RV_SUCCESS) {
		ERR_LOG("[RTIC] Driver:: hashonce was failed");
		return ret;
	}

	ret = rtic_read_hash_val(0, (uint32_t *)hashval);
	if (ret != RV_SUCCESS){
		ERR_LOG("[RTIC] Driver:: hash value reading was failed");
		return ret;
	}
	/* RTIC clock disable */
	/*Moved write to rtic_read_hash_val for 2 clock handling*/

	return ret;
}


#if defined(USE_INTERRUPT)
//=====================================================================
// Interrupt Service Routines
//=====================================================================
static uint32_t thread_id;

/**
 * Start the new thread for H/W Crypto interrupt mode
 *
 * @return : E_OK if operation has been successfully completed.
 */
uint32_t start_rtic_isr_thread(void)
{
	uint32_t ret = RV_SUCCESS;

	if (DRAPI_OK != drApiStartThread(DRIVER_THREAD_NO_IRQH, FUNC_PTR(rtic_isr_thread),
		getStackTop(RTIC_thread_stack), IRQH_PRIORITY, DRIVER_THREAD_NO_EXCH))
		ret = RV_ISR_THREAD_START_FAILED;

	return ret;
}


/**
 * Stop the thread which was created in startCryptoThread function
 *
 * @return : E_OK if operation has been successfully completed.
 */
uint32_t stop_rtic_isr_thread(void)
{
	uint32_t ret = RV_SUCCESS;

	if (DRAPI_OK != drApiStopThread(DRIVER_THREAD_NO_IRQH))
		ret = RV_ISR_THREAD_STOP_FAILED;

	return ret;
}


/**
 * RTIC interrupt service routine
 *
 */
_THREAD_ENTRY void rtic_isr_thread(void)
{
	uint32_t reg;

	if (DRAPI_OK != drApiIntrAttach(IRQ_INFEEDCTRL_RTIC, INTR_MODE_RAISING_EDGE)) {
		dbgSN("[RTIC] Driver:: Interrupt attach was failed");
	}else {
#ifdef DR_DEBUG
	dbgSN("[RTIC] Driver:: Interrupt was attached");
#endif
	}

	for (;;) {
		dbgSN("[RTIC] Driver:: Wait for RTIC Interrupt");
		drApiWaitForIntr(IRQ_INFEEDCTRL_RTIC, TIME_INFINITE, NULL);
		
#if TBASE_API_LEVEL >= 5
		reg = read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_INT_STATUS);
#else
		reg = read_sfr_value(RTIC_INT_STATUS);
#endif
		if (reg == RTIC_INT_HASH_MIS_DONE) {
			dbgSN("[RTIC] Driver:: Hash mismatch ouccur!!");
#if TBASE_API_LEVEL >= 5
			write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_INT_PEND, RTIC_INT_PEND_HASH_MIS);
#else
			write_sfr_value(RTIC_INT_PEND, RTIC_INT_PEND_HASH_MIS);
#endif
			/* signal to drmain */
			drApiIpcSignal(thread_id);
		}

		if (reg == RTIC_INT_HASH_ONCE_DONE) {
#if TBASE_API_LEVEL >= 5
			write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_INT_PEND, RTIC_INT_PEND_HASH_ONCE);
#else
			write_sfr_value(RTIC_INT_PEND, RTIC_INT_PEND_HASH_ONCE);
#endif
#ifdef DR_DEBUG
			dbgSN("[RTIC] Driver:: Hash once was finished");
#endif
			/* signal to drmain */
			drApiIpcSignal(thread_id);
		}
	}
}
#endif

//=====================================================================
// API functions for Hash-once
//=====================================================================

/**
 * Start RTIC hashonce operation
 */
uint32_t rtic_hashonce(void)
{
	uint32_t ret = RV_SUCCESS;
	uint32_t reg_data;
	uint32_t retry_count = 0;

#if defined(USE_INTERRUPT)
	thread_id = drApiGetLocalThreadid(DRIVER_THREAD_NO_IPCH);
#endif
	/* Enable the RTIC INT SET for Hashonce */
#if TBASE_API_LEVEL >= 5
	write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_INT_EN_SET, RTIC_INT_HASH_MIS_ON|RTIC_INT_HASH_ONCE_ON);
#else
	write_sfr_value(RTIC_INT_EN_SET, RTIC_INT_HASH_MIS_ON|RTIC_INT_HASH_ONCE_ON);
#endif
	/* start RTIC Hashonce */
#if TBASE_API_LEVEL >= 5
	write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_COMMAND, RTIC_RUNTIME_CON_EN|RTIC_HASH_ONCE_RUN);
#else
	write_sfr_value(RTIC_COMMAND, RTIC_RUNTIME_CON_EN|RTIC_HASH_ONCE_RUN);
#endif
#ifdef DR_DEBUG
	dbgSN("[RTIC] Driver:: rtic_hashonce started");
#endif

#if defined(USE_INTERRUPT)
	/* wait signal from interrupt thread */
	drApiIpcSigWait();
#else
	while(1) {
#if TBASE_API_LEVEL >= 5
		reg_data = read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_INT_STATUS);
#else
		reg_data = read_sfr_value(RTIC_INT_STATUS);
#endif
		if (reg_data == RTIC_INT_HASH_ONCE_DONE)
			break;
		else
			retry_count++;

		if (retry_count > TIME_OUT) {
			ERR_LOG("[RTIC] Driver:: Time out during Hash once");
			return RV_RTIC_TIME_OUT;
		}
	}
#if TBASE_API_LEVEL >= 5
	write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_INT_PEND, RTIC_INT_PEND_HASH_ONCE);
#else
	write_sfr_value(RTIC_INT_PEND, RTIC_INT_PEND_HASH_ONCE);
#endif
#endif

#ifdef DR_DEBUG
	dbgSN("[RTIC] Driver:: Hash once was finished");
#endif
	return ret;
}


/**
 * Initializes the RTIC hardware IP
 * Mapping two virtual addresses for RTIC SFR and Clock enabling
 * Enable ACLK_RTIC, CLK_RTIC, FIFO control, and Hash Engine
 */
uint32_t rtic_init(void)
{
	uint32_t ret = RV_SUCCESS;
	drApiResult_t drRet = DRAPI_OK;

#ifdef DR_DEBUG
	dbgSN("[RTIC] Driver:: rtic_init() start");
#endif

#if TBASE_API_LEVEL >= 5
	drRet = drApiMapPhysicalBuffer((uint64_t)RTIC_SFR_PHY_BASE,
			SIZE_4KB,
			MAP_READABLE | MAP_WRITABLE | MAP_IO,
			(void **)&rtic_sfr_base_va);
	if (drRet != DRAPI_OK) {
		ERR_LOG("[RTIC] Driver:: Cannot map rtic_sfr_base_va: %x", drRet);
		return drRet;
	}
#if !defined(CONFIG_RTIC_USE_HWACG)
	drRet = drApiMapPhysicalBuffer((uint64_t)RTIC_CLK_PHY_BASE,
			SIZE_4KB,
			MAP_READABLE | MAP_WRITABLE | MAP_IO,
			(void **)&rtic_clk_base_va);
	if (drRet != DRAPI_OK) {
		ERR_LOG("[RTIC] Driver:: Cannot map rtic_clk_base_va: %x", drRet);
		return drRet;
	}
#endif
#else  //TBASE_API_LEVEL >= 5
	/* Mapping the virtual address for RTIC SFR */
	sec_map(RTIC_SFR_VER_BASE, RTIC_SFR_PHY_BASE, SIZE_4KB);
#if !defined(CONFIG_RTIC_USE_HWACG)
	/* Mapping the virtual address for clock enable */
	sec_map(RTIC_CLK_VER_BASE, RTIC_CLK_PHY_BASE, SIZE_4KB);
#endif
#ifdef DR_DEBUG
	dbgSHN("[RTIC] Driver:: SFR_virtual_addr: ", RTIC_SFR_VER_BASE);
#endif
#endif //TBASE_API_LEVEL >= 5

#if defined(USE_INTERRUPT)
	/* start rtic interrupt thread */
	ret = start_rtic_isr_thread();
	if (ret != RV_SUCCESS) {
		dbgSN("[RTIC] Driver:: start RTIC Interrupt thread was failed!");
		return ret;
	}
	dbgSN("[RTIC] Driver:: start RTIC Interrupt thread was done!");
#endif

#if !defined(CONFIG_RTIC_USE_HWACG)
#if defined(CONFIG_SMDK7870) || defined(CONFIG_SMDK7570) || defined(CONFIG_SMDK7880)
	rtic_bus_clk_control(RTIC_CLK_ENABLE);
#endif
#endif
	dbgSN("[RTIC] Driver:: rtic_init_done");

	return ret;
}


/**
 * Stop/Disable RTIC hardware IP
 * reset all SFR setting
 */
uint32_t rtic_stop(void)
{
	uint32_t ret = RV_SUCCESS;
	drApiResult_t drRet = DRAPI_OK;

	/* stop during rtic_run */
#if TBASE_API_LEVEL >= 5
	write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_COMMAND, RTIC_SW_RESET);

#ifdef DR_DEBUG
	dbgSN("[RTIC] Driver:: just after S/W reset!");
	dbgSHN("[RTIC] Drvier:: value of RTIC_CONTROL reg:", read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_CONTROL));
	dbgSHN("[RTIC] Driver:: value of RTIC_FIFO_CONTROL reg:", read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_FIFO_CONTROL));
	dbgSHN("[RTIC] Driver:: value of RTIC_PERIOD_TIMER reg:", read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_PERIOD_TIMER));
#endif
#else
	write_sfr_value(RTIC_COMMAND, RTIC_SW_RESET);

#ifdef DR_DEBUG
	dbgSN("[RTIC] Driver:: just after S/W reset!");
	dbgSHN("[RTIC] Drvier:: value of RTIC_CONTROL reg:", read_sfr_value(RTIC_CONTROL));
	dbgSHN("[RTIC] Driver:: value of RTIC_FIFO_CONTROL reg:", read_sfr_value(RTIC_FIFO_CONTROL));
	dbgSHN("[RTIC] Driver:: value of RTIC_PERIOD_TIMER reg:", read_sfr_value(RTIC_PERIOD_TIMER));
#endif
#endif
#if defined(USE_INTERRUPT)
	ret = stop_rtic_isr_thread();
	if (ret != RV_SUCCESS)
		dbgSN("[RTIC] Driver:: RTIC thread stop was failed!!");
#endif

#if TBASE_API_LEVEL >= 5
	drRet = drApiUnmapBuffer(rtic_sfr_base_va);
	if (drRet != DRAPI_OK) {
		ERR_LOG("[RTIC] Driver:: Cannot unmap rtic_sfr_base_va: %x", drRet);
		return drRet;
	}
	drRet = drApiUnmapBuffer(rtic_clk_base_va);
	if (drRet != DRAPI_OK) {
		ERR_LOG("[RTIC] Driver:: Cannot unmap rtic_clk_base_va: %x", drRet);
		return drRet;
	}
#else
	sec_unmap(RTIC_CLK_VER_BASE, SIZE_4KB);
	sec_unmap(RTIC_SFR_VER_BASE, SIZE_4KB);
#endif

#if !defined(CONFIG_RTIC_USE_HWACG)
#if defined(CONFIG_SMDK7870) || defined(CONFIG_SMDK7570) || defined(CONFIG_SMDK7880)
	rtic_bus_clk_control(RTIC_CLK_DISABLE);
#endif
#endif
	dbgSN("[RTIC] Driver:: RTIC Stoped!!");

	return ret;
}

/**
 * setting a sepecific memory address area for hashonce or rtic operation
 */
uint32_t rtic_set_mem(uint32_t mem_no, uint32_t start_addr, uint32_t length )
{
	uint32_t ret = RV_SUCCESS;
	uint32_t op_mode = HASHONCE;
	uint32_t reg_data;
#if !defined(CONFIG_RTIC_USE_HWACG)
#if TBASE_API_LEVEL >= 5
	/* RTIC clock enable */
#if defined(CONFIG_SMDK5433) || defined(CONFIG_SMDK7870) || \
    defined(CONFIG_SMDK7880) || defined(CONFIG_SMDK7570)
	write_sfr_value((uint32_t)rtic_clk_base_va + RTIC_CLK_ADDR, RTIC_CLK_PASS);
#elif defined(CONFIG_SMDK7420) || defined(CONFIG_SMDK7580) || defined(CONFIG_SMDK3475)
	write_sfr_value((uint32_t)rtic_clk_base_va + RTIC_ACLK_ADDR, RTIC_CLK_PASS);
	write_sfr_value((uint32_t)rtic_clk_base_va + RTIC_PCLK_ADDR, RTIC_CLK_PASS);
#endif
#ifdef DR_DEBUG
#if defined(CONFIG_SMDK5433) || defined(CONFIG_SMDK7870) || \
    defined(CONFIG_SMDK7880) || defined(CONFIG_SMDK7570)
	dbgSHN("[RTIC] Driver:: CLK: ", read_sfr_value((uint32_t)rtic_clk_base_va + RTIC_CLK_ADDR));
#elif defined(CONFIG_SMDK7420) || defined(CONFIG_SMDK7580) || defined(CONFIG_SMDK3475)
	dbgSHN("[RTIC] Driver:: ACLK: ", read_sfr_value((uint32_t)rtic_clk_base_va + RTIC_ACLK_ADDR));
	dbgSHN("[RTIC] Driver:: PCLK: ", read_sfr_value((uint32_t)rtic_clk_base_va + RTIC_PCLK_ADDR));
#endif
#endif
#else
	/* RTIC clock enable */
#if defined(CONFIG_SMDK5433) || defined(CONFIG_SMDK7870) || \
    defined(CONFIG_SMDK7880) || defined(CONFIG_SMDK7570)
	write_sfr_value(RTIC_CLK_ADDR, RTIC_CLK_PASS);
#elif defined(CONFIG_SMDK7420) || defined(CONFIG_SMDK7580) || defined(CONFIG_SMDK3475)
	write_sfr_value(RTIC_ACLK_ADDR, RTIC_CLK_PASS);
	write_sfr_value(RTIC_PCLK_ADDR, RTIC_CLK_PASS);
#endif
#ifdef DR_DEBUG
#if defined(CONFIG_SMDK5433) || defined(CONFIG_SMDK7870) || \
    defined(CONFIG_SMDK7880) || defined(CONFIG_SMDK7570)
	dbgSHN("[RTIC] Driver:: CLK: ", read_sfr_value(RTIC_CLK_ADDR));
#elif defined(CONFIG_SMDK7420) || defined(CONFIG_SMDK7580) || defined(CONFIG_SMDK3475)
	dbgSHN("[RTIC] Driver:: ACLK: ", read_sfr_value(RTIC_ACLK_ADDR));
	dbgSHN("[RTIC] Driver:: PCLK: ", read_sfr_value(RTIC_PCLK_ADDR));
#endif
#endif
#endif
#endif
#if TBASE_API_LEVEL >= 5
	reg_data=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_CONTROL);
#else
	reg_data=read_sfr_value(RTIC_CONTROL);
#endif

#ifdef CONFIG_PKM_SHA256
	reg_data |= RTIC_HASH_ENGINE_CON4;
#endif

	/* Set the memory address/length */
	switch (mem_no){
	case MEMA:
		if(op_mode == HASHONCE)
			reg_data |= RTIC_MEMA_HASH_ONCE_ON;
		reg_data|= RTIC_MEMA_ON;
#if TBASE_API_LEVEL >= 5
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_CONTROL, reg_data);
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_MEMA_ADDR, start_addr);
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_MEMA_LEN, length);
#else
		write_sfr_value(RTIC_CONTROL, reg_data);
		write_sfr_value(RTIC_MEMA_ADDR, start_addr);
		write_sfr_value(RTIC_MEMA_LEN, length);
#endif
		break;
	case MEMB:
		if(op_mode == HASHONCE)
			reg_data |= RTIC_MEMB_HASH_ONCE_ON;
		reg_data|= RTIC_MEMB_ON;
#if TBASE_API_LEVEL >= 5
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_CONTROL, reg_data);
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_MEMB_ADDR, start_addr);
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_MEMB_LEN, length);
#else
		write_sfr_value(RTIC_CONTROL, reg_data);
		write_sfr_value(RTIC_MEMB_ADDR, start_addr);
		write_sfr_value(RTIC_MEMB_LEN, length);
#endif
		break;
	case MEMC:
		if(op_mode == HASHONCE)
			reg_data |= RTIC_MEMC_HASH_ONCE_ON;
		reg_data|= RTIC_MEMC_ON;
#if TBASE_API_LEVEL >= 5
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_CONTROL, reg_data);
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_MEMC_ADDR, start_addr);
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_MEMC_LEN, length);
#else
		write_sfr_value(RTIC_CONTROL, reg_data);
		write_sfr_value(RTIC_MEMC_ADDR, start_addr);
		write_sfr_value(RTIC_MEMC_LEN, length);
#endif
		break;
	case MEMD:
		if(op_mode == HASHONCE)
			reg_data |= RTIC_MEMD_HASH_ONCE_ON;
		reg_data|= RTIC_MEMD_ON;
#if TBASE_API_LEVEL >= 5
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_CONTROL, reg_data);
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_MEMD_ADDR, start_addr);
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_MEMD_LEN, length);
#else
		write_sfr_value(RTIC_CONTROL, reg_data);
		write_sfr_value(RTIC_MEMD_ADDR, start_addr);
		write_sfr_value(RTIC_MEMD_LEN, length);
#endif
		break;
	case MEME:
		if(op_mode == HASHONCE)
			reg_data |= RTIC_MEME_HASH_ONCE_ON;
		reg_data|= RTIC_MEME_ON;
#if TBASE_API_LEVEL >= 5
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_CONTROL, reg_data);
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_MEME_ADDR, start_addr);
		write_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_MEME_LEN, length);
#else
		write_sfr_value(RTIC_CONTROL, reg_data);
		write_sfr_value(RTIC_MEME_ADDR, start_addr);
		write_sfr_value(RTIC_MEME_LEN, length);
#endif
		break;
	default:
		ret = RV_INVALID_MEM_NUMBER;
		break;
	}
#ifdef DR_DEBUG
	dbgSDN("[RTIC] Driver:: sets memory block: ", mem_no);
	dbgSHN("[RTIC] Drvier:: mema_addr: ", start_addr);
	dbgSHN("[RTIC] Driver:: mema_len: ", length);
#endif
	return ret;
}


/**
 * Read an result hash value for specific memroy region from SFR
 */
uint32_t rtic_read_hash_val(uint32_t mem_no, uint32_t *hashval)
{
	uint32_t ret = RV_SUCCESS;
	/* Read a result hash value for a specific memory block */
	switch (mem_no){
#if TBASE_API_LEVEL >= 5
	case MEMA:
		hashval[0]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_1);
		hashval[1]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_2);
		hashval[2]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_3);
		hashval[3]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_4);
		hashval[4]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_5);
#ifdef CONFIG_PKM_SHA256
		hashval[5]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_6);
		hashval[6]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_7);
		hashval[7]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_8);
#endif
	break;
	case MEMB:
		hashval[0]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_6);
		hashval[1]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_7);
		hashval[2]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_8);
		hashval[3]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_9);
		hashval[4]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_10);
		break;
	case MEMC:
		hashval[0]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_11);
		hashval[1]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_12);
		hashval[2]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_13);
		hashval[3]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_14);
		hashval[4]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_15);
		break;
	case MEMD:
		hashval[0]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_16);
		hashval[1]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_17);
		hashval[2]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_18);
		hashval[3]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_19);
		hashval[4]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_20);
		break;
	case MEME:
		hashval[0]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_21);
		hashval[1]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_22);
		hashval[2]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_23);
		hashval[3]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_24);
		hashval[4]=read_sfr_value((uint32_t)rtic_sfr_base_va + RTIC_HASH_VALUE_25);
		break;
#else
	case MEMA:
		hashval[0]=read_sfr_value(RTIC_HASH_VALUE_1);
		hashval[1]=read_sfr_value(RTIC_HASH_VALUE_2);
		hashval[2]=read_sfr_value(RTIC_HASH_VALUE_3);
		hashval[3]=read_sfr_value(RTIC_HASH_VALUE_4);
		hashval[4]=read_sfr_value(RTIC_HASH_VALUE_5);
#ifdef CONFIG_PKM_SHA256
		hashval[5]=read_sfr_value(RTIC_HASH_VALUE_6);
		hashval[6]=read_sfr_value(RTIC_HASH_VALUE_7);
		hashval[7]=read_sfr_value(RTIC_HASH_VALUE_8);
#endif
	break;
	case MEMB:
		hashval[0]=read_sfr_value(RTIC_HASH_VALUE_6);
		hashval[1]=read_sfr_value(RTIC_HASH_VALUE_7);
		hashval[2]=read_sfr_value(RTIC_HASH_VALUE_8);
		hashval[3]=read_sfr_value(RTIC_HASH_VALUE_9);
		hashval[4]=read_sfr_value(RTIC_HASH_VALUE_10);
		break;
	case MEMC:
		hashval[0]=read_sfr_value(RTIC_HASH_VALUE_11);
		hashval[1]=read_sfr_value(RTIC_HASH_VALUE_12);
		hashval[2]=read_sfr_value(RTIC_HASH_VALUE_13);
		hashval[3]=read_sfr_value(RTIC_HASH_VALUE_14);
		hashval[4]=read_sfr_value(RTIC_HASH_VALUE_15);
		break;
	case MEMD:
		hashval[0]=read_sfr_value(RTIC_HASH_VALUE_16);
		hashval[1]=read_sfr_value(RTIC_HASH_VALUE_17);
		hashval[2]=read_sfr_value(RTIC_HASH_VALUE_18);
		hashval[3]=read_sfr_value(RTIC_HASH_VALUE_19);
		hashval[4]=read_sfr_value(RTIC_HASH_VALUE_20);
		break;
	case MEME:
		hashval[0]=read_sfr_value(RTIC_HASH_VALUE_21);
		hashval[1]=read_sfr_value(RTIC_HASH_VALUE_22);
		hashval[2]=read_sfr_value(RTIC_HASH_VALUE_23);
		hashval[3]=read_sfr_value(RTIC_HASH_VALUE_24);
		hashval[4]=read_sfr_value(RTIC_HASH_VALUE_25);
		break;
#endif
	default:
		ret = RV_INVALID_MEM_NUMBER;
		break;
	}
#ifdef DR_DEBUG
	dbgSHN("[RTIC] Driver:: hash value readed from meomry #:", mem_no);
#endif

#if !defined(CONFIG_RTIC_USE_HWACG)
#if TBASE_API_LEVEL >= 5
	/* RTIC clock disable */
#if defined(CONFIG_SMDK5433) || defined(CONFIG_SMDK7870) || \
    defined(CONFIG_SMDK7880) || defined(CONFIG_SMDK7570)
	write_sfr_value((uint32_t)rtic_clk_base_va + RTIC_CLK_ADDR, RTIC_CLK_MASK);
#elif defined(CONFIG_SMDK7420) || defined(CONFIG_SMDK7580) || defined(CONFIG_SMDK3475)
	write_sfr_value((uint32_t)rtic_clk_base_va + RTIC_ACLK_ADDR, RTIC_CLK_MASK);
	write_sfr_value((uint32_t)rtic_clk_base_va + RTIC_PCLK_ADDR, RTIC_CLK_MASK);
#endif
#else
	/* RTIC clock disable */
#if defined(CONFIG_SMDK5433) || defined(CONFIG_SMDK7870) || \
    defined(CONFIG_SMDK7880) || defined(CONFIG_SMDK7570)
	write_sfr_value(RTIC_CLK_ADDR, RTIC_CLK_MASK);
#elif defined(CONFIG_SMDK7420) || defined(CONFIG_SMDK7580) || defined(CONFIG_SMDK3475)
	write_sfr_value(RTIC_ACLK_ADDR, RTIC_CLK_MASK);
	write_sfr_value(RTIC_PCLK_ADDR, RTIC_CLK_MASK);
#endif
#endif
#endif
	return ret;
}

#if !defined(CONFIG_RTIC_USE_HWACG)
uint32_t rtic_bus_clk_control(uint32_t command)
{
	uint32_t regs[12];

	regs[0] = SMC_SECDRV_PREFIX | SMC_CM_RTIC_CLK_SET;
	regs[1] = command;
	regs[2] = 0x0;
	regs[3] = 0x0;

	drApiFastCall(regs,sizeof(regs));
	if (regs[0] == (SMC_SECDRV_PREFIX | SMC_CM_RTIC_CLK_SET))
		dbgSHN("[RTIC] Driver:: Error - CryptoManager is not loaded: ", regs[0]);

	return regs[0];
}
#endif
