/*
 * Copyright (c) 2015-2021, Renesas Electronics Corporation
 * All rights reserved.
 */

#define MODE_FIQ        (0x11)
#define MODE_IRQ        (0x12)
#define MODE_SVC        (0x13)
#define MODE_ABT        (0x17)
#define MODE_UND        (0x1B)
#define MODE_SYS        (0x1F)

#define ARMREG_P_CR7SS      (0xE6271800)
#define SYSRAM_BASE     (0xE6300000)
#define SCU_BASE        (0xF0000000)

#define TCM_ENABLE      (0x00000001)
#define ITCM_BASE       (0xEB000000)
#define DTCM_BASE       (0xEB020000)
#define ITCMRR_INIT_TADA    (ITCM_BASE | TCM_ENABLE)
#define DTCMRR_INIT_TADA    (DTCM_BASE | TCM_ENABLE)

#define WBWA            (0x00B)     /* Write-Back Write Allocate */
#define WT          (0x002)     /* Write-Through */
#define NC          (0x008)     /* Non-cacheable */
#define DEV         (0x001)     /* Device */
#define SO          (0x000)     /* Strongly Ordered */
#define SHARE           (0x004)     /* Shareable */
#define AP_FULL         (0x300)

#define REGION_SIZE_4KB     (0x16)
#define REGION_SIZE_8KB     (0x18)
#define REGION_SIZE_16KB    (0x1A)
#define REGION_SIZE_32KB    (0x1C)
#define REGION_SIZE_64KB    (0x1E)
#define REGION_SIZE_128KB   (0x20)
#define REGION_SIZE_256KB   (0x22)
#define REGION_SIZE_512KB   (0x24)
#define REGION_SIZE_1MB     (0x26)
#define REGION_SIZE_2MB     (0x28)
#define REGION_SIZE_4MB     (0x2A)
#define REGION_SIZE_8MB     (0x2C)
#define REGION_SIZE_16MB    (0x2E)
#define REGION_SIZE_32MB    (0x30)
#define REGION_SIZE_64MB    (0x32)
#define REGION_SIZE_128MB   (0x34)
#define REGION_SIZE_256MB   (0x36)
#define REGION_SIZE_512MB   (0x38)
#define REGION_SIZE_1GB     (0x3A)
#define REGION_SIZE_2GB     (0x3C)
#define REGION_SIZE_4GB     (0x3E)

#define REGION_ENABLE       (0x1)

#define REGION0_SIZE        (REGION_SIZE_4GB   | REGION_ENABLE)
#define REGION1_SIZE        (REGION_SIZE_512MB | REGION_ENABLE)
#define REGION2_SIZE        (REGION_SIZE_512KB | REGION_ENABLE)
#define REGION3_SIZE        (REGION_SIZE_64KB  | REGION_ENABLE)
#define REGION4_SIZE        (REGION_SIZE_64KB  | REGION_ENABLE)

#define REGION0_BASE        (0x00000000)
#define REGION1_BASE        (0xE0000000)
#define REGION2_BASE        (0xE6300000)
#define REGION3_BASE        (ITCM_BASE)
#define REGION4_BASE        (0xEB100000)

#define REGION0_ATTR        (AP_FULL | WBWA | SHARE)
#define REGION1_ATTR        (AP_FULL | DEV  | SHARE)
#define REGION2_ATTR        (AP_FULL | WBWA | SHARE)
#define REGION3_ATTR        (AP_FULL | WBWA | SHARE)
#define REGION4_ATTR        (AP_FULL | WBWA | SHARE)


#define SCTLR_I         (1 << 12)
#define SCTLR_M         (1 << 0)

    .global Startup
    .global do_panic

    .global loader_main
    .global ecc_init
    .global dram_ecc_init
    .global rcar_addr

    .align  5

/*****************************************************************************
 *  Reset Hander
 *****************************************************************************/
