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

/*******************************************************************************
 * DESCRIPTION   : memory protection function
 ******************************************************************************/
 /******************************************************************************
 * @file          ram_protection.c
 * - Version      : 0.03
 * @brief         Access protection setting of memory.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 19.12.2022 0.01     First Release
 *         : 11.01.2024 0.02     Added icu_remove_write_access function.
 *         : 19.01.2024 0.03     Updated debug log.
 *         : 31.01.2024 0.04     Fixed the error in SECDIVn register
 *                               setting value for ram_protect_init_4_rtsram()
 *                               and ram_protect_init_4_rtvram.
 *****************************************************************************/

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

/* 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 */

#if (ACC_PROT_ENABLE == PROTECTION_ENABLE)
static void ram_protect_init_4_rtsram(void);
static void ram_protect_init_4_rtvram(const RTRAM_PROTECTION_STRUCTUR *cnf_tbl);
static void ram_protect_init_4_sysram(void);
static void ram_protect_init_4_dram(void);
#endif /* #if (ACC_PROT_ENABLE == PROTECTION_ENABLE) */

void ram_protection(void)
{
#if (ACC_PROT_ENABLE == PROTECTION_ENABLE)
    /* RT-SRAM */
    NOTICE("RT-SRAM Protection setting...\n");
    ram_protect_init_4_rtsram();
    NOTICE("finish!\n");

    /* RT-VRAM */
    NOTICE("RT-VRAM Protection setting...\n");
    ram_protect_init_4_rtvram(g_rtvram1_protection_table_1);
    NOTICE("finish!\n");

    /* System RAM */
    NOTICE("System RAM Protection setting...\n");
    ram_protect_init_4_sysram();
    NOTICE("finish!\n");

    /* DRAM */
    NOTICE("DRAM Protection setting...\n");
    ram_protect_init_4_dram();
    NOTICE("finish!\n");
#endif /* #if (ACC_PROT_ENABLE == PROTECTION_ENABLE) */
}
/* End of function ram_protection(void) */

#if (RCAR_LSI == RCAR_S4)
void ram_protection_final(void)
{
#if (ACC_PROT_ENABLE == PROTECTION_ENABLE)
    NOTICE("RT-VRAM Protection setting(finally)...\n");
    ram_protect_init_4_rtvram(g_rtvram1_protection_table_2);
    NOTICE("finish!\n");
#endif /* #if (ACC_PROT_ENABLE == PROTECTION_ENABLE) */
}
/* End of function ram_protection_final(void) */
#endif /* #if (RCAR_LSI == RCAR_S4) */

#if (ACC_PROT_ENABLE == PROTECTION_ENABLE)
static void ram_protect_init_4_rtsram(void)
{
    uint32_t loop;
    uint32_t val;
    uint32_t set_val;
    uint32_t addr;

    /* set division point for RT-SRAM */
    for (loop = 0U; loop < (RAM_PROTECTION_MAX - 1U); ++loop)
    {
        addr = get_rtsram_secdivd_addr(loop);
        val = mem_read32(addr);
        val &= ~(RTSRAM_SECDIVD_DIVADDR_MASK);
        set_val = g_rtsram_protection_table[loop + 1U].addr - RTSRAM_SECDIVD_SUBVALUE;
        val |= ((set_val & RTSRAM_ADDR_OFFSET_MASK) >> 12U);
        mem_write32(addr, val);
        INFO("SECDIVD[%d](0x%08x)\t = 0x%08x\n", loop, addr, mem_read32(addr));
    }

    /* Set division area protection register for RT-SRAM */
    for (loop = 0U; loop < RAM_PROTECTION_MAX; ++loop)
    {
        /* Read Access Configuration */
        addr = get_rtsram_secctrrd_addr(loop);
        val = mem_read32(addr);
        val &= ~(RTSRAM_SECCTRRD_SECGRP_MASK | RTSRAM_SECCTRRD_SAFGRP_MASK);
        val |= g_rtsram_protection_table[loop].setting_value.read_val;
        mem_write32(addr, val);
        INFO("SECCTRRD[%d](0x%08x)\t = 0x%08x\n", loop, addr, mem_read32(addr));
        /* Write Access Configuration */
        addr = get_rtsram_secctrwd_addr(loop);
        val = mem_read32(addr);
        val &= ~(RTSRAM_SECCTRWD_SECGRP_MASK | RTSRAM_SECCTRWD_SAFGRP_MASK);
        val |= g_rtsram_protection_table[loop].setting_value.write_val;
        mem_write32(addr, val);
        INFO("SECCTRWD[%d](0x%08x)\t = 0x%08x\n", loop, addr, mem_read32(addr));
    }
}
/* End of function ram_protect_init_4_rtsram(void) */

