/*******************************************************************************
 * Copyright (c) 2022-2025 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   : ECC setting function
 ******************************************************************************/
/******************************************************************************
 * @file          ecc_enable_v4h.c
 * - Version      : 0.06
 * @brief         Enable setting process of ECC for DRAM.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 09.08.2022 0.01     First Release
 *         : 22.03.2023 0.02     Added AXI Timeout setting
 *         : 04.04.2023 0.03     Removed stdio.h and string.h.
 *         : 24.08.2023 0.04     Removed enable_ecc function.
 *         : 13.06.2024 0.05     Fix register setting for EDC_CFG, and revise
 *         :                     the ecm_lock()/ecm_unlock() process.
 *         : 07.04.2025 0.06     Remove unused functions.
 *****************************************************************************/

#include <stdint.h>
#include <cnf_tbl.h>
#include <remap.h>
#include <wdt.h>

#if (ECM_ENABLE == 1)
#include "ecc_enable_v4h.h"
#include "v4h/lpddr5/boot_init_dram_regdef.h"
#include "ecm_enable_v4h.h"

#define AXI_SICREMAP_NUM    (5U)
#define RGID_BASE1  (0xFE600000U)
#define RGID_BASE2  (0xE7A00000U)
#define RGID_BASE3  (0xEB800000U)
#define RGID_BASE4  (0xFD800000U)
#define RGID_BASE5  (0xFEA00000U)

#define FDT_COUNTER_MASK (0x0000FFFFU)

static void axi_timeout_setting(void);

void edc_axi_enable(void)
{
    uint32_t edc_tmp;

    /* Unlock the write protect of ECM registers */
    ecm_unlock();

    /* (1) Set the corresponding bits of the ECMERRTGTR and ECMERRCTLR registers
     to inform the external device of the error via the ERROROUT# pin. */

    /* Set bit 11 - bit 2 of ECMERRTGTR7 to all 0 and bit 11 - bit 2 of
        ECMERRCTLR7 to 1. (Error of AXI-Bus ECM of each hierarchy) */
    edc_tmp = mem_read32(ECMERRTGTR7);
    edc_tmp &= ~(0x3FFU << 2U);
    ecm_write(ECMERRTGTR7, edc_tmp);

    edc_tmp = mem_read32(ECMERRCTLR7);
    edc_tmp |= (0x3FFU << 2U);
    ecm_write(ECMERRCTLR7, edc_tmp);

    /* Set bit 28 - bit 16 of ECMERRTGTR39 to all 0 and bit 28 - bit 16 of
        ECMERRCTLR39 to 1. (Error of AXI-Bus ECM of each hierarchy) */
    edc_tmp = mem_read32(ECMERRTGTR39);
    edc_tmp &= ~(0x1FFFU << 16U);
    ecm_write(ECMERRTGTR39, edc_tmp);

    edc_tmp = mem_read32(ECMERRCTLR39);
    edc_tmp |= (0x1FFFU << 16U);
    ecm_write(ECMERRCTLR39, edc_tmp);

    /* Set bit 26 of ECMERRTGTR1 to 0 and bit 26 of
        ECMERRCTLR1 to 1. (CCI bus EDC error) */
    edc_tmp = mem_read32(ECMERRTGTR1);
    edc_tmp &= ~(0x1U << 26U);
    ecm_write(ECMERRTGTR1, edc_tmp);

    edc_tmp = mem_read32(ECMERRCTLR1);
    edc_tmp |= (0x1U << 26U);
    ecm_write(ECMERRCTLR1, edc_tmp);

    axi_timeout_setting();

    /* Lock the ECM registers */
    ecm_lock();
}

