1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <libfdt.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <platform_def.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <arch.h> 14*91f16700Schasinglulu #include <arch_helpers.h> 15*91f16700Schasinglulu #include <common/debug.h> 16*91f16700Schasinglulu #include <common/fdt_fixup.h> 17*91f16700Schasinglulu #include <common/fdt_wrappers.h> 18*91f16700Schasinglulu #include <drivers/arm/gicv2.h> 19*91f16700Schasinglulu #include <drivers/console.h> 20*91f16700Schasinglulu #include <drivers/generic_delay_timer.h> 21*91f16700Schasinglulu #include <drivers/ti/uart/uart_16550.h> 22*91f16700Schasinglulu #include <lib/mmio.h> 23*91f16700Schasinglulu #include <plat/common/platform.h> 24*91f16700Schasinglulu 25*91f16700Schasinglulu #include <sunxi_def.h> 26*91f16700Schasinglulu #include <sunxi_mmap.h> 27*91f16700Schasinglulu #include <sunxi_private.h> 28*91f16700Schasinglulu 29*91f16700Schasinglulu 30*91f16700Schasinglulu static entry_point_info_t bl32_image_ep_info; 31*91f16700Schasinglulu static entry_point_info_t bl33_image_ep_info; 32*91f16700Schasinglulu 33*91f16700Schasinglulu static console_t console; 34*91f16700Schasinglulu 35*91f16700Schasinglulu static void *fdt; 36*91f16700Schasinglulu 37*91f16700Schasinglulu static const gicv2_driver_data_t sunxi_gic_data = { 38*91f16700Schasinglulu .gicd_base = SUNXI_GICD_BASE, 39*91f16700Schasinglulu .gicc_base = SUNXI_GICC_BASE, 40*91f16700Schasinglulu }; 41*91f16700Schasinglulu 42*91f16700Schasinglulu /* 43*91f16700Schasinglulu * Try to find a DTB loaded in memory by previous stages. 44*91f16700Schasinglulu * 45*91f16700Schasinglulu * At the moment we implement a heuristic to find the DTB attached to U-Boot: 46*91f16700Schasinglulu * U-Boot appends its DTB to the end of the image. Assuming that BL33 is 47*91f16700Schasinglulu * U-Boot, try to find the size of the U-Boot image to learn the DTB address. 48*91f16700Schasinglulu * The generic ARMv8 U-Boot image contains the load address and its size 49*91f16700Schasinglulu * as u64 variables at the beginning of the image. There might be padding 50*91f16700Schasinglulu * or other headers before that data, so scan the first 2KB after the BL33 51*91f16700Schasinglulu * entry point to find the load address, which should be followed by the 52*91f16700Schasinglulu * size. Adding those together gives us the address of the DTB. 53*91f16700Schasinglulu */ 54*91f16700Schasinglulu static void sunxi_find_dtb(void) 55*91f16700Schasinglulu { 56*91f16700Schasinglulu uint64_t *u_boot_base; 57*91f16700Schasinglulu int i; 58*91f16700Schasinglulu 59*91f16700Schasinglulu u_boot_base = (void *)SUNXI_BL33_VIRT_BASE; 60*91f16700Schasinglulu 61*91f16700Schasinglulu for (i = 0; i < 2048 / sizeof(uint64_t); i++) { 62*91f16700Schasinglulu void *dtb_base; 63*91f16700Schasinglulu 64*91f16700Schasinglulu if (u_boot_base[i] != PRELOADED_BL33_BASE) 65*91f16700Schasinglulu continue; 66*91f16700Schasinglulu 67*91f16700Schasinglulu /* Does the suspected U-Boot size look anyhow reasonable? */ 68*91f16700Schasinglulu if (u_boot_base[i + 1] >= 256 * 1024 * 1024) 69*91f16700Schasinglulu continue; 70*91f16700Schasinglulu 71*91f16700Schasinglulu /* end of the image: base address + size */ 72*91f16700Schasinglulu dtb_base = (char *)u_boot_base + u_boot_base[i + 1]; 73*91f16700Schasinglulu 74*91f16700Schasinglulu if (fdt_check_header(dtb_base) == 0) { 75*91f16700Schasinglulu fdt = dtb_base; 76*91f16700Schasinglulu return; 77*91f16700Schasinglulu } 78*91f16700Schasinglulu } 79*91f16700Schasinglulu } 80*91f16700Schasinglulu 81*91f16700Schasinglulu void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, 82*91f16700Schasinglulu u_register_t arg2, u_register_t arg3) 83*91f16700Schasinglulu { 84*91f16700Schasinglulu /* Initialize the debug console as soon as possible */ 85*91f16700Schasinglulu console_16550_register(SUNXI_UART0_BASE, SUNXI_UART0_CLK_IN_HZ, 86*91f16700Schasinglulu SUNXI_UART0_BAUDRATE, &console); 87*91f16700Schasinglulu 88*91f16700Schasinglulu #ifdef BL32_BASE 89*91f16700Schasinglulu /* Populate entry point information for BL32 */ 90*91f16700Schasinglulu SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); 91*91f16700Schasinglulu SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); 92*91f16700Schasinglulu bl32_image_ep_info.pc = BL32_BASE; 93*91f16700Schasinglulu #endif 94*91f16700Schasinglulu 95*91f16700Schasinglulu /* Populate entry point information for BL33 */ 96*91f16700Schasinglulu SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0); 97*91f16700Schasinglulu /* 98*91f16700Schasinglulu * Tell BL31 where the non-trusted software image 99*91f16700Schasinglulu * is located and the entry state information 100*91f16700Schasinglulu */ 101*91f16700Schasinglulu bl33_image_ep_info.pc = PRELOADED_BL33_BASE; 102*91f16700Schasinglulu bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, 103*91f16700Schasinglulu DISABLE_ALL_EXCEPTIONS); 104*91f16700Schasinglulu SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); 105*91f16700Schasinglulu } 106*91f16700Schasinglulu 107*91f16700Schasinglulu void bl31_plat_arch_setup(void) 108*91f16700Schasinglulu { 109*91f16700Schasinglulu sunxi_configure_mmu_el3(0); 110*91f16700Schasinglulu } 111*91f16700Schasinglulu 112*91f16700Schasinglulu void bl31_platform_setup(void) 113*91f16700Schasinglulu { 114*91f16700Schasinglulu const char *soc_name; 115*91f16700Schasinglulu uint16_t soc_id = sunxi_read_soc_id(); 116*91f16700Schasinglulu 117*91f16700Schasinglulu switch (soc_id) { 118*91f16700Schasinglulu case SUNXI_SOC_A64: 119*91f16700Schasinglulu soc_name = "A64/H64/R18"; 120*91f16700Schasinglulu break; 121*91f16700Schasinglulu case SUNXI_SOC_H5: 122*91f16700Schasinglulu soc_name = "H5"; 123*91f16700Schasinglulu break; 124*91f16700Schasinglulu case SUNXI_SOC_H6: 125*91f16700Schasinglulu soc_name = "H6"; 126*91f16700Schasinglulu break; 127*91f16700Schasinglulu case SUNXI_SOC_H616: 128*91f16700Schasinglulu soc_name = "H616"; 129*91f16700Schasinglulu break; 130*91f16700Schasinglulu case SUNXI_SOC_R329: 131*91f16700Schasinglulu soc_name = "R329"; 132*91f16700Schasinglulu break; 133*91f16700Schasinglulu default: 134*91f16700Schasinglulu soc_name = "unknown"; 135*91f16700Schasinglulu break; 136*91f16700Schasinglulu } 137*91f16700Schasinglulu NOTICE("BL31: Detected Allwinner %s SoC (%04x)\n", soc_name, soc_id); 138*91f16700Schasinglulu 139*91f16700Schasinglulu generic_delay_timer_init(); 140*91f16700Schasinglulu 141*91f16700Schasinglulu sunxi_find_dtb(); 142*91f16700Schasinglulu if (fdt) { 143*91f16700Schasinglulu const char *model; 144*91f16700Schasinglulu int length; 145*91f16700Schasinglulu 146*91f16700Schasinglulu model = fdt_getprop(fdt, 0, "model", &length); 147*91f16700Schasinglulu NOTICE("BL31: Found U-Boot DTB at %p, model: %s\n", fdt, 148*91f16700Schasinglulu model ?: "unknown"); 149*91f16700Schasinglulu } else { 150*91f16700Schasinglulu NOTICE("BL31: No DTB found.\n"); 151*91f16700Schasinglulu } 152*91f16700Schasinglulu 153*91f16700Schasinglulu /* Configure the interrupt controller */ 154*91f16700Schasinglulu gicv2_driver_init(&sunxi_gic_data); 155*91f16700Schasinglulu gicv2_distif_init(); 156*91f16700Schasinglulu gicv2_pcpu_distif_init(); 157*91f16700Schasinglulu gicv2_cpuif_enable(); 158*91f16700Schasinglulu 159*91f16700Schasinglulu sunxi_security_setup(); 160*91f16700Schasinglulu 161*91f16700Schasinglulu /* 162*91f16700Schasinglulu * On the A64 U-Boot's SPL sets the bus clocks to some conservative 163*91f16700Schasinglulu * values, to work around FEL mode instabilities with SRAM C accesses. 164*91f16700Schasinglulu * FEL mode is gone when we reach ATF, so bring the AHB1 bus 165*91f16700Schasinglulu * (the "main" bus) clock frequency back to the recommended 200MHz, 166*91f16700Schasinglulu * for improved performance. 167*91f16700Schasinglulu */ 168*91f16700Schasinglulu if (soc_id == SUNXI_SOC_A64) 169*91f16700Schasinglulu mmio_write_32(SUNXI_CCU_BASE + 0x54, 0x00003180); 170*91f16700Schasinglulu 171*91f16700Schasinglulu /* 172*91f16700Schasinglulu * U-Boot or the kernel don't setup AHB2, which leaves it at the 173*91f16700Schasinglulu * AHB1 frequency (200 MHz, see above). However Allwinner recommends 174*91f16700Schasinglulu * 300 MHz, for improved Ethernet and USB performance. Switch the 175*91f16700Schasinglulu * clock to use "PLL_PERIPH0 / 2". 176*91f16700Schasinglulu */ 177*91f16700Schasinglulu if (soc_id == SUNXI_SOC_A64 || soc_id == SUNXI_SOC_H5) 178*91f16700Schasinglulu mmio_write_32(SUNXI_CCU_BASE + 0x5c, 0x1); 179*91f16700Schasinglulu 180*91f16700Schasinglulu sunxi_pmic_setup(soc_id, fdt); 181*91f16700Schasinglulu 182*91f16700Schasinglulu INFO("BL31: Platform setup done\n"); 183*91f16700Schasinglulu } 184*91f16700Schasinglulu 185*91f16700Schasinglulu void bl31_plat_runtime_setup(void) 186*91f16700Schasinglulu { 187*91f16700Schasinglulu /* Change the DTB if the configuration requires so. */ 188*91f16700Schasinglulu sunxi_prepare_dtb(fdt); 189*91f16700Schasinglulu 190*91f16700Schasinglulu console_switch_state(CONSOLE_FLAG_RUNTIME); 191*91f16700Schasinglulu } 192*91f16700Schasinglulu 193*91f16700Schasinglulu entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) 194*91f16700Schasinglulu { 195*91f16700Schasinglulu assert(sec_state_is_valid(type) != 0); 196*91f16700Schasinglulu 197*91f16700Schasinglulu if (type == NON_SECURE) 198*91f16700Schasinglulu return &bl33_image_ep_info; 199*91f16700Schasinglulu 200*91f16700Schasinglulu if ((type == SECURE) && bl32_image_ep_info.pc) 201*91f16700Schasinglulu return &bl32_image_ep_info; 202*91f16700Schasinglulu 203*91f16700Schasinglulu return NULL; 204*91f16700Schasinglulu } 205