/*******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only
* intended for use with Renesas products. No other uses are authorized. This
* software is owned by Renesas Electronics Corporation and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software
* and to discontinue the availability of this software. By using this software,
* you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
* Copyright 2018-2024 Renesas Electronics Corporation All rights reserved.
*******************************************************************************/

#include <stdint.h>
#if defined(__RH850G3K__)
#include "mem_io.h"
#include "log.h"
#else
#include "mem_io.h"
#include "log.h"
#endif
#include "boot_init_dram_config.h"
#include "boot_init_dram_regdef.h"

/*******************************************************************************
 *    PLEASE SET board number or board judge function
 ******************************************************************************/
// #define BOARD_JUDGE_AUTO
#ifdef BOARD_JUDGE_AUTO
static uint32_t r_board_judge(void);
uint32_t r_boardcnf_get_brd_type(void)
{
    return r_board_judge();
}
#else /* BOARD_JUDGE_AUTO */
uint32_t r_boardcnf_get_brd_type(void)
{
        return (2);
}
#endif /* BOARD_JUDGE_AUTO */

/**
* RENESAS WHITE HAWK BOARD EXAMPLE
* @par TraceID Cover_SW_UD:Cover_HW_DD
* V4H-LPDDR5-DDR-SW-UD-01-02:V4H-LPDDR5-DDR-HW-DD-01-04-01
* @param[in] brd Argument for dummy read
* @param[in] clk The pointer which indicate the clock frequency
* @param[in] div The pointer which indicate the clock frequency division
* @details judged by md14/md13\n
* 16.66MHz CLK,DIV= 50,3  (md14,md13==0,0)
* 20.00MHz CLK,DIV= 60,3  (md14,md13==0,1)
* 33.33MHz CLK,DIV=100,3  (md14,md13==1,1)
*/
void r_boardcnf_get_brd_clk(uint32_t brd, uint32_t *clk, uint32_t *clk_div)
{
    uint32_t md;

    md = (mmio_read_32(RST_MODEMR0) >> 13) & 0x3U;
    switch (md)
    {
        case 0x0U   : *clk =  50U; *clk_div = 3U;           break;  /*  50 / 3 = 16.66MHz */
        case 0x1U   : *clk =  60U; *clk_div = 3U;           break;  /*  60 / 3 = 20.00MHz */
        case 0x2U   : NOTICE("MD14/MD13 is invalid!!\n");   panic;  /*  Not supported     */
        case 0x3U   : *clk = 100U; *clk_div = 3U;           break;  /* 100 / 3 = 33.33MHz */
        default     : /* nop */                             break;
    }
    (void)brd;
}

/*******************************************************************************
 *  DDR MBPS TARGET
 *  PLEASE DEFINE HOW TO JUDGE DDR BPS
 ******************************************************************************/
