12f2abcf4SHaojian Zhuang /* 22f2abcf4SHaojian Zhuang * Copyright (c) 2017, 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 extern unsigned long __COHERENT_RAM_START__; 412f2abcf4SHaojian Zhuang extern unsigned long __COHERENT_RAM_END__; 422f2abcf4SHaojian Zhuang 432f2abcf4SHaojian Zhuang /* 442f2abcf4SHaojian Zhuang * The next 2 constants identify the extents of the coherent memory region. 452f2abcf4SHaojian Zhuang * These addresses are used by the MMU setup code and therefore they must be 462f2abcf4SHaojian Zhuang * page-aligned. It is the responsibility of the linker script to ensure that 472f2abcf4SHaojian Zhuang * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to 482f2abcf4SHaojian Zhuang * page-aligned addresses. 492f2abcf4SHaojian Zhuang */ 502f2abcf4SHaojian Zhuang #define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) 512f2abcf4SHaojian Zhuang #define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) 522f2abcf4SHaojian Zhuang 532f2abcf4SHaojian Zhuang /* Data structure which holds the extents of the trusted RAM for BL1 */ 542f2abcf4SHaojian Zhuang static meminfo_t bl1_tzram_layout; 552f2abcf4SHaojian Zhuang 562f2abcf4SHaojian Zhuang /****************************************************************************** 572f2abcf4SHaojian Zhuang * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 582f2abcf4SHaojian Zhuang * interrupts. 592f2abcf4SHaojian Zhuang *****************************************************************************/ 602f2abcf4SHaojian Zhuang const unsigned int g0_interrupt_array[] = { 612f2abcf4SHaojian Zhuang IRQ_SEC_PHY_TIMER, 622f2abcf4SHaojian Zhuang IRQ_SEC_SGI_0 632f2abcf4SHaojian Zhuang }; 642f2abcf4SHaojian Zhuang 652f2abcf4SHaojian Zhuang const gicv2_driver_data_t hikey960_gic_data = { 662f2abcf4SHaojian Zhuang .gicd_base = GICD_REG_BASE, 672f2abcf4SHaojian Zhuang .gicc_base = GICC_REG_BASE, 682f2abcf4SHaojian Zhuang .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array), 692f2abcf4SHaojian Zhuang .g0_interrupt_array = g0_interrupt_array, 702f2abcf4SHaojian Zhuang }; 712f2abcf4SHaojian Zhuang 722f2abcf4SHaojian Zhuang meminfo_t *bl1_plat_sec_mem_layout(void) 732f2abcf4SHaojian Zhuang { 742f2abcf4SHaojian Zhuang return &bl1_tzram_layout; 752f2abcf4SHaojian Zhuang } 762f2abcf4SHaojian Zhuang 77*2de0c5ccSVictor Chong #if LOAD_IMAGE_V2 78*2de0c5ccSVictor Chong /******************************************************************************* 79*2de0c5ccSVictor Chong * Function that takes a memory layout into which BL2 has been loaded and 80*2de0c5ccSVictor Chong * populates a new memory layout for BL2 that ensures that BL1's data sections 81*2de0c5ccSVictor Chong * resident in secure RAM are not visible to BL2. 82*2de0c5ccSVictor Chong ******************************************************************************/ 83*2de0c5ccSVictor Chong void bl1_init_bl2_mem_layout(const meminfo_t *bl1_mem_layout, 84*2de0c5ccSVictor Chong meminfo_t *bl2_mem_layout) 85*2de0c5ccSVictor Chong { 86*2de0c5ccSVictor Chong 87*2de0c5ccSVictor Chong assert(bl1_mem_layout != NULL); 88*2de0c5ccSVictor Chong assert(bl2_mem_layout != NULL); 89*2de0c5ccSVictor Chong 90*2de0c5ccSVictor Chong /* 91*2de0c5ccSVictor Chong * Cannot remove BL1 RW data from the scope of memory visible to BL2 92*2de0c5ccSVictor Chong * like arm platforms because they overlap in hikey960 93*2de0c5ccSVictor Chong */ 94*2de0c5ccSVictor Chong bl2_mem_layout->total_base = BL2_BASE; 95*2de0c5ccSVictor Chong bl2_mem_layout->total_size = NS_BL1U_LIMIT - BL2_BASE; 96*2de0c5ccSVictor Chong 97*2de0c5ccSVictor Chong flush_dcache_range((unsigned long)bl2_mem_layout, sizeof(meminfo_t)); 98*2de0c5ccSVictor Chong } 99*2de0c5ccSVictor Chong #endif /* LOAD_IMAGE_V2 */ 100*2de0c5ccSVictor Chong 1012f2abcf4SHaojian Zhuang /* 1022f2abcf4SHaojian Zhuang * Perform any BL1 specific platform actions. 1032f2abcf4SHaojian Zhuang */ 1042f2abcf4SHaojian Zhuang void bl1_early_platform_setup(void) 1052f2abcf4SHaojian Zhuang { 1062f2abcf4SHaojian Zhuang unsigned int id, uart_base; 1072f2abcf4SHaojian Zhuang 1082f2abcf4SHaojian Zhuang generic_delay_timer_init(); 1092f2abcf4SHaojian Zhuang hikey960_read_boardid(&id); 1102f2abcf4SHaojian Zhuang if (id == 5300) 1112f2abcf4SHaojian Zhuang uart_base = PL011_UART5_BASE; 1122f2abcf4SHaojian Zhuang else 1132f2abcf4SHaojian Zhuang uart_base = PL011_UART6_BASE; 1142f2abcf4SHaojian Zhuang /* Initialize the console to provide early debug support */ 1152f2abcf4SHaojian Zhuang console_init(uart_base, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE); 1162f2abcf4SHaojian Zhuang 1172f2abcf4SHaojian Zhuang /* Allow BL1 to see the whole Trusted RAM */ 1182f2abcf4SHaojian Zhuang bl1_tzram_layout.total_base = BL1_RW_BASE; 1192f2abcf4SHaojian Zhuang bl1_tzram_layout.total_size = BL1_RW_SIZE; 1202f2abcf4SHaojian Zhuang 121*2de0c5ccSVictor Chong #if !LOAD_IMAGE_V2 1222f2abcf4SHaojian Zhuang /* Calculate how much RAM BL1 is using and how much remains free */ 1232f2abcf4SHaojian Zhuang bl1_tzram_layout.free_base = BL1_RW_BASE; 1242f2abcf4SHaojian Zhuang bl1_tzram_layout.free_size = BL1_RW_SIZE; 1252f2abcf4SHaojian Zhuang reserve_mem(&bl1_tzram_layout.free_base, 1262f2abcf4SHaojian Zhuang &bl1_tzram_layout.free_size, 1272f2abcf4SHaojian Zhuang BL1_RAM_BASE, 128*2de0c5ccSVictor Chong BL1_RAM_LIMIT - BL1_RAM_BASE); /* bl1_size */ 129*2de0c5ccSVictor Chong #endif /* LOAD_IMAGE_V2 */ 1302f2abcf4SHaojian Zhuang 1312f2abcf4SHaojian Zhuang INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT, 132*2de0c5ccSVictor Chong BL1_RAM_LIMIT - BL1_RAM_BASE); /* bl1_size */ 1332f2abcf4SHaojian Zhuang } 1342f2abcf4SHaojian Zhuang 1352f2abcf4SHaojian Zhuang /* 1362f2abcf4SHaojian Zhuang * Perform the very early platform specific architecture setup here. At the 1372f2abcf4SHaojian Zhuang * moment this only does basic initialization. Later architectural setup 1382f2abcf4SHaojian Zhuang * (bl1_arch_setup()) does not do anything platform specific. 1392f2abcf4SHaojian Zhuang */ 1402f2abcf4SHaojian Zhuang void bl1_plat_arch_setup(void) 1412f2abcf4SHaojian Zhuang { 1422f2abcf4SHaojian Zhuang hikey960_init_mmu_el3(bl1_tzram_layout.total_base, 1432f2abcf4SHaojian Zhuang bl1_tzram_layout.total_size, 1442f2abcf4SHaojian Zhuang BL1_RO_BASE, 1452f2abcf4SHaojian Zhuang BL1_RO_LIMIT, 1462f2abcf4SHaojian Zhuang BL1_COHERENT_RAM_BASE, 1472f2abcf4SHaojian Zhuang BL1_COHERENT_RAM_LIMIT); 1482f2abcf4SHaojian Zhuang } 1492f2abcf4SHaojian Zhuang 1502f2abcf4SHaojian Zhuang static void hikey960_clk_init(void) 1512f2abcf4SHaojian Zhuang { 1522f2abcf4SHaojian Zhuang /* change ldi0 sel to ppll2 */ 1532f2abcf4SHaojian Zhuang mmio_write_32(0xfff350b4, 0xf0002000); 1542f2abcf4SHaojian Zhuang /* ldi0 20' */ 1552f2abcf4SHaojian Zhuang mmio_write_32(0xfff350bc, 0xfc004c00); 1562f2abcf4SHaojian Zhuang } 1572f2abcf4SHaojian Zhuang 1582f2abcf4SHaojian Zhuang static void hikey960_pmu_init(void) 1592f2abcf4SHaojian Zhuang { 1602f2abcf4SHaojian Zhuang /* clear np_xo_abb_dig_START bit in PMIC_CLK_TOP_CTRL7 register */ 1612f2abcf4SHaojian Zhuang mmio_clrbits_32(PMU_SSI0_CLK_TOP_CTRL7_REG, NP_XO_ABB_DIG); 1622f2abcf4SHaojian Zhuang } 1632f2abcf4SHaojian Zhuang 1642f2abcf4SHaojian Zhuang static void hikey960_enable_ppll3(void) 1652f2abcf4SHaojian Zhuang { 1662f2abcf4SHaojian Zhuang /* enable ppll3 */ 1672f2abcf4SHaojian Zhuang mmio_write_32(PMC_PPLL3_CTRL0_REG, 0x4904305); 1682f2abcf4SHaojian Zhuang mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x2300000); 1692f2abcf4SHaojian Zhuang mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x6300000); 1702f2abcf4SHaojian Zhuang } 1712f2abcf4SHaojian Zhuang 1722f2abcf4SHaojian Zhuang static void bus_idle_clear(unsigned int value) 1732f2abcf4SHaojian Zhuang { 1742f2abcf4SHaojian Zhuang unsigned int pmc_value, value1, value2; 1752f2abcf4SHaojian Zhuang int timeout = 100; 1762f2abcf4SHaojian Zhuang 1772f2abcf4SHaojian Zhuang pmc_value = value << 16; 1782f2abcf4SHaojian Zhuang pmc_value &= ~value; 1792f2abcf4SHaojian Zhuang mmio_write_32(PMC_NOC_POWER_IDLEREQ_REG, pmc_value); 1802f2abcf4SHaojian Zhuang 1812f2abcf4SHaojian Zhuang for (;;) { 1822f2abcf4SHaojian Zhuang value1 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLEACK_REG); 1832f2abcf4SHaojian Zhuang value2 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLE_REG); 1842f2abcf4SHaojian Zhuang if (((value1 & value) == 0) && ((value2 & value) == 0)) 1852f2abcf4SHaojian Zhuang break; 1862f2abcf4SHaojian Zhuang udelay(1); 1872f2abcf4SHaojian Zhuang timeout--; 1882f2abcf4SHaojian Zhuang if (timeout <= 0) { 1892f2abcf4SHaojian Zhuang WARN("%s timeout\n", __func__); 1902f2abcf4SHaojian Zhuang break; 1912f2abcf4SHaojian Zhuang } 1922f2abcf4SHaojian Zhuang } 1932f2abcf4SHaojian Zhuang } 1942f2abcf4SHaojian Zhuang 1952f2abcf4SHaojian Zhuang static void set_vivobus_power_up(void) 1962f2abcf4SHaojian Zhuang { 1972f2abcf4SHaojian Zhuang /* clk enable */ 1982f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x00020002); 1992f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN0_REG, 0x00001000); 2002f2abcf4SHaojian Zhuang } 2012f2abcf4SHaojian Zhuang 2022f2abcf4SHaojian Zhuang static void set_dss_power_up(void) 2032f2abcf4SHaojian Zhuang { 2042f2abcf4SHaojian Zhuang /* set edc0 133MHz = 1600MHz / 12 */ 2052f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV5_REG, 0x003f000b); 2062f2abcf4SHaojian Zhuang /* set ldi0 ppl0 */ 2072f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV3_REG, 0xf0001000); 2082f2abcf4SHaojian Zhuang /* set ldi0 133MHz, 1600MHz / 12 */ 2092f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV5_REG, 0xfc002c00); 2102f2abcf4SHaojian Zhuang /* mtcmos on */ 2112f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERPWREN_REG, 0x00000020); 2122f2abcf4SHaojian Zhuang udelay(100); 2132f2abcf4SHaojian Zhuang /* DISP CRG */ 2142f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000010); 2152f2abcf4SHaojian Zhuang /* clk enable */ 2162f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x01400140); 2172f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN0_REG, 0x00002000); 2182f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x0003b000); 2192f2abcf4SHaojian Zhuang udelay(1); 2202f2abcf4SHaojian Zhuang /* clk disable */ 2212f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS3_REG, 0x0003b000); 2222f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS0_REG, 0x00002000); 2232f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x01400000); 2242f2abcf4SHaojian Zhuang udelay(1); 2252f2abcf4SHaojian Zhuang /* iso disable */ 2262f2abcf4SHaojian Zhuang mmio_write_32(CRG_ISODIS_REG, 0x00000040); 2272f2abcf4SHaojian Zhuang /* unreset */ 2282f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000006); 2292f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000c00); 2302f2abcf4SHaojian Zhuang /* clk enable */ 2312f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x01400140); 2322f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN0_REG, 0x00002000); 2332f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x0003b000); 2342f2abcf4SHaojian Zhuang /* bus idle clear */ 2352f2abcf4SHaojian Zhuang bus_idle_clear(PMC_NOC_POWER_IDLEREQ_DSS); 2362f2abcf4SHaojian Zhuang /* set edc0 400MHz for 2K 1600MHz / 4 */ 2372f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV5_REG, 0x003f0003); 2382f2abcf4SHaojian Zhuang /* set ldi 266MHz, 1600MHz / 6 */ 2392f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV5_REG, 0xfc001400); 2402f2abcf4SHaojian Zhuang } 2412f2abcf4SHaojian Zhuang 2422f2abcf4SHaojian Zhuang static void set_vcodec_power_up(void) 2432f2abcf4SHaojian Zhuang { 2442f2abcf4SHaojian Zhuang /* clk enable */ 2452f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x00040004); 2462f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN0_REG, 0x00000060); 2472f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN2_REG, 0x10000000); 2482f2abcf4SHaojian Zhuang /* unreset */ 2492f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS0_REG, 0x00000018); 2502f2abcf4SHaojian Zhuang /* bus idle clear */ 2512f2abcf4SHaojian Zhuang bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VCODEC); 2522f2abcf4SHaojian Zhuang } 2532f2abcf4SHaojian Zhuang 2542f2abcf4SHaojian Zhuang static void set_vdec_power_up(void) 2552f2abcf4SHaojian Zhuang { 2562f2abcf4SHaojian Zhuang /* mtcmos on */ 2572f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERPWREN_REG, 0x00000004); 2582f2abcf4SHaojian Zhuang udelay(100); 2592f2abcf4SHaojian Zhuang /* clk enable */ 2602f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x80008000); 2612f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN2_REG, 0x20080000); 2622f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x00000800); 2632f2abcf4SHaojian Zhuang udelay(1); 2642f2abcf4SHaojian Zhuang /* clk disable */ 2652f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS3_REG, 0x00000800); 2662f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS2_REG, 0x20080000); 2672f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x80000000); 2682f2abcf4SHaojian Zhuang udelay(1); 2692f2abcf4SHaojian Zhuang /* iso disable */ 2702f2abcf4SHaojian Zhuang mmio_write_32(CRG_ISODIS_REG, 0x00000004); 2712f2abcf4SHaojian Zhuang /* unreset */ 2722f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000200); 2732f2abcf4SHaojian Zhuang /* clk enable */ 2742f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x80008000); 2752f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN2_REG, 0x20080000); 2762f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x00000800); 2772f2abcf4SHaojian Zhuang /* bus idle clear */ 2782f2abcf4SHaojian Zhuang bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VDEC); 2792f2abcf4SHaojian Zhuang } 2802f2abcf4SHaojian Zhuang 2812f2abcf4SHaojian Zhuang static void set_venc_power_up(void) 2822f2abcf4SHaojian Zhuang { 2832f2abcf4SHaojian Zhuang /* set venc ppll3 */ 2842f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV8_REG, 0x18001000); 2852f2abcf4SHaojian Zhuang /* set venc 258MHz, 1290MHz / 5 */ 2862f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV8_REG, 0x07c00100); 2872f2abcf4SHaojian Zhuang /* mtcmos on */ 2882f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERPWREN_REG, 0x00000002); 2892f2abcf4SHaojian Zhuang udelay(100); 2902f2abcf4SHaojian Zhuang /* clk enable */ 2912f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV19_REG, 0x00010001); 2922f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN2_REG, 0x40000100); 2932f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x00000400); 2942f2abcf4SHaojian Zhuang udelay(1); 2952f2abcf4SHaojian Zhuang /* clk disable */ 2962f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS3_REG, 0x00000400); 2972f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS2_REG, 0x40000100); 2982f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV19_REG, 0x00010000); 2992f2abcf4SHaojian Zhuang udelay(1); 3002f2abcf4SHaojian Zhuang /* iso disable */ 3012f2abcf4SHaojian Zhuang mmio_write_32(CRG_ISODIS_REG, 0x00000002); 3022f2abcf4SHaojian Zhuang /* unreset */ 3032f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000100); 3042f2abcf4SHaojian Zhuang /* clk enable */ 3052f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV19_REG, 0x00010001); 3062f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN2_REG, 0x40000100); 3072f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x00000400); 3082f2abcf4SHaojian Zhuang /* bus idle clear */ 3092f2abcf4SHaojian Zhuang bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VENC); 3102f2abcf4SHaojian Zhuang /* set venc 645MHz, 1290MHz / 2 */ 3112f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV8_REG, 0x07c00040); 3122f2abcf4SHaojian Zhuang } 3132f2abcf4SHaojian Zhuang 3142f2abcf4SHaojian Zhuang static void set_isp_power_up(void) 3152f2abcf4SHaojian Zhuang { 3162f2abcf4SHaojian Zhuang /* mtcmos on */ 3172f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERPWREN_REG, 0x00000001); 3182f2abcf4SHaojian Zhuang udelay(100); 3192f2abcf4SHaojian Zhuang /* clk enable */ 3202f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x70007000); 3212f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x00100010); 3222f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN5_REG, 0x01000010); 3232f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x0bf00000); 3242f2abcf4SHaojian Zhuang udelay(1); 3252f2abcf4SHaojian Zhuang /* clk disable */ 3262f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS5_REG, 0x01000010); 3272f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS3_REG, 0x0bf00000); 3282f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x70000000); 3292f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x00100000); 3302f2abcf4SHaojian Zhuang udelay(1); 3312f2abcf4SHaojian Zhuang /* iso disable */ 3322f2abcf4SHaojian Zhuang mmio_write_32(CRG_ISODIS_REG, 0x00000001); 3332f2abcf4SHaojian Zhuang /* unreset */ 3342f2abcf4SHaojian Zhuang mmio_write_32(CRG_ISP_SEC_RSTDIS_REG, 0x0000002f); 3352f2abcf4SHaojian Zhuang /* clk enable */ 3362f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x70007000); 3372f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x00100010); 3382f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN5_REG, 0x01000010); 3392f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x0bf00000); 3402f2abcf4SHaojian Zhuang /* bus idle clear */ 3412f2abcf4SHaojian Zhuang bus_idle_clear(PMC_NOC_POWER_IDLEREQ_ISP); 3422f2abcf4SHaojian Zhuang /* csi clk enable */ 3432f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x00700000); 3442f2abcf4SHaojian Zhuang } 3452f2abcf4SHaojian Zhuang 3462f2abcf4SHaojian Zhuang static void set_ivp_power_up(void) 3472f2abcf4SHaojian Zhuang { 3482f2abcf4SHaojian Zhuang /* set ivp ppll0 */ 3492f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV0_REG, 0xc0000000); 3502f2abcf4SHaojian Zhuang /* set ivp 267MHz, 1600MHz / 6 */ 3512f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV0_REG, 0x3c001400); 3522f2abcf4SHaojian Zhuang /* mtcmos on */ 3532f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERPWREN_REG, 0x00200000); 3542f2abcf4SHaojian Zhuang udelay(100); 3552f2abcf4SHaojian Zhuang /* IVP CRG unreset */ 3562f2abcf4SHaojian Zhuang mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000001); 3572f2abcf4SHaojian Zhuang /* clk enable */ 3582f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x02000200); 3592f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN4_REG, 0x000000a8); 3602f2abcf4SHaojian Zhuang udelay(1); 3612f2abcf4SHaojian Zhuang /* clk disable */ 3622f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS4_REG, 0x000000a8); 3632f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x02000000); 3642f2abcf4SHaojian Zhuang udelay(1); 3652f2abcf4SHaojian Zhuang /* iso disable */ 3662f2abcf4SHaojian Zhuang mmio_write_32(CRG_ISODIS_REG, 0x01000000); 3672f2abcf4SHaojian Zhuang /* unreset */ 3682f2abcf4SHaojian Zhuang mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000002); 3692f2abcf4SHaojian Zhuang /* clk enable */ 3702f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x02000200); 3712f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN4_REG, 0x000000a8); 3722f2abcf4SHaojian Zhuang /* bus idle clear */ 3732f2abcf4SHaojian Zhuang bus_idle_clear(PMC_NOC_POWER_IDLEREQ_IVP); 3742f2abcf4SHaojian Zhuang /* set ivp 533MHz, 1600MHz / 3 */ 3752f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV0_REG, 0x3c000800); 3762f2abcf4SHaojian Zhuang } 3772f2abcf4SHaojian Zhuang 3782f2abcf4SHaojian Zhuang static void set_audio_power_up(void) 3792f2abcf4SHaojian Zhuang { 3802f2abcf4SHaojian Zhuang unsigned int ret; 3812f2abcf4SHaojian Zhuang int timeout = 100; 3822f2abcf4SHaojian Zhuang /* mtcmos on */ 3832f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPWREN_REG, 0x00000001); 3842f2abcf4SHaojian Zhuang udelay(100); 3852f2abcf4SHaojian Zhuang /* clk enable */ 3862f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV19_REG, 0x80108010); 3872f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001); 3882f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000); 3892f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN0_REG, 0x04000000); 3902f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN5_REG, 0x00000080); 3912f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f); 3922f2abcf4SHaojian Zhuang udelay(1); 3932f2abcf4SHaojian Zhuang /* clk disable */ 3942f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPERDIS1_REG, 0x0000000f); 3952f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPERDIS0_REG, 0x0c000000); 3962f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS5_REG, 0x00000080); 3972f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS0_REG, 0x04000000); 3982f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010000); 3992f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV19_REG, 0x80100000); 4002f2abcf4SHaojian Zhuang udelay(1); 4012f2abcf4SHaojian Zhuang /* iso disable */ 4022f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCISODIS_REG, 0x00000001); 4032f2abcf4SHaojian Zhuang udelay(1); 4042f2abcf4SHaojian Zhuang /* unreset */ 4052f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_PERRSTDIS1_SEC_REG, 0x00000001); 4062f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPERRSTDIS0_REG, 0x00000780); 4072f2abcf4SHaojian Zhuang /* clk enable */ 4082f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV19_REG, 0x80108010); 4092f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001); 4102f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000); 4112f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN0_REG, 0x04000000); 4122f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN5_REG, 0x00000080); 4132f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f); 4142f2abcf4SHaojian Zhuang /* bus idle clear */ 4152f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPERCTRL7_REG, 0x00040000); 4162f2abcf4SHaojian Zhuang for (;;) { 4172f2abcf4SHaojian Zhuang ret = mmio_read_32(SCTRL_SCPERSTAT6_REG); 4182f2abcf4SHaojian Zhuang if (((ret & (1 << 5)) == 0) && ((ret & (1 << 8)) == 0)) 4192f2abcf4SHaojian Zhuang break; 4202f2abcf4SHaojian Zhuang udelay(1); 4212f2abcf4SHaojian Zhuang timeout--; 4222f2abcf4SHaojian Zhuang if (timeout <= 0) { 4232f2abcf4SHaojian Zhuang WARN("%s timeout\n", __func__); 4242f2abcf4SHaojian Zhuang break; 4252f2abcf4SHaojian Zhuang } 4262f2abcf4SHaojian Zhuang } 4272f2abcf4SHaojian Zhuang mmio_write_32(ASP_CFG_MMBUF_CTRL_REG, 0x00ff0000); 4282f2abcf4SHaojian Zhuang } 4292f2abcf4SHaojian Zhuang 4302f2abcf4SHaojian Zhuang static void set_pcie_power_up(void) 4312f2abcf4SHaojian Zhuang { 4322f2abcf4SHaojian Zhuang /* mtcmos on */ 4332f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPWREN_REG, 0x00000010); 4342f2abcf4SHaojian Zhuang udelay(100); 4352f2abcf4SHaojian Zhuang /* clk enable */ 4362f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800); 4372f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000); 4382f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN7_REG, 0x000003a0); 4392f2abcf4SHaojian Zhuang udelay(1); 4402f2abcf4SHaojian Zhuang /* clk disable */ 4412f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPERDIS2_REG, 0x00104000); 4422f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS7_REG, 0x000003a0); 4432f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000000); 4442f2abcf4SHaojian Zhuang udelay(1); 4452f2abcf4SHaojian Zhuang /* iso disable */ 4462f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCISODIS_REG, 0x00000030); 4472f2abcf4SHaojian Zhuang /* unreset */ 4482f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, 0x8c000000); 4492f2abcf4SHaojian Zhuang /* clk enable */ 4502f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800); 4512f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000); 4522f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN7_REG, 0x000003a0); 4532f2abcf4SHaojian Zhuang } 4542f2abcf4SHaojian Zhuang 4552f2abcf4SHaojian Zhuang static void ispfunc_enable(void) 4562f2abcf4SHaojian Zhuang { 4572f2abcf4SHaojian Zhuang /* enable ispfunc. Otherwise powerup isp_srt causes exception. */ 4582f2abcf4SHaojian Zhuang mmio_write_32(0xfff35000, 0x00000008); 4592f2abcf4SHaojian Zhuang mmio_write_32(0xfff35460, 0xc004ffff); 4602f2abcf4SHaojian Zhuang mmio_write_32(0xfff35030, 0x02000000); 4612f2abcf4SHaojian Zhuang mdelay(10); 4622f2abcf4SHaojian Zhuang } 4632f2abcf4SHaojian Zhuang 4642f2abcf4SHaojian Zhuang static void isps_control_clock(int flag) 4652f2abcf4SHaojian Zhuang { 4662f2abcf4SHaojian Zhuang unsigned int ret; 4672f2abcf4SHaojian Zhuang 4682f2abcf4SHaojian Zhuang /* flag: 0 -- disable clock, 1 -- enable clock */ 4692f2abcf4SHaojian Zhuang if (flag) { 4702f2abcf4SHaojian Zhuang ret = mmio_read_32(0xe8420364); 4712f2abcf4SHaojian Zhuang ret |= 1; 4722f2abcf4SHaojian Zhuang mmio_write_32(0xe8420364, ret); 4732f2abcf4SHaojian Zhuang } else { 4742f2abcf4SHaojian Zhuang ret = mmio_read_32(0xe8420364); 4752f2abcf4SHaojian Zhuang ret &= ~1; 4762f2abcf4SHaojian Zhuang mmio_write_32(0xe8420364, ret); 4772f2abcf4SHaojian Zhuang } 4782f2abcf4SHaojian Zhuang } 4792f2abcf4SHaojian Zhuang 4802f2abcf4SHaojian Zhuang static void set_isp_srt_power_up(void) 4812f2abcf4SHaojian Zhuang { 4822f2abcf4SHaojian Zhuang unsigned int ret; 4832f2abcf4SHaojian Zhuang 4842f2abcf4SHaojian Zhuang ispfunc_enable(); 4852f2abcf4SHaojian Zhuang /* reset */ 4862f2abcf4SHaojian Zhuang mmio_write_32(0xe8420374, 0x00000001); 4872f2abcf4SHaojian Zhuang mmio_write_32(0xe8420350, 0x00000000); 4882f2abcf4SHaojian Zhuang mmio_write_32(0xe8420358, 0x00000000); 4892f2abcf4SHaojian Zhuang /* mtcmos on */ 4902f2abcf4SHaojian Zhuang mmio_write_32(0xfff35150, 0x00400000); 4912f2abcf4SHaojian Zhuang udelay(100); 4922f2abcf4SHaojian Zhuang /* clk enable */ 4932f2abcf4SHaojian Zhuang isps_control_clock(1); 4942f2abcf4SHaojian Zhuang udelay(1); 4952f2abcf4SHaojian Zhuang isps_control_clock(0); 4962f2abcf4SHaojian Zhuang udelay(1); 4972f2abcf4SHaojian Zhuang /* iso disable */ 4982f2abcf4SHaojian Zhuang mmio_write_32(0xfff35148, 0x08000000); 4992f2abcf4SHaojian Zhuang /* unreset */ 5002f2abcf4SHaojian Zhuang ret = mmio_read_32(0xe8420374); 5012f2abcf4SHaojian Zhuang ret &= ~0x1; 5022f2abcf4SHaojian Zhuang mmio_write_32(0xe8420374, ret); 5032f2abcf4SHaojian Zhuang /* clk enable */ 5042f2abcf4SHaojian Zhuang isps_control_clock(1); 5052f2abcf4SHaojian Zhuang /* enable clock gating for accessing csi registers */ 5062f2abcf4SHaojian Zhuang mmio_write_32(0xe8420010, ~0); 5072f2abcf4SHaojian Zhuang } 5082f2abcf4SHaojian Zhuang 5092f2abcf4SHaojian Zhuang static void hikey960_regulator_enable(void) 5102f2abcf4SHaojian Zhuang { 5112f2abcf4SHaojian Zhuang set_vivobus_power_up(); 5122f2abcf4SHaojian Zhuang hikey960_enable_ppll3(); 5132f2abcf4SHaojian Zhuang set_dss_power_up(); 5142f2abcf4SHaojian Zhuang set_vcodec_power_up(); 5152f2abcf4SHaojian Zhuang set_vdec_power_up(); 5162f2abcf4SHaojian Zhuang set_venc_power_up(); 5172f2abcf4SHaojian Zhuang set_isp_power_up(); 5182f2abcf4SHaojian Zhuang set_ivp_power_up(); 5192f2abcf4SHaojian Zhuang set_audio_power_up(); 5202f2abcf4SHaojian Zhuang set_pcie_power_up(); 5212f2abcf4SHaojian Zhuang set_isp_srt_power_up(); 5222f2abcf4SHaojian Zhuang } 5232f2abcf4SHaojian Zhuang 5242f2abcf4SHaojian Zhuang static void hikey960_ufs_reset(void) 5252f2abcf4SHaojian Zhuang { 5262f2abcf4SHaojian Zhuang unsigned int data, mask; 5272f2abcf4SHaojian Zhuang 5282f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS7_REG, 1 << 14); 5292f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); 5302f2abcf4SHaojian Zhuang do { 5312f2abcf4SHaojian Zhuang data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); 5322f2abcf4SHaojian Zhuang } while (data & BIT_SYSCTRL_REF_CLOCK_EN); 5332f2abcf4SHaojian Zhuang /* use abb clk */ 5342f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_UFS_SYSCTRL_REG, BIT_UFS_REFCLK_SRC_SE1); 5352f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_REFCLK_ISO_EN); 5362f2abcf4SHaojian Zhuang mmio_write_32(PCTRL_PERI_CTRL3_REG, (1 << 0) | (1 << 16)); 5372f2abcf4SHaojian Zhuang mdelay(1); 5382f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN7_REG, 1 << 14); 5392f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); 5402f2abcf4SHaojian Zhuang 5412f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTEN3_REG, PERI_UFS_BIT); 5422f2abcf4SHaojian Zhuang do { 5432f2abcf4SHaojian Zhuang data = mmio_read_32(CRG_PERRSTSTAT3_REG); 5442f2abcf4SHaojian Zhuang } while ((data & PERI_UFS_BIT) == 0); 5452f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_MTCMOS_EN); 5462f2abcf4SHaojian Zhuang mdelay(1); 5472f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_PWR_READY); 5482f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, 5492f2abcf4SHaojian Zhuang MASK_UFS_DEVICE_RESET); 5502f2abcf4SHaojian Zhuang /* clear SC_DIV_UFS_PERIBUS */ 5512f2abcf4SHaojian Zhuang mask = SC_DIV_UFS_PERIBUS << 16; 5522f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV17_REG, mask); 5532f2abcf4SHaojian Zhuang /* set SC_DIV_UFSPHY_CFG(3) */ 5542f2abcf4SHaojian Zhuang mask = SC_DIV_UFSPHY_CFG_MASK << 16; 5552f2abcf4SHaojian Zhuang data = SC_DIV_UFSPHY_CFG(3); 5562f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV16_REG, mask | data); 5572f2abcf4SHaojian Zhuang data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); 5582f2abcf4SHaojian Zhuang data &= ~MASK_SYSCTRL_CFG_CLOCK_FREQ; 5592f2abcf4SHaojian Zhuang data |= 0x39; 5602f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_PHY_CLK_CTRL_REG, data); 5612f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, MASK_SYSCTRL_REF_CLOCK_SEL); 5622f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_CLOCK_GATE_BYPASS_REG, 5632f2abcf4SHaojian Zhuang MASK_UFS_CLK_GATE_BYPASS); 5642f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_UFS_SYSCTRL_REG, MASK_UFS_SYSCTRL_BYPASS); 5652f2abcf4SHaojian Zhuang 5662f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_PSW_CLK_CTRL_REG, BIT_SYSCTRL_PSW_CLK_EN); 5672f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_ISO_CTRL); 5682f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_PHY_ISO_CTRL); 5692f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_LP_ISOL_EN); 5702f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, PERI_ARST_UFS_BIT); 5712f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_RESET_CTRL_EN_REG, BIT_SYSCTRL_LP_RESET_N); 5722f2abcf4SHaojian Zhuang mdelay(1); 5732f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, 5742f2abcf4SHaojian Zhuang MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET); 5752f2abcf4SHaojian Zhuang mdelay(20); 5762f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, 5772f2abcf4SHaojian Zhuang 0x03300330); 5782f2abcf4SHaojian Zhuang 5792f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, PERI_UFS_BIT); 5802f2abcf4SHaojian Zhuang do { 5812f2abcf4SHaojian Zhuang data = mmio_read_32(CRG_PERRSTSTAT3_REG); 5822f2abcf4SHaojian Zhuang } while (data & PERI_UFS_BIT); 5832f2abcf4SHaojian Zhuang } 5842f2abcf4SHaojian Zhuang 5852f2abcf4SHaojian Zhuang static void hikey960_ufs_init(void) 5862f2abcf4SHaojian Zhuang { 5872f2abcf4SHaojian Zhuang dw_ufs_params_t ufs_params; 5882f2abcf4SHaojian Zhuang 5892f2abcf4SHaojian Zhuang memset(&ufs_params, 0, sizeof(ufs_params)); 5902f2abcf4SHaojian Zhuang ufs_params.reg_base = UFS_REG_BASE; 5912f2abcf4SHaojian Zhuang ufs_params.desc_base = HIKEY960_UFS_DESC_BASE; 5922f2abcf4SHaojian Zhuang ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE; 5932f2abcf4SHaojian Zhuang 5942f2abcf4SHaojian Zhuang if ((ufs_params.flags & UFS_FLAGS_SKIPINIT) == 0) 5952f2abcf4SHaojian Zhuang hikey960_ufs_reset(); 5962f2abcf4SHaojian Zhuang dw_ufs_init(&ufs_params); 5972f2abcf4SHaojian Zhuang } 5982f2abcf4SHaojian Zhuang 5992f2abcf4SHaojian Zhuang static void hikey960_tzc_init(void) 6002f2abcf4SHaojian Zhuang { 6012f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN0_REG, 0x7fbff066); 6022f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN1_REG, 0xfffff5fc); 6032f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN2_REG, 0x0007005c); 6042f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN3_REG, 0x37030700); 6052f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN4_REG, 0xf63fefae); 6062f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN5_REG, 0x000410fd); 6072f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN6_REG, 0x0063ff68); 6082f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN7_REG, 0x030000f3); 6092f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN8_REG, 0x00000007); 6102f2abcf4SHaojian Zhuang } 6112f2abcf4SHaojian Zhuang 6122f2abcf4SHaojian Zhuang static void hikey960_peri_init(void) 6132f2abcf4SHaojian Zhuang { 6142f2abcf4SHaojian Zhuang /* unreset */ 6152f2abcf4SHaojian Zhuang mmio_setbits_32(CRG_PERRSTDIS4_REG, 1); 6162f2abcf4SHaojian Zhuang } 6172f2abcf4SHaojian Zhuang 6182f2abcf4SHaojian Zhuang static void hikey960_pinmux_init(void) 6192f2abcf4SHaojian Zhuang { 6202f2abcf4SHaojian Zhuang unsigned int id; 6212f2abcf4SHaojian Zhuang 6222f2abcf4SHaojian Zhuang hikey960_read_boardid(&id); 6232f2abcf4SHaojian Zhuang if (id == 5301) { 6242f2abcf4SHaojian Zhuang /* hikey960 hardware v2 */ 6252f2abcf4SHaojian Zhuang /* GPIO150: LED */ 6262f2abcf4SHaojian Zhuang mmio_write_32(IOMG_FIX_006_REG, 0); 6272f2abcf4SHaojian Zhuang /* GPIO151: LED */ 6282f2abcf4SHaojian Zhuang mmio_write_32(IOMG_FIX_007_REG, 0); 6292f2abcf4SHaojian Zhuang /* GPIO189: LED */ 6302f2abcf4SHaojian Zhuang mmio_write_32(IOMG_AO_011_REG, 0); 6312f2abcf4SHaojian Zhuang /* GPIO190: LED */ 6322f2abcf4SHaojian Zhuang mmio_write_32(IOMG_AO_012_REG, 0); 6332f2abcf4SHaojian Zhuang /* GPIO46 */ 6342f2abcf4SHaojian Zhuang mmio_write_32(IOMG_044_REG, 0); 6352f2abcf4SHaojian Zhuang /* GPIO202 */ 6362f2abcf4SHaojian Zhuang mmio_write_32(IOMG_AO_023_REG, 0); 6372f2abcf4SHaojian Zhuang /* GPIO206 */ 6382f2abcf4SHaojian Zhuang mmio_write_32(IOMG_AO_026_REG, 0); 6392f2abcf4SHaojian Zhuang /* GPIO219 - PD pullup */ 6402f2abcf4SHaojian Zhuang mmio_write_32(IOMG_AO_039_REG, 0); 6412f2abcf4SHaojian Zhuang mmio_write_32(IOCG_AO_043_REG, 1 << 0); 6422f2abcf4SHaojian Zhuang } 6432f2abcf4SHaojian Zhuang /* GPIO005 - PMU SSI, 10mA */ 6442f2abcf4SHaojian Zhuang mmio_write_32(IOCG_006_REG, 2 << 4); 6452f2abcf4SHaojian Zhuang } 6462f2abcf4SHaojian Zhuang 6472f2abcf4SHaojian Zhuang /* 6482f2abcf4SHaojian Zhuang * Function which will perform any remaining platform-specific setup that can 6492f2abcf4SHaojian Zhuang * occur after the MMU and data cache have been enabled. 6502f2abcf4SHaojian Zhuang */ 6512f2abcf4SHaojian Zhuang void bl1_platform_setup(void) 6522f2abcf4SHaojian Zhuang { 6532f2abcf4SHaojian Zhuang hikey960_clk_init(); 6542f2abcf4SHaojian Zhuang hikey960_pmu_init(); 6552f2abcf4SHaojian Zhuang hikey960_regulator_enable(); 6562f2abcf4SHaojian Zhuang hikey960_tzc_init(); 6572f2abcf4SHaojian Zhuang hikey960_peri_init(); 6582f2abcf4SHaojian Zhuang hikey960_ufs_init(); 6592f2abcf4SHaojian Zhuang hikey960_pinmux_init(); 6602f2abcf4SHaojian Zhuang hikey960_io_setup(); 6612f2abcf4SHaojian Zhuang } 6622f2abcf4SHaojian Zhuang 6632f2abcf4SHaojian Zhuang /* 6642f2abcf4SHaojian Zhuang * The following function checks if Firmware update is needed, 6652f2abcf4SHaojian Zhuang * by checking if TOC in FIP image is valid or not. 6662f2abcf4SHaojian Zhuang */ 6672f2abcf4SHaojian Zhuang unsigned int bl1_plat_get_next_image_id(void) 6682f2abcf4SHaojian Zhuang { 6692f2abcf4SHaojian Zhuang unsigned int mode, ret; 6702f2abcf4SHaojian Zhuang 6712f2abcf4SHaojian Zhuang mode = mmio_read_32(SCTRL_BAK_DATA0_REG); 6722f2abcf4SHaojian Zhuang switch (mode & BOOT_MODE_MASK) { 6732f2abcf4SHaojian Zhuang case BOOT_MODE_RECOVERY: 6742f2abcf4SHaojian Zhuang ret = NS_BL1U_IMAGE_ID; 6752f2abcf4SHaojian Zhuang break; 6762f2abcf4SHaojian Zhuang case BOOT_MODE_NORMAL: 6772f2abcf4SHaojian Zhuang ret = BL2_IMAGE_ID; 6782f2abcf4SHaojian Zhuang break; 6792f2abcf4SHaojian Zhuang default: 6802f2abcf4SHaojian Zhuang WARN("Invalid boot mode is found:%d\n", mode); 6812f2abcf4SHaojian Zhuang panic(); 6822f2abcf4SHaojian Zhuang } 6832f2abcf4SHaojian Zhuang return ret; 6842f2abcf4SHaojian Zhuang } 6852f2abcf4SHaojian Zhuang 6862f2abcf4SHaojian Zhuang image_desc_t *bl1_plat_get_image_desc(unsigned int image_id) 6872f2abcf4SHaojian Zhuang { 6882f2abcf4SHaojian Zhuang unsigned int index = 0; 6892f2abcf4SHaojian Zhuang 6902f2abcf4SHaojian Zhuang while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) { 6912f2abcf4SHaojian Zhuang if (bl1_tbbr_image_descs[index].image_id == image_id) 6922f2abcf4SHaojian Zhuang return &bl1_tbbr_image_descs[index]; 6932f2abcf4SHaojian Zhuang index++; 6942f2abcf4SHaojian Zhuang } 6952f2abcf4SHaojian Zhuang 6962f2abcf4SHaojian Zhuang return NULL; 6972f2abcf4SHaojian Zhuang } 6982f2abcf4SHaojian Zhuang 6992f2abcf4SHaojian Zhuang void bl1_plat_set_ep_info(unsigned int image_id, 7002f2abcf4SHaojian Zhuang entry_point_info_t *ep_info) 7012f2abcf4SHaojian Zhuang { 7022f2abcf4SHaojian Zhuang unsigned int data = 0; 7032f2abcf4SHaojian Zhuang uintptr_t tmp = HIKEY960_NS_TMP_OFFSET; 7042f2abcf4SHaojian Zhuang 7052f2abcf4SHaojian Zhuang if (image_id == BL2_IMAGE_ID) 7062f2abcf4SHaojian Zhuang return; 7072f2abcf4SHaojian Zhuang /* Copy NS BL1U from 0x1AC1_8000 to 0x1AC9_8000 */ 7082f2abcf4SHaojian Zhuang memcpy((void *)tmp, (void *)HIKEY960_NS_IMAGE_OFFSET, 7092f2abcf4SHaojian Zhuang NS_BL1U_SIZE); 7102f2abcf4SHaojian Zhuang memcpy((void *)NS_BL1U_BASE, (void *)tmp, NS_BL1U_SIZE); 7112f2abcf4SHaojian Zhuang inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE); 7122f2abcf4SHaojian Zhuang /* Initialize the GIC driver, cpu and distributor interfaces */ 7132f2abcf4SHaojian Zhuang gicv2_driver_init(&hikey960_gic_data); 7142f2abcf4SHaojian Zhuang gicv2_distif_init(); 7152f2abcf4SHaojian Zhuang gicv2_pcpu_distif_init(); 7162f2abcf4SHaojian Zhuang gicv2_cpuif_enable(); 7172f2abcf4SHaojian Zhuang /* CNTFRQ is read-only in EL1 */ 7182f2abcf4SHaojian Zhuang write_cntfrq_el0(plat_get_syscnt_freq2()); 7192f2abcf4SHaojian Zhuang data = read_cpacr_el1(); 7202f2abcf4SHaojian Zhuang do { 7212f2abcf4SHaojian Zhuang data |= 3 << 20; 7222f2abcf4SHaojian Zhuang write_cpacr_el1(data); 7232f2abcf4SHaojian Zhuang data = read_cpacr_el1(); 7242f2abcf4SHaojian Zhuang } while ((data & (3 << 20)) != (3 << 20)); 7252f2abcf4SHaojian Zhuang INFO("cpacr_el1:0x%x\n", data); 7262f2abcf4SHaojian Zhuang 7272f2abcf4SHaojian Zhuang ep_info->args.arg0 = 0xffff & read_mpidr(); 7282f2abcf4SHaojian Zhuang ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, 7292f2abcf4SHaojian Zhuang DISABLE_ALL_EXCEPTIONS); 7302f2abcf4SHaojian Zhuang } 731