/*!
* @file     Crypto_Rng.c
*
* @version  1.0.0
*
* @brief    This file provides all the RNG firmware functions
*   
* @attention
*
* Project Name      : AUTOSAR MCAL
*
* Platform          : Arm
*
* Autosar Standard  : Classic Platform 4.4.0
*
* Compiled Version  : G32A10xx_MCAL_1_0_0_15-Nov-25
*
* Copyright (C) 2026 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (Geehy Semiconductor Software License Agreement).
*
* The program is only for reference, which is distributed in the hope
* that it will be usefull and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the Geehy Semiconductor Software License Agreement for the governing permissions
* and limitations under the License.
*/

#ifdef __cplusplus
extern "C"{
#endif
    
#include "Crypto_Rng.h"
#include "Crypto_RngReg.h"
#include "Mcu_RcmReg.h"
/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup CRYPTO_Driver
  * @brief CRYPTO driver modules
  @{
*/

/** @defgroup CRYPTO_Macros
  @{
*/
/*******************************************************************************
                    VENDOR ID & AUTOSAR VERSION INFO
*******************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define CRYPTO_RNG_VENDOR_ID                         0x00C1U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define CRYPTO_RNG_AR_RELEASE_MAJOR_VERSION          0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define CRYPTO_RNG_AR_RELEASE_MINOR_VERSION          0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define CRYPTO_RNG_AR_RELEASE_REVISION_VERSION       0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define CRYPTO_RNG_SW_MAJOR_VERSION                  0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define CRYPTO_RNG_SW_MINOR_VERSION                  0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define CRYPTO_RNG_SW_PATCH_VERSION                  0x00U
/**@} end of group CRYPTO_Macros */
/*******************************************************************************
                            GLOBAL FUNCTIONS
*******************************************************************************/
/** @defgroup CRYPTO_Fuctions
  @{
*/
/*!
* @brief     Reset RNG peripheral registers to their default reset values.
*
* @param     None
*
* @retval    None
*/
FUNC(void, CRYPTO_CODE) Crypto_Rng_Reset(void)
{
    REG_BIT_SET32(RCM_AHBRST_REG_ADDR,RCM_AHBRST_TRNGRST_MASK);
    REG_BIT_CLEAR32(RCM_AHBRST_REG_ADDR,RCM_AHBRST_TRNGRST_MASK);
}

/*!
* @brief     Enable the RNG peripheral.
*
* @param     None
*
* @retval    None
*/
FUNC(void, CRYPTO_CODE) Crypto_Rng_Enable(void)
{
    REG_BIT_SET32(TRNG_CTRL_REG_ADDR,TRNG_CTRL_RNGEN_MASK);
}

/*!
* @brief     Disable the RNG peripheral.
*
* @param     None
*
* @retval    None
*/
FUNC(void, CRYPTO_CODE) Crypto_Rng_Disable(void)
{
    REG_BIT_CLEAR32(TRNG_CTRL_REG_ADDR,TRNG_CTRL_RNGEN_MASK);
}
    
/*!
* @brief     Read the 32-bit random number.
*
* @param     None
*
* @retval    a 32-bit random number.
*/
FUNC(uint32, CRYPTO_CODE) Crypto_Rng_ReadRandomNumber(void)
{
    return REG_READ32(TRNG_DATA_REG_ADDR);
}

/*!
* @brief     Enable the RNG interrupt.
*
* @param     None
*
* @retval    None
*/
FUNC(void, CRYPTO_CODE) Crypto_Rng_EnableInterrupt(void)
{
    REG_BIT_SET32(TRNG_CTRL_REG_ADDR,TRNG_CTRL_INTEN_MASK);
}

/*!
* @brief     Disable the RNG interrupt.
*
* @param     None
*
* @retval    None
*/
FUNC(void, CRYPTO_CODE) Crypto_Rng_DisableInterrupt(void)
{
    REG_BIT_CLEAR32(TRNG_CTRL_REG_ADDR,TRNG_CTRL_INTEN_MASK);
}

/*!
* @brief     Read the specified RNG flag.
*
* @param     flag: specifies the RNG flag to check.
*                  This parameter can be one of the following values:
*                  RNG_FLAG_DATARDY  : Data Ready flag.
*                  RNG_FLAG_FSCSTS   : Faulty sequence flag.
*
* @retval    SET or RESET
*/
FUNC(uint8, CRYPTO_CODE) Crypto_Rng_ReadStatusFlag(VAR(Crypto_Rng_FlagType, AUTOMATIC) flag)
{
    VAR(boolean, AUTOMATIC) rettype = FALSE;
    if ((REG_READ32(TRNG_STS_REG_ADDR) & (uint32)flag) != 0u)
    {
        rettype = TRUE;
    }
    else
    {
        /* Nothing */
    }
    return rettype;
}

FUNC(Crypto_Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Rng_RandomGenerate(VAR(uint32, AUTOMATIC) size,P2VAR(uint8, AUTOMATIC, CRYPTO_APPL_DATA) srcPtr)
{
    VAR(uint32, AUTOMATIC) remainingSize = size;
    P2VAR(uint8, AUTOMATIC, CRYPTO_APPL_DATA) pDest = srcPtr;  
    Crypto_Cse_ErrorCodeType errorCode = CSE_ERC_OK;  
    uint32 i = 0;
    while (remainingSize > 0u)
    {
        uint32 randNum = Crypto_Rng_ReadRandomNumber(); 
        errorCode = Crypto_Rng_WaitReady(CRYPTO_TIMEOUT_VALUE);
        if (CSE_ERC_OK == errorCode)
        {
            uint32 copySize = (remainingSize >= 4u) ? 4u : remainingSize;
            for (i = 0u; i < copySize; i++)
            {
                pDest[i] = (uint8)(randNum >> (8u * i));
            }
            pDest = &pDest[copySize]; 
            remainingSize -= copySize; 
        }
        else
        {
            break;
        }
    }

    return errorCode; 
}

/*!
* @brief     Read the specified RNG flag.
*
* @param     flag: specifies the RNG flag to check.
*                  This parameter can be one of the following values:
*                  RNG_FLAG_DATARDY  : Data Ready flag.
*
* @retval    SUCCESS or ERROR
*/
FUNC(Crypto_Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Rng_WaitReady(VAR(uint32, AUTOMATIC) timeout)
{
    VAR(Crypto_Cse_ErrorCodeType, AUTOMATIC) status = CSE_ERC_ERROR;
    VAR(uint32, AUTOMATIC) tmCnt = 0;
    for(tmCnt = 0;tmCnt < timeout;tmCnt++)
    {
        if(Crypto_Rng_ReadStatusFlag(RNG_FLAG_DATARDY) == TRUE) 
        {
            status = CSE_ERC_OK;
        }
        else
        {
            /* Nothing */
        }
    }
    return status;
}

/*!
* @brief     Read the specified RNG interrupt flag.
*
* @param     flag: check status of specifies the RNG interrupt source.
*                  This parameter can be one of the following values:
*                  RNG_INT_FLAG_FSINT   : Faulty Sequence Interrupt.
*
* @retval    SET or RESET
*/
FUNC(uint8, CRYPTO_CODE) Crypto_Rng_ReadIntFlag(VAR(Crypto_Rng_IntFlagType, AUTOMATIC) flag)
{
    VAR(uint8, AUTOMATIC) rettype = FALSE;
    if ((REG_READ32(TRNG_STS_REG_ADDR) & (uint32)flag) != FALSE)
    {
        rettype = TRUE;
    }
    else
    {
        /* Nothing */
    }
    return rettype;
}

/*!
* @brief    Initialize and derives a key for the PRNG
* @details  This function must be called before the CMD_RND command and after
*           every power cycle or reset.
*
* @return   Error code returned from hardware
*/
FUNC(void, CRYPTO_CODE) Crypto_Rng_Init(void)
{
    Crypto_Rng_Disable();
    Crypto_Rng_Enable();
}

/*!
* @brief     Clears the RNG interrupt flags.
*
* @param     flag: clear flag specifies the RNG interrupt flag.
*                  This parameter can be any combination of the following values:
*                  RNG_INT_FLAG_FSINT   : Faulty Sequence Interrupt flag.
*
* @retval    None
*/
FUNC(void, CRYPTO_CODE) Crypto_Rng_ClearIntFlag(VAR(uint8, AUTOMATIC) flag)
{
    REG_BIT_CLEAR32(TRNG_STS_REG_ADDR,(uint32)flag);
}
/**@} end of group CRYPTO_Fuctions */
#ifdef __cplusplus
}
#endif
/**@} end of group CRYPTO_Driver */
/**@} end of group G32A10xx_StdPeriphDriver */

