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

#include "fsl_common.h"
#include "board.h"
#include "fsl_power.h"
#include "pmic_support.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define PMIC_DECREASE_LVD_LEVEL_IF_HIGHER_THAN(currVolt, targetVolt) \
    do                                                               \
    {                                                                \
        if ((uint32_t)(currVolt) > (uint32_t)(targetVolt))           \
        {                                                            \
            POWER_SetLvdFallingTripVoltage(kLvdFallingTripVol_720);  \
        }                                                            \
    } while (0)

/*******************************************************************************
 * Variables
 ******************************************************************************/
pca9420_handle_t pca9420Handle;
static pca9420_modecfg_t pca9420CurrModeCfg;
static pca9420_mode_t pca9420CurrMode;
/*******************************************************************************
 * Code
 ******************************************************************************/
void BOARD_InitPmic(void)
{
    pca9420_config_t pca9420Config;

    CLOCK_AttachClk(kSFRO_to_FLEXCOMM15);
    BOARD_PMIC_I2C_Init();
    PCA9420_GetDefaultConfig(&pca9420Config);
    pca9420Config.I2C_SendFunc    = BOARD_PMIC_I2C_Send;
    pca9420Config.I2C_ReceiveFunc = BOARD_PMIC_I2C_Receive;
    pca9420Config.powerGoodEnable = kPCA9420_PGoodDisabled;
    PCA9420_Init(&pca9420Handle, &pca9420Config);
}
void BOARD_SetPmicVoltageForFreq(uint32_t main_clk_freq, uint32_t dsp_main_clk_freq)
{
    power_lvd_falling_trip_vol_val_t lvdVolt;

    assert(main_clk_freq <= CLK_600MHZ);
    assert(dsp_main_clk_freq <= CLK_600MHZ);

    PCA9420_GetCurrentMode(&pca9420Handle, &pca9420CurrMode);
    PCA9420_ReadModeConfigs(&pca9420Handle, pca9420CurrMode, &pca9420CurrModeCfg, 1);

    lvdVolt = POWER_GetLvdFallingTripVoltage();
    /* Set SW1 output (vddcore) to 1.1V */
    if (pca9420CurrModeCfg.sw1OutVolt != kPCA9420_Sw1OutVolt1V100)
    {
        pca9420CurrModeCfg.sw1OutVolt = kPCA9420_Sw1OutVolt1V100;
        PCA9420_WriteModeConfigs(&pca9420Handle, pca9420CurrMode, &pca9420CurrModeCfg, 1);
    }
    /* Enter NBB mode first */
    if (POWER_GetBodyBiasMode(kCfg_Run) != kPmu_Nbb)
    {
        POWER_EnterNbb();
    }
    if (main_clk_freq <= CLK_60MHZ)
    {
        if (dsp_main_clk_freq <= CLK_60MHZ)
        {
            PMIC_DECREASE_LVD_LEVEL_IF_HIGHER_THAN(lvdVolt, kLvdFallingTripVol_795);
            /* Enter Rbb mode */
            POWER_EnterRbb();
            /* Set SW1 output to 0.8V */
            pca9420CurrModeCfg.sw1OutVolt = kPCA9420_Sw1OutVolt0V800;
            PCA9420_WriteModeConfigs(&pca9420Handle, pca9420CurrMode, &pca9420CurrModeCfg, 1);
        }
        else if (dsp_main_clk_freq <= CLK_306MHZ)
        {
            PMIC_DECREASE_LVD_LEVEL_IF_HIGHER_THAN(lvdVolt, kLvdFallingTripVol_795);
            /* Enter Fbb mode */
            POWER_EnterFbb();
            /* Set SW1 output to 0.8V */
            pca9420CurrModeCfg.sw1OutVolt = kPCA9420_Sw1OutVolt0V800;
            PCA9420_WriteModeConfigs(&pca9420Handle, pca9420CurrMode, &pca9420CurrModeCfg, 1);
        }
        else if (dsp_main_clk_freq <= CLK_424MHZ)
        {
            PMIC_DECREASE_LVD_LEVEL_IF_HIGHER_THAN(lvdVolt, kLvdFallingTripVol_885);
            /* Enter Fbb mode */
            POWER_EnterFbb();
            /* Set SW1 output to 0.9V */
            pca9420CurrModeCfg.sw1OutVolt = kPCA9420_Sw1OutVolt0V900;
            PCA9420_WriteModeConfigs(&pca9420Handle, pca9420CurrMode, &pca9420CurrModeCfg, 1);
        }
        else if (dsp_main_clk_freq <= CLK_529MHZ)
        {
            /* Enter Fbb mode */
            POWER_EnterFbb();
            /* Set SW1 output to 1.0V */
            pca9420CurrModeCfg.sw1OutVolt = kPCA9420_Sw1OutVolt1V000;
            PCA9420_WriteModeConfigs(&pca9420Handle, pca9420CurrMode, &pca9420CurrModeCfg, 1);
        }
        else
        {
            /* Enter Fbb mode with SW1 1.1V */
            POWER_EnterFbb();
        }
    }
    else
    {
        if (dsp_main_clk_freq > CLK_529MHZ)
        {
            /* Enter Fbb mode */
            POWER_EnterFbb();
        }
    }
}
