/*
 * Copyright 2019-2022 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "fsl_sfa.h"

/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.sfa"
#endif

/*******************************************************************************
 * Prototypes
 ******************************************************************************/
/*!
 * brief Get the instance from the base address.
 *
 * param base SFA peripheral base address.
 *
 * return The SFA instance.
 */
static uint8_t SFA_GetInstance(SFA_Type *base);

/*!
 * brief Start to measure the frequency of the clock under test.
 *
 * This function starts to measure the frequency of select CUT source.
 * This function does not return until the measurement starts.
 *
 * note If the CUT frequency > REF frequency, it is recommended CUT target be set to 0xFFFF_FFFF.
 *
 *  param base SFA peripheral base address.
 */
static void SFA_StartMeasureFrequency(SFA_Type *base);

/*!
 * brief Start to measure the period of the clock under test or the time between triggers.
 *
 * This function starts to measure the period of the selected CUT source or the time of the selected triggers.
 * This function does not return until the measurement starts.
 *
 * param base SFA peripheral base address.
 */
static void SFA_StartMeasurePeriod(SFA_Type *base);

/*!
 * brief Calculate the frequency of the selected CUT source when the selected mode is mode0.
 *
 * This function calculate the frequency of CUT in mode0 (when CUT frequency < REF frequency).
 *
 * note The unit of this function return value is HZ.
 *
 * param base SFA peripheral base address.
 * param refFrequency reference clock frequency (BUS clock frequency)
 */
static uint32_t SFA_Mode0Calculate(SFA_Type *base, uint32_t refFrequency);

/*!
 * brief Calculate the frequency of the selected CUT source when the selected mode is mode1.
 *
 * This function calculate the frequency of CUT in mode1 (when CUT frequency > REF frequency).
 *
 * note The unit of this function return value is HZ.
 *
 * param base SFA peripheral base address.
 * param refFrequency reference clock frequency (BUS clock frequency)
 */
static uint32_t SFA_Mode1Calculate(SFA_Type *base, uint32_t refFrequency);

/*!
 * brief Calculate the period of the selected CUT source in mode2 or the time of the selected triggers in mode3.
 *
 * In mode2 this function calculate the period of the selected CUT source.
 * In mode3 this function calculate the time of the selected triggers.
 *
 * note The return data is multiple of the reference clock.
 *
 * param base SFA peripheral base address.
 */
static uint32_t SFA_Mode2Mode3Calculate(SFA_Type *base);

/*!
 * brief Measure Frequency in blocking mode.
 *
 * param base SFA peripheral base address.
 * param mode SFA measurement mode.
 *
 * retval kStatus_SFA_ReferenceCounterTimeout error happens.
 * retval kStatus_SFA_MeasurementCompleted measure completes.
 * retval kStatus_SFA_CUTCounterTimeout error happens.
 */
static status_t SFA_MeasureFrequencyBlocking(SFA_Type *base, sfa_measurement_mode_t mode);

/*!
 * brief Measure Period in blocking mode.
 *
 * param base SFA peripheral base address.
 *
 * retval kStatus_SFA_ReferenceCounterTimeout error happens.
 * retval kStatus_SFA_MeasurementCompleted measure completes.
 */
static status_t SFA_MeasurePeriodBlocking(SFA_Type *base);

/*******************************************************************************
 * Variables
 ******************************************************************************/
/*! brief Pointers to SFA bases for each instance. */
static SFA_Type *const s_sfaBases[] = SFA_BASE_PTRS;

#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! brief Pointer to SFA clocks for each instance. */
static clock_ip_name_t const s_sfaClocks[] = SFA_CLOCKS;
#endif /*FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL*/

static sfa_callback_t s_sfaIsr[FSL_FEATURE_SOC_SFA_COUNT];

/*******************************************************************************
 * Code
 ******************************************************************************/

static uint8_t SFA_GetInstance(SFA_Type *base)
{
    uint8_t instance;

    /* Find the instance index from base address mappings. */
    for (instance = 0U; instance < ARRAY_SIZE(s_sfaBases); instance++)
    {
        if (s_sfaBases[instance] == base)
        {
            break;
        }
    }

    assert(instance < ARRAY_SIZE(s_sfaBases));

    return instance;
}

