/**
 * @file  gpio-fp.c
 * @brief GPIO API for Fastcall driver(Fingerprint)
 *
 * Copyright (c) 2014-2015 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 "drMobicore.h"
#include "DrApi/DrApiFastCall.h"

#include "gpio-fp.h"
#include "regs-tzpc.h"
#include "regs-gpio-fp.h"
#include "fcUART.h"

struct gpio_fp_saved_status {
	uint32_t gpiocon;
	uint32_t gpiodat;
	uint32_t gpiopud;
	uint32_t gpiodrv;
} g_saved_val;

#if defined(CONFIG_EXYNOS7420) || defined(CONFIG_EXYNOS5433) \
	|| defined(CONFIG_EXYNOS7580) || defined(CONFIG_EXYNOS8890) \
	|| defined(CONFIG_EXYNOS7880) || defined(CONFIG_EXYNOS7870) \
	|| defined(CONFIG_EXYNOS7570) || defined(CONFIG_EXYNOS8895) \
	|| defined(CONFIG_EXYNOS7885) || defined(CONFIG_EXYNOS9810)
uint32_t g_val_GPIOPUDPDN = FP_GPIOPUDPDN_VALUE;
#endif

#if TBASE_API_LEVEL >= 5
extern addr_t fp_tzpc_spi_sfr_va, fp_tzpc_gpio_sfr_va, fp_gpio_sfr_va;
#if defined(CONFIG_EXYNOS8895) || defined(CONFIG_EXYNOS9810)
extern addr_t fp_tzpc_usi_sfr_va, fp_usi_i_mode_sfr_va;
#endif
#else
uint32_t fp_tzpc_spi_sfr_va = FP_TZPC_SPI_SFR_VA;
uint32_t fp_tzpc_gpio_sfr_va = FP_TZPC_GPIO_SFR_VA;
uint32_t fp_gpio_sfr_va = FP_GPIO_SFR_VA;
#endif

/************************************************************************/
/* TZPC control functions                                               */
/************************************************************************/
uint32_t fp_set_tzpc_secure(fastcall_registers_t regs, uint32_t pin_conf) {
	uint32_t ret = 0;
	uint32_t tzpc_result = 0;
#ifndef FP_TEST_PROTECTION_FUNCTION 	/* This feature is enabled when only testing mode */
	uint32_t is_secure;
#if defined(CONFIG_EXYNOS8895) || defined(CONFIG_EXYNOS7885) \
	|| defined(CONFIG_EXYNOS9810)
	uint32_t read_value = 0, write_value = 0;
#endif

	projectname = pin_conf;
	/* set SPI TZPC secure */
	write_sfr_value((uint32_t)fp_tzpc_spi_sfr_va + FP_TZPC_SPI_DECPROT_NUM, FP_TZPC_SPI_DECPROT_BIT);
	/* check SPI TZPC Status */
	is_secure = read_sfr_value((uint32_t)fp_tzpc_spi_sfr_va + FP_TZPC_SPI_DECSTAT_NUM);
	UART_PSH("set_fp_tzpc_secure(spi) : is_secure = ", is_secure);
	is_secure &= FP_TZPC_SPI_DECPROT_BIT;
	if (is_secure != FP_TZPC_SECURE) {
		ret = (uint32_t) FP_RET_FAILED;
		UART_PSH("set_fp_tzpc_secure(spi) is failed");
		goto fp_secure_failed;
	}
	tzpc_result |= FP_SPI_PROTECTION_DONE;

#if defined(CONFIG_EXYNOS8895) || defined(CONFIG_EXYNOS9810)
	/* set USI I MODE TZPC secure */
	write_sfr_value((uint32_t)fp_tzpc_usi_sfr_va + FP_TZPC_USI_DECPROT_NUM, FP_TZPC_USI_DECPROT_BIT);
	/* check USI I MODE TZPC Status */
	is_secure = read_sfr_value((uint32_t)fp_tzpc_usi_sfr_va + FP_TZPC_USI_DECSTAT_NUM);
	UART_PSH("set_fp_tzpc_secure(usi) : is_secure = ", is_secure);
	is_secure &= FP_TZPC_USI_DECPROT_BIT;
	if (is_secure != FP_TZPC_SECURE) {
		ret = (uint32_t) FP_RET_FAILED;
		UART_PSH("set_fp_tzpc_secure(usi) is failed");
		goto fp_secure_failed;
	}
	tzpc_result |= FP_USI_I_MODE_PROTECTION_DONE;
#endif

#if defined(FP_GPIO_PROTECTION)
#if defined(CONFIG_EXYNOS8895) || defined(CONFIG_EXYNOS7885) \
	|| defined(CONFIG_EXYNOS9810)
	/* set GPIO TZPC secure */
	read_value = read_sfr_value((uint32_t)fp_tzpc_gpio_sfr_va + FP_TZPC_GPIO_DECSTAT_NUM);
	write_value = read_value & FP_TZPC_GPIO_DECPROT_BIT;
	UART_PSH("set_fp_tzpc_secure(gpio) : write_value = ", write_value);
	write_sfr_value((uint32_t)fp_tzpc_gpio_sfr_va + FP_TZPC_GPIO_DECPROT_NUM, write_value);
	/* check GPIO TZPC Status */
	is_secure = read_sfr_value((uint32_t)fp_tzpc_gpio_sfr_va + FP_TZPC_GPIO_DECSTAT_NUM);
	UART_PSH("set_fp_tzpc_secure(gpio) : is_secure = ", is_secure);
	is_secure &= ~FP_TZPC_GPIO_DECPROT_BIT;
	if (is_secure != FP_TZPC_SECURE) {
		ret = (uint32_t) FP_RET_FAILED;
		UART_PSH("set_fp_tzpc_secure(gpio) is failed");
		goto fp_secure_failed;
	}
#else
	/* set GPIO TZPC secure */
	write_sfr_value((uint32_t)fp_tzpc_gpio_sfr_va + FP_TZPC_GPIO_DECPROT_NUM, FP_TZPC_GPIO_DECPROT_BIT);
	/* check SPI TZPC Status */
	is_secure = read_sfr_value((uint32_t)fp_tzpc_gpio_sfr_va + FP_TZPC_GPIO_DECSTAT_NUM);
	UART_PSH("set_fp_tzpc_secure(gpio) : is_secure = ", is_secure);
	is_secure &= FP_TZPC_GPIO_DECPROT_BIT;
	if (is_secure != FP_TZPC_SECURE) {
		ret = (uint32_t) FP_RET_FAILED;
		UART_PSH("set_fp_tzpc_secure(gpio) is failed");
		goto fp_secure_failed;
	}
#endif
#endif
	tzpc_result |= FP_GPIO_PROTECTION_DONE;
fp_secure_failed:
#endif
	UART_PSH("set_fp_tzpc result : 0x", tzpc_result);
	return ret;

}

