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 <assert.h> 82f2abcf4SHaojian Zhuang #include <errno.h> 92f2abcf4SHaojian Zhuang #include <string.h> 102f2abcf4SHaojian Zhuang 11*09d40e0eSAntonio Nino Diaz #include <platform_def.h> 12*09d40e0eSAntonio Nino Diaz 13*09d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 14*09d40e0eSAntonio Nino Diaz #include <bl1/tbbr/tbbr_img_desc.h> 15*09d40e0eSAntonio Nino Diaz #include <common/bl_common.h> 16*09d40e0eSAntonio Nino Diaz #include <common/debug.h> 17*09d40e0eSAntonio Nino Diaz #include <common/interrupt_props.h> 18*09d40e0eSAntonio Nino Diaz #include <drivers/arm/gicv2.h> 19*09d40e0eSAntonio Nino Diaz #include <drivers/arm/pl011.h> 20*09d40e0eSAntonio Nino Diaz #include <drivers/delay_timer.h> 21*09d40e0eSAntonio Nino Diaz #include <drivers/dw_ufs.h> 22*09d40e0eSAntonio Nino Diaz #include <drivers/generic_delay_timer.h> 23*09d40e0eSAntonio Nino Diaz #include <drivers/ufs.h> 24*09d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 25*09d40e0eSAntonio Nino Diaz #include <plat/common/platform.h> 26*09d40e0eSAntonio Nino Diaz 27*09d40e0eSAntonio Nino Diaz #include <hi3660.h> 28*09d40e0eSAntonio Nino Diaz #include "../../../bl1/bl1_private.h" 292f2abcf4SHaojian Zhuang #include "hikey960_def.h" 302f2abcf4SHaojian Zhuang #include "hikey960_private.h" 312f2abcf4SHaojian Zhuang 322f2abcf4SHaojian Zhuang enum { 332f2abcf4SHaojian Zhuang BOOT_MODE_RECOVERY = 0, 342f2abcf4SHaojian Zhuang BOOT_MODE_NORMAL, 352f2abcf4SHaojian Zhuang BOOT_MODE_MASK = 1, 362f2abcf4SHaojian Zhuang }; 372f2abcf4SHaojian Zhuang 382f2abcf4SHaojian Zhuang /* 392f2abcf4SHaojian Zhuang * Declarations of linker defined symbols which will help us find the layout 402f2abcf4SHaojian Zhuang * of trusted RAM 412f2abcf4SHaojian Zhuang */ 422f2abcf4SHaojian Zhuang 432f2abcf4SHaojian Zhuang /* Data structure which holds the extents of the trusted RAM for BL1 */ 442f2abcf4SHaojian Zhuang static meminfo_t bl1_tzram_layout; 455189ea27SJerome Forissier static console_pl011_t console; 462f2abcf4SHaojian Zhuang 472f2abcf4SHaojian Zhuang /****************************************************************************** 482f2abcf4SHaojian Zhuang * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 492f2abcf4SHaojian Zhuang * interrupts. 502f2abcf4SHaojian Zhuang *****************************************************************************/ 51210d90a9SAntonio Nino Diaz static const interrupt_prop_t g0_interrupt_props[] = { 52210d90a9SAntonio Nino Diaz INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, 53210d90a9SAntonio Nino Diaz GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), 54210d90a9SAntonio Nino Diaz INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, 55210d90a9SAntonio Nino Diaz GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), 562f2abcf4SHaojian Zhuang }; 572f2abcf4SHaojian Zhuang 582f2abcf4SHaojian Zhuang const gicv2_driver_data_t hikey960_gic_data = { 592f2abcf4SHaojian Zhuang .gicd_base = GICD_REG_BASE, 602f2abcf4SHaojian Zhuang .gicc_base = GICC_REG_BASE, 61210d90a9SAntonio Nino Diaz .interrupt_props = g0_interrupt_props, 62210d90a9SAntonio Nino Diaz .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props), 632f2abcf4SHaojian Zhuang }; 642f2abcf4SHaojian Zhuang 652f2abcf4SHaojian Zhuang meminfo_t *bl1_plat_sec_mem_layout(void) 662f2abcf4SHaojian Zhuang { 672f2abcf4SHaojian Zhuang return &bl1_tzram_layout; 682f2abcf4SHaojian Zhuang } 692f2abcf4SHaojian Zhuang 702f2abcf4SHaojian Zhuang /* 712f2abcf4SHaojian Zhuang * Perform any BL1 specific platform actions. 722f2abcf4SHaojian Zhuang */ 732f2abcf4SHaojian Zhuang void bl1_early_platform_setup(void) 742f2abcf4SHaojian Zhuang { 752f2abcf4SHaojian Zhuang unsigned int id, uart_base; 762f2abcf4SHaojian Zhuang 772f2abcf4SHaojian Zhuang generic_delay_timer_init(); 782f2abcf4SHaojian Zhuang hikey960_read_boardid(&id); 792f2abcf4SHaojian Zhuang if (id == 5300) 802f2abcf4SHaojian Zhuang uart_base = PL011_UART5_BASE; 812f2abcf4SHaojian Zhuang else 822f2abcf4SHaojian Zhuang uart_base = PL011_UART6_BASE; 832f2abcf4SHaojian Zhuang /* Initialize the console to provide early debug support */ 845189ea27SJerome Forissier console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ, 855189ea27SJerome Forissier PL011_BAUDRATE, &console); 862f2abcf4SHaojian Zhuang 872f2abcf4SHaojian Zhuang /* Allow BL1 to see the whole Trusted RAM */ 882f2abcf4SHaojian Zhuang bl1_tzram_layout.total_base = BL1_RW_BASE; 892f2abcf4SHaojian Zhuang bl1_tzram_layout.total_size = BL1_RW_SIZE; 902f2abcf4SHaojian Zhuang 912f2abcf4SHaojian Zhuang INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT, 922de0c5ccSVictor Chong BL1_RAM_LIMIT - BL1_RAM_BASE); /* bl1_size */ 932f2abcf4SHaojian Zhuang } 942f2abcf4SHaojian Zhuang 952f2abcf4SHaojian Zhuang /* 962f2abcf4SHaojian Zhuang * Perform the very early platform specific architecture setup here. At the 972f2abcf4SHaojian Zhuang * moment this only does basic initialization. Later architectural setup 982f2abcf4SHaojian Zhuang * (bl1_arch_setup()) does not do anything platform specific. 992f2abcf4SHaojian Zhuang */ 1002f2abcf4SHaojian Zhuang void bl1_plat_arch_setup(void) 1012f2abcf4SHaojian Zhuang { 1022f2abcf4SHaojian Zhuang hikey960_init_mmu_el3(bl1_tzram_layout.total_base, 1032f2abcf4SHaojian Zhuang bl1_tzram_layout.total_size, 1042f2abcf4SHaojian Zhuang BL1_RO_BASE, 1052f2abcf4SHaojian Zhuang BL1_RO_LIMIT, 1069f85f9e3SJoel Hutton BL_COHERENT_RAM_BASE, 1079f85f9e3SJoel Hutton BL_COHERENT_RAM_END); 1082f2abcf4SHaojian Zhuang } 1092f2abcf4SHaojian Zhuang 1102f2abcf4SHaojian Zhuang static void hikey960_ufs_reset(void) 1112f2abcf4SHaojian Zhuang { 1122f2abcf4SHaojian Zhuang unsigned int data, mask; 1132f2abcf4SHaojian Zhuang 1142f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS7_REG, 1 << 14); 1152f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); 1162f2abcf4SHaojian Zhuang do { 1172f2abcf4SHaojian Zhuang data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); 1182f2abcf4SHaojian Zhuang } while (data & BIT_SYSCTRL_REF_CLOCK_EN); 1192f2abcf4SHaojian Zhuang /* use abb clk */ 1202f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_UFS_SYSCTRL_REG, BIT_UFS_REFCLK_SRC_SE1); 1212f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_REFCLK_ISO_EN); 1222f2abcf4SHaojian Zhuang mmio_write_32(PCTRL_PERI_CTRL3_REG, (1 << 0) | (1 << 16)); 1232f2abcf4SHaojian Zhuang mdelay(1); 1242f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN7_REG, 1 << 14); 1252f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); 1262f2abcf4SHaojian Zhuang 1272f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTEN3_REG, PERI_UFS_BIT); 1282f2abcf4SHaojian Zhuang do { 1292f2abcf4SHaojian Zhuang data = mmio_read_32(CRG_PERRSTSTAT3_REG); 1302f2abcf4SHaojian Zhuang } while ((data & PERI_UFS_BIT) == 0); 1312f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_MTCMOS_EN); 1322f2abcf4SHaojian Zhuang mdelay(1); 1332f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_PWR_READY); 1342f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, 1352f2abcf4SHaojian Zhuang MASK_UFS_DEVICE_RESET); 1362f2abcf4SHaojian Zhuang /* clear SC_DIV_UFS_PERIBUS */ 1372f2abcf4SHaojian Zhuang mask = SC_DIV_UFS_PERIBUS << 16; 1382f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV17_REG, mask); 1392f2abcf4SHaojian Zhuang /* set SC_DIV_UFSPHY_CFG(3) */ 1402f2abcf4SHaojian Zhuang mask = SC_DIV_UFSPHY_CFG_MASK << 16; 1412f2abcf4SHaojian Zhuang data = SC_DIV_UFSPHY_CFG(3); 1422f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV16_REG, mask | data); 1432f2abcf4SHaojian Zhuang data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); 1442f2abcf4SHaojian Zhuang data &= ~MASK_SYSCTRL_CFG_CLOCK_FREQ; 1452f2abcf4SHaojian Zhuang data |= 0x39; 1462f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_PHY_CLK_CTRL_REG, data); 1472f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, MASK_SYSCTRL_REF_CLOCK_SEL); 1482f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_CLOCK_GATE_BYPASS_REG, 1492f2abcf4SHaojian Zhuang MASK_UFS_CLK_GATE_BYPASS); 1502f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_UFS_SYSCTRL_REG, MASK_UFS_SYSCTRL_BYPASS); 1512f2abcf4SHaojian Zhuang 1522f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_PSW_CLK_CTRL_REG, BIT_SYSCTRL_PSW_CLK_EN); 1532f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_ISO_CTRL); 1542f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_PHY_ISO_CTRL); 1552f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_LP_ISOL_EN); 1562f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, PERI_ARST_UFS_BIT); 1572f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_RESET_CTRL_EN_REG, BIT_SYSCTRL_LP_RESET_N); 1582f2abcf4SHaojian Zhuang mdelay(1); 1592f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, 1602f2abcf4SHaojian Zhuang MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET); 1612f2abcf4SHaojian Zhuang mdelay(20); 1622f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, 1632f2abcf4SHaojian Zhuang 0x03300330); 1642f2abcf4SHaojian Zhuang 1652f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, PERI_UFS_BIT); 1662f2abcf4SHaojian Zhuang do { 1672f2abcf4SHaojian Zhuang data = mmio_read_32(CRG_PERRSTSTAT3_REG); 1682f2abcf4SHaojian Zhuang } while (data & PERI_UFS_BIT); 1692f2abcf4SHaojian Zhuang } 1702f2abcf4SHaojian Zhuang 1712f2abcf4SHaojian Zhuang static void hikey960_ufs_init(void) 1722f2abcf4SHaojian Zhuang { 1732f2abcf4SHaojian Zhuang dw_ufs_params_t ufs_params; 1742f2abcf4SHaojian Zhuang 1752f2abcf4SHaojian Zhuang memset(&ufs_params, 0, sizeof(ufs_params)); 1762f2abcf4SHaojian Zhuang ufs_params.reg_base = UFS_REG_BASE; 1772f2abcf4SHaojian Zhuang ufs_params.desc_base = HIKEY960_UFS_DESC_BASE; 1782f2abcf4SHaojian Zhuang ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE; 1792f2abcf4SHaojian Zhuang 1802f2abcf4SHaojian Zhuang if ((ufs_params.flags & UFS_FLAGS_SKIPINIT) == 0) 1812f2abcf4SHaojian Zhuang hikey960_ufs_reset(); 1822f2abcf4SHaojian Zhuang dw_ufs_init(&ufs_params); 1832f2abcf4SHaojian Zhuang } 1842f2abcf4SHaojian Zhuang 1852f2abcf4SHaojian Zhuang /* 1862f2abcf4SHaojian Zhuang * Function which will perform any remaining platform-specific setup that can 1872f2abcf4SHaojian Zhuang * occur after the MMU and data cache have been enabled. 1882f2abcf4SHaojian Zhuang */ 1892f2abcf4SHaojian Zhuang void bl1_platform_setup(void) 1902f2abcf4SHaojian Zhuang { 1912f2abcf4SHaojian Zhuang hikey960_clk_init(); 1922f2abcf4SHaojian Zhuang hikey960_pmu_init(); 1932f2abcf4SHaojian Zhuang hikey960_regulator_enable(); 1942f2abcf4SHaojian Zhuang hikey960_tzc_init(); 1952f2abcf4SHaojian Zhuang hikey960_peri_init(); 1962f2abcf4SHaojian Zhuang hikey960_ufs_init(); 1972f2abcf4SHaojian Zhuang hikey960_pinmux_init(); 19816bec9c2SKaihua Zhong hikey960_gpio_init(); 1992f2abcf4SHaojian Zhuang hikey960_io_setup(); 2002f2abcf4SHaojian Zhuang } 2012f2abcf4SHaojian Zhuang 2022f2abcf4SHaojian Zhuang /* 2032f2abcf4SHaojian Zhuang * The following function checks if Firmware update is needed, 2042f2abcf4SHaojian Zhuang * by checking if TOC in FIP image is valid or not. 2052f2abcf4SHaojian Zhuang */ 2062f2abcf4SHaojian Zhuang unsigned int bl1_plat_get_next_image_id(void) 2072f2abcf4SHaojian Zhuang { 2082f2abcf4SHaojian Zhuang unsigned int mode, ret; 2092f2abcf4SHaojian Zhuang 2102f2abcf4SHaojian Zhuang mode = mmio_read_32(SCTRL_BAK_DATA0_REG); 2112f2abcf4SHaojian Zhuang switch (mode & BOOT_MODE_MASK) { 2122f2abcf4SHaojian Zhuang case BOOT_MODE_RECOVERY: 2132f2abcf4SHaojian Zhuang ret = NS_BL1U_IMAGE_ID; 2142f2abcf4SHaojian Zhuang break; 2152f2abcf4SHaojian Zhuang default: 2162f2abcf4SHaojian Zhuang WARN("Invalid boot mode is found:%d\n", mode); 2172f2abcf4SHaojian Zhuang panic(); 2182f2abcf4SHaojian Zhuang } 2192f2abcf4SHaojian Zhuang return ret; 2202f2abcf4SHaojian Zhuang } 2212f2abcf4SHaojian Zhuang 2222f2abcf4SHaojian Zhuang image_desc_t *bl1_plat_get_image_desc(unsigned int image_id) 2232f2abcf4SHaojian Zhuang { 2242f2abcf4SHaojian Zhuang unsigned int index = 0; 2252f2abcf4SHaojian Zhuang 2262f2abcf4SHaojian Zhuang while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) { 2272f2abcf4SHaojian Zhuang if (bl1_tbbr_image_descs[index].image_id == image_id) 2282f2abcf4SHaojian Zhuang return &bl1_tbbr_image_descs[index]; 2292f2abcf4SHaojian Zhuang index++; 2302f2abcf4SHaojian Zhuang } 2312f2abcf4SHaojian Zhuang 2322f2abcf4SHaojian Zhuang return NULL; 2332f2abcf4SHaojian Zhuang } 2342f2abcf4SHaojian Zhuang 2352f2abcf4SHaojian Zhuang void bl1_plat_set_ep_info(unsigned int image_id, 2362f2abcf4SHaojian Zhuang entry_point_info_t *ep_info) 2372f2abcf4SHaojian Zhuang { 2382f2abcf4SHaojian Zhuang unsigned int data = 0; 2392f2abcf4SHaojian Zhuang uintptr_t tmp = HIKEY960_NS_TMP_OFFSET; 2402f2abcf4SHaojian Zhuang 241d2128731SHaojian Zhuang if (image_id != NS_BL1U_IMAGE_ID) 242d2128731SHaojian Zhuang panic(); 2432f2abcf4SHaojian Zhuang /* Copy NS BL1U from 0x1AC1_8000 to 0x1AC9_8000 */ 2442f2abcf4SHaojian Zhuang memcpy((void *)tmp, (void *)HIKEY960_NS_IMAGE_OFFSET, 2452f2abcf4SHaojian Zhuang NS_BL1U_SIZE); 2462f2abcf4SHaojian Zhuang memcpy((void *)NS_BL1U_BASE, (void *)tmp, NS_BL1U_SIZE); 2472f2abcf4SHaojian Zhuang inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE); 2482f2abcf4SHaojian Zhuang /* Initialize the GIC driver, cpu and distributor interfaces */ 2492f2abcf4SHaojian Zhuang gicv2_driver_init(&hikey960_gic_data); 2502f2abcf4SHaojian Zhuang gicv2_distif_init(); 2512f2abcf4SHaojian Zhuang gicv2_pcpu_distif_init(); 2522f2abcf4SHaojian Zhuang gicv2_cpuif_enable(); 2532f2abcf4SHaojian Zhuang /* CNTFRQ is read-only in EL1 */ 2542f2abcf4SHaojian Zhuang write_cntfrq_el0(plat_get_syscnt_freq2()); 2552f2abcf4SHaojian Zhuang data = read_cpacr_el1(); 2562f2abcf4SHaojian Zhuang do { 2572f2abcf4SHaojian Zhuang data |= 3 << 20; 2582f2abcf4SHaojian Zhuang write_cpacr_el1(data); 2592f2abcf4SHaojian Zhuang data = read_cpacr_el1(); 2602f2abcf4SHaojian Zhuang } while ((data & (3 << 20)) != (3 << 20)); 2612f2abcf4SHaojian Zhuang INFO("cpacr_el1:0x%x\n", data); 2622f2abcf4SHaojian Zhuang 2632f2abcf4SHaojian Zhuang ep_info->args.arg0 = 0xffff & read_mpidr(); 2642f2abcf4SHaojian Zhuang ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, 2652f2abcf4SHaojian Zhuang DISABLE_ALL_EXCEPTIONS); 2662f2abcf4SHaojian Zhuang } 267