static void SFA_StartMeasureFrequency(SFA_Type *base)
{
    bool triggerable = false;

#if defined(RF_SFA)
    if (1 == FSL_FEATURE_SFA_INSTANCE_HAS_TRIGGERn(base))
    {
        triggerable = ((base->CTRL & SFA_CTRL_SFA_TRIG_MEAS_EN_MASK) != 0U);
    }
#endif

    (*(volatile uint32_t *)&(base->REF_CNT)) = 0U; /* Dummy write to REF counter. */

    /* Poll the CUT_STOPPED bit to make sure it cleared. */
    while ((base->CNT_STAT & SFA_CNT_STAT_CUT_STOPPED_MASK) != 0U)
    {
        ;
    }

    if (!triggerable)
    {
        (*(volatile uint32_t *)&(base->CUT_CNT)) = 0U; /* Dummy write to CUT counter. */
    }

    while (0U == (base->CNT_STAT & SFA_CNT_STAT_MEAS_STARTED_MASK))
    {
        ; /* Loop until measurement start. */
    }
}

static void SFA_StartMeasurePeriod(SFA_Type *base)
{
    (*(volatile uint32_t *)&(base->REF_CNT)) = 0U; /* Dummy write to REF counter. */
    while ((base->CNT_STAT & SFA_CNT_STAT_CUT_STOPPED_MASK) != 0U)
    {
        ;
    }

    while (0U == (base->CNT_STAT & SFA_CNT_STAT_MEAS_STARTED_MASK))
    {
        ; /* Loop until measurement start. */
    }
}

static uint32_t SFA_Mode0Calculate(SFA_Type *base, uint32_t refFrequency)
{
    uint64_t frequency;
    uint8_t prediv;

    prediv    = SFA_GetCUTPredivide(base);
    frequency = ((uint64_t)SFA_GetCUTCounter(base) - 1ULL) * (uint64_t)refFrequency;
    frequency /= ((uint64_t)SFA_GetREFEndCount(base) - (uint64_t)SFA_GetREFStartCount(base));
    if (prediv > 1U)
    {
        /* If the cut predivide is provided. */
        frequency *= prediv;
    }
    return (uint32_t)frequency;
}

static uint32_t SFA_Mode1Calculate(SFA_Type *base, uint32_t refFrequency)
{
    uint64_t frequency;
    uint8_t prediv;

    prediv    = SFA_GetCUTPredivide(base);
    frequency = ((uint64_t)SFA_GetCUTCounter(base) - 1ULL) * (uint64_t)refFrequency;
    frequency /= (uint64_t)SFA_GetREFTargetCount(base);
    if (prediv > 1U)
    {
        /* If the cut predivide is provided. */
        frequency *= prediv;
    }
    return (uint32_t)frequency;
}

static uint32_t SFA_Mode2Mode3Calculate(SFA_Type *base)
{
    uint32_t count;
    uint8_t prediv;

    prediv = SFA_GetCUTPredivide(base);
    count  = SFA_GetREFEndCount(base) - SFA_GetREFStartCount(base);
    if (prediv > 1U)
    {
        /* If the cut predivide is provided. */
        count /= prediv;
    }
    return count;
}

static status_t SFA_MeasureFrequencyBlocking(SFA_Type *base, sfa_measurement_mode_t mode)
{
    status_t status = kStatus_Success;

    if (mode == kSFA_FrequencyMeasurement0)
    {
        while (((base->CNT_STAT & SFA_CNT_STAT_REF_STOPPED_MASK) == 0U) ||
               ((base->CNT_STAT & SFA_CNT_STAT_CUT_STOPPED_MASK) == 0U))
        {
            ;
        }
        if ((base->CNT_STAT & SFA_CNT_STAT_REF_CNT_TIMEOUT_MASK) != 0U)
        {
            /* REF counter reached the target before CUT counter reaching target,
             * Reference clock timeout occurred. */
            status = kStatus_SFA_ReferenceCounterTimeout;
        }
        else
        {
            status = kStatus_SFA_MeasurementCompleted;
        }
    }
    else if (mode == kSFA_FrequencyMeasurement1)
    {
        while (0U == (base->CNT_STAT & SFA_CNT_STAT_CUT_STOPPED_MASK))
        {
            ;
        }
        if ((base->CUT_CNT) < (base->CUT_TARGET))
        {
            status = kStatus_SFA_MeasurementCompleted;
        }
        else
        {
            /* CUT counter reached target, CUT timeout occurred. */
            status = kStatus_SFA_CUTCounterTimeout;
        }
    }
    else
    {
        /* Add comment to prevent the case of MISRA C-2012 rule 15.7. */
    }
    return status;
}

