/*******************************************************************************
* 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   : Image load function
 ******************************************************************************/
/******************************************************************************
 * @file          loader_v4m.S
 * - Version      : 0.02
 * @brief         
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 21.08.2023 0.01     First Release
 *         : 19.12.2024 0.02     Added the process that jump to RTOS#1.
 *****************************************************************************/

/* SCTLR definitions */ 
#define SCTLR_I         (1 << 12)
#define SCTLR_M         (1 << 0)

/* MAIR definitions */
#define MAIR_ATTR0      (0x00 <<  0)   /* Device-nGnRnE memory */
#define MAIR_ATTR1      (0x4A <<  8)   /* Normal memory, Outer Non-cacheable, Inner Write-Through Non-transient */
#define MAIR_ATTR2      (0x44 << 16)   /* Normal memory, Outer Non-cacheable, Inner Non-cacheable */
#define MAIR_VAL        (MAIR_ATTR2 | MAIR_ATTR1 | MAIR_ATTR0)

#define SUP_EXCEPTION   (0x2U)
#define HYP_EXCEPTION   (0x5U)
#define IRQ_EXCEPTION   (0x6U)
#define FIQ_EXCEPTION   (0x7U)

#define RTOS_LOAD_NUM_1 (1)     /* RTOS is RTOS#0 only. */
#define RTOS_LOAD_NUM_3 (3)     /* RTOS are RTOS#0, RTOS#1, and RTOS#2. */

    .global Startup
    .global Vector
    .global dabt_report_exception
    .global pabt_report_exception

    .extern dabort_error
    .extern pabort_error
    .extern Undefined_error
    .extern handler_error

    .align  5

Vector:
    b Startup               /* Reset */
    b Undefined_Handler     /* Undefined Instruction */
    b Supervisor_Handler    /* Supervisor Call */
    b Prefetch_Handler      /* Prefetch Abort */
    b Abort_Handler         /* Data Abort */
    b HypTrap_Handler       /* Hyp Trap */
    b IRQ_Handler           /* IRQ interrupt */
    b FIQ_Handler           /* FIQ interrupt */

/*****************************************************************************
 *  Reset Hander
 *****************************************************************************/
Startup:
/* initialize registers*/
    /* initialize registers*/
    mov    r0,  #0
    mov    r1,  #0
    mov    r2,  #0
    mov    r3,  #0
    mov    r4,  #0
    mov    r5,  #0
    mov    r6,  #0
    mov    r7,  #0
    mov    r8,  #0
    mov    r9,  #0
    mov    r10, #0
    mov    r11, #0
    mov    r12, #0
    mov    lr,  #0

    ldr    r13, =__STACKS_END__

/* Instruction cache enable */
    mrc    p15, 4, r0, c1, c0, 0       /* HSCTLR  */
    mrc    p15, 0, r1, c1, c0, 0       /* SCTLR   */
    bic    r0, r0, #SCTLR_M            /* M=0     */
    bic    r1, r1, #SCTLR_M            /* M=0     */
    orr    r0, r0, #SCTLR_I            /* I=1     */
    orr    r1, r1, #SCTLR_I            /* I=1     */
    mcr    p15, 0, r0, c7, c5, 0       /* ICIALLU */
    mcr    p15, 4, r0, c1, c0, 0       /* HSCTLR  */
    mcr    p15, 0, r1, c1, c0, 0       /* SCTLR   */
    isb
    mcr    p15, 0, r0, c7, c5, 6       /* BPIALL */
    isb

/* CR52_CONFIGURE_MPU */
    mrc    p15, 0, r0, c10, c2, 0      /* Read MAIR0 into R0        */
    mrc    p15, 4, r1, c10, c2, 0      /* Read HMAIR0 into R1       */
    ldr    r0, =MAIR_VAL               /* Set MAIR                  */
    ldr    r1, =MAIR_VAL               /* Set MAIR                  */
    mcr    p15, 0, r0, c10, c2, 0      /* Write R0 to MAIR0         */
    mcr    p15, 4, r1, c10, c2, 0      /* Write R1 to HMAIR0        */

