/*******************************************************************************
 * 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   : LifeC Access Protection function
 ******************************************************************************/
 /******************************************************************************
 * @file          acc_prot_lifec.c
 * - Version      : 0.01
 * @brief         Access protection setting of LifeC.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 03.07.2020 0.01     First Release
 *****************************************************************************/

#include <stdint.h>     /* for uint32_t */
#include <mem_io.h>
#include <lifec_register.h>
#include <acc_prot_lifec.h>
#include <log.h>

#define REG_BITS_MASK   (0x000000FFU)


void acc_prot_lifec(void)
{
    uint32_t loop;
    const LIFEC_SETTING_TABLE lifec_reg_tbl[] = {
        {   LIFEC_SEC_GRP0CR2       ,   0x00000000U },
        {   LIFEC_SEC_GRP1CR2       ,   0x00000000U },
        {   LIFEC_SAFE_GRP0CR2      ,   0x00000000U },
        {   LIFEC_SAFE_GRP1CR2      ,   0x00000000U },

        {   LIFEC_SEC_GRP0CR0       ,   0x00000000U },
        {   LIFEC_SEC_GRP1CR0       ,   0x00000000U },
        {   LIFEC_SAFE_GRP0CR0      ,   0x00000000U },
        {   LIFEC_SAFE_GRP1CR0      ,   0x00000000U },

        {   LIFEC_SEC_GRP0CR1       ,   0x00000000U },
        {   LIFEC_SEC_GRP1CR1       ,   0x00000000U },
        {   LIFEC_SAFE_GRP0CR1      ,   0x00000000U },
        {   LIFEC_SAFE_GRP1CR1      ,   0x00000000U },

        {   LIFEC_SEC_GRP0CR3       ,   0x00000000U },
        {   LIFEC_SEC_GRP1CR3       ,   0x00000000U },
        {   LIFEC_SAFE_GRP0CR3      ,   0x00000000U },
        {   LIFEC_SAFE_GRP1CR3      ,   0x00000000U },

        {   LIFEC_SEC_SEL0          ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND0     ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND0     ,   0x00000000U },
        {   LIFEC_SEC_READONLY0     ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND0    ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND0    ,   0x00000000U },
        {   LIFEC_SAFE_READONLY0    ,   0x00000000U },

        {   LIFEC_SEC_SEL1          ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND1     ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND1     ,   0x00000000U },
        {   LIFEC_SEC_READONLY1     ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND1    ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND1    ,   0x00000000U },
        {   LIFEC_SAFE_READONLY1    ,   0x00000000U },

        {   LIFEC_SEC_SEL2          ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND2     ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND2     ,   0x00000000U },
        {   LIFEC_SEC_READONLY2     ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND2    ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND2    ,   0x00000000U },
        {   LIFEC_SAFE_READONLY2    ,   0x00000000U },

        {   LIFEC_SEC_SEL3          ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND3     ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND3     ,   0x00000000U },
        {   LIFEC_SEC_READONLY3     ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND3    ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND3    ,   0x00000000U },
        {   LIFEC_SAFE_READONLY3    ,   0x00000000U },

        {   LIFEC_SEC_SEL4          ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND4     ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND4     ,   0x00000000U },
        {   LIFEC_SEC_READONLY4     ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND4    ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND4    ,   0x00000000U },
        {   LIFEC_SAFE_READONLY4    ,   0x00000000U },

        {   LIFEC_SEC_SEL5          ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND5     ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND5     ,   0x00000000U },
        {   LIFEC_SEC_READONLY5     ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND5    ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND5    ,   0x00000000U },
        {   LIFEC_SAFE_READONLY5    ,   0x00000000U },

        {   LIFEC_SEC_SEL6          ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND6     ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND6     ,   0x00000000U },
        {   LIFEC_SEC_READONLY6     ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND6    ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND6    ,   0x00000000U },
        {   LIFEC_SAFE_READONLY6    ,   0x00000000U },

        {   LIFEC_SEC_SEL7          ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND7     ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND7     ,   0x00000000U },
        {   LIFEC_SEC_READONLY7     ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND7    ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND7    ,   0x00000000U },
        {   LIFEC_SAFE_READONLY7    ,   0x00000000U },

        {   LIFEC_SEC_SEL8          ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND8     ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND8     ,   0x00000000U },
        {   LIFEC_SEC_READONLY8     ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND8    ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND8    ,   0x00000000U },
        {   LIFEC_SAFE_READONLY8    ,   0x00000000U },

        {   LIFEC_SEC_SEL9          ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND9     ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND9     ,   0x00000000U },
        {   LIFEC_SEC_READONLY9     ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND9    ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND9    ,   0x00000000U },
        {   LIFEC_SAFE_READONLY9    ,   0x00000000U },

        {   LIFEC_SEC_SEL10         ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND10    ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND10    ,   0x00000000U },
        {   LIFEC_SEC_READONLY10    ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND10   ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND10   ,   0x00000000U },
        {   LIFEC_SAFE_READONLY10   ,   0x00000000U },

        {   LIFEC_SEC_SEL11         ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND11    ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND11    ,   0x00000000U },
        {   LIFEC_SEC_READONLY11    ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND11   ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND11   ,   0x00000000U },
        {   LIFEC_SAFE_READONLY11   ,   0x00000000U },

        {   LIFEC_SEC_SEL12         ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND12    ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND12    ,   0x00000000U },
        {   LIFEC_SEC_READONLY12    ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND12   ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND12   ,   0x00000000U },
        {   LIFEC_SAFE_READONLY12   ,   0x00000000U },

        {   LIFEC_SEC_SEL13         ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND13    ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND13    ,   0x00000000U },
        {   LIFEC_SEC_READONLY13    ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND13   ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND13   ,   0x00000000U },
        {   LIFEC_SAFE_READONLY13   ,   0x00000000U },

        {   LIFEC_SEC_SEL14         ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND14    ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND14    ,   0x00000000U },
        {   LIFEC_SEC_READONLY14    ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND14   ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND14   ,   0x00000000U },
        {   LIFEC_SAFE_READONLY14   ,   0x00000000U },

        {   LIFEC_SEC_SEL15         ,   0xFFFFFFFFU },
        {   LIFEC_SEC_GRP0COND15    ,   0x00000000U },
        {   LIFEC_SEC_GRP1COND15    ,   0x00000000U },
        {   LIFEC_SEC_READONLY15    ,   0x00000000U },
        {   LIFEC_SAFE_GRP0COND15   ,   0x00000000U },
        {   LIFEC_SAFE_GRP1COND15   ,   0x00000000U },
        {   LIFEC_SAFE_READONLY15   ,   0x00000000U },
    };

    for (loop = 0U;
        loop < (sizeof(lifec_reg_tbl) / sizeof(lifec_reg_tbl[0]));
        loop++)
    {
        mem_write32(lifec_reg_tbl[loop].address, lifec_reg_tbl[loop].value);
    }

    (void)mem_read32(LIFEC_SEC_SRC);    /* dummy read */
}
/* End of function acc_prot_lifec(void) */

