395 lines
7.7 KiB
C
Executable File
395 lines
7.7 KiB
C
Executable File
/**
|
|
NVT OTP
|
|
This file will operate otp
|
|
@file nvt-otp.c
|
|
@ingroup
|
|
@note
|
|
Copyright Novatek Microelectronics Corp. 2018. All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License version 2 as
|
|
published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <linux/crypto.h>
|
|
#include <plat/efuse_protected.h>
|
|
#include <plat/dma_protected.h>
|
|
#include <linux/mutex.h>
|
|
#include <mach/rcw_macro.h>
|
|
|
|
|
|
#ifndef CHKPNT
|
|
#define CHKPNT printk("\033[37mCHK: %d, %s\033[0m\r\n", __LINE__, __func__)
|
|
#endif
|
|
|
|
#ifndef DBGD
|
|
#define DBGD(x) printk("\033[0;35m%s=%d\033[0m\r\n", #x, x)
|
|
#endif
|
|
|
|
#ifndef DBGH
|
|
#define DBGH(x) printk("\033[0;35m%s=0x%08X\033[0m\r\n", #x, x)
|
|
#endif
|
|
|
|
#ifndef DBG_DUMP
|
|
#define DBG_DUMP(fmtstr, args...) printk(fmtstr, ##args)
|
|
#endif
|
|
|
|
#ifndef DBG_ERR
|
|
#define DBG_ERR(fmtstr, args...) printk("\033[0;31mERR:%s() \033[0m" fmtstr, __func__, ##args)
|
|
#endif
|
|
|
|
#ifndef DBG_WRN
|
|
#define DBG_WRN(fmtstr, args...) printk("\033[0;33mWRN:%s() \033[0m" fmtstr, __func__, ##args)
|
|
#endif
|
|
|
|
#if 0
|
|
#define DBG_IND(fmtstr, args...) printk("%s(): " fmtstr, __func__, ##args)
|
|
#else
|
|
#ifndef DBG_IND
|
|
#define DBG_IND(fmtstr, args...)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
struct mutex otp_lock;
|
|
|
|
|
|
#define otp_loc() {mutex_lock(&otp_lock); }
|
|
#define otp_unl() {mutex_unlock(&otp_lock); }
|
|
extern INT32 efuse_read_addr(UINT32 efuse_addr, UINT32 address);
|
|
|
|
|
|
static UINT32 OTP_READ[] = {
|
|
0xE92D41F0,
|
|
0xE1A04000,
|
|
0xE1A06001,
|
|
0xE30F2D66,
|
|
0xE3E00020,
|
|
0xE2867094,
|
|
0xE3A0800D,
|
|
0xE3A0501F,
|
|
0xE0045005,
|
|
0xE1550008,
|
|
0xC1A0F007,
|
|
0xE1A00802,
|
|
0xE286703C,
|
|
0xE3A01001,
|
|
0xE5801020,
|
|
0xE5901030,
|
|
0xE7E01051,
|
|
0xE3510001,
|
|
0x11A0F007,
|
|
0xE3A01000,
|
|
0xE0811004,
|
|
0xE3A05000,
|
|
0xE3A05000,
|
|
0xE2867070,
|
|
0xE5801004,
|
|
0xE5902020,
|
|
0xE3822002,
|
|
0xE5802020,
|
|
0xE5902020,
|
|
0xE7E020D2,
|
|
0xE3520001,
|
|
0x01A0F007,
|
|
0xE5902030,
|
|
0xE5802030,
|
|
0xE3A02000,
|
|
0xE5802020,
|
|
0xE5900008,
|
|
0xE8BD81F0,
|
|
0xE320F000,
|
|
0xEAFFFFFE,
|
|
0xE320F000,
|
|
};
|
|
|
|
static UINT32 OTP_OP[] = {
|
|
0xE92D41F0,
|
|
0xE1A04000,
|
|
0xE1A06001,
|
|
0xE30F2D66,
|
|
0xE1A00802,
|
|
0xE30F2D62,
|
|
0xE1A03802,
|
|
0xE2867028,
|
|
0xE3A01001,
|
|
0xE5801020,
|
|
0xE5901030,
|
|
0xE7E01051,
|
|
0xE3510001,
|
|
0x11A0F007,
|
|
0xE3A01010,
|
|
0xE0811104,
|
|
0xE3A05001,
|
|
0xE5835020,
|
|
0xE286705C,
|
|
0xE5801004,
|
|
0xE5902020,
|
|
0xE3822002,
|
|
0xE5802020,
|
|
0xE5902020,
|
|
0xE7E020D2,
|
|
0xE3520001,
|
|
0x01A0F007,
|
|
0xE5902030,
|
|
0xE5802030,
|
|
0xE2811001,
|
|
0xE3A05002,
|
|
0xE5835020,
|
|
0xE2867094,
|
|
0xE5801004,
|
|
0xE5902020,
|
|
0xE3822002,
|
|
0xE5802020,
|
|
0xE5902020,
|
|
0xE7E020D2,
|
|
0xE3520001,
|
|
0x01A0F007,
|
|
0xE5902030,
|
|
0xE5802030,
|
|
0xE2811001,
|
|
0xE3A05004,
|
|
0xE5835020,
|
|
0xE28670CC,
|
|
0xE5801004,
|
|
0xE5902020,
|
|
0xE3822002,
|
|
0xE5802020,
|
|
0xE5902020,
|
|
0xE7E020D2,
|
|
0xE3520001,
|
|
0x01A0F007,
|
|
0xE5902030,
|
|
0xE5802030,
|
|
0xE2811001,
|
|
0xE3A05008,
|
|
0xE5835020,
|
|
0xE2867F41,
|
|
0xE5801004,
|
|
0xE5902020,
|
|
0xE3822002,
|
|
0xE5802020,
|
|
0xE5902020,
|
|
0xE7E020D2,
|
|
0xE3520001,
|
|
0x01A0F007,
|
|
0xE5902030,
|
|
0xE5802030,
|
|
0xE3A02000,
|
|
0xE5802020,
|
|
0xE8BD81F0,
|
|
0xE320F000,
|
|
0xEAFFFFFE,
|
|
0xE320F000,
|
|
};
|
|
|
|
|
|
static UINT32 DMA_USAGE_DATA[] = {
|
|
0xE92D41F0,
|
|
0xE1A04000,
|
|
0xE1A06001,
|
|
0xE2868020,
|
|
0xE30F2D00,
|
|
0xE1A02802,
|
|
0xE1A03A04,
|
|
0xE3A07A09,
|
|
0xE1822003,
|
|
0xE1827007,
|
|
0xE5921054,
|
|
0xE5970000,
|
|
0xE1A05001,
|
|
0xE1A06000,
|
|
0xE3500000,
|
|
0x01A0F008,
|
|
0xE3A03064,
|
|
0xE7F91051,
|
|
0xE7F90050,
|
|
0xE0030193,
|
|
0xE730F013,
|
|
0xE8BD81F0,
|
|
0xE320F000,
|
|
0xEAFFFFFE,
|
|
0xE320F000,
|
|
};
|
|
|
|
static INT32 efuse_check_read_data(UINT16 data)
|
|
{
|
|
INT32 i_ret;
|
|
|
|
if ((data & EFUSE_STATUS_VALID) != EFUSE_STATUS_VALID) {
|
|
i_ret = EFUSE_INACTIVE_ERR;
|
|
} else {
|
|
if ((data & EFUSE_STATUS_FORCE_INVALID) == EFUSE_STATUS_FORCE_INVALID) {
|
|
i_ret = EFUSE_INVALIDATE_ERR;
|
|
} else {
|
|
i_ret = EFUSE_SUCCESS;
|
|
}
|
|
}
|
|
return i_ret;
|
|
}
|
|
|
|
static INT32 efuse_read_data(UINT32 efuse_addr, UINT32 address)
|
|
{
|
|
INT32 result;
|
|
|
|
otp_loc();
|
|
__asm__("MOV r0, %1\n\t"
|
|
"MOV r1, %2\n\t"
|
|
"MOV lr, pc\n\t"
|
|
"MOV pc, %2\n\t"
|
|
"MOV %0, r0\n\t"
|
|
: "=r"(result)
|
|
: "r"(efuse_addr), "r"(address)
|
|
: "lr", "r0", "r1");
|
|
otp_unl();
|
|
return result;
|
|
}
|
|
|
|
static INT32 efuse_set_key(EFUSE_OTP_KEY_SET_FIELD key_set_index, UINT32 address)
|
|
{
|
|
otp_loc();
|
|
__asm__("MOV r0, %0\n\t"
|
|
"MOV r1, %1\n\t"
|
|
"MOV lr, pc\n\t"
|
|
"MOV pc, %1\n\t"
|
|
:
|
|
: "r"(key_set_index), "r"(address)
|
|
: "lr", "r0", "r1");
|
|
otp_unl();
|
|
return E_OK;
|
|
}
|
|
|
|
static UINT32 dma_get_utilization_data(UINT32 id, UINT32 address)
|
|
{
|
|
UINT32 result;
|
|
__asm__("MOV r0, %1\n\t"
|
|
"MOV r1, %2\n\t"
|
|
"MOV lr, pc\n\t"
|
|
"MOV pc, %2\n\t"
|
|
"MOV %0, r0\n\t"
|
|
: "=r"(result)
|
|
:"r"(id), "r"(address)
|
|
: "lr", "r0", "r1");
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
#define EFUSE_READDATA(addr) efuse_read_data(addr, (UINT32)OTP_READ)
|
|
|
|
/*
|
|
efuse_read_param_ops
|
|
|
|
efuse read system parameter
|
|
|
|
@note for EFUSE_PARAM_DATA
|
|
|
|
@param[in] param efuse system internal data field
|
|
@param[in] data data ready to programmed
|
|
|
|
@return
|
|
-@b EFUSE_SUCCESS success
|
|
-@b EFUSE_UNKNOW_PARAM_ERR unknow system internal data field
|
|
-@b EFUSE_INVALIDATE_ERR system internal data field invalidate
|
|
-@b EFUSE_OPS_ERR efuse operation error
|
|
*/
|
|
INT32 efuse_read_param_ops(EFUSE_PARAM_DATA param, UINT16 *data)
|
|
{
|
|
INT32 i_ret = EFUSE_SUCCESS;
|
|
UINT16 tmp_data;
|
|
UINT32 paramdatacnt;
|
|
UINT32 pri_param_id_no;
|
|
|
|
switch (param) {
|
|
case EFUSE_DDR2P_TRIM_DATA:
|
|
case EFUSE_USBC2_TRIM_DATA:
|
|
case EFUSE_HDMI_TRIM_DATA:
|
|
case EFUSE_TVDC_TRIM_DATA:
|
|
case EFUSE_USBC_TRIM_DATA:
|
|
case EFUSE_DDRP_TRIM_DATA:
|
|
case EFUSE_SLVSEC_TRIM_DATA:
|
|
case EFUSE_VX1_TRIM_DATA:
|
|
if (EFUSE_HDMI_TRIM_DATA == param) {
|
|
pri_param_id_no = EFUSE_TRIM_DATA_HDMI_PRI;
|
|
} else if (EFUSE_USBC_TRIM_DATA == param) {
|
|
pri_param_id_no = EFUSE_TRIM_DATA_USB_PRI;
|
|
} else if (EFUSE_DDRP_TRIM_DATA == param) {
|
|
pri_param_id_no = EFUSE_TRIM_DATA_DDR_DRIVING_PRI;
|
|
} else if (EFUSE_TVDC_TRIM_DATA == param) {
|
|
pri_param_id_no = EFUSE_TRIM_DATA_TVDEC_PRI;
|
|
} else if (EFUSE_VX1_TRIM_DATA == param) {
|
|
pri_param_id_no = EFUSE_TRIM_DATA_VX1_PRI;
|
|
} else if (EFUSE_SLVSEC_TRIM_DATA == param) {
|
|
pri_param_id_no = EFUSE_TRIM_DATA_SLVSEC_PRI;
|
|
} else if (EFUSE_USBC2_TRIM_DATA == param) {
|
|
pri_param_id_no = EFUSE_TRIM_DATA_USB2_PRI;
|
|
} else {
|
|
pri_param_id_no = EFUSE_TRIM_DATA_DDR2_DRIVING_PRI;
|
|
}
|
|
for (paramdatacnt = 0; paramdatacnt < EFUSE_PARAM_OP_CNT; paramdatacnt++) {
|
|
if (paramdatacnt == 0) {
|
|
tmp_data = EFUSE_READDATA(pri_param_id_no) & 0xFFFF;
|
|
} else {
|
|
tmp_data = (EFUSE_READDATA(pri_param_id_no) >> 16) & 0xFFFF;
|
|
}
|
|
if (tmp_data < 0) {
|
|
i_ret = EFUSE_OPS_ERR;
|
|
DBG_DUMP("^RERR:PKG UID[%d] op error\r\n", paramdatacnt);
|
|
continue;
|
|
} else {
|
|
*data = (tmp_data & 0x3FFF);
|
|
|
|
i_ret = efuse_check_read_data(tmp_data);
|
|
|
|
if (EFUSE_UNKNOW_PARAM_ERR == i_ret) {
|
|
DBG_DUMP("^RERR:unknow param error\r\n");
|
|
} else if (EFUSE_INVALIDATE_ERR == i_ret) {
|
|
if (!paramdatacnt) {
|
|
DBG_IND("^YWRN:[PRI] param invalidate\r\n");
|
|
} else {
|
|
DBG_IND("^YWRN:[SEC] param invalidate\r\n");
|
|
}
|
|
} else if (EFUSE_INACTIVE_ERR == i_ret) {
|
|
if (!paramdatacnt) {
|
|
DBG_IND("^YWRN:[PRI] param inactive\r\n");
|
|
} else {
|
|
DBG_IND("^YWRN:[SEC] param inactive\r\n");
|
|
}
|
|
} else {
|
|
DBG_IND("[%d] success = 0\r\n", paramdatacnt);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
i_ret = EFUSE_UNKNOW_PARAM_ERR;
|
|
break;
|
|
}
|
|
return i_ret;
|
|
}
|
|
|
|
INT32 efuse_otp_set_key(EFUSE_OTP_KEY_SET_FIELD key_set_index)
|
|
{
|
|
efuse_set_key(key_set_index, (UINT32)OTP_OP);
|
|
return E_OK;
|
|
}
|
|
|
|
UINT32 dma_get_utilization(DMA_ID id)
|
|
{
|
|
return dma_get_utilization_data(id, (UINT32)&DMA_USAGE_DATA[0]);
|
|
}
|
|
|
|
|
|
static int __init nvt_init_otp_mutex(void)
|
|
{
|
|
mutex_init(&otp_lock);
|
|
return 0;
|
|
}
|
|
|
|
core_initcall(nvt_init_otp_mutex);
|
|
EXPORT_SYMBOL(efuse_read_param_ops);
|
|
EXPORT_SYMBOL(efuse_otp_set_key);
|
|
EXPORT_SYMBOL(dma_get_utilization);
|