/* region 0: 0x00000000~0x3FFFFFFF */
    ldr    r0, =0x00000006             /* SH=b'00/AP=b'11/XN=b'0    */
    ldr    r1, =0x3FFFFFC5             /* AttrIndx=2(Non-Cacheable) */
    mcr    p15, 0, r0, c6, c8, 0       /* Write R0 into PRBAR0      */
    mcr    p15, 0, r1, c6, c8, 1       /* Write R1 into PRLAR0      */
    mcr    p15, 4, r0, c6, c8, 0       /* Write R0 into HPRBAR0     */
    mcr    p15, 4, r1, c6, c8, 1       /* Write R1 into HPRLAR0     */
/* region 1: 0x40000000~0xBFFFFFFF */
    ldr    r0, =0x40000003             /* SH=b'00/AP=b'01/XN=b'1    */
    ldr    r1, =0xBFFFFFC5             /* AttrIndx=2(Non-Cacheable) */
    mcr    p15, 0, r0, c6, c8, 4       /* Write R0 into PRBAR1      */
    mcr    p15, 0, r1, c6, c8, 5       /* Write R1 into PRLAR1      */
    mcr    p15, 4, r0, c6, c8, 4       /* Write R0 into HPRBAR1     */
    mcr    p15, 4, r1, c6, c8, 5       /* Write R1 into HPRLAR1     */
/* region 2: 0xC0000000~0xE3FFFFFF */
    ldr    r0, =0xC0000003             /* SH=b'00/AP=b'01/XN=b'1    */
    ldr    r1, =0xE3FFFFC1             /* AttrIndx=0(Device)        */
    mcr    p15, 0, r0, c6, c9, 0       /* Write R0 into PRBAR2      */
    mcr    p15, 0, r1, c6, c9, 1       /* Write R1 into PRLAR2      */
    mcr    p15, 4, r0, c6, c9, 0       /* Write R0 into HPRBAR2     */
    mcr    p15, 4, r1, c6, c9, 1       /* Write R1 into HPRLAR2     */
/* region 3: 0xE4000000~0xE4FFFFFF */
    ldr    r0, =0xE4000003             /* SH=b'00/AP=b'01/XN=b'1    */
    ldr    r1, =0xE4FFFFC5             /* AttrIndx=2(Non-Cacheable) */
    mcr    p15, 0, r0, c6, c9, 4       /* Write R0 into PRBAR3      */
    mcr    p15, 0, r1, c6, c9, 5       /* Write R1 into PRLAR3      */
    mcr    p15, 4, r0, c6, c9, 4       /* Write R0 into HPRBAR3     */
    mcr    p15, 4, r1, c6, c9, 5       /* Write R1 into HPRLAR3     */
/* region 4: 0xE5000000~0xE62FFFFF */
    ldr    r0, =0xE5000003             /* SH=b'00/AP=b'01/XN=b'1    */
    ldr    r1, =0xE62FFFC1             /* AttrIndx=0(Device)        */
    mcr    p15, 0, r0, c6, c10, 0      /* Write R0 into PRBAR4      */
    mcr    p15, 0, r1, c6, c10, 1      /* Write R1 into PRLAR4      */
    mcr    p15, 4, r0, c6, c10, 0      /* Write R0 into HPRBAR4     */
    mcr    p15, 4, r1, c6, c10, 1      /* Write R1 into HPRLAR4     */
/* region 5: 0xE6300000~0xE632FFFF */
    ldr    r0, =0xE6300006             /* SH=b'00/AP=b'11/XN=b'0    */
    ldr    r1, =0xE632FFC3             /* AttrIndx=1(Write-Through) */
    mcr    p15, 0, r0, c6, c10, 4      /* Write R0 into PRBAR5      */
    mcr    p15, 0, r1, c6, c10, 5      /* Write R1 into PRLAR5      */
    mcr    p15, 4, r0, c6, c10, 4      /* Write R0 into HPRBAR5     */
    mcr    p15, 4, r1, c6, c10, 5      /* Write R1 into HPRLAR5     */
