Home | History | Annotate | Download | only in aarch64
      1 /*
      2  * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are met:
      6  *
      7  * Redistributions of source code must retain the above copyright notice, this
      8  * list of conditions and the following disclaimer.
      9  *
     10  * Redistributions in binary form must reproduce the above copyright notice,
     11  * this list of conditions and the following disclaimer in the documentation
     12  * and/or other materials provided with the distribution.
     13  *
     14  * Neither the name of ARM nor the names of its contributors may be used
     15  * to endorse or promote products derived from this software without specific
     16  * prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
     22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     28  * POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include <arch.h>
     32 #include <asm_macros.S>
     33 #include <bl_common.h>
     34 #include <gic_v2.h>
     35 #include <platform_def.h>
     36 #include <pl011.h>
     37 #include "../drivers/pwrc/fvp_pwrc.h"
     38 
     39 	.globl	platform_get_entrypoint
     40 	.globl	plat_secondary_cold_boot_setup
     41 	.globl	platform_mem_init
     42 	.globl	plat_report_exception
     43 	.globl	platform_is_primary_cpu
     44 	.globl	plat_crash_console_init
     45 	.globl	plat_crash_console_putc
     46 
     47 	.macro	fvp_choose_gicmmap  param1, param2, x_tmp, w_tmp, res
     48 	ldr	\x_tmp, =VE_SYSREGS_BASE + V2M_SYS_ID
     49 	ldr	\w_tmp, [\x_tmp]
     50 	ubfx	\w_tmp, \w_tmp, #SYS_ID_BLD_SHIFT, #SYS_ID_BLD_LENGTH
     51 	cmp	\w_tmp, #BLD_GIC_VE_MMAP
     52 	csel	\res, \param1, \param2, eq
     53 	.endm
     54 
     55 	/* -----------------------------------------------------
     56 	 * void plat_secondary_cold_boot_setup (void);
     57 	 *
     58 	 * This function performs any platform specific actions
     59 	 * needed for a secondary cpu after a cold reset e.g
     60 	 * mark the cpu's presence, mechanism to place it in a
     61 	 * holding pen etc.
     62 	 * TODO: Should we read the PSYS register to make sure
     63 	 * that the request has gone through.
     64 	 * -----------------------------------------------------
     65 	 */
     66 func plat_secondary_cold_boot_setup
     67 	/* ---------------------------------------------
     68 	 * Power down this cpu.
     69 	 * TODO: Do we need to worry about powering the
     70 	 * cluster down as well here. That will need
     71 	 * locks which we won't have unless an elf-
     72 	 * loader zeroes out the zi section.
     73 	 * ---------------------------------------------
     74 	 */
     75 	mrs	x0, mpidr_el1
     76 	ldr	x1, =PWRC_BASE
     77 	str	w0, [x1, #PPOFFR_OFF]
     78 
     79 	/* ---------------------------------------------
     80 	 * Deactivate the gic cpu interface as well
     81 	 * ---------------------------------------------
     82 	 */
     83 	ldr	x0, =VE_GICC_BASE
     84 	ldr	x1, =BASE_GICC_BASE
     85 	fvp_choose_gicmmap	x0, x1, x2, w2, x1
     86 	mov	w0, #(IRQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP1)
     87 	orr	w0, w0, #(IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP0)
     88 	str	w0, [x1, #GICC_CTLR]
     89 
     90 	/* ---------------------------------------------
     91 	 * There is no sane reason to come out of this
     92 	 * wfi so panic if we do. This cpu will be pow-
     93 	 * ered on and reset by the cpu_on pm api
     94 	 * ---------------------------------------------
     95 	 */
     96 	dsb	sy
     97 	wfi
     98 cb_panic:
     99 	b	cb_panic
    100 
    101 
    102 	/* -----------------------------------------------------
    103 	 * void platform_get_entrypoint (unsigned int mpid);
    104 	 *
    105 	 * Main job of this routine is to distinguish between
    106 	 * a cold and warm boot.
    107 	 * On a cold boot the secondaries first wait for the
    108 	 * platform to be initialized after which they are
    109 	 * hotplugged in. The primary proceeds to perform the
    110 	 * platform initialization.
    111 	 * On a warm boot, each cpu jumps to the address in its
    112 	 * mailbox.
    113 	 *
    114 	 * TODO: Not a good idea to save lr in a temp reg
    115 	 * TODO: PSYSR is a common register and should be
    116 	 * 	accessed using locks. Since its not possible
    117 	 * 	to use locks immediately after a cold reset
    118 	 * 	we are relying on the fact that after a cold
    119 	 * 	reset all cpus will read the same WK field
    120 	 * -----------------------------------------------------
    121 	 */
    122 func platform_get_entrypoint
    123 	mov	x9, x30 // lr
    124 	mov	x2, x0
    125 	ldr	x1, =PWRC_BASE
    126 	str	w2, [x1, #PSYSR_OFF]
    127 	ldr	w2, [x1, #PSYSR_OFF]
    128 	ubfx	w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_MASK
    129 	cmp	w2, #WKUP_PPONR
    130 	beq	warm_reset
    131 	cmp	w2, #WKUP_GICREQ
    132 	beq	warm_reset
    133 	mov	x0, #0
    134 	b	exit
    135 warm_reset:
    136 	/* ---------------------------------------------
    137 	 * A per-cpu mailbox is maintained in the tru-
    138 	 * sted DRAM. Its flushed out of the caches
    139 	 * after every update using normal memory so
    140 	 * its safe to read it here with SO attributes
    141 	 * ---------------------------------------------
    142 	 */
    143 	ldr	x10, =MBOX_BASE
    144 	bl	platform_get_core_pos
    145 	lsl	x0, x0, #CACHE_WRITEBACK_SHIFT
    146 	ldr	x0, [x10, x0]
    147 	cbz	x0, _panic
    148 exit:
    149 	ret	x9
    150 _panic:	b	_panic
    151 
    152 
    153 	/* -----------------------------------------------------
    154 	 * void platform_mem_init (void);
    155 	 *
    156 	 * Zero out the mailbox registers in the shared memory.
    157 	 * The mmu is turned off right now and only the primary can
    158 	 * ever execute this code. Secondaries will read the
    159 	 * mailboxes using SO accesses. In short, BL31 will
    160 	 * update the mailboxes after mapping the tzdram as
    161 	 * normal memory. It will flush its copy after update.
    162 	 * BL1 will always read the mailboxes with the MMU off
    163 	 * -----------------------------------------------------
    164 	 */
    165 func platform_mem_init
    166 	ldr	x0, =MBOX_BASE
    167 	mov	w1, #PLATFORM_CORE_COUNT
    168 loop:
    169 	str	xzr, [x0], #CACHE_WRITEBACK_GRANULE
    170 	subs	w1, w1, #1
    171 	b.gt	loop
    172 	ret
    173 
    174 	/* ---------------------------------------------
    175 	 * void plat_report_exception(unsigned int type)
    176 	 * Function to report an unhandled exception
    177 	 * with platform-specific means.
    178 	 * On FVP platform, it updates the LEDs
    179 	 * to indicate where we are
    180 	 * ---------------------------------------------
    181 	 */
    182 func plat_report_exception
    183 	mrs	x1, CurrentEl
    184 	lsr	x1, x1, #MODE_EL_SHIFT
    185 	lsl	x1, x1, #SYS_LED_EL_SHIFT
    186 	lsl	x0, x0, #SYS_LED_EC_SHIFT
    187 	mov	x2, #(SECURE << SYS_LED_SS_SHIFT)
    188 	orr	x0, x0, x2
    189 	orr	x0, x0, x1
    190 	mov	x1, #VE_SYSREGS_BASE
    191 	add	x1, x1, #V2M_SYS_LED
    192 	str	w0, [x1]
    193 	ret
    194 
    195 func platform_is_primary_cpu
    196 	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
    197 	cmp	x0, #FVP_PRIMARY_CPU
    198 	cset	x0, eq
    199 	ret
    200 
    201 	/* Define a crash console for the plaform */
    202 #define FVP_CRASH_CONSOLE_BASE		PL011_UART1_BASE
    203 
    204 	/* ---------------------------------------------
    205 	 * int plat_crash_console_init(void)
    206 	 * Function to initialize the crash console
    207 	 * without a C Runtime to print crash report.
    208 	 * Clobber list : x0, x1, x2
    209 	 * ---------------------------------------------
    210 	 */
    211 func plat_crash_console_init
    212 	mov_imm	x0, FVP_CRASH_CONSOLE_BASE
    213 	mov_imm	x1, PL011_UART1_CLK_IN_HZ
    214 	mov_imm	x2, PL011_BAUDRATE
    215 	b	console_core_init
    216 
    217 	/* ---------------------------------------------
    218 	 * int plat_crash_console_putc(int c)
    219 	 * Function to print a character on the crash
    220 	 * console without a C Runtime.
    221 	 * Clobber list : x1, x2
    222 	 * ---------------------------------------------
    223 	 */
    224 func plat_crash_console_putc
    225 	mov_imm	x1, FVP_CRASH_CONSOLE_BASE
    226 	b	console_core_putc
    227