#include "drStd.h"
#include "drMobicore.h"
#include "drTimaMm.h"
#if TBASE_API_LEVEL >= 5
#include "DrApi/DrApiMmExt.h"
#endif

#define NUM_TZ		2
#define IL_SHIFT	1
#define TZ_ALIGN	16

#define TZASC0_SFR_BASE	0x10D40000
#define TZASC1_SFR_BASE	0x10D50000

#define TL_VA_BASE	TL_ADDR(0x10000)

#define TZRS_LOW8	0x180
#define TZRS_HIGH8	0x184
#define TZRS_ATTR8	0x188

#define TZ_BASE_ALIGN	0x10000
#define TZ_SIZE_ALIGN	0x10000

#define TZ_RW_PERMISSION	((uint32_t)0xC << 28)
#define TZ_ENABLE	(0x1 << 0)
#define TZ_SIZE_OFFSET	4

inline int get_order_from_size(
	const uint32_t size
)
{
	return (size >> IL_SHIFT) >> TZ_ALIGN;
}

inline void write_sfr_value(
	uint32_t sfr_addr,
	uint32_t in
)
{
	*((volatile uint32_t *)(sfr_addr)) = in;
}

/**
 * protect TZ buffer for tima
 *
 * @base : base address to protect
 * @size : size to protect
 *
 * @return : NONE
 */
#if TBASE_API_LEVEL < 5
int sec_tz_protect(
	uint32_t base,
	uint32_t size
)
{
	uint32_t index;
	uint32_t tzasc_base[NUM_TZ] = { TZASC0_SFR_BASE, TZASC1_SFR_BASE };

	if (base & (TZ_BASE_ALIGN - 1)) {
		dbgSHN
		    ("sec_tz_protect(): Fail to protect due to base alignment. base = ",
		     base);
		return -1;
	}

	if (size & (TZ_SIZE_ALIGN - 1)) {
		dbgSHN
		    ("sec_tz_protect(): Fail to protect due to size alignment. size = ",
		     size);
		return -1;
	}

	for (index = 0; index < (sizeof(tzasc_base) / sizeof(uint32_t));
	     index++) {
		sec_map(TIMA_SFR_VADDR, tzasc_base[index], TIMA_LOG_MAP_SIZE);

		write_sfr_value(TIMA_SFR_VADDR + TZRS_LOW8, base >> IL_SHIFT);
		write_sfr_value(TIMA_SFR_VADDR + TZRS_HIGH8, 0);
		write_sfr_value(TIMA_SFR_VADDR + TZRS_ATTR8, TZ_RW_PERMISSION |
				get_order_from_size(size) << TZ_SIZE_OFFSET |
				TZ_ENABLE);
		sec_unmap(TIMA_SFR_VADDR, TIMA_LOG_MAP_SIZE);
	}

	return 0;
}
#endif
