/*******************************************************************************
 * Copyright (c) 2018-2021 Renesas Electronics Corporation. All rights reserved.
 *
 *     RENESAS ELECTRONICS CONFIDENTIAL AND PROPRIETARY
 *
 * This software is provided as reference/sample code under the license
 * agreement between Renesas Electronics Corporation and licensee (the
 * "License Agreement") and shall be treated as specified in the License
 * Agreement.
 * These instructions, statements, and software are the confidential
 * information of Renesas Electronics Corporation. They must be used and
 * modified solely for the purpose for which it was furnished by Renesas
 * Electronics Corporation. All or part of these instructions, statements and
 * software must not be reproduced nor disclosed to any third party in any
 * form, unless permitted by the License Agreement.
 *
 * THIS SOFTWARE IS PROVIDED BY RENESAS ELEOCTRONICS CORPORATION "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
 * SATISFACTORY QUALITY, ACCURACY, TITLE AND NON-INFRINGEMENT ARE DISCLAIMED.
 * IN NO EVENT SHALL RENESAS ELECTRONICS CORPORATION BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 ******************************************************************************/

/*******************************************************************************
 * DESCRIPTION   : memory protection function
 ******************************************************************************/
 /******************************************************************************
 * @file          acc_prot_memory.c
 * - Version      : 0.01
 * @brief         Access protection setting of memory.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 03.07.2020 0.01     First Release
 *****************************************************************************/

#include <stdint.h>
#include <acc_prot_memory.h>
#include <axi_register.h>
#include <rtsram_register.h>
#include <mem_io.h>
#include <log.h>
#include <remap.h>

#define RT_SRAM_ADDR_OFFSET_MASK    (0x000FF000U)
#define SYSTEM_RAM_ADDR_MASK        (0xFFFFF000U)
#define SDRAM_ADDR_MASK             (0x0000002FFFFF0000UL)

#define READ_SET_VAL_MASK           ((uint8_t)(0xF0U))
#define WRITE_SET_VAL_MASK          ((uint8_t)(0x0FU))