static status_t SFA_MeasurePeriodBlocking(SFA_Type *base)
{
    status_t status = kStatus_Success;

    while (0U == (base->CNT_STAT & SFA_CNT_STAT_REF_STOPPED_MASK))
    {
        ;
    }
    if ((base->CNT_STAT & SFA_CNT_STAT_REF_CNT_TIMEOUT_MASK) != 0U)
    {
        /* REF counter reached the target before SFA receiving a full period or
         * before receiving trigger end signal. */
        status = kStatus_SFA_ReferenceCounterTimeout;
    }
    else
    {
        status = kStatus_SFA_MeasurementCompleted;
    }
    return status;
}

/*!
 * brief Clear the SFA status flags.
 *
 * param base SFA peripheral base address.
 * param mask SFA status flag mask (see @ref _sfa_status_flags for bit definition).
 */
void SFA_ClearStatusFlag(SFA_Type *base, uint32_t mask)
{
    /*Clear interrupt status flag */
    base->CNT_STAT =
        (mask & (SFA_CNT_STAT_SFA_IRQ_MASK | SFA_CNT_STAT_FREQ_GT_MAX_IRQ_MASK | SFA_CNT_STAT_FREQ_LT_MIN_IRQ_MASK));
}

/*!
 * brief Fill the SFA configuration structure with default settings.
 *
 * The default values are:
 * code
 *      config->mode = kSFA_FrequencyMeasurement0;
 *      config->cutSelect = kSFA_CUTSelect0;
 *      config->refSelect = kSFA_REFSelect0;
 *      config->prediv = 0U;
 *      config->trigStart = kSFA_TriggerStartSelect0;
 *      config->startPolarity = kSFA_TriggerStartPolarityRiseEdge;
 *      config->trigEnd = kSFA_TriggerEndSelect0;
 *      config->endPolarity = kSFA_TriggerEndPolarityRiseEdge;
 *      config->enableTrigMeasurement = false;
 *      config->enableCUTPin = false;
 *      config->cutTarget = 0xffffU;
 *      config->refTarget = 0xffffffffU;
 * endcode
 *
 * param config Pointer to the user configuration structure.
 */
void SFA_GetDefaultConfig(sfa_config_t *config)
{
    assert(config);

    (void *)memset(config, 0, sizeof(*config));

    config->mode                  = kSFA_FrequencyMeasurement0;
    config->cutSelect             = kSFA_CUTSelect0;
    config->refSelect             = kSFA_REFSelect0;
    config->prediv                = 0U;
    config->trigStart             = kSFA_TriggerStartSelect0;
    config->startPolarity         = kSFA_TriggerStartPolarityRiseEdge;
    config->trigEnd               = kSFA_TriggerEndSelect0;
    config->endPolarity           = kSFA_TriggerEndPolarityRiseEdge;
    config->enableTrigMeasurement = false;
    config->enableCUTPin          = false;
    config->cutTarget             = 0xffffU;
    config->refTarget             = 0xffffffffU;
}

/*!
 * brief Initialize SFA.
 *
 * param base SFA peripheral base address.
 */
void SFA_Init(SFA_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
    CLOCK_EnableClock(s_sfaClocks[SFA_GetInstance(base)]);
#endif /*FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL*/

    /* dummy write REF_CNT to clear each counters and status flags */
    (*(volatile uint32_t *)&(base->REF_CNT)) = 0U;
}

/*!
 * brief Clear counter, disable SFA and gate the SFA clock.
 *
 * param base SFA peripheral base address.
 */
void SFA_Deinit(SFA_Type *base)
{
    (*(volatile uint32_t *)&(base->REF_CNT)) = 0U; /* Dummy write REF counter to clear flags and counters. */
    while ((base->CNT_STAT & SFA_CNT_STAT_CUT_STOPPED_MASK) != 0U)
    {
        ;
    }
    base->CTRL &= ~SFA_CTRL_SFA_EN_MASK;

#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
    CLOCK_DisableClock(s_sfaClocks[SFA_GetInstance(base)]);
#endif /*FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL*/
}

/*!
 * brief Set Measurement options with the passed in configuration structure.
 *
 * param base SFA peripheral base address.
 * param config SFA configuration structure.
 */