/************************************************************************/
/* GPIO control functions                                               */
/************************************************************************/
uint32_t fp_set_gpio_init(fastcall_registers_t regs) {
	/* Setting GPIO SFR for SPI function */
#if defined(CONFIG_EXYNOS7420) || defined(CONFIG_EXYNOS5433) \
	|| defined(CONFIG_EXYNOS7580) || defined(CONFIG_EXYNOS8890)
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON, FP_GPIOCON_INIT_VALUE);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT, FP_GPIODAT_INIT_VALUE);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUD, FP_GPIOPUD_INIT_VALUE);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODRV, FP_GPIODRV_INIT_VALUE);
#elif defined(CONFIG_EXYNOS7870) || defined(CONFIG_EXYNOS7570)
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON, FP_GPIOCON_INIT_VALUE_OFF);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT, FP_GPIODAT_INIT_VALUE_OFF);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUD, FP_GPIOPUD_INIT_VALUE_OFF);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODRV, FP_GPIODRV_INIT_VALUE_OFF);
#elif defined(CONFIG_EXYNOS7880) || defined(CONFIG_EXYNOS8895) \
	|| defined(CONFIG_EXYNOS7885) || defined(CONFIG_EXYNOS9810)
	uint32_t read_con = 0, read_dat = 0, read_pud = 0, read_drv = 0;
	uint32_t write_con = 0, write_dat = 0, write_pud = 0, write_drv = 0;

	read_con = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON) & ~FP_GPIOCON_MASK;
	read_dat = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT) & ~FP_GPIODAT_MASK;
	read_pud = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUD) & ~FP_GPIOPUD_MASK;
	read_drv = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODRV) & ~FP_GPIODRV_MASK;
	write_con = read_con | FP_GPIOCON_INIT_VALUE_OFF;
	write_dat = read_dat | FP_GPIODAT_INIT_VALUE_OFF;
	write_pud = read_pud | FP_GPIOPUD_INIT_VALUE_OFF;
	write_drv = read_drv | FP_GPIODRV_INIT_VALUE_OFF;

	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON, write_con);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT, write_dat);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUD, write_pud);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODRV, write_drv);