/**
* DDRxxxx (judge by md19, md17) : Mbps
* @par TraceID Cover_SW_UD:Cover_HW_DD
* V4H-LPDDR5-DDR-SW-UD-01-03:V4H-LPDDR5-DDR-HW-DD-01-04-02
* @param[in] brd Argument for dummy read
* @param[in] mbps The pointer which indicate the ddr frequency
* @param[in] div  The pointer which indicate the ddr frequency division
* @details SSCG enable / disable for PLL1 (judge by md37/md36)
* According to Bit[17] of RST_MODEMR0 and Bit[5:4] of RST_MODEMR1,
* determine the value of ddr mbps and mbps division.
*/
void r_boardcnf_get_ddr_mbps(uint32_t brd, uint32_t *mbps, uint32_t *mbps_div, uint32_t *sscg)
{
    uint32_t md;
    uint32_t product;

    md = (mmio_read_32(RST_MODEMR0) >> 17) & 0x05U;
    md = (md | (md >> 1)) & 0x03U;
    *sscg = (mmio_read_32(RST_MODEMR1) >> 4) & 0x03U;
    product = mmio_read_32(OTP_MEM_OTPMONITOR17) & OTP_MEM_PRODUCT_MASK;

    if (product == 0x01U)
    {
        /* V4H-5 */
        switch (md)
        {
            case 0x0U : *mbps =   5000U; *mbps_div = 1U; break;    /* 5000Mbps */
            case 0x1U : *mbps =   5000U; *mbps_div = 1U; break;    /* 5000Mbps */
            case 0x2U : *mbps =   5000U; *mbps_div = 1U; break;    /* 5000Mbps */
            case 0x3U : *mbps =   4800U; *mbps_div = 1U; break;    /* 4800Mbps */
            default   : /* Nothing */                    break;
        }
    }
    else if (product == 0x02U)
    {
        /* V4H-3 */
        switch (md)
        {
            case 0x0U : *mbps =   4800U; *mbps_div = 1U; break;    /* 4800Mbps */
            case 0x1U : *mbps =   4800U; *mbps_div = 1U; break;    /* 4800Mbps */
            case 0x2U : *mbps =   4800U; *mbps_div = 1U; break;    /* 4800Mbps */
            case 0x3U : *mbps =   4800U; *mbps_div = 1U; break;    /* 4800Mbps */
            default   : /* Nothing */                    break;
        }
    }
    else
    {
        /* V4H-7 */
        switch (*sscg)
        {
            case 0x0U :
                switch (md)
                {
                    case 0x0U   :   *mbps =  6400U; *mbps_div = 1U; break;  /* 6400Mbps */
                    case 0x1U   :   *mbps =  6000U; *mbps_div = 1U; break;  /* 6000Mbps */
                    case 0x2U   :   *mbps =  5500U; *mbps_div = 1U; break;  /* 5500Mbps */
                    case 0x3U   :   *mbps =  4800U; *mbps_div = 1U; break;  /* 4800Mbps */
                    default     :   /* nop */                       break;
                }
                break;
            case 0x1U :
                switch (md)
                {
                    case 0x0U   :   *mbps = 19000U; *mbps_div = 3U; break;  /* 6333Mbps */
                    case 0x1U   :   *mbps =  6000U; *mbps_div = 1U; break;  /* 6000Mbps */
                    case 0x2U   :   *mbps =  5500U; *mbps_div = 1U; break;  /* 5500Mbps */
                    case 0x3U   :   *mbps =  4800U; *mbps_div = 1U; break;  /* 4800Mbps */
                    default     :   /* nop */                       break;
                }
                break;
            case 0x2U :                                                     /* Not supported  */
                NOTICE("This MD37/MD36 value is invalid!!\n");panic;
            case 0x3U :
                switch (md)
                {
                    case 0x0U   :   *mbps = 19000U; *mbps_div = 3U;  break;  /* 6333Mbps */
                    case 0x1U   :   *mbps =  6000U; *mbps_div = 1U;  break;  /* 6000Mbps */
                    case 0x2U   :   *mbps =  5500U; *mbps_div = 1U;  break;  /* 5500Mbps */
                    case 0x3U   :   *mbps =  4800U; *mbps_div = 1U;  break;  /* 4800Mbps */
                    default     :   /* nop */                        break;
                }
                break;
            default :
                /* nop */
                break;
        }
    }
    (void)brd;
}

#ifdef BOARD_JUDGE_AUTO
/*******************************************************************************
 *  SAMPLE board detect function
 ******************************************************************************/
/**
* Select the setting parameters about the Spieder board you use.
* @par TraceID Cover_SW_UD:Cover_HW_DD
* V4H-LPDDR5-DDR-SW-UD-10:V4H-LPDDR5-DDR-HW-DD-01-03-02
* @return uint32_t Selected table index, this is sample value 0.
* @details Pass the return value from the r_board_judge function.
* In case that "BOARD_JUDGE_AUTO" is not defined, Another process will be called.\n\n
*/
static uint32_t r_board_judge(void)
{
    uint32_t brd;

    brd = 0U;    /* white hawk (64Gbit 1rank)*/

    return brd;
}
#endif
