/*******************************************************************************
* 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-2025 Renesas Electronics Corporation All rights reserved.
*******************************************************************************/



/*******************************************************************************
 * DESCRIPTION   : Access protection Function function
 ******************************************************************************/
 /******************************************************************************
 * @file          region_id.c
 * - Version      : 0.05
 * @brief         Each module to R/W access protection by Region ID.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 15.12.2022 0.01     First Release
 *         : 24.02.2023 0.02     Polling the RGID setting process finish
 *         : 23.01.2024 0.03     Added ram_protection_check function.
 *         : 31.01.2024 0.04     Fixed the error in SECDIVn register
 *                               calculating value.
 *         : 06.01.2025 0.05     Added reading back IMP Region ID register
 *                               value.
 *                               Added reading back IPMMU Region ID register
 *                               value.
 *****************************************************************************/

#include <stdint.h>
#include "access_protection.h"
#include "axmm_register.h"
#include "cnf_tbl.h"
#include "mem_io.h"
#include "log.h"
#include "rtvram_register.h"

#define RGID_SET_RGID_FIN_FLG_ADDR  (0xE635EFFCU)
#define RGID_SET_RGID_FIN_FLG_VAL   (0x64U)

/* RAM protection for RT-VRAM0/RT-VRAM1 */
#define SHIFT_FOR_SECDIVD       (12U)
/* RAM protection for System RAM */
#define SHIFT_FOR_SPTDIVCR      (12U)
/* RAM protection for SDRAM */
#define SHIFT_FOR_DPTDIVCR      (16U)

/* Value for calculating the offset address to set in SECDIVD. */
#define RTSRAM_SECDIVD_SUBVALUE (0xE0000000U)   /* RT-VRAM0 Base address */
#define RTVRAM_SECDIVD_SUBVALUE (0xE2000000U)   /* RT-VRAM1 Base address */

#define RTSRAM_ADDR_OFFSET_MASK (0xFFFFF000U)
#define RTVRAM_ADDR_MASK        (0xFFFFF000U)

