/*
@brief Contains test code for most of the QSEE fuse APIs.

*/
/*===========================================================================
   Copyright (c) 2011 by Qualcomm Technologies, Incorporated.  All Rights Reserved.
===========================================================================*/

/*
 * Copyright (C) 2016, Samsung Electronics Co., Ltd. All Rights Reserved.
 *
 * Written by Trusted System Service Part, Enterprise Service Group, Mobile Communication Division.
 */

 /*
 * Engineer Mode Fusing implementation.
 */

/*===========================================================================

                            EDIT HISTORY FOR FILE
  $Header:
  $DateTime:
  $Author: pwbldsvc $

# when       who     what, where, why
# 2016-05-17 woochang810.lee first implement

===========================================================================*/
#include <stdbool.h>
#include "qsee_log.h"
#include "qsee_heap.h"
#include "qsee_fuse.h"
#include "qfprom.h"
#include "bksecapp_common.h"

/* Bus frequency is required when calling the qfprom APIs,
   but the value is not actually used.*/
#define BUS_FREQUENCY 0

/* Fuse for Engineering Kernel control is one of the EM */
int32_t set_ek_fuse(uint32_t val)
{
	uint32_t qfprom_status = 0;
	uint32_t row_data_write[2] = {0x0, 0x0};
	uint32_t fuse_addr;
	int32_t ret = 0;

	if(val & ~(EK_FUSE_BMSK))
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "[EM] Invalid value 0x%x", val);
		return BKERR_EK_WRITE_INVALID_INPUT_VALUE;
	}

	fuse_addr = BK_OEM_SPARE_REGION_SECURE_BOOT_SOLUTION;
	qsee_log(QSEE_LOG_MSG_ERROR, "Write address [0x%x]", fuse_addr);

	row_data_write[0] = (uint32_t)(val << EK_FUSE_SHFT);
	qsee_log(QSEE_LOG_MSG_ERROR, "Write value [%x, %x]", row_data_write[0], row_data_write[1]);

	ret = qsee_fuse_write(fuse_addr, row_data_write, BUS_FREQUENCY, &qfprom_status);
	if ((ret != 0) || (qfprom_status != QFPROM_NO_ERR))
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Write error: %d, %d",ret, qfprom_status);
		if (ret)
			return BKERR_EK_WRITE_QFPROM_ERROR;
		else
			return BKERR_EK_WRITE_QFPROM_API_ERROR;
	}

	qsee_log(QSEE_LOG_MSG_ERROR, "EM Fuse Write Successful" );
	return BKERR_EK_WRITE_SUCCESS;
}

int32_t get_ek_fuse(void)
{
	uint32_t qfprom_status = 0;
	uint32_t row_data_read[2] = {0x0, 0x0};
	uint32_t fuse_data = 0x0;
	uint32_t fuse_addr;
	int32_t ret = 0;

	fuse_addr = BK_OEM_SPARE_REGION_SECURE_BOOT_SOLUTION;
	qsee_log(QSEE_LOG_MSG_ERROR, "Read address [%x]", fuse_addr);

	ret = qsee_fuse_read(fuse_addr, QFPROM_ADDR_SPACE_RAW, row_data_read, &qfprom_status);
	if ((ret != 0) || (qfprom_status != QFPROM_NO_ERR))
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Read error: %d, %d",ret, qfprom_status);
		if (ret)
			return BKERR_EK_READ_QFPROM_ERROR;
		else
			return BKERR_EK_READ_QFPROM_API_ERROR;
	}

	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value: %x %x",row_data_read[0],row_data_read[1]);
	fuse_data = (row_data_read[0] & (EK_FUSE_BMSK << EK_FUSE_SHFT)) >> EK_FUSE_SHFT;
	ret = (int32_t)fuse_data;
	qsee_log(QSEE_LOG_MSG_ERROR, "Final read value: %x",ret);

	return ret;
}