#else
	UART_PSH("fp_set_gpio_init is unused");
	return (uint32_t) FP_RET_UNUSED_FUNCTION;
#endif
	UART_PSH("fp_set_gpio_init is called");
	return (uint32_t) FP_RET_SUCCESS;
}

uint32_t fp_save_gpio_regs(fastcall_registers_t regs) {
#if defined(CONFIG_EXYNOS7420) || defined(CONFIG_EXYNOS5433) \
	|| defined(CONFIG_EXYNOS7580) || defined(CONFIG_EXYNOS8890) \
	|| defined(CONFIG_EXYNOS7870) || defined(CONFIG_EXYNOS7570)
	g_saved_val.gpiocon = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON);
	g_saved_val.gpiodat = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT);
	g_saved_val.gpiopud = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUD);
	g_saved_val.gpiodrv = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODRV);

	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCONPDN, FP_GPIOCONPDN_VALUE);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUDPDN, g_val_GPIOPUDPDN);
#elif defined(CONFIG_EXYNOS7880) || defined(CONFIG_EXYNOS8895) \
	|| defined(CONFIG_EXYNOS7885) || defined(CONFIG_EXYNOS9810)
	uint32_t read_conpdn = 0, read_pudpdn = 0;
	uint32_t write_conpdn = 0, write_pudpdn = 0;

	g_saved_val.gpiocon = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON) & FP_GPIOCON_MASK;
	g_saved_val.gpiodat = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT) & FP_GPIODAT_MASK;
	g_saved_val.gpiopud = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUD) & FP_GPIOPUD_MASK;
	g_saved_val.gpiodrv = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODRV) & FP_GPIODRV_MASK;

	read_conpdn = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCONPDN) & ~FP_GPIOCONPDN_MASK;
	read_pudpdn = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUDPDN) & ~FP_GPIOPUDPDN_MASK;
	write_conpdn = read_conpdn | FP_GPIOCONPDN_VALUE;
	write_pudpdn = read_pudpdn | g_val_GPIOPUDPDN;

	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCONPDN, write_conpdn);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUDPDN, write_pudpdn);
#else
	UART_PSH("fp_save_gpio_regs is unused");
	return (uint32_t) FP_RET_UNUSED_FUNCTION;
#endif
	UART_PSH("fp_save_gpio_regs() : g_saved_val.gpiocon = ", g_saved_val.gpiocon);
	UART_PSH("fp_save_gpio_regs() : g_saved_val.gpiodat = ", g_saved_val.gpiodat);
	UART_PSH("fp_save_gpio_regs() : g_saved_val.gpiopud = ", g_saved_val.gpiopud);
	UART_PSH("fp_save_gpio_regs() : g_saved_val.gpiodrv = ", g_saved_val.gpiodrv);
	return (uint32_t) FP_RET_SUCCESS;
}

uint32_t fp_save_gpio_regs_cs_high(fastcall_registers_t regs) {
#if defined(CONFIG_EXYNOS7870) || defined(CONFIG_EXYNOS7570) \
	|| defined(CONFIG_EXYNOS8890) || defined(CONFIG_EXYNOS7420)
	g_saved_val.gpiocon = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON);
	g_saved_val.gpiodat = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT);
	g_saved_val.gpiopud = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUD);
	g_saved_val.gpiodrv = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODRV);

	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCONPDN, FP_GPIOCONPDN_CSHIGH_VALUE);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUDPDN, g_val_GPIOPUDPDN);