void acc_prot_rt_sram(void)
{
    uint32_t loop;
    uint32_t mapped_addr;
    uint32_t reg;

    RT_SRAM_PROT rt_sram_prot_data[16] = {
        /*    |                |    register   |                access              | */
        /*    |     address    |   sec  safety |   security             safety      | */
        [0] = {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [1] = {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [2] = {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [3] = {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [4] = {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [5] = {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [6] = {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [7] = {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [8] = {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [9] = {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [10]= {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [11]= {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [12]= {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [13]= {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [14]= {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [15]= {RT_SRAM_ADDR_END,{W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
    };

    mapped_addr = remap_get_remap_addr(SECDIVnD_BASE);

    INFO("RT-SRAM Protection setting...\n");

    /* Set division address register. */
    for (loop = 0U; loop < 15U; ++loop)
    {
        reg = ((uint32_t)(rt_sram_prot_data[loop].prot.reg_sec) << 24U);
        reg |= ((uint32_t)(rt_sram_prot_data[loop].prot.reg_saf) << 28U);
        reg |= ((uint32_t)(rt_sram_prot_data[loop + 1U].addr_off
            & RT_SRAM_ADDR_END) >> 12U);
        mem_write32(SECDIVnD(mapped_addr, loop), reg);
    }

    /* Set division area protection register. */
    for (loop = 0U; loop < 16U; ++loop)
    {
        reg = ((uint32_t)(rt_sram_prot_data[loop].prot.reg_sec) << 24U);
        reg |= ((uint32_t)(rt_sram_prot_data[loop].prot.reg_saf) << 28U);
        reg |= ((uint32_t)(rt_sram_prot_data[loop].prot.acc_sec
            & (uint32_t)(READ_SET_VAL_MASK)) << 4U);    /* Secure read */
        reg |= ((uint32_t)(rt_sram_prot_data[loop].prot.acc_sec
            & (uint32_t)(WRITE_SET_VAL_MASK)));     /* Secure write */
        reg |= ((uint32_t)(rt_sram_prot_data[loop].prot.acc_saf
            & (uint32_t)(READ_SET_VAL_MASK)) << 8U);    /* Safety read */
        reg |= ((uint32_t)(rt_sram_prot_data[loop].prot.acc_saf
            & (uint32_t)(WRITE_SET_VAL_MASK)) << 4U);   /* Safety write */
        mem_write32(SECCTRnD(mapped_addr, loop), reg);
    }
}
/* End of function acc_prot_rt_sram(void) */


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

    SYSTEM_RAM_PROT system_ram_prot_data[16] = {
        /*    |                   |     register   |                access              | */
        /*    |       address     |   sec   safety |   security             safety      | */
        [0] = {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [1] = {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [2] = {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [3] = {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [4] = {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [5] = {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [6] = {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [7] = {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [8] = {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [9] = {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [10]= {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [11]= {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [12]= {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [13]= {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [14]= {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [15]= {SYSTEM_RAM_ADDR_END, {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
    };

    INFO("System RAM Protection setting...\n");

    /* Set division address register. */
    for (loop = 0U; loop < 15U; ++loop)
    {
        reg = ((uint32_t)(system_ram_prot_data[loop].prot.reg_sec) << 24U);
        reg |= ((uint32_t)(system_ram_prot_data[loop].prot.reg_saf) << 28U);
        reg |= ((uint32_t)(system_ram_prot_data[loop + 1U].addr
            & SYSTEM_RAM_ADDR_END) >> 12U);
        mem_write32(SPTDIVCR(loop), reg);
    }

    /* Set division area protection register. */
    for (loop = 0U; loop < 16U; ++loop)
    {
        reg = ((uint32_t)(system_ram_prot_data[loop].prot.reg_sec) << 24U);
        reg |= ((uint32_t)(system_ram_prot_data[loop].prot.reg_saf) << 28U);
        reg |= ((uint32_t)(system_ram_prot_data[loop].prot.acc_sec
            & (uint32_t)(READ_SET_VAL_MASK)) << 4U);    /* Secure read */
        reg |= ((uint32_t)(system_ram_prot_data[loop].prot.acc_sec
            & (uint32_t)(WRITE_SET_VAL_MASK)));     /* Secure write */
        reg |= ((uint32_t)(system_ram_prot_data[loop].prot.acc_saf
            & (uint32_t)(READ_SET_VAL_MASK)) << 8U);    /* Safety read */
        reg |= ((uint32_t)(system_ram_prot_data[loop].prot.acc_saf
            & (uint32_t)(WRITE_SET_VAL_MASK)) << 4U);   /* Safety write */
        mem_write32(SPTCR(loop), reg);
    }
}
/* End of function acc_prot_system_ram(void) */


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

    DRAM_PROT dram_prot_data[16] = {
        /*    |             |       register   |                access              | */
        /*    |   address   |      sec  safety |   security             safety      | */
        [0] = {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [1] = {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [2] = {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [3] = {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [4] = {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [5] = {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [6] = {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [7] = {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [8] = {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [9] = {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [10]= {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [11]= {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [12]= {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [13]= {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [14]= {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
        [15]= {DRAM_ADDR_END,   {W_YYYY,W_YYYY, R_YYYY | W_YYYY,    R_YYYY | W_YYYY}},
    };

    INFO("DRAM Protection setting...\n");

    /* Set division address register. */
    for (loop = 0U; loop < 15U; ++loop)
    {
        reg = ((uint32_t)(dram_prot_data[loop].prot.reg_sec) << 24U);
        reg |= ((uint32_t)(dram_prot_data[loop].prot.reg_saf) << 28U);
        reg |= (uint32_t)((dram_prot_data[loop + 1U].addr & DRAM_ADDR_END) >> 16U);
        mem_write32(DPTDIVCR(loop), reg);
    }

    /* Set division area protection register. */
    for (loop = 0U; loop < 16U; ++loop)
    {
        reg = ((uint32_t)(dram_prot_data[loop].prot.reg_sec) << 24U);
        reg |= ((uint32_t)(dram_prot_data[loop].prot.reg_saf) << 28U);
        reg |= ((uint32_t)(dram_prot_data[loop].prot.acc_sec
            & (uint32_t)(READ_SET_VAL_MASK)) << 4U);    /* Secure read */
        reg |= ((uint32_t)(dram_prot_data[loop].prot.acc_sec
            & (uint32_t)(WRITE_SET_VAL_MASK)));     /* Secure write */
        reg |= ((uint32_t)(dram_prot_data[loop].prot.acc_saf
            & (uint32_t)(READ_SET_VAL_MASK)) << 8U);    /* Safety read */
        reg |= ((uint32_t)(dram_prot_data[loop].prot.acc_saf
            & (uint32_t)(WRITE_SET_VAL_MASK)) << 4U);   /* Safety write */
        mem_write32(DPTCR(loop), reg);
    }
}
/* End of function acc_prot_dram(void) */
