u-boot tegra tx1

本文深入探讨了U-Boot在Tegra TX1处理器上的启动过程,主要关注了两个关键文件:arch/arm/cpu/armv8/start.S和arch/arm/lib/gic_64.S。start.S涉及CPU初始化,而gic_64.S处理了ARMv8架构下的全局中断控制器(GIC)设置。
摘要由CSDN通过智能技术生成

arch/arm/cpu/armv8/start.S

/*
 * (C) Copyright 2013
 * David Feng <fenghua@phytium.com.cn>
 *
 * SPDX-License-Identifier: GPL-2.0+
 */

#include <asm-offsets.h>
#include <config.h>
#include <linux/linkage.h>
#include <asm/macro.h>
#include <asm/armv8/mmu.h>

/*************************************************************************
 *
 * Startup Code (reset vector)
 *
 *************************************************************************/

.globl  _start
_start:
    b   reset

    .align 3

.globl  _TEXT_BASE
_TEXT_BASE:
    .quad   CONFIG_SYS_TEXT_BASE

/*
 * These are defined in the linker script.
 */
.globl  _end_ofs
_end_ofs:
    .quad   _end - _start

.globl  _bss_start_ofs
_bss_start_ofs:
    .quad   __bss_start - _start

.globl  _bss_end_ofs
_bss_end_ofs:
    .quad   __bss_end - _start

reset:
#ifdef CONFIG_SYS_RESET_SCTRL
    bl reset_sctrl
#endif
    /*
     * Could be EL3/EL2/EL1, Initial State:
     * Little Endian, MMU Disabled, i/dCache Disabled
     */
    adr x0, vectors
    switch_el x1, 3f, 2f, 1f
3:  msr vbar_el3, x0
    mrs x0, scr_el3
    orr x0, x0, #0xf            /* SCR_EL3.NS|IRQ|FIQ|EA */  //gshen:all interrupt handle by EL3
    msr scr_el3, x0
    msr cptr_el3, xzr           /* Enable FP/SIMD */
#ifdef COUNTER_FREQUENCY
    ldr x0, =COUNTER_FREQUENCY
    msr cntfrq_el0, x0          /* Initialize CNTFRQ */
#endif
    b   0f
2:  msr vbar_el2, x0
    mov x0, #0x33ff
    msr cptr_el2, x0            /* Enable FP/SIMD */  //gshen: hardware FP/SIMD, so no need to trap
    b   0f
1:  msr vbar_el1, x0
    mov x0, #3 << 20
    msr cpacr_el1, x0           /* Enable FP/SIMD */
0:

    /* Apply ARM core specific erratas */
    bl  apply_core_errata

    /*
     * Cache/BPB/TLB Invalidate
     * i-cache is invalidated before enabled in icache_enable()
     * tlb is invalidated before mmu is enabled in dcache_enable()
     * d-cache is invalidated before enabled in dcache_enable()
     */

    /* Processor specific initialization */
    bl  lowlevel_init

#ifdef CONFIG_ARMV8_MULTIENTRY
    branch_if_master x0, x1, master_cpu

    /*
     * Slave CPUs
     */
slave_cpu:
    wfe
    ldr x1, =CPU_RELEASE_ADDR
    ldr x0, [x1]
    cbz x0, slave_cpu
    br  x0          /* branch to the given address */
master_cpu:
    /* On the master CPU */
#endif /* CONFIG_ARMV8_MULTIENTRY */

    bl  _main    //gshen: "arch/arm/lib/crt0_64.S"

#ifdef CONFIG_SYS_RESET_SCTRL
reset_sctrl:
    switch_el x1, 3f, 2f, 1f
3:
    mrs x0, sctlr_el3
    b   0f
2:
    mrs x0, sctlr_el2
    b   0f
1:
    mrs x0, sctlr_el1

0:
    ldr x1, =0xfdfffffa
    and x0, x0, x1

    switch_el x1, 6f, 5f, 4f
6:
    msr sctlr_el3, x0
    b   7f
5:
    msr sctlr_el2, x0
    b   7f
4:
    msr sctlr_el1, x0

7:
    dsb sy
    isb
    b   __asm_invalidate_tlb_all
    ret