#elif defined(CONFIG_EXYNOS7880) || defined(CONFIG_EXYNOS8895) \
	|| defined(CONFIG_EXYNOS7885) || defined(CONFIG_EXYNOS9810)
	uint32_t read_conpdn = 0, read_pudpdn = 0;
	uint32_t write_conpdn = 0, write_pudpdn = 0;

	g_saved_val.gpiocon = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON) & FP_GPIOCON_MASK;
	g_saved_val.gpiodat = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT) & FP_GPIODAT_MASK;
	g_saved_val.gpiopud = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUD) & FP_GPIOPUD_MASK;
	g_saved_val.gpiodrv = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODRV) & FP_GPIODRV_MASK;

	read_conpdn = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCONPDN) & ~FP_GPIOCONPDN_MASK;
	read_pudpdn = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUDPDN) & ~FP_GPIOPUDPDN_MASK;
	write_conpdn = read_conpdn | FP_GPIOCONPDN_CSHIGH_VALUE;
	write_pudpdn = read_pudpdn | g_val_GPIOPUDPDN;

	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCONPDN, write_conpdn);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUDPDN, write_pudpdn);
#else
	UART_PSH("fp_save_gpio_regs_cs_high is unused");
	return (uint32_t) FP_RET_UNUSED_FUNCTION;
#endif
	UART_PSH("fp_save_gpio_regs_cs_high() : g_saved_val.gpiocon = ", g_saved_val.gpiocon);
	UART_PSH("fp_save_gpio_regs_cs_high() : g_saved_val.gpiodat = ", g_saved_val.gpiodat);
	UART_PSH("fp_save_gpio_regs_cs_high() : g_saved_val.gpiopud = ", g_saved_val.gpiopud);
	UART_PSH("fp_save_gpio_regs_cs_high() : g_saved_val.gpiodrv = ", g_saved_val.gpiodrv);
	return (uint32_t) FP_RET_SUCCESS;
}

uint32_t fp_restore_gpio_regs(fastcall_registers_t regs) {
#if defined(CONFIG_EXYNOS7420) || defined(CONFIG_EXYNOS5433) \
	|| defined(CONFIG_EXYNOS7580) || defined(CONFIG_EXYNOS8890) \
	|| defined(CONFIG_EXYNOS7870) || defined(CONFIG_EXYNOS7570)
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON, g_saved_val.gpiocon);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT, g_saved_val.gpiodat);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUD, g_saved_val.gpiopud);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODRV, g_saved_val.gpiodrv);
#elif defined(CONFIG_EXYNOS7880) || defined(CONFIG_EXYNOS8895) \
	|| defined(CONFIG_EXYNOS7885) || defined(CONFIG_EXYNOS9810)
	uint32_t read_con = 0, read_dat = 0, read_pud = 0, read_drv = 0;
	uint32_t write_con = 0, write_dat = 0, write_pud = 0, write_drv = 0;

	read_con = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON) & ~FP_GPIOCON_MASK;
	read_dat = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT) & ~FP_GPIODAT_MASK;
	read_pud = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUD) & ~FP_GPIOPUD_MASK;
	read_drv = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODRV) & ~FP_GPIODRV_MASK;

	write_con = read_con | g_saved_val.gpiocon;
	write_dat = read_dat | g_saved_val.gpiodat;
	write_pud = read_pud | g_saved_val.gpiopud;
	write_drv = read_drv | g_saved_val.gpiodrv;

	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON, write_con);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT, write_dat);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUD, write_pud);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODRV, write_drv);
#if defined(CONFIG_EXYNOS8895) || defined(CONFIG_EXYNOS9810)
	/* set the usi_i_mode */
	write_sfr_value((uint32_t)fp_usi_i_mode_sfr_va + FP_USI_I_MODE_SFR, FP_USI_I_MODE_VALUE);