void lifec_set_master_grp(uint32_t target, uint32_t sec_grp, uint32_t safe_grp)
{
    uint32_t reg_off;
    uint32_t reg_bits;

    const uint32_t sec_master_reg[][2] =
    {
        [0] = {LIFEC_SEC_GRP0CR0, LIFEC_SEC_GRP1CR0},
        [1] = {LIFEC_SEC_GRP0CR1, LIFEC_SEC_GRP1CR1},
        [2] = {LIFEC_SEC_GRP0CR2, LIFEC_SEC_GRP1CR2},
        [3] = {LIFEC_SEC_GRP0CR3, LIFEC_SEC_GRP1CR3},
    };

    const uint32_t safe_master_reg[][2] =
    {
        [0] = {LIFEC_SAFE_GRP0CR0, LIFEC_SAFE_GRP1CR0},
        [1] = {LIFEC_SAFE_GRP0CR1, LIFEC_SAFE_GRP1CR1},
        [2] = {LIFEC_SAFE_GRP0CR2, LIFEC_SAFE_GRP1CR2},
        [3] = {LIFEC_SAFE_GRP0CR3, LIFEC_SAFE_GRP1CR3},
    };

    /* Calculate the setting target */
    reg_off = target >> 16U;
    reg_bits = target & REG_BITS_MASK;

    /* Set security access group */
    mem_bitclrset32(sec_master_reg[reg_off][0], ((uint32_t)1U << reg_bits),
            ((uint32_t)(sec_grp & 0x1U) << reg_bits));
    mem_bitclrset32(sec_master_reg[reg_off][1], ((uint32_t)1U << reg_bits),
            ((uint32_t)(sec_grp & 0x2U) << (reg_bits - 1U)));

    /* Set safety access group */
    mem_bitclrset32(safe_master_reg[reg_off][0], ((uint32_t)1U << reg_bits),
            ((uint32_t)(safe_grp & 0x1U) << reg_bits));
    mem_bitclrset32(safe_master_reg[reg_off][1], ((uint32_t)1U << reg_bits),
            ((uint32_t)(safe_grp & 0x2U) << (reg_bits - 1U)));
}
/* End of function lifec_set_master_grp(uint32_t target, uint32_t sec_grp, uint32_t safe_grp) */
