12f2abcf4SHaojian Zhuang /* 2d2128731SHaojian Zhuang * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. 32f2abcf4SHaojian Zhuang * 42f2abcf4SHaojian Zhuang * SPDX-License-Identifier: BSD-3-Clause 52f2abcf4SHaojian Zhuang */ 62f2abcf4SHaojian Zhuang 72f2abcf4SHaojian Zhuang #include <arch_helpers.h> 82f2abcf4SHaojian Zhuang #include <arm_gic.h> 92f2abcf4SHaojian Zhuang #include <assert.h> 102f2abcf4SHaojian Zhuang #include <bl_common.h> 112f2abcf4SHaojian Zhuang #include <console.h> 122f2abcf4SHaojian Zhuang #include <debug.h> 132f2abcf4SHaojian Zhuang #include <delay_timer.h> 142f2abcf4SHaojian Zhuang #include <dw_ufs.h> 152f2abcf4SHaojian Zhuang #include <errno.h> 16ee1ebbd1SIsla Mitchell #include <generic_delay_timer.h> 172f2abcf4SHaojian Zhuang #include <gicv2.h> 182f2abcf4SHaojian Zhuang #include <hi3660.h> 192f2abcf4SHaojian Zhuang #include <mmio.h> 202f2abcf4SHaojian Zhuang #include <platform.h> 212f2abcf4SHaojian Zhuang #include <platform_def.h> 222f2abcf4SHaojian Zhuang #include <string.h> 232f2abcf4SHaojian Zhuang #include <tbbr/tbbr_img_desc.h> 242f2abcf4SHaojian Zhuang #include <ufs.h> 252f2abcf4SHaojian Zhuang 262f2abcf4SHaojian Zhuang #include "../../bl1/bl1_private.h" 272f2abcf4SHaojian Zhuang #include "hikey960_def.h" 282f2abcf4SHaojian Zhuang #include "hikey960_private.h" 292f2abcf4SHaojian Zhuang 302f2abcf4SHaojian Zhuang enum { 312f2abcf4SHaojian Zhuang BOOT_MODE_RECOVERY = 0, 322f2abcf4SHaojian Zhuang BOOT_MODE_NORMAL, 332f2abcf4SHaojian Zhuang BOOT_MODE_MASK = 1, 342f2abcf4SHaojian Zhuang }; 352f2abcf4SHaojian Zhuang 362f2abcf4SHaojian Zhuang /* 372f2abcf4SHaojian Zhuang * Declarations of linker defined symbols which will help us find the layout 382f2abcf4SHaojian Zhuang * of trusted RAM 392f2abcf4SHaojian Zhuang */ 402f2abcf4SHaojian Zhuang 412f2abcf4SHaojian Zhuang /* Data structure which holds the extents of the trusted RAM for BL1 */ 422f2abcf4SHaojian Zhuang static meminfo_t bl1_tzram_layout; 432f2abcf4SHaojian Zhuang 442f2abcf4SHaojian Zhuang /****************************************************************************** 452f2abcf4SHaojian Zhuang * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 462f2abcf4SHaojian Zhuang * interrupts. 472f2abcf4SHaojian Zhuang *****************************************************************************/ 482f2abcf4SHaojian Zhuang const unsigned int g0_interrupt_array[] = { 492f2abcf4SHaojian Zhuang IRQ_SEC_PHY_TIMER, 502f2abcf4SHaojian Zhuang IRQ_SEC_SGI_0 512f2abcf4SHaojian Zhuang }; 522f2abcf4SHaojian Zhuang 532f2abcf4SHaojian Zhuang const gicv2_driver_data_t hikey960_gic_data = { 542f2abcf4SHaojian Zhuang .gicd_base = GICD_REG_BASE, 552f2abcf4SHaojian Zhuang .gicc_base = GICC_REG_BASE, 562f2abcf4SHaojian Zhuang .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array), 572f2abcf4SHaojian Zhuang .g0_interrupt_array = g0_interrupt_array, 582f2abcf4SHaojian Zhuang }; 592f2abcf4SHaojian Zhuang 602f2abcf4SHaojian Zhuang meminfo_t *bl1_plat_sec_mem_layout(void) 612f2abcf4SHaojian Zhuang { 622f2abcf4SHaojian Zhuang return &bl1_tzram_layout; 632f2abcf4SHaojian Zhuang } 642f2abcf4SHaojian Zhuang 652de0c5ccSVictor Chong /******************************************************************************* 662de0c5ccSVictor Chong * Function that takes a memory layout into which BL2 has been loaded and 672de0c5ccSVictor Chong * populates a new memory layout for BL2 that ensures that BL1's data sections 682de0c5ccSVictor Chong * resident in secure RAM are not visible to BL2. 692de0c5ccSVictor Chong ******************************************************************************/ 702de0c5ccSVictor Chong void bl1_init_bl2_mem_layout(const meminfo_t *bl1_mem_layout, 712de0c5ccSVictor Chong meminfo_t *bl2_mem_layout) 722de0c5ccSVictor Chong { 732de0c5ccSVictor Chong 742de0c5ccSVictor Chong assert(bl1_mem_layout != NULL); 752de0c5ccSVictor Chong assert(bl2_mem_layout != NULL); 762de0c5ccSVictor Chong 772de0c5ccSVictor Chong /* 782de0c5ccSVictor Chong * Cannot remove BL1 RW data from the scope of memory visible to BL2 792de0c5ccSVictor Chong * like arm platforms because they overlap in hikey960 802de0c5ccSVictor Chong */ 812de0c5ccSVictor Chong bl2_mem_layout->total_base = BL2_BASE; 822de0c5ccSVictor Chong bl2_mem_layout->total_size = NS_BL1U_LIMIT - BL2_BASE; 832de0c5ccSVictor Chong 842de0c5ccSVictor Chong flush_dcache_range((unsigned long)bl2_mem_layout, sizeof(meminfo_t)); 852de0c5ccSVictor Chong } 862de0c5ccSVictor Chong 872f2abcf4SHaojian Zhuang /* 882f2abcf4SHaojian Zhuang * Perform any BL1 specific platform actions. 892f2abcf4SHaojian Zhuang */ 902f2abcf4SHaojian Zhuang void bl1_early_platform_setup(void) 912f2abcf4SHaojian Zhuang { 922f2abcf4SHaojian Zhuang unsigned int id, uart_base; 932f2abcf4SHaojian Zhuang 942f2abcf4SHaojian Zhuang generic_delay_timer_init(); 952f2abcf4SHaojian Zhuang hikey960_read_boardid(&id); 962f2abcf4SHaojian Zhuang if (id == 5300) 972f2abcf4SHaojian Zhuang uart_base = PL011_UART5_BASE; 982f2abcf4SHaojian Zhuang else 992f2abcf4SHaojian Zhuang uart_base = PL011_UART6_BASE; 1002f2abcf4SHaojian Zhuang /* Initialize the console to provide early debug support */ 1012f2abcf4SHaojian Zhuang console_init(uart_base, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE); 1022f2abcf4SHaojian Zhuang 1032f2abcf4SHaojian Zhuang /* Allow BL1 to see the whole Trusted RAM */ 1042f2abcf4SHaojian Zhuang bl1_tzram_layout.total_base = BL1_RW_BASE; 1052f2abcf4SHaojian Zhuang bl1_tzram_layout.total_size = BL1_RW_SIZE; 1062f2abcf4SHaojian Zhuang 1072f2abcf4SHaojian Zhuang INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT, 1082de0c5ccSVictor Chong BL1_RAM_LIMIT - BL1_RAM_BASE); /* bl1_size */ 1092f2abcf4SHaojian Zhuang } 1102f2abcf4SHaojian Zhuang 1112f2abcf4SHaojian Zhuang /* 1122f2abcf4SHaojian Zhuang * Perform the very early platform specific architecture setup here. At the 1132f2abcf4SHaojian Zhuang * moment this only does basic initialization. Later architectural setup 1142f2abcf4SHaojian Zhuang * (bl1_arch_setup()) does not do anything platform specific. 1152f2abcf4SHaojian Zhuang */ 1162f2abcf4SHaojian Zhuang void bl1_plat_arch_setup(void) 1172f2abcf4SHaojian Zhuang { 1182f2abcf4SHaojian Zhuang hikey960_init_mmu_el3(bl1_tzram_layout.total_base, 1192f2abcf4SHaojian Zhuang bl1_tzram_layout.total_size, 1202f2abcf4SHaojian Zhuang BL1_RO_BASE, 1212f2abcf4SHaojian Zhuang BL1_RO_LIMIT, 122*9f85f9e3SJoel Hutton BL_COHERENT_RAM_BASE, 123*9f85f9e3SJoel Hutton BL_COHERENT_RAM_END); 1242f2abcf4SHaojian Zhuang } 1252f2abcf4SHaojian Zhuang 1262f2abcf4SHaojian Zhuang static void hikey960_ufs_reset(void) 1272f2abcf4SHaojian Zhuang { 1282f2abcf4SHaojian Zhuang unsigned int data, mask; 1292f2abcf4SHaojian Zhuang 1302f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS7_REG, 1 << 14); 1312f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); 1322f2abcf4SHaojian Zhuang do { 1332f2abcf4SHaojian Zhuang data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); 1342f2abcf4SHaojian Zhuang } while (data & BIT_SYSCTRL_REF_CLOCK_EN); 1352f2abcf4SHaojian Zhuang /* use abb clk */ 1362f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_UFS_SYSCTRL_REG, BIT_UFS_REFCLK_SRC_SE1); 1372f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_REFCLK_ISO_EN); 1382f2abcf4SHaojian Zhuang mmio_write_32(PCTRL_PERI_CTRL3_REG, (1 << 0) | (1 << 16)); 1392f2abcf4SHaojian Zhuang mdelay(1); 1402f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN7_REG, 1 << 14); 1412f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); 1422f2abcf4SHaojian Zhuang 1432f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTEN3_REG, PERI_UFS_BIT); 1442f2abcf4SHaojian Zhuang do { 1452f2abcf4SHaojian Zhuang data = mmio_read_32(CRG_PERRSTSTAT3_REG); 1462f2abcf4SHaojian Zhuang } while ((data & PERI_UFS_BIT) == 0); 1472f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_MTCMOS_EN); 1482f2abcf4SHaojian Zhuang mdelay(1); 1492f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_PWR_READY); 1502f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, 1512f2abcf4SHaojian Zhuang MASK_UFS_DEVICE_RESET); 1522f2abcf4SHaojian Zhuang /* clear SC_DIV_UFS_PERIBUS */ 1532f2abcf4SHaojian Zhuang mask = SC_DIV_UFS_PERIBUS << 16; 1542f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV17_REG, mask); 1552f2abcf4SHaojian Zhuang /* set SC_DIV_UFSPHY_CFG(3) */ 1562f2abcf4SHaojian Zhuang mask = SC_DIV_UFSPHY_CFG_MASK << 16; 1572f2abcf4SHaojian Zhuang data = SC_DIV_UFSPHY_CFG(3); 1582f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV16_REG, mask | data); 1592f2abcf4SHaojian Zhuang data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); 1602f2abcf4SHaojian Zhuang data &= ~MASK_SYSCTRL_CFG_CLOCK_FREQ; 1612f2abcf4SHaojian Zhuang data |= 0x39; 1622f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_PHY_CLK_CTRL_REG, data); 1632f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, MASK_SYSCTRL_REF_CLOCK_SEL); 1642f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_CLOCK_GATE_BYPASS_REG, 1652f2abcf4SHaojian Zhuang MASK_UFS_CLK_GATE_BYPASS); 1662f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_UFS_SYSCTRL_REG, MASK_UFS_SYSCTRL_BYPASS); 1672f2abcf4SHaojian Zhuang 1682f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_PSW_CLK_CTRL_REG, BIT_SYSCTRL_PSW_CLK_EN); 1692f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_ISO_CTRL); 1702f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_PHY_ISO_CTRL); 1712f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_LP_ISOL_EN); 1722f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, PERI_ARST_UFS_BIT); 1732f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_RESET_CTRL_EN_REG, BIT_SYSCTRL_LP_RESET_N); 1742f2abcf4SHaojian Zhuang mdelay(1); 1752f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, 1762f2abcf4SHaojian Zhuang MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET); 1772f2abcf4SHaojian Zhuang mdelay(20); 1782f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, 1792f2abcf4SHaojian Zhuang 0x03300330); 1802f2abcf4SHaojian Zhuang 1812f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, PERI_UFS_BIT); 1822f2abcf4SHaojian Zhuang do { 1832f2abcf4SHaojian Zhuang data = mmio_read_32(CRG_PERRSTSTAT3_REG); 1842f2abcf4SHaojian Zhuang } while (data & PERI_UFS_BIT); 1852f2abcf4SHaojian Zhuang } 1862f2abcf4SHaojian Zhuang 1872f2abcf4SHaojian Zhuang static void hikey960_ufs_init(void) 1882f2abcf4SHaojian Zhuang { 1892f2abcf4SHaojian Zhuang dw_ufs_params_t ufs_params; 1902f2abcf4SHaojian Zhuang 1912f2abcf4SHaojian Zhuang memset(&ufs_params, 0, sizeof(ufs_params)); 1922f2abcf4SHaojian Zhuang ufs_params.reg_base = UFS_REG_BASE; 1932f2abcf4SHaojian Zhuang ufs_params.desc_base = HIKEY960_UFS_DESC_BASE; 1942f2abcf4SHaojian Zhuang ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE; 1952f2abcf4SHaojian Zhuang 1962f2abcf4SHaojian Zhuang if ((ufs_params.flags & UFS_FLAGS_SKIPINIT) == 0) 1972f2abcf4SHaojian Zhuang hikey960_ufs_reset(); 1982f2abcf4SHaojian Zhuang dw_ufs_init(&ufs_params); 1992f2abcf4SHaojian Zhuang } 2002f2abcf4SHaojian Zhuang 2012f2abcf4SHaojian Zhuang /* 2022f2abcf4SHaojian Zhuang * Function which will perform any remaining platform-specific setup that can 2032f2abcf4SHaojian Zhuang * occur after the MMU and data cache have been enabled. 2042f2abcf4SHaojian Zhuang */ 2052f2abcf4SHaojian Zhuang void bl1_platform_setup(void) 2062f2abcf4SHaojian Zhuang { 2072f2abcf4SHaojian Zhuang hikey960_clk_init(); 2082f2abcf4SHaojian Zhuang hikey960_pmu_init(); 2092f2abcf4SHaojian Zhuang hikey960_regulator_enable(); 2102f2abcf4SHaojian Zhuang hikey960_tzc_init(); 2112f2abcf4SHaojian Zhuang hikey960_peri_init(); 2122f2abcf4SHaojian Zhuang hikey960_ufs_init(); 2132f2abcf4SHaojian Zhuang hikey960_pinmux_init(); 2142f2abcf4SHaojian Zhuang hikey960_io_setup(); 2152f2abcf4SHaojian Zhuang } 2162f2abcf4SHaojian Zhuang 2172f2abcf4SHaojian Zhuang /* 2182f2abcf4SHaojian Zhuang * The following function checks if Firmware update is needed, 2192f2abcf4SHaojian Zhuang * by checking if TOC in FIP image is valid or not. 2202f2abcf4SHaojian Zhuang */ 2212f2abcf4SHaojian Zhuang unsigned int bl1_plat_get_next_image_id(void) 2222f2abcf4SHaojian Zhuang { 2232f2abcf4SHaojian Zhuang unsigned int mode, ret; 2242f2abcf4SHaojian Zhuang 2252f2abcf4SHaojian Zhuang mode = mmio_read_32(SCTRL_BAK_DATA0_REG); 2262f2abcf4SHaojian Zhuang switch (mode & BOOT_MODE_MASK) { 2272f2abcf4SHaojian Zhuang case BOOT_MODE_RECOVERY: 2282f2abcf4SHaojian Zhuang ret = NS_BL1U_IMAGE_ID; 2292f2abcf4SHaojian Zhuang break; 2302f2abcf4SHaojian Zhuang default: 2312f2abcf4SHaojian Zhuang WARN("Invalid boot mode is found:%d\n", mode); 2322f2abcf4SHaojian Zhuang panic(); 2332f2abcf4SHaojian Zhuang } 2342f2abcf4SHaojian Zhuang return ret; 2352f2abcf4SHaojian Zhuang } 2362f2abcf4SHaojian Zhuang 2372f2abcf4SHaojian Zhuang image_desc_t *bl1_plat_get_image_desc(unsigned int image_id) 2382f2abcf4SHaojian Zhuang { 2392f2abcf4SHaojian Zhuang unsigned int index = 0; 2402f2abcf4SHaojian Zhuang 2412f2abcf4SHaojian Zhuang while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) { 2422f2abcf4SHaojian Zhuang if (bl1_tbbr_image_descs[index].image_id == image_id) 2432f2abcf4SHaojian Zhuang return &bl1_tbbr_image_descs[index]; 2442f2abcf4SHaojian Zhuang index++; 2452f2abcf4SHaojian Zhuang } 2462f2abcf4SHaojian Zhuang 2472f2abcf4SHaojian Zhuang return NULL; 2482f2abcf4SHaojian Zhuang } 2492f2abcf4SHaojian Zhuang 2502f2abcf4SHaojian Zhuang void bl1_plat_set_ep_info(unsigned int image_id, 2512f2abcf4SHaojian Zhuang entry_point_info_t *ep_info) 2522f2abcf4SHaojian Zhuang { 2532f2abcf4SHaojian Zhuang unsigned int data = 0; 2542f2abcf4SHaojian Zhuang uintptr_t tmp = HIKEY960_NS_TMP_OFFSET; 2552f2abcf4SHaojian Zhuang 256d2128731SHaojian Zhuang if (image_id != NS_BL1U_IMAGE_ID) 257d2128731SHaojian Zhuang panic(); 2582f2abcf4SHaojian Zhuang /* Copy NS BL1U from 0x1AC1_8000 to 0x1AC9_8000 */ 2592f2abcf4SHaojian Zhuang memcpy((void *)tmp, (void *)HIKEY960_NS_IMAGE_OFFSET, 2602f2abcf4SHaojian Zhuang NS_BL1U_SIZE); 2612f2abcf4SHaojian Zhuang memcpy((void *)NS_BL1U_BASE, (void *)tmp, NS_BL1U_SIZE); 2622f2abcf4SHaojian Zhuang inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE); 2632f2abcf4SHaojian Zhuang /* Initialize the GIC driver, cpu and distributor interfaces */ 2642f2abcf4SHaojian Zhuang gicv2_driver_init(&hikey960_gic_data); 2652f2abcf4SHaojian Zhuang gicv2_distif_init(); 2662f2abcf4SHaojian Zhuang gicv2_pcpu_distif_init(); 2672f2abcf4SHaojian Zhuang gicv2_cpuif_enable(); 2682f2abcf4SHaojian Zhuang /* CNTFRQ is read-only in EL1 */ 2692f2abcf4SHaojian Zhuang write_cntfrq_el0(plat_get_syscnt_freq2()); 2702f2abcf4SHaojian Zhuang data = read_cpacr_el1(); 2712f2abcf4SHaojian Zhuang do { 2722f2abcf4SHaojian Zhuang data |= 3 << 20; 2732f2abcf4SHaojian Zhuang write_cpacr_el1(data); 2742f2abcf4SHaojian Zhuang data = read_cpacr_el1(); 2752f2abcf4SHaojian Zhuang } while ((data & (3 << 20)) != (3 << 20)); 2762f2abcf4SHaojian Zhuang INFO("cpacr_el1:0x%x\n", data); 2772f2abcf4SHaojian Zhuang 2782f2abcf4SHaojian Zhuang ep_info->args.arg0 = 0xffff & read_mpidr(); 2792f2abcf4SHaojian Zhuang ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, 2802f2abcf4SHaojian Zhuang DISABLE_ALL_EXCEPTIONS); 2812f2abcf4SHaojian Zhuang } 282