void rgid_protection_check(void)
{
    uint32_t loop;
    uint32_t reg;

    /* Polling until RGID setting completion flag is set by ICUMX IPL. */
    do{
        reg = mem_read8(RGID_SET_RGID_FIN_FLG_ADDR);
    } while(reg != RGID_SET_RGID_FIN_FLG_VAL);

    for(loop = 0U; loop < RGID_MASTER_MAX; loop++)
    {
       /* Get RGIDM_MODID value */
        reg = mem_read32((uintptr_t)g_rgid_master_tbl[loop].phys_addr);   /* Read */
        if (reg != g_rgid_master_tbl[loop].value)
        {
            ERROR("Region ID check error.\n");
            ERROR("RGIDM_MODID:%d 0x%x value = 0x%x expected value = 0x%x.\n", loop,
                g_rgid_master_tbl[loop].phys_addr, reg, g_rgid_master_tbl[loop].value);
            panic;
        }
    }

    for(loop = 0U; loop < RGID_READ_MAX; loop++)
    {
       /* Get RGIDR_MODID value */
        reg = mem_read32((uintptr_t)g_rgid_read_tbl[loop].phys_addr);   /* Read */
        if (reg != g_rgid_read_tbl[loop].value)
        {
            ERROR("Region ID check error.\n");
            ERROR("RGIDR_MODID:%d  0x%x value = 0x%x expected value = 0x%x.\n", loop,
                g_rgid_read_tbl[loop].phys_addr, reg, g_rgid_read_tbl[loop].value);
            panic;
        }
    }

    for(loop = 0U; loop < RGID_WRITE_MAX; loop++)
    {
        /* Get RGIDW_MODID value */
        reg = mem_read32((uintptr_t)g_rgid_write_tbl[loop].phys_addr);   /* Read */
        if (reg != g_rgid_write_tbl[loop].value)
        {
            ERROR("Region ID check error.\n");
            ERROR("RGIDW_MODID:%d  0x%x value = 0x%x expected value = 0x%x.\n", loop,
                g_rgid_write_tbl[loop].phys_addr, reg, g_rgid_write_tbl[loop].value);
            panic;
        }
    }

    for(loop = 0U; loop < RGID_SEC_MAX; loop++)
    {
        /* Get SEC_MODID value */
        reg = mem_read32((uintptr_t)g_rgid_sec_tbl[loop].phys_addr);   /* Read */
        if (reg != g_rgid_sec_tbl[loop].value)
        {
            ERROR("Region ID check error.\n");
            ERROR("SEC_MODID:%d 0x%x value = 0x%x expected value = 0x%x.\n", loop,
                g_rgid_sec_tbl[loop].phys_addr, reg, g_rgid_sec_tbl[loop].value);
            panic;
        }
    }

	for(loop = 0U; loop < RGID_AXI_MAX; loop++)
    {
        /* Get AXI_MODID value */
        reg = mem_read32((uintptr_t)g_rgid_axi_tbl[loop].phys_addr);   /* Read */
        if (reg != g_rgid_axi_tbl[loop].value)
        {
            ERROR("Region ID check error.\n");
            ERROR("AXI_MODID:%d 0x%x value = 0x%x expected value = 0x%x.\n", loop,
                g_rgid_axi_tbl[loop].phys_addr, reg, g_rgid_axi_tbl[loop].value);
            panic;
        }
    }

#if (RCAR_LSI == RCAR_V4H)
	for(loop = 0U; loop < IMP_MASTER_MAX; loop++)
    {
        /* Get IMP Region ID Master value */
        reg = mem_read32((uintptr_t)g_imp_rgid_m_tbl[loop].phys_addr);   /* Read */
        if (reg != g_imp_rgid_m_tbl[loop].value)
        {
            ERROR("Region ID check error.\n");
            ERROR("IMP_RGID_MASTER:%d 0x%x value = 0x%x expected value = 0x%x.\n", loop,
                g_imp_rgid_m_tbl[loop].phys_addr, reg, g_imp_rgid_m_tbl[loop].value);
            panic;
        }
    }

	for(loop = 0U; loop < IMP_SLAVE_MAX; loop++)
    {
        /* Get IMP Region ID Slave value */
        reg = mem_read32((uintptr_t)g_imp_rgid_s_tbl[loop].phys_addr);   /* Read */
        if (reg != g_imp_rgid_s_tbl[loop].value)
        {
            ERROR("Region ID check error.\n");
            ERROR("IMP_RGID_SLAVE:%d 0x%x value = 0x%x expected value = 0x%x.\n", loop,
                g_imp_rgid_s_tbl[loop].phys_addr, reg, g_imp_rgid_s_tbl[loop].value);
            panic;
        }
    }
#endif /* (RCAR_LSI == RCAR_V4H) */

    for(loop = 0U; loop < IPMMU_RGID_MAX; loop++)
    {
        /* Get IPMMU Region ID */
        reg = mem_read32((uintptr_t)g_ipmmu_rgid_tbl[loop].phys_addr);   /* Read */
        if (reg != g_ipmmu_rgid_tbl[loop].value)
        {
            ERROR("Region ID check error.\n");
            ERROR("IMRGID_IPMMU:%d 0x%x value = 0x%x expected value = 0x%x.\n", loop,
                g_ipmmu_rgid_tbl[loop].phys_addr, reg, g_ipmmu_rgid_tbl[loop].value);
            panic;
        }
    }

    for(loop = 0U; loop < IPMMU_RGID_MAX; loop++)
    {
        /* Get IPMMU Region ID Secure */
        reg = mem_read32((uintptr_t)g_ipmmu_rgid_sec_tbl[loop].phys_addr);   /* Read */
        if (reg != g_ipmmu_rgid_sec_tbl[loop].value)
        {
            ERROR("Region ID check error.\n");
            ERROR("IMSECGRP_IPMMU:%d 0x%x value = 0x%x expected value = 0x%x.\n", loop,
                g_ipmmu_rgid_sec_tbl[loop].phys_addr, reg, g_ipmmu_rgid_sec_tbl[loop].value);
            panic;
        }
    }

    for(loop = 0U; loop < IPMMU_RGID_MAX; loop++)
    {
        /* Get IPMMU Region ID Enable */
        reg = mem_read32((uintptr_t)g_ipmmu_rgid_en_tbl[loop].phys_addr);   /* Read */
        if (reg != g_ipmmu_rgid_en_tbl[loop].value)
        {
            ERROR("Region ID check error.\n");
            ERROR("IMRGIDEN_IPMMU:%d 0x%x value = 0x%x expected value = 0x%x.\n", loop,
                g_ipmmu_rgid_en_tbl[loop].phys_addr, reg, g_ipmmu_rgid_en_tbl[loop].value);
            panic;
        }
    }

}
/* End of function rgid_protection_check(void) */

