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

/*******************************************************************************
 * DESCRIPTION   : Loader main function for V4M
 ******************************************************************************/
/******************************************************************************
 * @file          loader_main_v4m.c
 * - Version      : 0.04
 * @brief         1. IP initialization.
 *                2. DMA transfer the binary image from Flash to RAM.
 *                3. Authentication of the transferred image.
 *                4. Boot CR and CA core.
 *                5. Release of used resources.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 21.08.2023 0.01     First Release
 *         : 14.11.2023 0.02     Fixed file header path of ECC.
 *         : 16.11.2023 0.03     Added avs_low_power_mode_setting function
 *                               calling.
 *         : 07.04.2025 0.04     Added ecm_init_setting function calling.
 *****************************************************************************/

#include <stdint.h>
#include <stdbool.h>
#include <loader_main.h>
#include <loader_main_common.h>
#include <cpu_on.h>
#include <image_load.h>
#include <ip_control.h>
#include <qos.h>
#include <rcar_def.h>
#include <remap.h>
#include <remap_register.h>
#include <rom_api.h>
#include <mem_io.h>
#include <log.h>
#include <wdt.h>
#include <micro_wait.h>
#include <rtvram.h>
#include <ram_def.h>
#include <access_protection.h>
#include <avs.h>
#include "rcar_def.h"
#if (ECM_ERROR_ENABLE == 1)
#include "../ip/ddr/v4m/lpddr5/ecm_enable_v4m.h"
#endif /* ECM_ERROR_ENABLE == 1 */

/* Provided code */
#include "../ip/ddr/boot_init_dram.h"
#include "../ip/ddr/v4m/lpddr5/ecc_enable_v4m.h"
#include <cpg_register.h>

#define ICISTP_BASE    (BASE_ICISTP_ADDR)
#define ICISTPSTPER000 (ICISTP_BASE + 0x30300U)

#define EDC_BASE       (BASE_ECM_ADDR)
#define EDCSTRT20      (EDC_BASE + 0x80C0U)
#define TIDSTRT20      (EDC_BASE + 0x81C0U)

/* SYSC register */
#define SYSC_BASE       (BASE_SYSC_ADDR)
#define SYSC_SYSCSR     (SYSC_BASE + 0x0000U)   /* SYSC Status Register */
#define SYSC_SYSCISCR1  (SYSC_BASE + 0x0814U)   /* Interrupt Status/Clear Register1 */
#define SYSC_SYSCIER1   (SYSC_BASE + 0x0824U)   /* Interrupt Enable Register1 */
#define SYSC_SYSCIMR1   (SYSC_BASE + 0x0834U)   /* Interrupt MASK Register1 */

/* Power Domain Register */
#define SYSC_PDR41      (0x0A40U)   /* A1CNN0 */
#define SYSC_PDR42      (0x0A80U)   /* A2CN0 */
#define SYSC_PDR43      (0x0AC0U)   /* A3IR */
#define SYSC_PDRSR      (SYSC_BASE + 0x1000U)   /* Base address of Power Domain Status Register */
#define SYSC_PDRSR41    (SYSC_PDRSR + (SYSC_PDR41))
#define SYSC_PDRSR42    (SYSC_PDRSR + (SYSC_PDR42))
#define SYSC_PDRSR43    (SYSC_PDRSR + (SYSC_PDR43))
#define SYSC_PDRONCR    (SYSC_BASE + 0x1004U)   /* Base address of Power Domain Power-ON Control Register */
#define SYSC_PDRONCR41  (SYSC_PDRONCR + (SYSC_PDR41))
#define SYSC_PDRONCR42  (SYSC_PDRONCR + (SYSC_PDR42))
#define SYSC_PDRONCR43  (SYSC_PDRONCR + (SYSC_PDR43))

#define PDR_MAX         (3U)                /* Number of PDR's to be set */
#define SYSC_BIT_PDR41  (0x00000200U)       /* SYSC register target PDR41 bit */
#define SYSC_BIT_PDR42  (0x00000400U)       /* SYSC register target PDR42 bit */
#define SYSC_BIT_PDR43  (0x00000800U)       /* SYSC register target PDR43 bit */

#define SYSCSR_BUSY_MASK    (0x00000003U)   /* SYSC Power On or Power Off seaquence status */
#define SYSCSR_NOT_BUSY     (0x00000003U)   /* Not processing */

#define SYSC_PDRSR_PWR_MASK (0x00001111U)   /* PDR Power On / Off Status MASK */
#define SYSC_PDRSR_PWROFF   (0x00000001U)   /* PDR Power OFF Status */
#define SYSC_PDRONCR_PWRON  (0x00000001U)   /* PDR Power On request */
#define SYSC_PDR_PWR_PROC   (0x00000000U)   /* PDR Power On or Poweer off processing */

#define RGID_SET_RGID_FIN_FLG_ADDR  (0xFD95EFFCU)  /* 0xE635EFFC:Remap 12 */
#define RGID_SET_RGID_FIN_FLG_VAL   (0x64U)