#endif

/*-----------------------------------------------------------------------*/

WEAK(apply_core_errata)

    mov x29, lr         /* Save LR */
    /* For now, we support Cortex-A57 specific errata only */

    /* Check if we are running on a Cortex-A57 core */
    branch_if_a57_core x0, apply_a57_core_errata
0:
    mov lr, x29         /* Restore LR */
    ret

apply_a57_core_errata:

#ifdef CONFIG_ARM_ERRATA_828024
    mrs x0, S3_1_c15_c2_0   /* cpuactlr_el1 */
    /* Disable non-allocate hint of w-b-n-a memory type */
    orr x0, x0, #1 << 49
    /* Disable write streaming no L1-allocate threshold */
    orr x0, x0, #3 << 25
    /* Disable write streaming no-allocate threshold */
    orr x0, x0, #3 << 27
    msr S3_1_c15_c2_0, x0   /* cpuactlr_el1 */
#endif

#ifdef CONFIG_ARM_ERRATA_826974
    mrs x0, S3_1_c15_c2_0   /* cpuactlr_el1 */
    /* Disable speculative load execution ahead of a DMB */
    orr x0, x0, #1 << 59
    msr S3_1_c15_c2_0, x0   /* cpuactlr_el1 */
#endif

#ifdef CONFIG_ARM_ERRATA_833471
    mrs x0, S3_1_c15_c2_0   /* cpuactlr_el1 */
    /* FPSCR write flush.
     * Note that in some cases where a flush is unnecessary this
        could impact performance. */
    orr x0, x0, #1 << 38
    msr S3_1_c15_c2_0, x0   /* cpuactlr_el1 */
#endif

#ifdef CONFIG_ARM_ERRATA_829520
    mrs x0, S3_1_c15_c2_0   /* cpuactlr_el1 */
    /* Disable Indirect Predictor bit will prevent this erratum
        from occurring
     * Note that in some cases where a flush is unnecessary this
        could impact performance. */
    orr x0, x0, #1 << 4
    msr S3_1_c15_c2_0, x0   /* cpuactlr_el1 */
#endif

#ifdef CONFIG_ARM_ERRATA_833069
    mrs x0, S3_1_c15_c2_0   /* cpuactlr_el1 */
    /* Disable Enable Invalidates of BTB bit */
    and x0, x0, #0xE
    msr S3_1_c15_c2_0, x0   /* cpuactlr_el1 */
#endif
    b 0b
ENDPROC(apply_core_errata)

/*-----------------------------------------------------------------------*/

WEAK(lowlevel_init)
    mov x29, lr         /* Save LR */

#ifndef CONFIG_ARMV8_MULTIENTRY
    /*
     * For single-entry systems the lowlevel init is very simple.
     */ //gshen: tx1 use this branch
    ldr x0, =GICD_BASE
    bl  gic_init_secure

#else /* CONFIG_ARMV8_MULTIENTRY is set */

#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
    branch_if_slave x0, 1f
    ldr x0, =GICD_BASE
    bl  gic_init_secure
1:
#if defined(CONFIG_GICV3)
    ldr x0, =GICR_BASE
    bl  gic_init_secure_percpu
#elif defined(CONFIG_GICV2)
    ldr x0, =GICD_BASE
    ldr x1, =GICC_BASE
    bl  gic_init_secure_percpu
#endif
#endif

    branch_if_master x0, x1, 2f

    /*
     * Slave should wait for master clearing spin table.
     * This sync prevent salves observing incorrect
     * value of spin table and jumping to wrong place.
     */
#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
#ifdef CONFIG_GICV2
    ldr x0, =GICC_BASE
#endif
    bl  gic_wait_for_interrupt
#endif

    /*
     * All slaves will enter EL2 and optionally EL1.
     */
    bl  armv8_switch_to_el2
#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
    bl  armv8_switch_to_el1
#endif

#endif /* CONFIG_ARMV8_MULTIENTRY */

2:
    mov lr, x29         /* Restore LR */
    ret
ENDPROC(lowlevel_init)