/* region 6: 0xE6330000~0xE635FFFF */
    ldr    r0, =0xE6330003             /* SH=b'00/AP=b'01/XN=b'1    */
    ldr    r1, =0xE635FFC5             /* AttrIndx=2(Non-Cacheable) */
    mcr    p15, 0, r0, c6, c11, 0      /* Write R0 into PRBAR6      */
    mcr    p15, 0, r1, c6, c11, 1      /* Write R1 into PRLAR6      */
    mcr    p15, 4, r0, c6, c11, 0      /* Write R0 into HPRBAR6     */
    mcr    p15, 4, r1, c6, c11, 1      /* Write R1 into HPRLAR6     */
/* region 7: 0xE6360000~0xEB1FFFFF */
    ldr    r0, =0xE6360003             /* SH=b'00/AP=b'01/XN=b'1    */
    ldr    r1, =0xEB1FFFC1             /* AttrIndx=0(Device)        */
    mcr    p15, 0, r0, c6, c11, 4      /* Write R0 into PRBAR7      */
    mcr    p15, 0, r1, c6, c11, 5      /* Write R1 into PRLAR7      */
    mcr    p15, 4, r0, c6, c11, 4      /* Write R0 into HPRBAR7     */
    mcr    p15, 4, r1, c6, c11, 5      /* Write R1 into HPRLAR7     */
/* region 8: 0xEB200000~0xEB3FFFFF */
    ldr    r0, =0xEB200003             /* SH=b'00/AP=b'01/XN=b'1    */
    ldr    r1, =0xEB3FFFC5             /* AttrIndx=2(Non-Cacheable) */
    mcr    p15, 0, r0, c6, c12, 0      /* Write R0 into PRBAR8      */
    mcr    p15, 0, r1, c6, c12, 1      /* Write R1 into PRLAR8      */
    mcr    p15, 4, r0, c6, c12, 0      /* Write R0 into HPRBAR8     */
    mcr    p15, 4, r1, c6, c12, 1      /* Write R1 into HPRLAR8     */
/* region 9: 0xEB400000~0xFFFFFFFF */
    ldr    r0, =0xEB400003             /* SH=b'00/AP=b'01/XN=b'1    */
    ldr    r1, =0xFFFFFFC1             /* AttrIndx=0(Device)        */
    mcr    p15, 0, r0, c6, c12, 4      /* Write R0 into PRBAR9      */
    mcr    p15, 0, r1, c6, c12, 5      /* Write R1 into PRLAR9      */
    mcr    p15, 4, r0, c6, c12, 4      /* Write R0 into HPRBAR9     */
    mcr    p15, 4, r1, c6, c12, 5      /* Write R1 into HPRLAR9     */

/* CR52_SET_MPU_ON */
    mrc    p15, 4, r0, c1, c0, 0       /* Read HSCTLR  */
    mrc    p15, 0, r1, c1, c0, 0       /* Read SCTLR   */
    orr    r0, r0, #SCTLR_M            /* MPU enable   */
    orr    r1, r1, #SCTLR_M            /* MPU enable   */
    mcr    p15, 4, r0, c1, c0, 0       /* Write HSCTLR */
    mcr    p15, 0, r1, c1, c0, 0       /* Write SCTLR  */
    isb

    mcr    p15, 0, r0, c7, c5, 6       /* BPIALL */
    isb

/* Jump to physical address from mirror address */
    ldr    r0, =JUMP_MAIN
    bx     r0

JUMP_MAIN:
    ldr    r0, =Vector
    mcr    p15, 4, r0, c12, c0, 0      /* HVBAR */

/* clear bss section */
    mov    r0, #0x0
    ldr    r1, =__BSS_START__
    ldr    r2, =__BSS_SIZE__