static void ram_protect_init_4_rtvram(const RTRAM_PROTECTION_STRUCTUR *cnf_tbl)
{
    uint32_t loop;
    uint32_t val;
    uint32_t set_val;
    uint32_t addr;

    /* set division point for RT-VRAM1 */
    for (loop = 0U; loop < (RAM_PROTECTION_MAX - 1U); ++loop)
    {
        addr = get_rtvram_secdivd_addr(loop);
        val = mem_read32(addr);
        val &= ~(RTVRAM_SECDIVD_DIVADDR_MASK);
        set_val = cnf_tbl[loop + 1U].addr - RTVRAM_SECDIVD_SUBVALUE;
        val |= ((set_val & RTVRAM_ADDR_MASK) >> 12U);
        mem_write32(addr, val);
        INFO("SECDIVD[%d](0x%08x)\t = 0x%08x\n", loop, addr, mem_read32(addr));
    }

    /* Set division area protection register for RT-VRAM1 */
    for (loop = 0U; loop < RAM_PROTECTION_MAX; ++loop)
    {
        /* Read Access Configuration */
        addr = get_rtvram_secctrrd_addr(loop);
        val = mem_read32(addr);
        val &= ~(RTVRAM_SECCTRRD_SECGRP_MASK | RTVRAM_SECCTRRD_SAFGRP_MASK);
        val |= cnf_tbl[loop].setting_value.read_val;
        mem_write32(addr, val);
        INFO("SECCTRRD[%d](0x%08x)\t = 0x%08x\n", loop, addr, mem_read32(addr));
        /* Write Access Configuration */
        addr = get_rtvram_secctrwd_addr(loop);
        val = mem_read32(addr);
        val &= ~(RTVRAM_SECCTRWD_SECGRP_MASK | RTVRAM_SECCTRWD_SAFGRP_MASK);
        val |= cnf_tbl[loop].setting_value.write_val;
        mem_write32(addr, val);
        INFO("SECCTRWD[%d](0x%08x)\t = 0x%08x\n", loop, addr, mem_read32(addr));
    }
}
/* End of function ram_protect_init_4_rtvram(const RTRAM_PROTECTION_STRUCTUR *cnf_tbl) */


static void ram_protect_init_4_sysram(void)
{
    uint32_t loop;
    uint32_t val;
    uint32_t addr;

    /* set division point for SystemRAM */
    for (loop = 0U; loop < (RAM_PROTECTION_MAX - 1U); ++loop)
    {
        addr = get_sptdivcr_addr(loop);
        val = mem_read32(addr);
        val &= ~(AXMM_SPTDIVCR_DIVADDR_MASK);
        val |= ((g_system_ram_protection_table[loop + 1U].addr & SYSTEM_RAM_ADDR_MASK) >> 12U);
        mem_write32(addr, val);
        INFO("SPTDIVCR[%d](0x%08x)\t = 0x%08x\n", loop, addr, mem_read32(addr));
    }

    /* Set division area protection register for RT-VRAM */
    for (loop = 0U; loop < RAM_PROTECTION_MAX; ++loop)
    {
        /* Read / Write Access Configuration */
        addr = get_sptrgncr_addr(loop);
        val = g_system_ram_protection_table[loop].setting_value.rw_val;
        mem_write32(addr, val);
        INFO("SPTRGNCR[%d](0x%08x)\t = 0x%08x\n", loop, addr, mem_read32(addr));
        /* Secure setting */
        addr = get_sptseccr_addr(loop);
        val = mem_read32(addr);
        val &= ~(AXMM_SPTSECCR_SECGRP_MASK | AXMM_SPTSECCR_SECGWP_MASK);
        val |= g_system_ram_protection_table[loop].setting_value.sec_val;
        mem_write32(addr, val);
        INFO("SPTSECCR[%d](0x%08x)\t = 0x%08x\n", loop, addr, mem_read32(addr));
    }
}
/* End of function ram_protect_init_4_sysram(void) */


static void ram_protect_init_4_dram(void)
{
    uint32_t loop;
    uint32_t val;
    uint32_t addr;

    /* set division point for SDRAM */
    for (loop = 0U; loop < (DRAM_PROTECTION_MAX - 1U); ++loop)
    {
        addr = get_dptdivcr_addr(loop);
        val = mem_read32(addr);
        val &= ~(AXMM_DPTDIVCR_DIVADDR_MASK);
        val |= ((g_dram_protection_table[loop + 1U].addr & SDRAM_ADDR_MASK) >> 16U);
        mem_write32(addr, val);
        INFO("DPTDIVCR[%d](0x%08x)\t = 0x%08x\n", loop, addr, mem_read32(addr));
    }

    /* Set division area protection register for RT-VRAM */
    for (loop = 0U; loop < DRAM_PROTECTION_MAX; ++loop)
    {
        /* Read / Write Access Configuration */
        addr = get_dptrgncr_addr(loop);
        val = g_dram_protection_table[loop].setting_value.rw_val;
        mem_write32(addr, val);
        INFO("DPTRGNCR[%d](0x%08x)\t = 0x%08x\n", loop, addr, mem_read32(addr));
        /* Secure setting */
        addr = get_dptseccr_addr(loop);
        val = mem_read32(addr);
        val &= ~(AXMM_DPTSECCR_SECGRP_MASK | AXMM_DPTSECCR_SECGWP_MASK);
        val |= g_dram_protection_table[loop].setting_value.sec_val;
        mem_write32(addr, val);
        INFO("DPTSECCR[%d](0x%08x)\t = 0x%08x\n", loop, addr, mem_read32(addr));
    }
}
/* End of function ram_protect_init_4_dram(void) */
#endif /* #if (ACC_PROT_ENABLE == PROTECTION_ENABLE) */

void icu_remove_write_access(void)
{
#if (ACC_PROT_ENABLE == PROTECTION_ENABLE)
    uint32_t reg;
    uint32_t addr;

    addr = get_sptrgncr_addr(SYSTEM_RAM_CX_2ND_IPL);
    reg  = mem_read32(addr);
    reg |= REGIONID0_WRITE_PRIVILEGE;   /* Remove write privilege to System RAM Area0 from RGID0(ICUMX). */
    mem_write32(addr, reg);
#endif /* #if (ACC_PROT_ENABLE == PROTECTION_ENABLE) */
}
/* End of function icu_remove_write_access(void) */