Startup:
    /* 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 r0, =__STACKS_END__

    /* stack initialize */
    msr CPSR_c, #(0x17 | 0x80 | 0x40)   /* ABT */
    mov sp, r0              /* STACK_BASE_ABT */

    msr CPSR_c, #(0x1B | 0x80 | 0x40)   /* UND */
    sub r0, r0, #0x80           /* STACK_BASE_UND */
    mov sp, r0

    msr CPSR_c, #(0x11 | 0x80 | 0x40)   /* FIQ */
    sub r0, r0, #0x80           /* STACK_BASE_FIQ */
    mov sp, r0

    msr CPSR_c, #(0x12 | 0x80 | 0x40)   /* IRQ */
    sub r0, r0, #0x80           /* STACK_BASE_IRQ */
    mov sp, r0

    msr CPSR_c, #(0x13 | 0x80 | 0x40)   /* SVC */
    sub r0, r0, #0x80           /* STACK_BASE_SVC */
    mov sp, r0

    /* Dual core lock step enable */
    ldr r0, =(0xE6271800)       /* ARMREG_P_CR7SS */
    ldr r1, [r0]
    orr r1, r1, #0x80000000     /* bit31 */
    str r1, [r0]

    /* Cache ECC error detection enable */
    mov r0, #0
    mcr p15, 0, r0, c15, c2, 0      /* DEER0 */
    mcr p15, 0, r0, c15, c2, 1      /* DEER1 */
    mcr p15, 0, r0, c15, c2, 2      /* DEER2 */
    mcr p15, 0, r0, c15, c3, 0      /* IEER0 */
    mcr p15, 0, r0, c15, c3, 1      /* IEER1 */
    mcr p15, 0, r0, c15, c3, 2      /* IEER2 */


    /* Instruction cache enable */
    mrc p15, 0, r1, c1, c0, 0       /* SCTLR */
    orr     R1, R1, #1 << 12        /* I=1 */
    orr     R1, R1, #1 << 11        /* Z=1 */
    mcr     p15, 0, r0, c7, c5, 0       /* ICIALLU */
    mcr p15, 0, r0, c7, c5, 6       /* BPIALL */
    mcr     p15, 0, r1, c1, c0, 0       /* SCTLR */
    isb

    /* Invalidate D-Cache */
    mov r10, #0
    mcr p15, 2, r10, c0, c0, 0      /* CSSELR */
    isb

    mrc p15, 1, r1, c0, c0, 0       /* CCSIDR */
    and r2, r1, #7          /* b001=8word/line */
    add r2, r2, #4          /* DCISW calc shift */
    ldr r4, =0x3FF          /* mac way mask */
    ands    r4, r4, r1, LSR #3      /* r4 = way */
    clz r5, r4
    ldr r7,=0x7FFF
    ands    r7, r7, r1, LSR #13
inv_d_cache_loop2:
    mov r9, r4
inv_d_cache_loop3:
    orr r11, r10, r9, LSL r5
    orr r11, r11, r7, LSL r2
    mcr p15, 0, r11, c7, c6, 2
    subs    r9, r9, #1
    bge inv_d_cache_loop3
    subs    r7, r7, #1
    bge inv_d_cache_loop2

    /* 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

    /* System RAM/SDRAM ECC enable */
    bl  ecc_init
    bl  dram_ecc_init

    /* Loader Main */
    sub sp, sp, #8
    mov r0, sp
    bl  rcar_addr
    ldr r1, [sp, #0]
    add sp, sp, #8
    push    {r0, r1}            /* r0 = CR7 boot address */
    mov r0, r1
    push    {r0, r1}            /* r0 = CA5x boot address */

    /* serial outpu wait */
    bl  console_wait

    /* GIC Non Secure setting */
    bl  gic_security_setting

#if RCAR_DISABLE_AXI_LIFEC_SYSC == 0
    /* SRAM/DRAM protection setting */
    bl  axi_security_setting

    /* LifeC setting */
    bl  lifec_init
#endif

    /* CA57/53 bootup */
    pop {r0, r1}
    bl  rcar_pwrc_cpuon

#if RCAR_DISABLE_AXI_LIFEC_SYSC == 0
    /* LifeC setting for CR7 */
    bl  lifec_cr7_setting

    /* SYSC setting */
    bl  sysc_security_setting
#endif

    /* Instruction cache invalidate & branch predictor invalidate */
    mrc p15, 0, r0, c1, c0, 0       /* SCTLR */
    bic R0, R0, #0x1 <<12       /* I = 0 */
    bic R0, R0, #0x1 <<11       /* Z = 0 */
    mcr p15, 0, r0, c1, c0, 0
    mcr p15, 0, r0, c7, c5, 0       /* ICIALLU */
    mcr p15, 0, r0, c7, c5, 6       /* BPIALL */
    isb

    /* Jump to RTOS */
    pop {r0, r1}
    bx  r0              /* RTOS_BASE */
    NOP
    NOP
    NOP

do_panic:
    nop
1:
    wfe
    b   1b


/*****************************************************************************
 *  Exception Handers
 *****************************************************************************/
