/**
 *
 * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd.
 *
 */

#include <core/types.h>
#include "gpio-fp.h"
#include "kernel_api.h"
#include "regs-gpio-fp.h"

struct gpio_fp_saved_status {
	uint32_t gpiocon;
	uint32_t gpiodat;
	uint32_t gpiopud;
	uint32_t gpiodrv;
} g_saved_val;

/************************************************************************/
/* TZPC control functions                                               */
/************************************************************************/
uint32_t set_tzpc_fp_secure(void)
{
	uint32_t ret = 0;
	uint32_t is_secure;

	/* set SPI TZPC secure */
	write_sfr_value(TZPC_SPI_SFR_VA + TZPC_SPI_DECPROT_NUM, TZPC_SPI_DECPROT_BIT);

#if defined(FP_GPIO_PROTECTION)
	/* set GPIO TZPC secure */
	write_sfr_value(TZPC_GPIO_SFR_VA + TZPC_GPIO_DECPROT_NUM, TZPC_GPIO_DECPROT_BIT);
#endif

	/* check SPI TZPC Status */
	is_secure = read_sfr_value(TZPC_SPI_SFR_VA + TZPC_SPI_DECSTAT_NUM);
	is_secure &= TZPC_SPI_DECPROT_BIT;
	if (is_secure != TZPC_SECURE) {
		ret = 1;
	}

#if defined(FP_GPIO_PROTECTION)
	/* check SPI TZPC Status */
	is_secure = read_sfr_value(TZPC_GPIO_SFR_VA + TZPC_GPIO_DECSTAT_NUM);
	is_secure &= TZPC_GPIO_DECPROT_BIT;
	if (is_secure != TZPC_SECURE) {
		ret = 1;
	}
#endif

	return ret;
}

/************************************************************************/
/* GPIO control functions                                               */
/************************************************************************/
uint32_t gpio_set_fp_init(void)
{
	/* Setting GPIO SFR for SPI function */
#if defined(CONFIG_EXYNOS7420) || defined(CONFIG_EXYNOS5433)
	write_sfr_value(FP_GPIO_SFR_VA + GPIOCON, FP_GPIOCON_INIT_VALUE);
	write_sfr_value(FP_GPIO_SFR_VA + GPIODAT, FP_GPIODAT_INIT_VALUE);
	write_sfr_value(FP_GPIO_SFR_VA + GPIOPUD, FP_GPIOPUD_INIT_VALUE);
	write_sfr_value(FP_GPIO_SFR_VA + GPIODRV, FP_GPIODRV_INIT_VALUE);
#elif defined(CONFIG_EXYNOS5430) || defined(CONFIG_EXYNOS5422) || defined(CONFIG_EXYNOS5420)
	/* TODO : GPIO Control is needed for these chipsets? */
#endif

	return 0;
}

uint32_t save_fp_gpio_regs(void)
{
#if defined(CONFIG_EXYNOS7420) || defined(CONFIG_EXYNOS5433)
	g_saved_val.gpiocon = read_sfr_value(FP_GPIO_SFR_VA + GPIOCON);
	g_saved_val.gpiodat = read_sfr_value(FP_GPIO_SFR_VA + GPIODAT);
	g_saved_val.gpiopud = read_sfr_value(FP_GPIO_SFR_VA + GPIOPUD);
	g_saved_val.gpiodrv = read_sfr_value(FP_GPIO_SFR_VA + GPIODRV);

	write_sfr_value(FP_GPIO_SFR_VA + GPIOCONPDN, FP_GPIOCONPDN_VALUE);
	write_sfr_value(FP_GPIO_SFR_VA + GPIOPUDPDN, FP_GPIOPUDPDN_VALUE);
#elif defined(CONFIG_EXYNOS5430) || defined(CONFIG_EXYNOS5422) || defined(CONFIG_EXYNOS5420)
	/* TODO : GPIO Control is needed for these chipsets? */
#endif

	return 0;
}

uint32_t restore_fp_gpio_regs(void)
{
#if defined(CONFIG_EXYNOS7420) || defined(CONFIG_EXYNOS5433)
	write_sfr_value(FP_GPIO_SFR_VA + GPIOCON, g_saved_val.gpiocon);
	write_sfr_value(FP_GPIO_SFR_VA + GPIODAT, g_saved_val.gpiodat);
	write_sfr_value(FP_GPIO_SFR_VA + GPIOPUD, g_saved_val.gpiopud);
	write_sfr_value(FP_GPIO_SFR_VA + GPIODRV, g_saved_val.gpiodrv);
#elif defined(CONFIG_EXYNOS5430) || defined(CONFIG_EXYNOS5422) || defined(CONFIG_EXYNOS5420)
	/* TODO : GPIO Control is needed for these chipsets? */
#endif

	return 0;
}

uint32_t gpio_set_fp_btp_ocp( uint32_t gpio_dat_bit)
{
#if defined(CONFIG_EXYNOS7420)
	uint32_t sfr = 0;
    printf("regulator_control %s\n", (gpio_dat_bit==GPIO_HIGH)?"ON":"OFF");
	sfr = read_sfr_value(FP_GPIO_SFR_VA + GPIODAT);
	if (gpio_dat_bit == GPIO_HIGH)
		sfr |= 0x10;
	else
		sfr &= 0x0F;

	write_sfr_value(FP_GPIO_SFR_VA + GPIODAT, sfr);
#endif

	return 0;
}