#endif
#else
	UART_PSH("fp_restore_gpio_regs is unused");
	return (uint32_t) FP_RET_UNUSED_FUNCTION;
#endif
	UART_PSH("fp_restore_gpio_regs is called");
	return (uint32_t) FP_RET_SUCCESS;
}

uint32_t fp_set_gpio_btp_ocp(fastcall_registers_t regs,	uint32_t gpio_dat_bit) {
#if defined(CONFIG_EXYNOS7420)
	uint32_t sfr = 0;
	sfr = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT);

	if (gpio_dat_bit == FP_GPIO_HIGH)
		sfr |= 0x10;
	else
		sfr &= 0x0F;

	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT, sfr);
#else
	return (uint32_t) FP_RET_UNUSED_FUNCTION;
#endif
	return (uint32_t) FP_RET_SUCCESS;
}

uint32_t fp_disable_gpio_btp_ocp(fastcall_registers_t regs) {
#if defined(CONFIG_EXYNOS7420)
	/* Set OCP_EN as input */
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON, FP_GPIOCON_WO_OCP);

	/* Change GPIOPUDPDN value(make OCP_EN as Pull-down) */
	g_val_GPIOPUDPDN = FP_GPIOPUDPDN_WO_OCP;
#else
	return (uint32_t) FP_RET_UNUSED_FUNCTION;
#endif
	return (uint32_t) FP_RET_SUCCESS;
}

uint32_t fp_set_spi_cs(fastcall_registers_t regs) {
#if defined(CONFIG_EXYNOS7570) || defined(CONFIG_EXYNOS7870)
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON, FP_GPIOCON_CSSET_VALUE);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT, FP_GPIODAT_INIT_VALUE);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUD, FP_GPIOPUD_CSSET_VALUE);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODRV, FP_GPIODRV_INIT_VALUE_OFF);
#elif defined(CONFIG_EXYNOS7880) || defined(CONFIG_EXYNOS8895) \
	|| defined(CONFIG_EXYNOS7885) || defined(CONFIG_EXYNOS9810)
	uint32_t read_con = 0, read_dat = 0, read_pud = 0, read_drv = 0;
	uint32_t write_con = 0, write_dat = 0, write_pud = 0, write_drv = 0;

	read_con = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON) & ~FP_GPIOCON_MASK;
	read_dat = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT) & ~FP_GPIODAT_MASK;
	read_pud = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUD) & ~FP_GPIOPUD_MASK;
	read_drv = read_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODRV) & ~FP_GPIODRV_MASK;

	write_con = read_con | FP_GPIOCON_CSSET_VALUE;
	write_dat = read_dat | FP_GPIODAT_INIT_VALUE;
	write_pud = read_pud | FP_GPIOPUD_CSSET_VALUE;
	write_drv = read_drv | FP_GPIODRV_INIT_VALUE;

	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOCON, write_con);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODAT, write_dat);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIOPUD, write_pud);
	write_sfr_value((uint32_t)fp_gpio_sfr_va + FP_GPIODRV, write_drv);
#else
	return (uint32_t) FP_RET_UNUSED_FUNCTION;
#endif
	return (uint32_t) FP_RET_SUCCESS;
}