bss_loop:
    subs   r2, r2, #4
    bcc    bss_end
    str    r0, [r1, +r2]
    b      bss_loop
bss_end:

/* copy data section */
    ldr    r0, =__DATA_COPY_START__
    ldr    r1, =__DATA_START__
    ldr    r2, =__DATA_SIZE__
data_loop:
    subs   r2, r2, #4
    bcc    data_end
    ldr    r3, [r0, +r2]
    str    r3, [r1, +r2]
    b      data_loop
data_end:

/* Loader Main */
    bl     loader_main

#if (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
/* Keep return value from loader_main function (Boot address of RTOS#1) */
    mov    r11, r0
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */

/* region 0: 0x00000000~0x3FFFFFFF */
    ldr    r0, =0x00000002             /* SH=b'00/AP=b'01/XN=b'0    */
    ldr    r1, =0x3FFFFFC5             /* AttrIndx=2(Non-Cacheable) */
    mcr    p15, 0, r0, c6, c8, 0       /* Write R0 into PRBAR0      */
    mcr    p15, 0, r1, c6, c8, 1       /* Write R1 into PRLAR0      */
    mcr    p15, 4, r0, c6, c8, 0       /* Write R0 into HPRBAR0     */
    mcr    p15, 4, r1, c6, c8, 1       /* Write R1 into HPRLAR0     */
/* region 1: 0x40000000~0xBFFFFFFF */
    ldr    r0, =0x40000002             /* SH=b'00/AP=b'01/XN=b'0    */
    ldr    r1, =0xBFFFFFC5             /* AttrIndx=2(Non-Cacheable) */
    mcr    p15, 0, r0, c6, c8, 4       /* Write R0 into PRBAR1      */
    mcr    p15, 0, r1, c6, c8, 5       /* Write R1 into PRLAR1      */
    mcr    p15, 4, r0, c6, c8, 4       /* Write R0 into HPRBAR1     */
    mcr    p15, 4, r1, c6, c8, 5       /* Write R1 into HPRLAR1     */
#if (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
/* region 2: 0xC0000000~0xE3FFFFFF */
/* Change MPU setting for RTOS#1.  */
    ldr    r0, =0xC0000002             /* SH=b'00/AP=b'01/XN=b'0    */
    ldr    r1, =0xE3FFFFC5             /* AttrIndx=2(Non-Cacheable) */
    mcr    p15, 0, r0, c6, c9, 0       /* Write R0 into PRBAR2      */
    mcr    p15, 0, r1, c6, c9, 1       /* Write R1 into PRLAR2      */
    mcr    p15, 4, r0, c6, c9, 0       /* Write R0 into HPRBAR2     */
    mcr    p15, 4, r1, c6, c9, 1       /* Write R1 into HPRLAR2     */
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */
/* region 3: 0xE4000000~0xE4FFFFFF */
    ldr    r0, =0xE4000002             /* SH=b'00/AP=b'01/XN=b'0    */
    ldr    r1, =0xE4FFFFC5             /* AttrIndx=2(Non-Cacheable) */
    mcr    p15, 0, r0, c6, c9, 4       /* Write R0 into PRBAR3      */
    mcr    p15, 0, r1, c6, c9, 5       /* Write R1 into PRLAR3      */
    mcr    p15, 4, r0, c6, c9, 4       /* Write R0 into HPRBAR3     */
    mcr    p15, 4, r1, c6, c9, 5       /* Write R1 into HPRLAR3     */
/* region 5: 0xE6300000~0xE632FFFF */
    ldr    r0, =0xE6300002             /* SH=b'00/AP=b'01/XN=b'0    */
    ldr    r1, =0xE632FFC5             /* AttrIndx=2(Non-Cacheable) */
    mcr    p15, 0, r0, c6, c10, 4      /* Write R0 into PRBAR5      */
    mcr    p15, 0, r1, c6, c10, 5      /* Write R1 into PRLAR5      */
    mcr    p15, 4, r0, c6, c10, 4      /* Write R0 into HPRBAR5     */
    mcr    p15, 4, r1, c6, c10, 5      /* Write R0 into HPRLAR5     */
