1/* 2 * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7#include <platform_def.h> 8 9#include <arch.h> 10#include <asm_macros.S> 11#include <common/bl_common.h> 12#include <drivers/st/stm32_gpio.h> 13 14#define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1) 15 16 .globl platform_mem_init 17 .globl plat_report_exception 18 .globl plat_report_prefetch_abort 19 .globl plat_report_data_abort 20 .globl plat_get_my_entrypoint 21 .globl plat_secondary_cold_boot_setup 22 .globl plat_reset_handler 23 .globl plat_is_my_cpu_primary 24 .globl plat_my_core_pos 25 .globl plat_crash_console_init 26 .globl plat_crash_console_flush 27 .globl plat_crash_console_putc 28 .globl plat_panic_handler 29 30func platform_mem_init 31 /* Nothing to do, don't need to init SYSRAM */ 32 bx lr 33endfunc platform_mem_init 34 35#if DEBUG 36func plat_report_exception 37 mov r8, lr 38 39 /* 40 * Test if an abort occurred 41 * In this case the error message has already been displayed 42 * by dedicated functions 43 */ 44 cmp r0, #MODE32_abt 45 beq 1f 46 47 /* Test for an undefined instruction */ 48 cmp r0, #MODE32_und 49 bne other_exception_lbl 50 ldr r4, =undefined_str 51 bl asm_print_str 52 mrs r4, lr_und 53 b print_exception_info 54 55other_exception_lbl: 56 /* Other exceptions */ 57 mov r9, r0 58 ldr r4, =exception_start_str 59 bl asm_print_str 60 mov r4, r9 61 bl asm_print_hex 62 ldr r4, =exception_end_str 63 bl asm_print_str 64 mov r4, r6 65 66print_exception_info: 67 bl asm_print_hex 68 69 ldr r4, =end_error_str 70 bl asm_print_str 71 721: 73 bx r8 74endfunc plat_report_exception 75 76func plat_report_prefetch_abort 77 mov r8, lr 78 mov r9, r0 79 80 ldr r4, =prefetch_abort_str 81 bl asm_print_str 82 83 mov r4, r9 84 sub r4, r4, #4 85 bl asm_print_hex 86 87 ldr r4, =ifsr_str 88 bl asm_print_str 89 90 ldcopr r4, IFSR 91 bl asm_print_hex 92 93 ldr r4, =ifar_str 94 bl asm_print_str 95 96 ldcopr r4, IFAR 97 bl asm_print_hex 98 99 ldr r4, =end_error_str 100 bl asm_print_str 101 102 bx r8 103endfunc plat_report_prefetch_abort 104 105func plat_report_data_abort 106 mov r8, lr 107 mov r9, r0 108 109 ldr r4, =data_abort_str 110 bl asm_print_str 111 112 mov r4, r9 113 sub r4, r4, #8 114 bl asm_print_hex 115 116 ldr r4, =dfsr_str 117 bl asm_print_str 118 119 ldcopr r4, DFSR 120 bl asm_print_hex 121 122 ldr r4, =dfar_str 123 bl asm_print_str 124 125 ldcopr r4, DFAR 126 bl asm_print_hex 127 128 ldr r4, =end_error_str 129 bl asm_print_str 130 131 bx r8 132endfunc plat_report_data_abort 133#endif /* DEBUG */ 134 135func plat_reset_handler 136 bx lr 137endfunc plat_reset_handler 138 139 /* ------------------------------------------------------------------ 140 * unsigned long plat_get_my_entrypoint (void); 141 * 142 * Main job of this routine is to distinguish between a cold and warm 143 * boot. 144 * 145 * Currently supports only cold boot 146 * ------------------------------------------------------------------ 147 */ 148func plat_get_my_entrypoint 149 mov r0, #0 150 bx lr 151endfunc plat_get_my_entrypoint 152 153 /* --------------------------------------------- 154 * void plat_secondary_cold_boot_setup (void); 155 * 156 * Cold-booting secondary CPUs is not supported. 157 * --------------------------------------------- 158 */ 159func plat_secondary_cold_boot_setup 160 b . 161endfunc plat_secondary_cold_boot_setup 162 163 /* ----------------------------------------------------- 164 * unsigned int plat_is_my_cpu_primary (void); 165 * 166 * Find out whether the current cpu is the primary cpu. 167 * ----------------------------------------------------- 168 */ 169func plat_is_my_cpu_primary 170 ldcopr r0, MPIDR 171 ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) 172 and r0, r1 173 cmp r0, #STM32MP_PRIMARY_CPU 174 moveq r0, #1 175 movne r0, #0 176 bx lr 177endfunc plat_is_my_cpu_primary 178 179 /* ------------------------------------------- 180 * int plat_stm32mp1_get_core_pos(int mpidr); 181 * 182 * Return CorePos = (ClusterId * 4) + CoreId 183 * ------------------------------------------- 184 */ 185func plat_stm32mp1_get_core_pos 186 and r1, r0, #MPIDR_CPU_MASK 187 and r0, r0, #MPIDR_CLUSTER_MASK 188 add r0, r1, r0, LSR #6 189 bx lr 190endfunc plat_stm32mp1_get_core_pos 191 192 /* ------------------------------------ 193 * unsigned int plat_my_core_pos(void) 194 * ------------------------------------ 195 */ 196func plat_my_core_pos 197 ldcopr r0, MPIDR 198 b plat_stm32mp1_get_core_pos 199endfunc plat_my_core_pos 200 201 /* --------------------------------------------- 202 * int plat_crash_console_init(void) 203 * 204 * Initialize the crash console without a C Runtime stack. 205 * --------------------------------------------- 206 */ 207func plat_crash_console_init 208 /* Reset UART peripheral */ 209 ldr r1, =(RCC_BASE + DEBUG_UART_RST_REG) 210 ldr r2, =DEBUG_UART_RST_BIT 211 str r2, [r1] 2121: 213 ldr r0, [r1] 214 ands r2, r0, r2 215 beq 1b 216 str r2, [r1, #4] /* RSTCLR register */ 2172: 218 ldr r0, [r1] 219 ands r2, r0, r2 220 bne 2b 221 /* Enable GPIOs for UART TX */ 222 ldr r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG) 223 ldr r2, [r1] 224 /* Configure GPIO */ 225 orr r2, r2, #DEBUG_UART_TX_GPIO_BANK_CLK_EN 226 str r2, [r1] 227 ldr r1, =DEBUG_UART_TX_GPIO_BANK_ADDRESS 228 /* Set GPIO mode alternate */ 229 ldr r2, [r1, #GPIO_MODE_OFFSET] 230 bic r2, r2, #(GPIO_MODE_MASK << GPIO_TX_SHIFT) 231 orr r2, r2, #(GPIO_MODE_ALTERNATE << GPIO_TX_SHIFT) 232 str r2, [r1, #GPIO_MODE_OFFSET] 233 /* Set GPIO speed low */ 234 ldr r2, [r1, #GPIO_SPEED_OFFSET] 235 bic r2, r2, #(GPIO_SPEED_MASK << GPIO_TX_SHIFT) 236 str r2, [r1, #GPIO_SPEED_OFFSET] 237 /* Set no-pull */ 238 ldr r2, [r1, #GPIO_PUPD_OFFSET] 239 bic r2, r2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT) 240 str r2, [r1, #GPIO_PUPD_OFFSET] 241 /* Set alternate */ 242#if DEBUG_UART_TX_GPIO_PORT >= GPIO_ALT_LOWER_LIMIT 243 ldr r2, [r1, #GPIO_AFRH_OFFSET] 244 bic r2, r2, #(GPIO_ALTERNATE_MASK << \ 245 ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2)) 246 orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << \ 247 ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2)) 248 str r2, [r1, #GPIO_AFRH_OFFSET] 249#else 250 ldr r2, [r1, #GPIO_AFRL_OFFSET] 251 bic r2, r2, #(GPIO_ALTERNATE_MASK << (DEBUG_UART_TX_GPIO_PORT << 2)) 252 orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << (DEBUG_UART_TX_GPIO_PORT << 2)) 253 str r2, [r1, #GPIO_AFRL_OFFSET] 254#endif 255 /* Enable UART clock, with its source */ 256 ldr r1, =(RCC_BASE + DEBUG_UART_TX_CLKSRC_REG) 257 mov r2, #DEBUG_UART_TX_CLKSRC 258 str r2, [r1] 259 ldr r1, =(RCC_BASE + DEBUG_UART_TX_EN_REG) 260 ldr r2, [r1] 261 orr r2, r2, #DEBUG_UART_TX_EN 262 str r2, [r1] 263 264 ldr r0, =STM32MP_DEBUG_USART_BASE 265 ldr r1, =STM32MP_DEBUG_USART_CLK_FRQ 266 ldr r2, =STM32MP_UART_BAUDRATE 267 b console_stm32_core_init 268endfunc plat_crash_console_init 269 270 /* --------------------------------------------- 271 * void plat_crash_console_flush(void) 272 * 273 * Flush the crash console without a C Runtime stack. 274 * --------------------------------------------- 275 */ 276func plat_crash_console_flush 277 ldr r0, =STM32MP_DEBUG_USART_BASE 278 b console_stm32_core_flush 279endfunc plat_crash_console_flush 280 281 /* --------------------------------------------- 282 * int plat_crash_console_putc(int c) 283 * 284 * Print a character on the crash console without a C Runtime stack. 285 * Clobber list : r1 - r3 286 * 287 * In case of bootloading through uart, we keep console crash as this. 288 * Characters could be sent to the programmer, but will be ignored. 289 * No specific code in that case. 290 * --------------------------------------------- 291 */ 292func plat_crash_console_putc 293 ldr r1, =STM32MP_DEBUG_USART_BASE 294 b console_stm32_core_putc 295endfunc plat_crash_console_putc 296 297 /* ---------------------------------------------------------- 298 * void plat_panic_handler(void) __dead2; 299 * Report exception + endless loop. 300 * 301 * r6 holds the address where the fault occurred. 302 * Filling lr with this value allows debuggers to reconstruct 303 * the backtrace. 304 * ---------------------------------------------------------- 305 */ 306func plat_panic_handler 307 mrs r0, cpsr 308 and r0, #MODE32_MASK 309 bl plat_report_exception 310 mov lr, r6 311 b . 312endfunc plat_panic_handler 313 314#if DEBUG 315.section .rodata.rev_err_str, "aS" 316prefetch_abort_str: 317 .asciz "\nPrefetch Abort at: 0x" 318data_abort_str: 319 .asciz "\nData Abort at: 0x" 320undefined_str: 321 .asciz "\nUndefined instruction at: 0x" 322exception_start_str: 323 .asciz "\nException mode=0x" 324exception_end_str: 325 .asciz " at: 0x" 326dfsr_str: 327 .asciz " DFSR = 0x" 328dfar_str: 329 .asciz " DFAR = 0x" 330ifsr_str: 331 .asciz " IFSR = 0x" 332ifar_str: 333 .asciz " IFAR = 0x" 334end_error_str: 335 .asciz "\n\r" 336#endif 337