void SFA_SetMeasureConfig(SFA_Type *base, const sfa_config_t *config)
{
    assert(config);
    assert(((1 != FSL_FEATURE_SFA_CTRL_HAS_CUT_PIN_ENn(base)) &&
            ((config->refSelect < kSFA_REFSelect2) && (config->cutSelect < kSFA_CUTSelect2))) ||
           (1 == FSL_FEATURE_SFA_CTRL_HAS_CUT_PIN_ENn(base)));
    assert(((1 != FSL_FEATURE_SFA_INSTANCE_HAS_TRIGGERn(base)) && (config->mode < kSFA_TriggerBasedMeasurement)) ||
           (1 == FSL_FEATURE_SFA_INSTANCE_HAS_TRIGGERn(base)));

    sfa_measurement_mode_t mode;

    mode = config->mode;

    /* Enable selected clock under test source. */
    base->CTRL_EXT |= SFA_CUT_CLK_Enable(config->cutSelect);

    /* Enable selected REF clock. */
    base->CTRL2 = (base->CTRL2 & ~SFA_CTRL2_REF_CLK_SEL_MASK) | SFA_CTRL2_REF_CLK_SEL(config->refSelect);

#if defined(FSL_FEATURE_SFA_CTRL_EXT_HAS_CUT_PIN_EN) && FSL_FEATURE_SFA_CTRL_EXT_HAS_CUT_PIN_EN
    if (config->enableCUTPin)
    {
        base->CTRL_EXT |= SFA_CTRL_EXT_CUT_PIN_EN_MASK;
    }
    else
    {
        base->CTRL_EXT &= ~SFA_CTRL_EXT_CUT_PIN_EN_MASK;
    }
#elif defined(FSL_FEATURE_SFA_CTRL_HAS_CUT_PIN_EN) && FSL_FEATURE_SFA_CTRL_HAS_CUT_PIN_EN
    if (config->enableCUTPin)
    {
        base->CTRL |= SFA_CTRL_CUT_PIN_EN_MASK;
    }
    else
    {
        base->CTRL &= ~SFA_CTRL_CUT_PIN_EN_MASK;
    }
#endif

    /* Before modifying measurement basic options, disable SFA general enable signal. */
    base->CTRL &= ~SFA_CTRL_SFA_EN_MASK;
    switch (mode)
    {
        case kSFA_FrequencyMeasurement0:
        case kSFA_FrequencyMeasurement1:
        {
            base->CTRL =
                SFA_CTRL_MODE(config->mode) | SFA_CTRL_CUT_SEL(config->cutSelect) | SFA_CTRL_CUT_PREDIV(config->prediv);

#if defined(RF_SFA)
            if (1 == FSL_FEATURE_SFA_INSTANCE_HAS_TRIGGERn(base))
            {
                if (config->enableTrigMeasurement)
                {
                    base->CTRL |= SFA_CTRL_SFA_TRIG_MEAS_EN_MASK;
                    base->CTRL |=
                        SFA_CTRL_TRIG_START_SEL(config->trigStart) | SFA_CTRL_TRIG_START_POL(config->startPolarity);
                }
                else
                {
                    base->CTRL &= ~SFA_CTRL_SFA_TRIG_MEAS_EN_MASK;
                }
            }
#endif

            base->CTRL |= SFA_CTRL_SFA_EN_MASK;

            SFA_SetCUTTargetCount(base, config->cutTarget);
            SFA_SetREFTargetCount(base, config->refTarget);
            break;
        }
        case kSFA_CUTPeriodMeasurement:
        {
            base->CTRL =
                SFA_CTRL_MODE(config->mode) | SFA_CTRL_CUT_SEL(config->cutSelect) | SFA_CTRL_CUT_PREDIV(config->prediv);

            base->CTRL |= SFA_CTRL_SFA_EN_MASK;

            SFA_SetREFTargetCount(base, config->refTarget);
            break;
        }
        case kSFA_TriggerBasedMeasurement:
        {
#if defined(RF_SFA)
            base->CTRL = SFA_CTRL_MODE(config->mode) | SFA_CTRL_TRIG_START_SEL(config->trigStart) |
                         SFA_CTRL_TRIG_START_POL(config->startPolarity) | SFA_CTRL_TRIG_END_SEL(config->trigEnd) |
                         SFA_CTRL_TRIG_END_POL(config->endPolarity);

            base->CTRL |= SFA_CTRL_SFA_EN_MASK;

            SFA_SetREFTargetCount(base, config->refTarget);
#endif

            break;
        }
        default:
            assert(false);
            break;
    }
}