/* region 6: 0xE6330000~0xE635FFFF */
    ldr    r0, =0xE6330002             /* SH=b'00/AP=b'01/XN=b'0    */
    ldr    r1, =0xE635FFC5             /* AttrIndx=2(Non-Cacheable) */
    mcr    p15, 0, r0, c6, c11, 0      /* Write R0 into PRBAR6      */
    mcr    p15, 0, r1, c6, c11, 1      /* Write R1 into PRLAR6      */
    mcr    p15, 4, r0, c6, c11, 0      /* Write R0 into HPRBAR6     */
    mcr    p15, 4, r1, c6, c11, 1      /* Write R1 into HPRLAR6     */
/* region 8: 0xEB200000~0xEB3FFFFF */
    ldr    r0, =0xEB200002             /* SH=b'00/AP=b'01/XN=b'0    */
    ldr    r1, =0xEB3FFFC5             /* AttrIndx=2(Non-Cacheable) */
    mcr    p15, 0, r0, c6, c12, 0      /* Write R0 into PRBAR8      */
    mcr    p15, 0, r1, c6, c12, 1      /* Write R1 into PRLAR8      */
    mcr    p15, 4, r0, c6, c12, 0      /* Write R0 into HPRBAR8     */
    mcr    p15, 4, r1, c6, c12, 1      /* Write R1 into HPRLAR8     */

    isb
    mcr    p15, 0, r0, c7, c5, 6        /* BPIALL       */
    isb

/* Instruction cache disable */
    mrc    p15, 4, r0, c1, c0, 0        /* Read HSCTLR  */
    mrc    p15, 0, r1, c1, c0, 0        /* Read SCTLR   */
    bic    r0, r0, #SCTLR_I             /* I=0          */
    bic    r1, r1, #SCTLR_I             /* I=0          */
    mcr    p15, 4, r0, c1, c0, 0        /* Write HSCTLR */
    mcr    p15, 0, r1, c1, c0, 0        /* Write SCTLR  */
    mcr    p15, 0, r0, c7, c5, 0        /* ICIALLU      */
    isb

#if (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
/* Jump to RTOS#1 */
    bx     r11
#elif (RTOS_LOAD_NUM == RTOS_LOAD_NUM_1)
loader_end:
    wfi
    b      loader_end
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */

anker:
    wfi
    b      anker

/* Undefined Instruction */
Undefined_Handler:
    mrs    r0, ELR_hyp
    b      Undefined_error

/* Supervisor Call */
Supervisor_Handler:
    mov    r0, #SUP_EXCEPTION
    b      handler_error

/* Prefetch Abort */
Prefetch_Handler:
    b      pabt_report_exception

/* Data Abort */
Abort_Handler:
    mrs    r0, ELR_hyp
    b      dabt_report_exception

/* Hyp Trap */
HypTrap_Handler:
    mov    r0, #HYP_EXCEPTION
    b      handler_error

/*IRQ interrupt */
IRQ_Handler:
    mov    r0, #IRQ_EXCEPTION
    b      handler_error

/* FIQ interrupt */
FIQ_Handler:
    mov    r0, #FIQ_EXCEPTION
    b      handler_error

/********************************************************
 * abort exception
 ********************************************************/
dabt_report_exception:
    mrc    p15, 0, r1, c5, c0, 0        /* Read DFSR */
    mrc    p15, 0, r2, c6, c0, 0        /* Read DFAR */
    b      dabort_error

pabt_report_exception:
    mrc    p15, 0, r0, c5, c0, 1        /* Read IFSR */
    mrc    p15, 0, r1, c6, c0, 2        /* Read IFAR */
    b      pabort_error

    .end