WEAK(smp_kick_all_cpus)
    /* Kick secondary cpus up by SGI 0 interrupt */
    mov x29, lr         /* Save LR */
#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
    ldr x0, =GICD_BASE
    bl  gic_kick_secondary_cpus
#endif
    mov lr, x29         /* Restore LR */
    ret
ENDPROC(smp_kick_all_cpus)

/*-----------------------------------------------------------------------*/

ENTRY(c_runtime_cpu_setup)
    /* Relocate vBAR */
    adr x0, vectors
    switch_el x1, 3f, 2f, 1f
3:  msr vbar_el3, x0
    b   0f
2:  msr vbar_el2, x0
    b   0f
1:  msr vbar_el1, x0
0:

    ret
ENDPROC(c_runtime_cpu_setup)

arch/arm/lib/gic_64.S

/*
 * GIC Initialization Routines.
 *
 * (C) Copyright 2013
 * David Feng <fenghua@phytium.com.cn>
 *
 * SPDX-License-Identifier: GPL-2.0+
 */

#include <asm-offsets.h>
#include <config.h>
#include <linux/linkage.h>
#include <asm/gic.h>
#include <asm/macro.h>


/*************************************************************************
 *
 * void gic_init_secure(DistributorBase);
 *
 * Initialize secure copy of GIC at EL3.
 *
 *************************************************************************/
ENTRY(gic_init_secure)
    /*
     * Initialize Distributor
     * x0: Distributor Base
     */
#if defined(CONFIG_GICV3)
    mov w9, #0x37       /* EnableGrp0 | EnableGrp1NS */
                    /* EnableGrp1S | ARE_S | ARE_NS */
    str w9, [x0, GICD_CTLR] /* Secure GICD_CTLR */
    ldr w9, [x0, GICD_TYPER]
    and w10, w9, #0x1f      /* ITLinesNumber */
    cbz w10, 1f         /* No SPIs */
    add x11, x0, (GICD_IGROUPRn + 4)
    add x12, x0, (GICD_IGROUPMODRn + 4)
    mov w9, #~0
0:  str w9, [x11], #0x4
    str wzr, [x12], #0x4    /* Config SPIs as Group1NS */
    sub w10, w10, #0x1
    cbnz    w10, 0b
#elif defined(CONFIG_GICV2)
    mov w9, #0x3        /* EnableGrp0 | EnableGrp1 */
    str w9, [x0, GICD_CTLR] /* Secure GICD_CTLR */
    ldr w9, [x0, GICD_TYPER]
    and w10, w9, #0x1f      /* ITLinesNumber */
    cbz w10, 1f         /* No SPIs */    //gshen:check whether SPI is supported
    add x11, x0, GICD_IGROUPRn
    mov w9, #~0            /* Config SPIs as Grp1 */   //gshen: seems useless for tx1
    str w9, [x11], #0x4