uint32_t fp_test_fastcall_function(fastcall_registers_t regs) {
#ifdef FP_TEST_PROTECTION_FUNCTION
	uint32_t ret = (uint32_t) FP_RET_SUCCESS;
	uint32_t is_secure;
	uint32_t test_case = (uint32_t)regs[1];
#if defined(CONFIG_EXYNOS8895) || defined(CONFIG_EXYNOS7885) \
	|| defined(CONFIG_EXYNOS9810)
	uint32_t read_value = 0, write_value = 0;
#endif

	UART_PSH("fp_test : TestCase = ", test_case);
	switch (test_case) {
		case (uint32_t) FP_TEST_SPI_PROTECTION:
			write_sfr_value((uint32_t)fp_tzpc_spi_sfr_va + FP_TZPC_SPI_DECPROT_NUM, FP_TZPC_SPI_DECPROT_BIT);
			is_secure = read_sfr_value((uint32_t)fp_tzpc_spi_sfr_va + FP_TZPC_SPI_DECSTAT_NUM);
			UART_PSH("fp_test TZPC(SPI) : is_secure = ", is_secure);
			is_secure &= FP_TZPC_SPI_DECPROT_BIT;
			if (is_secure != FP_TZPC_SECURE)
				ret = (uint32_t) FP_RET_FAILED;
			UART_PSH("fp_test TZPC(SPI) : ret = ", ret);
			break;
		case (uint32_t) FP_TEST_GPIO_PROTECTION:
#if defined(FP_GPIO_PROTECTION)
#if defined(CONFIG_EXYNOS8895) || defined(CONFIG_EXYNOS7885) \
	|| defined(CONFIG_EXYNOS9810)
			// set GPIO TZPC secure
			read_value = read_sfr_value((uint32_t)fp_tzpc_gpio_sfr_va + FP_TZPC_GPIO_DECSTAT_NUM);
			write_value = read_value & FP_TZPC_GPIO_DECPROT_BIT;
			UART_PSH("fp_test TZPC(GPIO) : write_value = ", write_value);
			write_sfr_value((uint32_t)fp_tzpc_gpio_sfr_va + FP_TZPC_GPIO_DECPROT_NUM, write_value);
			// check GPIO TZPC Status
			is_secure = read_sfr_value((uint32_t)fp_tzpc_gpio_sfr_va + FP_TZPC_GPIO_DECSTAT_NUM);
			UART_PSH("fp_test TZPC(GPIO) : is_secure = ", is_secure);
			is_secure &= ~FP_TZPC_GPIO_DECPROT_BIT;
			if (is_secure != FP_TZPC_SECURE)
				ret = (uint32_t) FP_RET_FAILED;
			UART_PSH("fp_test TZPC(GPIO) : ret = ", ret);
#else
			// set GPIO TZPC secure
			write_sfr_value((uint32_t)fp_tzpc_gpio_sfr_va + FP_TZPC_GPIO_DECPROT_NUM, FP_TZPC_GPIO_DECPROT_BIT);
			// check SPI TZPC Status
			is_secure = read_sfr_value((uint32_t)fp_tzpc_gpio_sfr_va + FP_TZPC_GPIO_DECSTAT_NUM);
			UART_PSH("fp_test TZPC(GPIO) : is_secure = ", is_secure);
			is_secure &= FP_TZPC_GPIO_DECPROT_BIT;
			if (is_secure != FP_TZPC_SECURE)
				ret = (uint32_t) FP_RET_FAILED;
			UART_PSH("fp_test TZPC(GPIO) : ret = ", ret);
#endif
#endif
			break;
		case (uint32_t) FP_TEST_SET_GPIO_INIT:
			ret = fp_set_gpio_init(regs);
			UART_PSH("fp_test GPIO_INIT : ret = ", ret);
			break;
		case (uint32_t) FP_TEST_SAVE_GPIO:
			ret = fp_save_gpio_regs(regs);
			UART_PSH("fp_test SAVE_GPIO : ret = ", ret);
			break;
		case (uint32_t) FP_TEST_SAVE_GPIO_CS_HIGH:
			ret = fp_save_gpio_regs_cs_high(regs);
			UART_PSH("fp_test SAVE_GPIO_CS_HIGH : ret = ", ret);
			break;
		case (uint32_t) FP_TEST_RESOTRE_GPIO:
			ret = fp_restore_gpio_regs(regs);
			UART_PSH("fp_test RESOTRE_GPIO : ret = ", ret);
			break;
		case (uint32_t) FP_TEST_SET_SPI_CS:
			ret = fp_set_spi_cs(regs);
			UART_PSH("fp_test SPI_CS : ret = ", ret);
			break;
		default:
			UART_PSH("fp_test wrong test case : ", test_case);
			break;
	}
	return ret;
#else
	UART_PSH("fp_test : UNUSED_FUNCTION");
	return (uint32_t) FP_RET_UNUSED_FUNCTION;
#endif
}