void ram_protection_check(void)
{
    uint32_t loop;
    uint32_t expect_val;
    uint32_t area_addr;
    uint32_t area_reg_val;
    /* For RT-VRAM0 / RT-VRAM1 */
    uint32_t read_addr;
    uint32_t read_reg_val;
    uint32_t write_addr;
    uint32_t write_reg_val;
    /* For System RAM / SDRAM */
    uint32_t rw_addr;
    uint32_t rw_reg_val;
    uint32_t sec_addr;
    uint32_t sec_reg_val;

    /* Check RAM protection for RT-VRAM0 */
    /* Check SECDIV[n]D_0 register */
    for (loop = 0; loop < RAM_PROTECTION_MAX - 1U; loop++)
    {
        area_addr    = get_rtvram0_secdivd_addr(loop);
        area_reg_val = mem_read32((uintptr_t)area_addr);
        expect_val   = g_rtvram0_protection_table[loop + 1U].addr - RTSRAM_SECDIVD_SUBVALUE;
        expect_val   = ((expect_val & RTSRAM_ADDR_OFFSET_MASK) >> 12U);

        if (area_reg_val != expect_val)
        {
            ERROR("RAM protection check error\n");
            ERROR("SECDIVnD_0:%d 0x%x value=0x%x expected value=0x%x\n"
                , loop
                , area_addr
                , area_reg_val
                , expect_val);
            panic;
        }
    }


    /* Check SECCTRR[m]D_0 / SECCTRW[m]D_0 register */
    for (loop = 0; loop < RAM_PROTECTION_MAX; loop++)
    {
        read_addr     = get_rtvram0_secctrrd_addr(loop);
        read_reg_val  = mem_read32((uintptr_t)read_addr);
        write_addr    = get_rtvram0_secctrwd_addr(loop);
        write_reg_val = mem_read32((uintptr_t)write_addr);

        if (read_reg_val != g_rtvram0_protection_table[loop].setting_value.read_val)
        {
            ERROR("RAM protection check error\n");
            ERROR("SECCTRRmD_0:%d 0x%x value=0x%x expected value=0x%x\n"
                , loop
                , read_addr
                , read_reg_val
                , g_rtvram0_protection_table[loop].setting_value.read_val);
            panic;
        }
        if (write_reg_val != g_rtvram0_protection_table[loop].setting_value.write_val)
        {
            ERROR("RAM protection check error\n");
            ERROR("SECCTRWmD_0:%d 0x%x value=0x%x expected value=0x%x\n"
                , loop
                , write_addr
                , write_reg_val
                , g_rtvram0_protection_table[loop].setting_value.write_val);
            panic;
        }
    }

    /* Check RAM protection for RT-VRAM1 */
    /* Check SECDIV[n]D_1 register */
    for (loop = 0; loop < RAM_PROTECTION_MAX - 1U; loop++)
    {
        area_addr    = get_rtvram1_secdivd_addr(loop);
        area_reg_val = mem_read32((uintptr_t)area_addr);
        expect_val   = g_rtvram1_protection_table[loop + 1U].addr - RTVRAM_SECDIVD_SUBVALUE;
        expect_val   = ((expect_val & RTVRAM_ADDR_MASK) >> 12U);

        if (area_reg_val != expect_val)
        {
            ERROR("RAM protection check error\n");
            ERROR("SECDIVnD_1:%d 0x%x value=0x%x expected value=0x%x\n"
                , loop
                , area_addr
                , area_reg_val
                , expect_val);
            panic;
        }
    }

    /* Check SECCTRR[m]D_1 / SECCTRW[m]D_1 register */
    for (loop = 0; loop < RAM_PROTECTION_MAX; loop++)
    {
        read_addr     = get_rtvram1_secctrrd_addr(loop);
        read_reg_val  = mem_read32((uintptr_t)read_addr);
        write_addr    = get_rtvram1_secctrwd_addr(loop);
        write_reg_val = mem_read32((uintptr_t)write_addr);

        if (read_reg_val != g_rtvram1_protection_table[loop].setting_value.read_val)
        {
            ERROR("RAM protection check error\n");
            ERROR("SECCTRRmD_1:%d 0x%x value=0x%x expected value=0x%x\n"
                , loop
                , read_addr
                , read_reg_val
                , g_rtvram1_protection_table[loop].setting_value.read_val);
            panic;
        }
        if (write_reg_val != g_rtvram1_protection_table[loop].setting_value.write_val)
        {
            ERROR("RAM protection check error\n");
            ERROR("SECCTRWmD_1:%d 0x%x value=0x%x expected value=0x%x\n"
                , loop
                , write_addr
                , write_reg_val
                , g_rtvram1_protection_table[loop].setting_value.write_val);
            panic;
        }
    }

    /* Check RAM protection for System RAM */
    /* Check SPTDIVCR[n] register */
    for (loop = 0; loop < RAM_PROTECTION_MAX - 1U; loop++)
    {
        area_addr    = get_sptdivcr_addr(loop);
        area_reg_val = mem_read32((uintptr_t)area_addr);

        if (area_reg_val != (g_system_ram_protection_table[loop + 1U].addr >> SHIFT_FOR_SPTDIVCR))
        {
            ERROR("RAM protection check error\n");
            ERROR("SPTDIVCR:%d 0x%x value=0x%x expected value=0x%x\n"
                , loop
                , area_addr
                , area_reg_val
                , (g_system_ram_protection_table[loop + 1U].addr >> SHIFT_FOR_SPTDIVCR));
            panic;
        }
    }

    /* Check SPTRGNCR[n] / SPTSECCR[n] register */
    for (loop = 0; loop < RAM_PROTECTION_MAX; loop++)
    {
        rw_addr     = get_sptrgncr_addr(loop);
        rw_reg_val  = mem_read32((uintptr_t)rw_addr);
        sec_addr    = get_sptseccr_addr(loop);
        sec_reg_val = mem_read32((uintptr_t)sec_addr);

        if (rw_reg_val != g_system_ram_protection_table[loop].setting_value.rw_val)
        {
            ERROR("RAM protection check error\n");
            ERROR("SPTRGNCR:%d 0x%x value=0x%x expected value=0x%x\n"
                , loop
                , rw_addr
                , rw_reg_val
                , g_system_ram_protection_table[loop].setting_value.rw_val);
            panic;
        }
        if (sec_reg_val != g_system_ram_protection_table[loop].setting_value.sec_val)
        {
            ERROR("RAM protection check error\n");
            ERROR("SPTSECCR:%d 0x%x value=0x%x expected value=0x%x\n"
                , loop
                , sec_addr
                , sec_reg_val
                , g_system_ram_protection_table[loop].setting_value.sec_val);
            panic;
        }
    }

    /* Check RAM protection for SDRAM */
    /* Check DPTDIVCR[n] register */
    for (loop = 0; loop < DRAM_PROTECTION_MAX - 1U; loop++)
    {
        area_addr    = get_dptdivcr_addr(loop);
        area_reg_val = mem_read32((uintptr_t)area_addr);

        if (area_reg_val != (g_dram_protection_table[loop + 1U].addr >> SHIFT_FOR_DPTDIVCR))
        {
            ERROR("RAM protection check error\n");
            ERROR("DPTDIVCR:%d 0x%x value=0x%x expected value=0x%x\n"
                , loop
                , area_addr
                , area_reg_val
                , (g_dram_protection_table[loop + 1U].addr >> SHIFT_FOR_DPTDIVCR));
            panic;
        }
    }

    /* Check DPTRGNCR[n] / DPTSECCR[n] register */
    for (loop = 0; loop < DRAM_PROTECTION_MAX; loop++)
    {
        rw_addr     = get_dptrgncr_addr(loop);
        rw_reg_val  = mem_read32((uintptr_t)rw_addr);
        sec_addr    = get_dptseccr_addr(loop);
        sec_reg_val = mem_read32((uintptr_t)sec_addr);

        if (rw_reg_val != g_dram_protection_table[loop].setting_value.rw_val)
        {
            ERROR("RAM protection check error\n");
            ERROR("DPTRGNCR:%d 0x%x value=0x%x expected value=0x%x\n"
                , loop
                , rw_addr
                , rw_reg_val
                , g_dram_protection_table[loop].setting_value.rw_val);
            panic;
        }
        if (sec_reg_val != g_dram_protection_table[loop].setting_value.sec_val)
        {
            ERROR("RAM protection check error\n");
            ERROR("DPTSECCR:%d 0x%x value=0x%x expected value=0x%x\n"
                , loop
                , sec_addr
                , sec_reg_val
                , g_dram_protection_table[loop].setting_value.sec_val);
            panic;
        }
    }

}
/* End of function ram_protection_check(void) */