/*!
 * brief Install the callback routine to be called when IRQ happens or measurement completes.
 *
 * param base SFA peripheral base address.
 * param function the SFA measure completed callback function.
 */
void SFA_InstallCallback(SFA_Type *base, sfa_callback_t function)
{
    assert(function);
    assert(1 == FSL_FEATURE_SFA_INSTANCE_HAS_INTERRUPTn(base));

    uint8_t instance;

    instance = SFA_GetInstance(base);
    if (s_sfaIsr[instance] == NULL)
    {
        s_sfaIsr[instance] = function;
    }
}

/*!
 * brief Start SFA measurement in blocking mode
 *
 * This function start SFA measurement based on the configged mode.
 * The user must config measure mode before invoking this function.
 * This function will return the measurement status until measure completes or timeout error happens.
 *
 * param base SFA peripheral base address.
 *
 * retval kStatus_SFA_MeasurementCompleted SFA measure completes.
 * retval kStatus_SFA_ReferenceCounterTimeout reference counter timeout error happens.
 * retval kStatus_SFA_CUTCounterTimeout CUT counter time out happens.
 */
status_t SFA_MeasureBlocking(SFA_Type *base)
{
    sfa_measurement_mode_t mode;
    status_t status = kStatus_Success;

    mode = (sfa_measurement_mode_t)SFA_GetMode(base);

    if (mode == kSFA_FrequencyMeasurement0 || mode == kSFA_FrequencyMeasurement1)
    {
        SFA_StartMeasureFrequency(base);
        status = SFA_MeasureFrequencyBlocking(base, mode);
    }
    else if (mode == kSFA_CUTPeriodMeasurement || mode == kSFA_TriggerBasedMeasurement)
    {
        SFA_StartMeasurePeriod(base);
        status = SFA_MeasurePeriodBlocking(base);
    }
    else
    {
        /* Add comments to prevent the case of MISRA C-2012 rule 15.7. */
    }

    return status;
}

/*!
 * brief Start measure sequence in NonBlocking mode.
 *
 * This function performs nonblocking measurement by enabling sfa interrupt (Please enable the FreqGreaterThanMax and
 * FreqLessThanMin interrupts individually as needed). The callback function must be installed before invoking this
 * function.
 * note This function has different functions for different instances.
 * param base SFA peripheral base address.
 */
void SFA_MeasureNonBlocking(SFA_Type *base)
{
    assert(1 == FSL_FEATURE_SFA_INSTANCE_HAS_INTERRUPTn(base));

    sfa_measurement_mode_t mode;

    mode = (sfa_measurement_mode_t)SFA_GetMode(base);

    SFA_EnableInterrupts(base, (uint32_t)kSFA_InterruptEnable);

    if (mode == kSFA_FrequencyMeasurement0 || mode == kSFA_FrequencyMeasurement1)
    {
        SFA_StartMeasureFrequency(base);
    }
    else if (mode == kSFA_CUTPeriodMeasurement || mode == kSFA_TriggerBasedMeasurement)
    {
        SFA_StartMeasurePeriod(base);
    }
    else
    {
        /* Add comments to prevent the case of MISRA C-2012 ruel 15.7. */
    }
}

/*!
 * brief Abort SFA measurement sequence.
 *
 * This function will clear each counters and each status flags firstly, and then disable SFA.
 *
 * param base SFA peripheral base address.
 */
void SFA_AbortMeasureSequence(SFA_Type *base)
{
    /* Dummy write REF counter to clear each counters and status flags. */
    (*(volatile uint32_t *)&(base->REF_CNT)) = 0U;
    base->CTRL &= ~SFA_CTRL_SFA_EN_MASK;
}

/*!
 * brief Calculate the frequency or period.
 *
 * This funcion will calculate the frequency or period based on configged measure mode.
 * This function must be invoked after the measurement completes.
 *
 * note This function returns frequency with Hz as the unit when used to calculate frequency.
 * note This function returns period with the counts of reference clock when used to calculate period or triggers time.
 *
 * param base SFA peripheral base address.
 * param refFrequency The reference clock frequency(BUS clock recommended).
 */