#if (ADD_HOTPLUG_MAGIC == ADD_MAGIC_NUMBER)
#define HOTPLUG_MAGIC_NUM       (0x853F912EU)
#else
#define HOTPLUG_MAGIC_NUM       (0x00000000U)
#endif
__attribute__ ((section (".cr_hot_plug_magic"))) const uint32_t magic_num[4] = {0x00000000U, 0x00000000U,
                                                                                0x00000000U, HOTPLUG_MAGIC_NUM};

uint32_t loader_main(void)
{
    uint32_t boot_ca_id;
    uint32_t auth_count = 0U;
    uint32_t boot_cpu;
    uint32_t tmp;
    __attribute__((__unused__)) uint32_t loop = 0U;
    __attribute__((__unused__)) uint32_t ca_load_num; /* number of load for Optional CA program */
    LOAD_INFO li[MAX_PLACED] = {0U};


/*****************************************************************************
 *  Initialize Hardware
 *****************************************************************************/
    /* IP initialize */
    ip_init();

#if (ECM_ERROR_ENABLE == 1)
    ecm_init_setting();
#endif /* ECM_ERROR_ENABLE == 1 */

#if (ECM_ENABLE == 1)
/*****************************************************************************
 *  ECC and EDC Initialize
 *****************************************************************************/
    edc_axi_enable();
    edc_vram_enable();
#endif

/*****************************************************************************
 *  Work Around for APMU
 *****************************************************************************/
    wa_setting_apmu();

/*****************************************************************************
 *  Output boot message
 *****************************************************************************/
    print_boot_msg();

/*****************************************************************************
 *  Low Power Mode setting for V4M
 *****************************************************************************/
    avs_low_power_mode_setting();

/*****************************************************************************
 *  WA for V4M
 *****************************************************************************/
    /* WA OTLINT-5556 increased latency: APMU FRSTCTRL bit[29] disable */
    tmp = mem_read32(BASE_APMU_ADDR + 0x68U);
    tmp = tmp & ~(1U << 29U);
    mem_write32((BASE_APMU_ADDR + 0x68U), tmp);

/*****************************************************************************
 *  Setting Access protection
 *****************************************************************************/
    /* Region ID access protection */
    rgid_protection();
    ram_protection();

    /* Change the Region ID (Master) of the Module used for data transfer to a temporary setting.  */
    set_master_rgid_4_tfr_mod();

/*****************************************************************************
 *  Load Certficate from QSPI
 *****************************************************************************/
    /* Load content certificate */
    ca_load_num = load_content_cert();

    /* Get load information */
    load_init(li);

    /* verify the each content certs before Image load */
    preload_verify_cntcert(li);

/*****************************************************************************
 *  Authenticate Software minimum version table
 *****************************************************************************/
    auth_min_ver_tbl(li);

/*****************************************************************************
 *  Load Cx IPL from Flash
 *****************************************************************************/
    /* Start loading Cx IPL image from Flash into SDRAM */
    load_image(&li[CA_PROGRAM_ID]);

    /* The CA image to boot is CA IPL. */
    boot_ca_id = CA_PROGRAM_ID;

    /* boot CPU is CR */
    boot_cpu = RCAR_PWR_TARGET_CR;

    /* finish loading Cx IPL */
    load_end();
/*****************************************************************************
 *  Load Secure Firmware from Flash
 *****************************************************************************/
    /* Start loading Secure FW image from Flash into SDRAM */
    load_image(&li[SECURE_FW_ID]);

    /* Authenticate of CA Program#n */
    rom_secureboot(&li[boot_ca_id + auth_count]);

    /* SystemRAM has an undefined initial value, clear the address of
     * the SystemRAM that is going to store set finish flag of RGID. */
    mem_write8(RGID_SET_RGID_FIN_FLG_ADDR, 0xFFU);

    /* Before Boot CPU, Set the division ratio for CPU operating frequency */
    adj_cr_variant_freq();

    /* boot CA */
    arm_cpu_on(boot_cpu, li[boot_ca_id].boot_addr);

    /* finish loading Secure Firmware */
    load_end();

    /* load_secure data(for ICUMXB) */
    load_securedata(SECURE_FW_ID);

    /* Authenticate of Secure Firmware */
    rom_secureboot(&li[SECURE_FW_ID]);

    /* finish loading secure data */
    load_end();

    /* Finally Protection setting */
    rgid_protection_final();

    /* set RGID setting finish flag.
     * because polling from CX 2nd IPL. */
    mem_write8(RGID_SET_RGID_FIN_FLG_ADDR, RGID_SET_RGID_FIN_FLG_VAL);

#if (ECM_ENABLE == 1)
    /* Notice the ecc enable */
    NOTICE("Enabled EDC for AXI-Bus, RT-VRAM. \n");
#endif
    NOTICE("Load finish.\n");
    ip_release();

    return get_cfremap_addr(li[SECURE_FW_ID].boot_addr);
}
/* End of function loader_main(void) */