void edc_vram_enable(void)
{
    uint32_t edc_tmp;

    /* Unlock the write protect of ECM registers */
    ecm_unlock();

    /* (1) Set the corresponding bits of the ECMERRTGTR and ECMERRCTLR registers
     to inform the external device of the error via the ERROROUT# pin. */

    /* Set bit 30 of ECMERRTGTR7 to 0 and bit 30 of ECMERRCTLR7 to 1.
                                                    (RT-VRAM edc 1-bit error) */
    edc_tmp = mem_read32(ECMERRTGTR7);
    edc_tmp &= ~(0x1U << 30U);
    ecm_write(ECMERRTGTR7, edc_tmp);

    edc_tmp = mem_read32(ECMERRCTLR7);
    edc_tmp |= (0x1U << 30U);
    ecm_write(ECMERRCTLR7, edc_tmp);

    /* Set bit 29 of ECMERRTGTR7 to 0 and bit 29 of ECMERRCTLR7 to 1.
                                                (RT-VRAM edc multi-bit error) */
    edc_tmp = mem_read32(ECMERRTGTR7);
    edc_tmp &= ~(0x1U << 29U);
    ecm_write(ECMERRTGTR7, edc_tmp);

    edc_tmp = mem_read32(ECMERRCTLR7);
    edc_tmp |= (0x1U << 29U);
    ecm_write(ECMERRCTLR7, edc_tmp);

    /* Set bit 19 of ECMERRTGTR17 to 0 and bit 19 of ECMERRCTLR17 to 1.
                                                    (RT-VRAM edc 1-bit error) */
    edc_tmp = mem_read32(ECMERRTGTR17);
    edc_tmp &= ~(0x1U << 19U);
    ecm_write(ECMERRTGTR17, edc_tmp);

    edc_tmp = mem_read32(ECMERRCTLR17);
    edc_tmp |= (0x1U << 19U);
    ecm_write(ECMERRCTLR17, edc_tmp);

    /* Set bit 18 of ECMERRTGTR17 to 0 and bit 18 of ECMERRCTLR17 to 1.
                                                (RT-VRAM edc multi-bit error) */
    edc_tmp = mem_read32(ECMERRTGTR17);
    edc_tmp &= ~(0x1U << 18U);
    ecm_write(ECMERRTGTR17, edc_tmp);

    edc_tmp = mem_read32(ECMERRCTLR17);
    edc_tmp |= (0x1U << 18U);
    ecm_write(ECMERRCTLR17, edc_tmp);

    /* Set bit 0 of EDC_CFG to 1. (EDC Error Control) */
    edc_tmp = mem_read32(EDC_CFG);
    edc_tmp |= (0x1U << 0U);
    mem_write32(EDC_CFG, edc_tmp);

    /* Lock the ECM registers */
    ecm_lock();
}

static void axi_timeout_setting(void)
{
    uint32_t reg;
    uint32_t loop;
    REMAP_TABLE axi_remap_tbl[AXI_SICREMAP_NUM] = {
        {RGID_BASE1, 0U},
        {RGID_BASE2, 0U},
        {RGID_BASE3, 0U},
        {RGID_BASE4, 0U},
        {RGID_BASE5, 0U},
    };

    /* Register of AXI Base */
    for (loop = 0U; loop < AXI_SICREMAP_NUM; loop++)
    {
        remap_register(axi_remap_tbl[loop].base_addr, &axi_remap_tbl[loop].rmp_addr);
    }

    /* Set the COUNTER bits of the FDT_* registers for all safety-related modules to minimum value with 1ms or more. */
    for (loop = 0U; loop < FDT_REG_MAX; loop++)
    {
        reg = mem_read32(g_fdt_tbl[loop].reg_addr);
        reg &= ~(FDT_COUNTER_MASK);
        reg |= g_fdt_tbl[loop].value;
        mem_write32(g_fdt_tbl[loop].reg_addr, reg);

        INFO("FDT[%d] =\t0x%08x \tsetting value = 0x%08x\n", loop, mem_read32(g_fdt_tbl[loop].reg_addr), g_fdt_tbl[loop].value);
    }

    for(loop = 0U; loop < INTEN_REG_MAX; loop++)
    {
        /* Set access protection setting value of Region ID (AXI bus of Region ID register) */
        mem_write32(g_inten_tbl[loop].reg_addr, g_inten_tbl[loop].value);

        INFO("INTEN[%d] =\t0x%08x \tsetting value = 0x%08x\n", loop, mem_read32(g_inten_tbl[loop].reg_addr), g_inten_tbl[loop].value);
    }

    /* Unregister of AXI Base */
    for (loop = 0U; loop < AXI_SICREMAP_NUM; loop++)
    {
        remap_unregister(axi_remap_tbl[loop].rmp_addr);
    }

    wdt_restart();
}
#endif /* ECM_ENABLE == 1 */