uint32_t SFA_CalculateFrequencyOrPeriod(SFA_Type *base, uint32_t refFrequency)
{
    sfa_measurement_mode_t mode;
    uint32_t result;

    mode = (sfa_measurement_mode_t)SFA_GetMode(base);
    switch (mode)
    {
        case kSFA_FrequencyMeasurement0:
        {
            result = SFA_Mode0Calculate(base, refFrequency);
            break;
        }
        case kSFA_FrequencyMeasurement1:
        {
            result = SFA_Mode1Calculate(base, refFrequency);
            break;
        }
        case kSFA_CUTPeriodMeasurement:
        case kSFA_TriggerBasedMeasurement:
        {
            result = SFA_Mode2Mode3Calculate(base);
            break;
        }
        default:
            assert(false);
            break;
    }
    return result;
}

/*!
 * brief Common IRQ handler for each instance.
 *
 * If enable SFA IRQ, this function will be invoked when the measurement is complete.
 * The installed callback function will be invoked with status as the parameter.
 *
 * param base SFA peripheral base address.
 */
static void SFA_CommonIRQHandler(SFA_Type *base)
{
    uint8_t instance;
    sfa_measurement_mode_t mode;
    status_t status = kStatus_Success;
    uint32_t flags;

    instance = (uint8_t)SFA_GetInstance(base);
    flags    = SFA_GetStatusFlags(base);

    assert(s_sfaIsr[instance]);

    if ((flags & (uint32_t)kSFA_InterruptRequestFlag) != 0U)
    {
        mode = (sfa_measurement_mode_t)SFA_GetMode(base);

        SFA_ClearStatusFlag(base, (uint32_t)kSFA_InterruptRequestFlag);
        SFA_DisableInterrupts(base, (uint32_t)kSFA_InterruptEnable);
        switch (mode)
        {
            case kSFA_FrequencyMeasurement0:
            {
                if ((flags & ((uint32_t)kSFA_RefStoppedFlag | (uint32_t)kSFA_CutStoppedFlag)) != 0U)
                {
                    status = kStatus_SFA_MeasurementCompleted;
                }
                if ((flags & (uint32_t)kSFA_ReferenceCounterTimeOutFlag) != 0U)
                {
                    status = kStatus_SFA_ReferenceCounterTimeout;
                }
                break;
            }
            case kSFA_FrequencyMeasurement1:
            {
                if ((flags & (uint32_t)kSFA_RefStoppedFlag) != 0U)
                {
                    status = kStatus_SFA_MeasurementCompleted;
                }
                if (SFA_GetCUTCounter(base) >= SFA_GetCUTTargetCount(base))
                {
                    status = kStatus_SFA_CUTCounterTimeout;
                }
                break;
            }
            case kSFA_CUTPeriodMeasurement:
            case kSFA_TriggerBasedMeasurement:
            {
                if ((flags & (uint32_t)kSFA_RefStoppedFlag) != 0U)
                {
                    status = kStatus_SFA_MeasurementCompleted;
                }
                if ((flags & (uint32_t)kSFA_ReferenceCounterTimeOutFlag) != 0U)
                {
                    status = kStatus_SFA_ReferenceCounterTimeout;
                }
                break;
            }
            default:
                assert(false);
                break;
        }
    }
    else if ((flags & (uint32_t)kSFA_FreqLessThanMinInterruptFlag) != 0U)
    {
        SFA_ClearStatusFlag(base, (uint32_t)kSFA_FreqLessThanMinInterruptFlag);
        SFA_DisableInterrupts(base, (uint32_t)kSFA_FreqLessThanMinInterruptEnable);
        status = kStatus_SFA_CUTClockFreqLessThanMinLimit;
    }
    else if ((flags & (uint32_t)kSFA_FreqGreaterThanMaxInterruptFlag) != 0U)
    {
        SFA_ClearStatusFlag(base, (uint32_t)kSFA_FreqGreaterThanMaxInterruptFlag);
        SFA_DisableInterrupts(base, (uint32_t)kSFA_FreqGreaterThanMaxInterruptEnable);
        status = kStatus_SFA_CUTClockFreqGreaterThanMaxLimit;
    }
    else
    {
        /* Add comments to prevent the case of MISRA C-2012 ruel 15.7. */
    }

    s_sfaIsr[instance](status);
    SDK_ISR_EXIT_BARRIER;
}

#if defined(SFA0)
void SFA0_DriverIRQHandler(void);
void SFA0_DriverIRQHandler(void)
{
    SFA_CommonIRQHandler(SFA0);
}
#endif

#if defined(RF_SFA)
void RF_32K_Calibration_DriverIRQHandler(void);
void RF_32K_Calibration_DriverIRQHandler(void)
{
    SFA_CommonIRQHandler((SFA_Type *)RF_SFA);
}
#endif
