/*
@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_fuse_location.h"
#include "bksecapp_em_fuse.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 */
int set_ek_fuse(uint32 val)
{
	uint32 qfprom_status = 0;
	uint32 row_data_write[2] = {0x0, 0x0};
	uint32 fuse_addr;
	int ret = 0;

	if(val & ~(EK_FUSE_BMSK))
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "[EM] Invalid value 0x%x", val);
		return -100;
	}

	fuse_addr = HWIO_QFPROM_RAW_OEM_SPARE_REGn_ROW0_LSB_ADDR(QFPROM_RAW_OEM_SPARE_REG_EK_FUSE);
	qsee_log(QSEE_LOG_MSG_ERROR, "Write address [0x%x]", fuse_addr);

	row_data_write[0] = (uint32)(val << EK_FUSE_SHFT);
	qsee_log(QSEE_LOG_MSG_ERROR, "Write value [%x, %x]", row_data_write[0], row_data_write[1]);
	qsee_fuse_write(fuse_addr, row_data_write, BUS_FREQUENCY, &qfprom_status);
	if(qfprom_status != QFPROM_NO_ERR)
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Write error: %d", qfprom_status);
		ret -= qfprom_status;
		return ret;
	}

	qsee_log(QSEE_LOG_MSG_ERROR, "EM Fuse Write Successful" );
	return 0;
}

int get_ek_fuse()
{
	uint32 qfprom_status = 0;
	uint32 row_data_read[2] = {0x0, 0x0};
	uint32 fuse_data = 0x0;
	uint32 fuse_addr;
	int ret = 0;

	fuse_addr = HWIO_QFPROM_RAW_OEM_SPARE_REGn_ROW0_LSB_ADDR(QFPROM_RAW_OEM_SPARE_REG_EK_FUSE);
	qsee_log(QSEE_LOG_MSG_ERROR, "Read address [%x]", fuse_addr);

	qsee_fuse_read(fuse_addr, QFPROM_ADDR_SPACE_RAW, row_data_read, &qfprom_status);
	if(qfprom_status != QFPROM_NO_ERR)
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Read error: %d", qfprom_status);
		ret -= qfprom_status;
		return ret;
	}

	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 = (int)fuse_data;
	qsee_log(QSEE_LOG_MSG_ERROR, "Final read value: %x",ret);

	return ret;
}