0:  str w9, [x11], #0x4
    sub w10, w10, #0x1
    cbnz    w10, 0b

    ldr x1, =GICC_BASE      /* GICC_CTLR */
    mov w0, #3          /* EnableGrp0 | EnableGrp1 */
    str w0, [x1]

    mov w0, #1 << 7     /* allow NS access to GICC_PMR */
    str w0, [x1, #4]        /* GICC_PMR */
#endif
1:
    ret
ENDPROC(gic_init_secure)


/*************************************************************************
 * For Gicv2:
 * void gic_init_secure_percpu(DistributorBase, CpuInterfaceBase);
 * For Gicv3:
 * void gic_init_secure_percpu(ReDistributorBase);
 *
 * Initialize secure copy of GIC at EL3.
 *
 *************************************************************************/
ENTRY(gic_init_secure_percpu)
#if defined(CONFIG_GICV3)
    /*
     * Initialize ReDistributor
     * x0: ReDistributor Base
     */
    mrs x10, mpidr_el1
    lsr x9, x10, #32
    bfi x10, x9, #24, #8    /* w10 is aff3:aff2:aff1:aff0 */
    mov x9, x0
1:  ldr x11, [x9, GICR_TYPER]
    lsr x11, x11, #32       /* w11 is aff3:aff2:aff1:aff0 */
    cmp w10, w11
    b.eq    2f
    add x9, x9, #(2 << 16)
    b   1b

    /* x9: ReDistributor Base Address of Current CPU */
2:  mov w10, #~0x2
    ldr w11, [x9, GICR_WAKER]
    and w11, w11, w10       /* Clear ProcessorSleep */
    str w11, [x9, GICR_WAKER]
    dsb st
    isb
3:  ldr w10, [x9, GICR_WAKER]
    tbnz    w10, #2, 3b     /* Wait Children be Alive */

    add x10, x9, #(1 << 16) /* SGI_Base */
    mov w11, #~0
    str w11, [x10, GICR_IGROUPRn]
    str wzr, [x10, GICR_IGROUPMODRn]    /* SGIs|PPIs Group1NS */
    mov w11, #0x1       /* Enable SGI 0 */
    str w11, [x10, GICR_ISENABLERn]

    /* Initialize Cpu Interface */
    mrs x10, ICC_SRE_EL3
    orr x10, x10, #0xf      /* SRE & Disable IRQ/FIQ Bypass & */
                    /* Allow EL2 access to ICC_SRE_EL2 */
    msr ICC_SRE_EL3, x10
    isb

    mrs x10, ICC_SRE_EL2
    orr x10, x10, #0xf      /* SRE & Disable IRQ/FIQ Bypass & */
                    /* Allow EL1 access to ICC_SRE_EL1 */
    msr ICC_SRE_EL2, x10
    isb

    mov x10, #0x3       /* EnableGrp1NS | EnableGrp1S */
    msr ICC_IGRPEN1_EL3, x10
    isb

    msr ICC_CTLR_EL3, xzr
    isb

    msr ICC_CTLR_EL1, xzr   /* NonSecure ICC_CTLR_EL1 */
    isb

    mov x10, #0x1 << 7      /* Non-Secure access to ICC_PMR_EL1 */
    msr ICC_PMR_EL1, x10
    isb
#elif defined(CONFIG_GICV2)
    /*
     * Initialize SGIs and PPIs
     * x0: Distributor Base
     * x1: Cpu Interface Base
     */
    mov w9, #~0            /* Config SGIs and PPIs as Grp1 */
    str w9, [x0, GICD_IGROUPRn] /* GICD_IGROUPR0 */
    mov w9, #0x1        /* Enable SGI 0 */
    str w9, [x0, GICD_ISENABLERn]

    /* Initialize Cpu Interface */
    mov w9, #0x1e7      /* Disable IRQ/FIQ Bypass & */
                    /* Enable Ack Group1 Interrupt & */
                    /* EnableGrp0 & EnableGrp1 */
    str w9, [x1, GICC_CTLR] /* Secure GICC_CTLR */

    mov w9, #0x1 << 7       /* Non-Secure access to GICC_PMR */
    str w9, [x1, GICC_PMR]
#endif
    ret
ENDPROC(gic_init_secure_percpu)


/*************************************************************************
 * For Gicv2:
 * void gic_kick_secondary_cpus(DistributorBase);
 * For Gicv3:
 * void gic_kick_secondary_cpus(void);
 *
 *************************************************************************/
ENTRY(gic_kick_secondary_cpus)
#if defined(CONFIG_GICV3)
    mov x9, #(1 << 40)
    msr ICC_ASGI1R_EL1, x9
    isb
#elif defined(CONFIG_GICV2)
    mov w9, #0x8000
    movk    w9, #0x100, lsl #16
    str w9, [x0, GICD_SGIR]
#endif
    ret
ENDPROC(gic_kick_secondary_cpus)


/*************************************************************************
 * For Gicv2:
 * void gic_wait_for_interrupt(CpuInterfaceBase);
 * For Gicv3:
 * void gic_wait_for_interrupt(void);
 *
 * Wait for SGI 0 from master.
 *
 *************************************************************************/
ENTRY(gic_wait_for_interrupt)
#if defined(CONFIG_GICV3)
    gic_wait_for_interrupt_m x9
#elif defined(CONFIG_GICV2)
    gic_wait_for_interrupt_m x0, w9
#endif
    ret
ENDPROC(gic_wait_for_interrupt)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值