mirror of
https://github.com/revyos/th1520-vendor-uboot.git
synced 2026-09-18 13:22:07 +02:00
503 lines
14 KiB
C
503 lines
14 KiB
C
/*
|
|
* Copyright (C) 2017-2020 Alibaba Group Holding Limited
|
|
*/
|
|
|
|
/* eip76_random.c
|
|
*
|
|
* Module implements the EIP-76 Driver Library Read Random Number API
|
|
*/
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* This module implements (provides) the following interface(s):
|
|
*/
|
|
|
|
// EIP-76 Driver Library Read Random Number API
|
|
#include "eip76_read.h"
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* This module uses (requires) the following interface(s):
|
|
*/
|
|
|
|
// Default configuration
|
|
#include "c_eip76.h"
|
|
|
|
// Driver Framework Basic Definitions API
|
|
#include "basic_defs.h" // uint32_t
|
|
|
|
// Driver Framework Device API
|
|
#include "device_types.h" // Device_Handle_t
|
|
|
|
// EIP-76 Driver Library Types API
|
|
#include "eip76_types.h" // EIP76_* types
|
|
|
|
// EIP-76 Driver Library Internal interfaces
|
|
#include "eip76_level0.h" // Level 0 macros
|
|
#include "eip76_fsm.h" // State machine
|
|
#include "eip76_internal.h" // Internal macros
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Definitions and macros
|
|
*/
|
|
|
|
extern uint32_t g_rb_trng_reseed_max;
|
|
extern uint32_t g_rb_trng_reseed_enable;
|
|
|
|
extern uint32_t g_rb_trng_reseed_cur;
|
|
|
|
#define ADAPTER_EIP76_PS_WORD32_COUNT 12
|
|
#define DEFAULT_TIMEOUT 1000U
|
|
|
|
extern uint32_t Adapter_EIP76_PS_Data[ADAPTER_EIP76_PS_WORD32_COUNT];
|
|
|
|
uint32_t trng_reseed(
|
|
EIP76_IOArea_t * const IOArea_p,
|
|
uint32_t block)
|
|
{
|
|
EIP76_Status_t res;
|
|
EIP76_EventStatus_t events = 0;
|
|
unsigned int actual = 0;
|
|
uint32_t timestart;
|
|
uint32_t rt = 0;
|
|
uint32_t ret = 0;
|
|
|
|
if (g_rb_trng_reseed_enable == 0) {
|
|
return 0;
|
|
}
|
|
g_rb_trng_reseed_cur += block;
|
|
if ((g_rb_trng_reseed_cur) >= g_rb_trng_reseed_max) {
|
|
/* do reseed*/
|
|
//timestart = csi_tick_get();
|
|
timestart = 0;//TODO
|
|
rt = timestart;
|
|
while ((rt - timestart) < DEFAULT_TIMEOUT) {
|
|
res = EIP76_PostProcessor_Reseed_Start(IOArea_p, &events);
|
|
if (res != EIP76_NO_ERROR) {
|
|
//rt = csi_tick_get();
|
|
rt = 0;
|
|
ret = -1;
|
|
continue;
|
|
}
|
|
/* set PS */
|
|
res = EIP76_PostProcessor_Reseed_Write(IOArea_p,
|
|
Adapter_EIP76_PS_Data,
|
|
ADAPTER_EIP76_PS_WORD32_COUNT,
|
|
&events);
|
|
if (res != EIP76_NO_ERROR) {
|
|
//rt = csi_tick_get();
|
|
rt = 0;
|
|
ret = -1;
|
|
continue;
|
|
}
|
|
g_rb_trng_reseed_cur = 0;
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
extern uint32_t g_rb_trng_reseed_max;
|
|
extern uint32_t g_long_request_mode;
|
|
/*----------------------------------------------------------------------------
|
|
* EIP76_Request_Random_Data
|
|
*
|
|
*/
|
|
EIP76_Status_t
|
|
EIP76_Request_Random_Data(
|
|
EIP76_IOArea_t * const IOArea_p,
|
|
unsigned int NumberOfBytes)
|
|
{
|
|
Device_Handle_t Device;
|
|
uint32_t ControlValue, StatusValue, NumberOfBlks, WriteValue;
|
|
|
|
volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
|
|
|
|
EIP76_CHECK_POINTER(IOArea_p);
|
|
|
|
trng_reseed(IOArea_p, 1);
|
|
|
|
Device = TrueIOArea_p->Device;
|
|
|
|
ControlValue = EIP76_CONTROL_RD(Device);
|
|
|
|
// First check if number of data_bloacks is zero, else return
|
|
if ((ControlValue >> 20) & MASK_12_BITS)
|
|
return EIP76_BUSY_RETRY_LATER;
|
|
|
|
StatusValue = EIP76_STATUS_RD(Device);
|
|
|
|
// Count available data blocks
|
|
NumberOfBlks = (StatusValue & MASK_1_BIT) +
|
|
((StatusValue >> 16) & MASK_8_BITS);
|
|
if (NumberOfBlks * 16 < NumberOfBytes)
|
|
{
|
|
if (g_long_request_mode) {
|
|
printf("===%s, %d\n", __FUNCTION__, __LINE__);
|
|
NumberOfBlks = g_rb_trng_reseed_max;
|
|
}else {
|
|
printf("===%s, %d\n", __FUNCTION__, __LINE__);
|
|
NumberOfBlks = (NumberOfBytes + 15) / 16; // Round up
|
|
|
|
// Reduce blocks by the number of blocks already available
|
|
NumberOfBlks -= ((StatusValue & MASK_1_BIT) +
|
|
((StatusValue >> 16) & MASK_8_BITS));
|
|
|
|
}
|
|
|
|
EIP76_CHECK_INT_ATMOST(NumberOfBlks, EIP76_REQUEST_DATA_MAX_BLK_COUNT);
|
|
|
|
// Only data_blocks field is updated in register.
|
|
WriteValue = EIP76_REQUEST_DATA |
|
|
((NumberOfBlks & MASK_12_BITS) << 20);
|
|
EIP76_CONTROL_WR(Device, WriteValue);
|
|
|
|
#ifdef EIP76_BLOCKS_THRESHOLD_OPTION
|
|
// Do not write Threshold when in test mode
|
|
if (!(ControlValue & EIP76_ENABLE_TEST_MODE))
|
|
{
|
|
WriteValue = EIP76_BUFFER_SIZE_RD(Device);
|
|
|
|
if (WriteValue > 0)
|
|
{
|
|
NumberOfBlks += ((StatusValue & MASK_1_BIT) +
|
|
((StatusValue >> 16) & MASK_8_BITS));
|
|
if ( NumberOfBlks > WriteValue)
|
|
{
|
|
NumberOfBlks = WriteValue;
|
|
}
|
|
// Set threshold value one less then the needed number of blocks
|
|
WriteValue = NumberOfBlks - 1;
|
|
|
|
// Set the number of blocks in threshold register
|
|
EIP76_BLOCKS_THRESHOLD_WR(Device, WriteValue);
|
|
}
|
|
}
|
|
#endif // EIP76_BLOCKS_THRESHOLD_OPTION
|
|
}
|
|
|
|
return EIP76_NO_ERROR;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* EIP76Lib_PostProcessor_Random_Read
|
|
*
|
|
*/
|
|
static EIP76_Status_t
|
|
EIP76Lib_Random_Read(
|
|
const Device_Handle_t Device,
|
|
EIP76_Random128_t * Random128_p)
|
|
{
|
|
#if EIP76_READ_TIMEOUT > 0
|
|
EIP76_INTACK_WR(Device, 0);
|
|
Random128_p->word[0] = EIP76_OUTPUT_0_RD(Device);
|
|
Random128_p->word[1] = EIP76_OUTPUT_1_RD(Device);
|
|
Random128_p->word[2] = EIP76_OUTPUT_2_RD(Device);
|
|
Random128_p->word[3] = EIP76_OUTPUT_3_RD(Device);
|
|
#else
|
|
Random128_p->word[0] = EIP76_OUTPUT_0_RD(Device);
|
|
Random128_p->word[1] = EIP76_OUTPUT_1_RD(Device);
|
|
Random128_p->word[2] = EIP76_OUTPUT_2_RD(Device);
|
|
Random128_p->word[3] = EIP76_OUTPUT_3_RD(Device);
|
|
|
|
LOG_INFO("8 %s, %x\n", __FUNCTION__, Random128_p->word[0]);
|
|
LOG_INFO("8 %s, %x\n", __FUNCTION__, Random128_p->word[1]);
|
|
LOG_INFO("8 %s, %x\n", __FUNCTION__, Random128_p->word[2]);
|
|
LOG_INFO("8 %s, %x\n", __FUNCTION__, Random128_p->word[3]);
|
|
#endif // EIP76_READ_TIMEOUT
|
|
|
|
return EIP76_NO_ERROR;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* EIP76_Random_IsBusy
|
|
*
|
|
*/
|
|
EIP76_Status_t
|
|
EIP76_Random_IsBusy(
|
|
EIP76_IOArea_t * const IOArea_p,
|
|
EIP76_EventStatus_t * const Events_p)
|
|
{
|
|
Device_Handle_t Device;
|
|
uint32_t StatusRegVal;
|
|
EIP76_Status_t rv = EIP76_NO_ERROR;
|
|
volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
|
|
|
|
EIP76_CHECK_POINTER(Events_p);
|
|
|
|
// No events detected yet
|
|
*Events_p = 0;
|
|
|
|
EIP76_CHECK_POINTER(IOArea_p);
|
|
|
|
Device = TrueIOArea_p->Device;
|
|
|
|
StatusRegVal = EIP76_STATUS_RD(Device);
|
|
|
|
// Store event status with the available random data 128-bit block count
|
|
*Events_p = StatusRegVal;
|
|
|
|
if ( EIP76_STATUS_IS_READY(StatusRegVal))
|
|
{
|
|
LOG_INFO("6 %s, %d\n", __FUNCTION__, __LINE__);
|
|
// Transit to a new state
|
|
rv = EIP76_State_Set((volatile EIP76_State_t*)&TrueIOArea_p->State,
|
|
EIP76_STATE_RANDOM_READY);
|
|
}
|
|
else
|
|
{
|
|
// Keep the state, no random data ready yet
|
|
rv = EIP76_BUSY_RETRY_LATER;
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* EIP76_Random_Get
|
|
*
|
|
*/
|
|
EIP76_Status_t
|
|
EIP76_Random_Get(
|
|
EIP76_IOArea_t * const IOArea_p,
|
|
EIP76_Random128_t * Data_p,
|
|
const unsigned int NumberCount,
|
|
unsigned int * const GeneratedNumberCount_p,
|
|
EIP76_EventStatus_t * const Events_p)
|
|
{
|
|
uint32_t StatusRegVal;
|
|
unsigned int i;
|
|
Device_Handle_t Device;
|
|
EIP76_Status_t rv = EIP76_NO_ERROR;
|
|
volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
|
|
|
|
EIP76_CHECK_POINTER(Events_p);
|
|
|
|
// No events detected yet
|
|
*Events_p = 0;
|
|
|
|
EIP76_CHECK_POINTER(GeneratedNumberCount_p);
|
|
|
|
*GeneratedNumberCount_p = 0;
|
|
|
|
EIP76_CHECK_POINTER(IOArea_p);
|
|
|
|
EIP76_CHECK_POINTER(Data_p);
|
|
|
|
EIP76_CHECK_INT_ATLEAST(NumberCount, 1);
|
|
|
|
Device = TrueIOArea_p->Device;
|
|
|
|
for (i = 0; i < NumberCount; i++)
|
|
{
|
|
StatusRegVal = EIP76_STATUS_RD(Device);
|
|
|
|
// Store event status with the available random data 128-bit block count
|
|
*Events_p = StatusRegVal;
|
|
|
|
if (!EIP76_STATUS_IS_READY(StatusRegVal) )
|
|
{
|
|
if (i == 0)
|
|
{
|
|
// Keep the state, no random data ready yet
|
|
return EIP76_ILLEGAL_IN_STATE; // May never occur
|
|
}
|
|
else
|
|
{
|
|
// Transit to a new state
|
|
rv = EIP76_State_Set((volatile EIP76_State_t* const)&TrueIOArea_p->State,
|
|
EIP76_STATE_RANDOM_GENERATING);
|
|
|
|
if (rv != EIP76_NO_ERROR)
|
|
{
|
|
return EIP76_ILLEGAL_IN_STATE; // May never occur
|
|
}
|
|
else
|
|
{
|
|
*GeneratedNumberCount_p = i;
|
|
return EIP76_BUSY_RETRY_LATER;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Random data is ready, transit to a new state
|
|
rv = EIP76_State_Set((volatile EIP76_State_t* const)&TrueIOArea_p->State,
|
|
EIP76_STATE_RANDOM_READING);
|
|
|
|
if (rv != EIP76_NO_ERROR)
|
|
{
|
|
return EIP76_ILLEGAL_IN_STATE;
|
|
}
|
|
}
|
|
|
|
// In the EIP76_STATE_RANDOM_READING state now, random data is ready
|
|
|
|
#ifdef EIP76_BLOCKS_THRESHOLD_OPTION
|
|
// Set Theshold back to 0 to get all data
|
|
EIP76_BLOCKS_THRESHOLD_WR(Device, 0);
|
|
#endif // EIP76_BLOCKS_THRESHOLD_OPTION
|
|
|
|
// Read the random number
|
|
rv = EIP76Lib_Random_Read(Device, Data_p++);
|
|
|
|
if (rv != EIP76_NO_ERROR)
|
|
{
|
|
// Failed to read a random number, transit to a new state
|
|
rv = EIP76_State_Set((volatile EIP76_State_t*)&TrueIOArea_p->State,
|
|
EIP76_STATE_RANDOM_GENERATING);
|
|
|
|
if (rv != EIP76_NO_ERROR)
|
|
{
|
|
return EIP76_ILLEGAL_IN_STATE; // May never occur
|
|
}
|
|
else
|
|
{
|
|
return EIP76_RANDOM_READ_ERROR;
|
|
}
|
|
}
|
|
|
|
// Acknowledge the read number
|
|
LOG_INFO("8 %s, %d\n", __FUNCTION__, __LINE__);
|
|
EIP76_INTACK_WR(Device, EIP76_STATUS_READY);
|
|
} // for
|
|
|
|
*GeneratedNumberCount_p = i;
|
|
|
|
// Transit to a new state
|
|
rv = EIP76_State_Set((volatile EIP76_State_t*)&TrueIOArea_p->State,
|
|
EIP76_STATE_RANDOM_GENERATING);
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* EIP76_Alarm_Handle
|
|
*
|
|
*/
|
|
EIP76_Status_t
|
|
EIP76_Alarm_Handle(
|
|
EIP76_IOArea_t * const IOArea_p,
|
|
EIP76_EventStatus_t * const Events_p,
|
|
uint32_t * FROAlarmMask_p)
|
|
{
|
|
uint32_t RegVal;
|
|
Device_Handle_t Device;
|
|
volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
|
|
|
|
EIP76_CHECK_POINTER(IOArea_p);
|
|
|
|
EIP76_CHECK_POINTER(Events_p);
|
|
|
|
EIP76_CHECK_POINTER(FROAlarmMask_p);
|
|
|
|
Device = TrueIOArea_p->Device;
|
|
|
|
// No events detected yet
|
|
*Events_p = 0;
|
|
|
|
RegVal = EIP76_STATUS_RD(Device);
|
|
|
|
// Store detected events
|
|
*Events_p = (RegVal & EIP76_EVENTS_MASK);
|
|
|
|
#ifndef EIP76_AUTO_DETUNE_OPTION
|
|
// Determine what FRO's are stopped
|
|
*FROAlarmMask_p = EIP76_ALARMSTOP_RD(Device);
|
|
RegVal = ((*FROAlarmMask_p) & ((uint32_t)EIP76_FRO_ENABLED_MASK));
|
|
if( RegVal != 0 )
|
|
{
|
|
// Perform FRO de-tune operation for all the stopped FRO's,
|
|
// this must be done before the FRO's are enabled.
|
|
// This operations disables the FRO's
|
|
EIP76_FRO_DETUNE(Device, RegVal);
|
|
|
|
// Clear alarm mask
|
|
EIP76_ALARMMASK_WR(Device, 0);
|
|
|
|
// Clear alarm stop mask
|
|
EIP76_ALARMSTOP_WR(Device, 0);
|
|
|
|
// Enable the configured FRO's
|
|
EIP76_FROENABLE_WR(Device, EIP76_FRO_ENABLED_MASK);
|
|
}
|
|
#endif // EIP76_AUTO_DETUNE_OPTION
|
|
|
|
// Acknowledge the detected alarm events,
|
|
// Data ready status bit is not an alarm event
|
|
EIP76_INTACK_WR(Device, ((*Events_p) & (~EIP76_STATUS_READY)));
|
|
|
|
return EIP76_NO_ERROR;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* EIP76_FatalError_Handle
|
|
*
|
|
*/
|
|
EIP76_Status_t
|
|
EIP76_FatalError_Handle(
|
|
EIP76_IOArea_t * const IOArea_p)
|
|
{
|
|
uint32_t RegVal;
|
|
Device_Handle_t Device;
|
|
volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
|
|
|
|
EIP76_CHECK_POINTER(IOArea_p);
|
|
|
|
// EIP76_CHECK_POINTER(Events_p);
|
|
|
|
Device = TrueIOArea_p->Device;
|
|
|
|
RegVal = EIP76_STATUS_RD(Device);
|
|
LOG_INFO("fatal %s, %d\n", __FUNCTION__, __LINE__);
|
|
|
|
// Check if fatal events are present
|
|
if ( (RegVal & (EIP76_STUCK_OUT_EVENT | EIP76_NOISE_FAIL_EVENT)) != 0 )
|
|
{
|
|
// Acknowledge all the fatal error events before disabling TRNG
|
|
EIP76_INTACK_WR(Device,
|
|
(EIP76_STUCK_OUT_EVENT |
|
|
EIP76_NOISE_FAIL_EVENT |
|
|
EIP76_SHUTDOWN_OFLO_EVENT) );
|
|
|
|
// Acknowledge all the fatal error events before disabling TRNG
|
|
EIP76_INTACK_WR(Device,
|
|
(EIP76_STUCK_OUT_EVENT |
|
|
EIP76_SHUTDOWN_OFLO_EVENT) );
|
|
|
|
// Disable TRNG
|
|
EIP76_CONTROL_WR(Device, 0);
|
|
|
|
// Transit to a new state
|
|
return EIP76_State_Set((volatile EIP76_State_t*)&TrueIOArea_p->State,
|
|
EIP76_STATE_RESET);
|
|
}
|
|
|
|
// #if (EIP76_SHUTDOWN_FATAL == 1)
|
|
// // Check if fatal events are present
|
|
// if ( (RegVal & EIP76_SHUTDOWN_OFLO_EVENT ) != 0 )
|
|
// {
|
|
// // Acknowledge all the fatal error events before disabling TRNG
|
|
// EIP76_INTACK_WR(Device,
|
|
// (EIP76_STUCK_OUT_EVENT |
|
|
// EIP76_NOISE_FAIL_EVENT |
|
|
// EIP76_SHUTDOWN_OFLO_EVENT) );
|
|
|
|
// // Disable TRNG
|
|
// EIP76_CONTROL_WR(Device, 0);
|
|
|
|
// // Transit to a new state
|
|
// return EIP76_State_Set((EIP76_State_t*)&TrueIOArea_p->State,
|
|
// EIP76_STATE_RESET);
|
|
// }
|
|
// #endif
|
|
|
|
return EIP76_NO_ERROR;
|
|
}
|
|
|
|
|
|
/* end of file eip76_random.c */
|