1*2f2abcf4SHaojian Zhuang /* 2*2f2abcf4SHaojian Zhuang * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3*2f2abcf4SHaojian Zhuang * 4*2f2abcf4SHaojian Zhuang * SPDX-License-Identifier: BSD-3-Clause 5*2f2abcf4SHaojian Zhuang */ 6*2f2abcf4SHaojian Zhuang 7*2f2abcf4SHaojian Zhuang #include <arch_helpers.h> 8*2f2abcf4SHaojian Zhuang #include <arm_gic.h> 9*2f2abcf4SHaojian Zhuang #include <assert.h> 10*2f2abcf4SHaojian Zhuang #include <bl_common.h> 11*2f2abcf4SHaojian Zhuang #include <console.h> 12*2f2abcf4SHaojian Zhuang #include <debug.h> 13*2f2abcf4SHaojian Zhuang #include <delay_timer.h> 14*2f2abcf4SHaojian Zhuang #include <dw_ufs.h> 15*2f2abcf4SHaojian Zhuang #include <errno.h> 16*2f2abcf4SHaojian Zhuang #include <gicv2.h> 17*2f2abcf4SHaojian Zhuang #include <hi3660.h> 18*2f2abcf4SHaojian Zhuang #include <mmio.h> 19*2f2abcf4SHaojian Zhuang #include <generic_delay_timer.h> 20*2f2abcf4SHaojian Zhuang #include <platform.h> 21*2f2abcf4SHaojian Zhuang #include <platform_def.h> 22*2f2abcf4SHaojian Zhuang #include <string.h> 23*2f2abcf4SHaojian Zhuang #include <tbbr/tbbr_img_desc.h> 24*2f2abcf4SHaojian Zhuang #include <ufs.h> 25*2f2abcf4SHaojian Zhuang 26*2f2abcf4SHaojian Zhuang #include "../../bl1/bl1_private.h" 27*2f2abcf4SHaojian Zhuang #include "hikey960_def.h" 28*2f2abcf4SHaojian Zhuang #include "hikey960_private.h" 29*2f2abcf4SHaojian Zhuang 30*2f2abcf4SHaojian Zhuang enum { 31*2f2abcf4SHaojian Zhuang BOOT_MODE_RECOVERY = 0, 32*2f2abcf4SHaojian Zhuang BOOT_MODE_NORMAL, 33*2f2abcf4SHaojian Zhuang BOOT_MODE_MASK = 1, 34*2f2abcf4SHaojian Zhuang }; 35*2f2abcf4SHaojian Zhuang 36*2f2abcf4SHaojian Zhuang /* 37*2f2abcf4SHaojian Zhuang * Declarations of linker defined symbols which will help us find the layout 38*2f2abcf4SHaojian Zhuang * of trusted RAM 39*2f2abcf4SHaojian Zhuang */ 40*2f2abcf4SHaojian Zhuang extern unsigned long __COHERENT_RAM_START__; 41*2f2abcf4SHaojian Zhuang extern unsigned long __COHERENT_RAM_END__; 42*2f2abcf4SHaojian Zhuang 43*2f2abcf4SHaojian Zhuang /* 44*2f2abcf4SHaojian Zhuang * The next 2 constants identify the extents of the coherent memory region. 45*2f2abcf4SHaojian Zhuang * These addresses are used by the MMU setup code and therefore they must be 46*2f2abcf4SHaojian Zhuang * page-aligned. It is the responsibility of the linker script to ensure that 47*2f2abcf4SHaojian Zhuang * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to 48*2f2abcf4SHaojian Zhuang * page-aligned addresses. 49*2f2abcf4SHaojian Zhuang */ 50*2f2abcf4SHaojian Zhuang #define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) 51*2f2abcf4SHaojian Zhuang #define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) 52*2f2abcf4SHaojian Zhuang 53*2f2abcf4SHaojian Zhuang /* Data structure which holds the extents of the trusted RAM for BL1 */ 54*2f2abcf4SHaojian Zhuang static meminfo_t bl1_tzram_layout; 55*2f2abcf4SHaojian Zhuang 56*2f2abcf4SHaojian Zhuang /****************************************************************************** 57*2f2abcf4SHaojian Zhuang * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 58*2f2abcf4SHaojian Zhuang * interrupts. 59*2f2abcf4SHaojian Zhuang *****************************************************************************/ 60*2f2abcf4SHaojian Zhuang const unsigned int g0_interrupt_array[] = { 61*2f2abcf4SHaojian Zhuang IRQ_SEC_PHY_TIMER, 62*2f2abcf4SHaojian Zhuang IRQ_SEC_SGI_0 63*2f2abcf4SHaojian Zhuang }; 64*2f2abcf4SHaojian Zhuang 65*2f2abcf4SHaojian Zhuang const gicv2_driver_data_t hikey960_gic_data = { 66*2f2abcf4SHaojian Zhuang .gicd_base = GICD_REG_BASE, 67*2f2abcf4SHaojian Zhuang .gicc_base = GICC_REG_BASE, 68*2f2abcf4SHaojian Zhuang .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array), 69*2f2abcf4SHaojian Zhuang .g0_interrupt_array = g0_interrupt_array, 70*2f2abcf4SHaojian Zhuang }; 71*2f2abcf4SHaojian Zhuang 72*2f2abcf4SHaojian Zhuang meminfo_t *bl1_plat_sec_mem_layout(void) 73*2f2abcf4SHaojian Zhuang { 74*2f2abcf4SHaojian Zhuang return &bl1_tzram_layout; 75*2f2abcf4SHaojian Zhuang } 76*2f2abcf4SHaojian Zhuang 77*2f2abcf4SHaojian Zhuang /* 78*2f2abcf4SHaojian Zhuang * Perform any BL1 specific platform actions. 79*2f2abcf4SHaojian Zhuang */ 80*2f2abcf4SHaojian Zhuang void bl1_early_platform_setup(void) 81*2f2abcf4SHaojian Zhuang { 82*2f2abcf4SHaojian Zhuang const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE; 83*2f2abcf4SHaojian Zhuang unsigned int id, uart_base; 84*2f2abcf4SHaojian Zhuang 85*2f2abcf4SHaojian Zhuang generic_delay_timer_init(); 86*2f2abcf4SHaojian Zhuang hikey960_read_boardid(&id); 87*2f2abcf4SHaojian Zhuang if (id == 5300) 88*2f2abcf4SHaojian Zhuang uart_base = PL011_UART5_BASE; 89*2f2abcf4SHaojian Zhuang else 90*2f2abcf4SHaojian Zhuang uart_base = PL011_UART6_BASE; 91*2f2abcf4SHaojian Zhuang /* Initialize the console to provide early debug support */ 92*2f2abcf4SHaojian Zhuang console_init(uart_base, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE); 93*2f2abcf4SHaojian Zhuang 94*2f2abcf4SHaojian Zhuang /* Allow BL1 to see the whole Trusted RAM */ 95*2f2abcf4SHaojian Zhuang bl1_tzram_layout.total_base = BL1_RW_BASE; 96*2f2abcf4SHaojian Zhuang bl1_tzram_layout.total_size = BL1_RW_SIZE; 97*2f2abcf4SHaojian Zhuang 98*2f2abcf4SHaojian Zhuang /* Calculate how much RAM BL1 is using and how much remains free */ 99*2f2abcf4SHaojian Zhuang bl1_tzram_layout.free_base = BL1_RW_BASE; 100*2f2abcf4SHaojian Zhuang bl1_tzram_layout.free_size = BL1_RW_SIZE; 101*2f2abcf4SHaojian Zhuang reserve_mem(&bl1_tzram_layout.free_base, 102*2f2abcf4SHaojian Zhuang &bl1_tzram_layout.free_size, 103*2f2abcf4SHaojian Zhuang BL1_RAM_BASE, 104*2f2abcf4SHaojian Zhuang bl1_size); 105*2f2abcf4SHaojian Zhuang 106*2f2abcf4SHaojian Zhuang INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT, 107*2f2abcf4SHaojian Zhuang bl1_size); 108*2f2abcf4SHaojian Zhuang } 109*2f2abcf4SHaojian Zhuang 110*2f2abcf4SHaojian Zhuang /* 111*2f2abcf4SHaojian Zhuang * Perform the very early platform specific architecture setup here. At the 112*2f2abcf4SHaojian Zhuang * moment this only does basic initialization. Later architectural setup 113*2f2abcf4SHaojian Zhuang * (bl1_arch_setup()) does not do anything platform specific. 114*2f2abcf4SHaojian Zhuang */ 115*2f2abcf4SHaojian Zhuang void bl1_plat_arch_setup(void) 116*2f2abcf4SHaojian Zhuang { 117*2f2abcf4SHaojian Zhuang hikey960_init_mmu_el3(bl1_tzram_layout.total_base, 118*2f2abcf4SHaojian Zhuang bl1_tzram_layout.total_size, 119*2f2abcf4SHaojian Zhuang BL1_RO_BASE, 120*2f2abcf4SHaojian Zhuang BL1_RO_LIMIT, 121*2f2abcf4SHaojian Zhuang BL1_COHERENT_RAM_BASE, 122*2f2abcf4SHaojian Zhuang BL1_COHERENT_RAM_LIMIT); 123*2f2abcf4SHaojian Zhuang } 124*2f2abcf4SHaojian Zhuang 125*2f2abcf4SHaojian Zhuang static void hikey960_clk_init(void) 126*2f2abcf4SHaojian Zhuang { 127*2f2abcf4SHaojian Zhuang /* change ldi0 sel to ppll2 */ 128*2f2abcf4SHaojian Zhuang mmio_write_32(0xfff350b4, 0xf0002000); 129*2f2abcf4SHaojian Zhuang /* ldi0 20' */ 130*2f2abcf4SHaojian Zhuang mmio_write_32(0xfff350bc, 0xfc004c00); 131*2f2abcf4SHaojian Zhuang } 132*2f2abcf4SHaojian Zhuang 133*2f2abcf4SHaojian Zhuang static void hikey960_pmu_init(void) 134*2f2abcf4SHaojian Zhuang { 135*2f2abcf4SHaojian Zhuang /* clear np_xo_abb_dig_START bit in PMIC_CLK_TOP_CTRL7 register */ 136*2f2abcf4SHaojian Zhuang mmio_clrbits_32(PMU_SSI0_CLK_TOP_CTRL7_REG, NP_XO_ABB_DIG); 137*2f2abcf4SHaojian Zhuang } 138*2f2abcf4SHaojian Zhuang 139*2f2abcf4SHaojian Zhuang static void hikey960_enable_ppll3(void) 140*2f2abcf4SHaojian Zhuang { 141*2f2abcf4SHaojian Zhuang /* enable ppll3 */ 142*2f2abcf4SHaojian Zhuang mmio_write_32(PMC_PPLL3_CTRL0_REG, 0x4904305); 143*2f2abcf4SHaojian Zhuang mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x2300000); 144*2f2abcf4SHaojian Zhuang mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x6300000); 145*2f2abcf4SHaojian Zhuang } 146*2f2abcf4SHaojian Zhuang 147*2f2abcf4SHaojian Zhuang static void bus_idle_clear(unsigned int value) 148*2f2abcf4SHaojian Zhuang { 149*2f2abcf4SHaojian Zhuang unsigned int pmc_value, value1, value2; 150*2f2abcf4SHaojian Zhuang int timeout = 100; 151*2f2abcf4SHaojian Zhuang 152*2f2abcf4SHaojian Zhuang pmc_value = value << 16; 153*2f2abcf4SHaojian Zhuang pmc_value &= ~value; 154*2f2abcf4SHaojian Zhuang mmio_write_32(PMC_NOC_POWER_IDLEREQ_REG, pmc_value); 155*2f2abcf4SHaojian Zhuang 156*2f2abcf4SHaojian Zhuang for (;;) { 157*2f2abcf4SHaojian Zhuang value1 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLEACK_REG); 158*2f2abcf4SHaojian Zhuang value2 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLE_REG); 159*2f2abcf4SHaojian Zhuang if (((value1 & value) == 0) && ((value2 & value) == 0)) 160*2f2abcf4SHaojian Zhuang break; 161*2f2abcf4SHaojian Zhuang udelay(1); 162*2f2abcf4SHaojian Zhuang timeout--; 163*2f2abcf4SHaojian Zhuang if (timeout <= 0) { 164*2f2abcf4SHaojian Zhuang WARN("%s timeout\n", __func__); 165*2f2abcf4SHaojian Zhuang break; 166*2f2abcf4SHaojian Zhuang } 167*2f2abcf4SHaojian Zhuang } 168*2f2abcf4SHaojian Zhuang } 169*2f2abcf4SHaojian Zhuang 170*2f2abcf4SHaojian Zhuang static void set_vivobus_power_up(void) 171*2f2abcf4SHaojian Zhuang { 172*2f2abcf4SHaojian Zhuang /* clk enable */ 173*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x00020002); 174*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN0_REG, 0x00001000); 175*2f2abcf4SHaojian Zhuang } 176*2f2abcf4SHaojian Zhuang 177*2f2abcf4SHaojian Zhuang static void set_dss_power_up(void) 178*2f2abcf4SHaojian Zhuang { 179*2f2abcf4SHaojian Zhuang /* set edc0 133MHz = 1600MHz / 12 */ 180*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV5_REG, 0x003f000b); 181*2f2abcf4SHaojian Zhuang /* set ldi0 ppl0 */ 182*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV3_REG, 0xf0001000); 183*2f2abcf4SHaojian Zhuang /* set ldi0 133MHz, 1600MHz / 12 */ 184*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV5_REG, 0xfc002c00); 185*2f2abcf4SHaojian Zhuang /* mtcmos on */ 186*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERPWREN_REG, 0x00000020); 187*2f2abcf4SHaojian Zhuang udelay(100); 188*2f2abcf4SHaojian Zhuang /* DISP CRG */ 189*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000010); 190*2f2abcf4SHaojian Zhuang /* clk enable */ 191*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x01400140); 192*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN0_REG, 0x00002000); 193*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x0003b000); 194*2f2abcf4SHaojian Zhuang udelay(1); 195*2f2abcf4SHaojian Zhuang /* clk disable */ 196*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS3_REG, 0x0003b000); 197*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS0_REG, 0x00002000); 198*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x01400000); 199*2f2abcf4SHaojian Zhuang udelay(1); 200*2f2abcf4SHaojian Zhuang /* iso disable */ 201*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_ISODIS_REG, 0x00000040); 202*2f2abcf4SHaojian Zhuang /* unreset */ 203*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000006); 204*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000c00); 205*2f2abcf4SHaojian Zhuang /* clk enable */ 206*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x01400140); 207*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN0_REG, 0x00002000); 208*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x0003b000); 209*2f2abcf4SHaojian Zhuang /* bus idle clear */ 210*2f2abcf4SHaojian Zhuang bus_idle_clear(PMC_NOC_POWER_IDLEREQ_DSS); 211*2f2abcf4SHaojian Zhuang /* set edc0 400MHz for 2K 1600MHz / 4 */ 212*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV5_REG, 0x003f0003); 213*2f2abcf4SHaojian Zhuang /* set ldi 266MHz, 1600MHz / 6 */ 214*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV5_REG, 0xfc001400); 215*2f2abcf4SHaojian Zhuang } 216*2f2abcf4SHaojian Zhuang 217*2f2abcf4SHaojian Zhuang static void set_vcodec_power_up(void) 218*2f2abcf4SHaojian Zhuang { 219*2f2abcf4SHaojian Zhuang /* clk enable */ 220*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x00040004); 221*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN0_REG, 0x00000060); 222*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN2_REG, 0x10000000); 223*2f2abcf4SHaojian Zhuang /* unreset */ 224*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS0_REG, 0x00000018); 225*2f2abcf4SHaojian Zhuang /* bus idle clear */ 226*2f2abcf4SHaojian Zhuang bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VCODEC); 227*2f2abcf4SHaojian Zhuang } 228*2f2abcf4SHaojian Zhuang 229*2f2abcf4SHaojian Zhuang static void set_vdec_power_up(void) 230*2f2abcf4SHaojian Zhuang { 231*2f2abcf4SHaojian Zhuang /* mtcmos on */ 232*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERPWREN_REG, 0x00000004); 233*2f2abcf4SHaojian Zhuang udelay(100); 234*2f2abcf4SHaojian Zhuang /* clk enable */ 235*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x80008000); 236*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN2_REG, 0x20080000); 237*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x00000800); 238*2f2abcf4SHaojian Zhuang udelay(1); 239*2f2abcf4SHaojian Zhuang /* clk disable */ 240*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS3_REG, 0x00000800); 241*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS2_REG, 0x20080000); 242*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x80000000); 243*2f2abcf4SHaojian Zhuang udelay(1); 244*2f2abcf4SHaojian Zhuang /* iso disable */ 245*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_ISODIS_REG, 0x00000004); 246*2f2abcf4SHaojian Zhuang /* unreset */ 247*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000200); 248*2f2abcf4SHaojian Zhuang /* clk enable */ 249*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x80008000); 250*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN2_REG, 0x20080000); 251*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x00000800); 252*2f2abcf4SHaojian Zhuang /* bus idle clear */ 253*2f2abcf4SHaojian Zhuang bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VDEC); 254*2f2abcf4SHaojian Zhuang } 255*2f2abcf4SHaojian Zhuang 256*2f2abcf4SHaojian Zhuang static void set_venc_power_up(void) 257*2f2abcf4SHaojian Zhuang { 258*2f2abcf4SHaojian Zhuang /* set venc ppll3 */ 259*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV8_REG, 0x18001000); 260*2f2abcf4SHaojian Zhuang /* set venc 258MHz, 1290MHz / 5 */ 261*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV8_REG, 0x07c00100); 262*2f2abcf4SHaojian Zhuang /* mtcmos on */ 263*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERPWREN_REG, 0x00000002); 264*2f2abcf4SHaojian Zhuang udelay(100); 265*2f2abcf4SHaojian Zhuang /* clk enable */ 266*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV19_REG, 0x00010001); 267*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN2_REG, 0x40000100); 268*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x00000400); 269*2f2abcf4SHaojian Zhuang udelay(1); 270*2f2abcf4SHaojian Zhuang /* clk disable */ 271*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS3_REG, 0x00000400); 272*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS2_REG, 0x40000100); 273*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV19_REG, 0x00010000); 274*2f2abcf4SHaojian Zhuang udelay(1); 275*2f2abcf4SHaojian Zhuang /* iso disable */ 276*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_ISODIS_REG, 0x00000002); 277*2f2abcf4SHaojian Zhuang /* unreset */ 278*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000100); 279*2f2abcf4SHaojian Zhuang /* clk enable */ 280*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV19_REG, 0x00010001); 281*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN2_REG, 0x40000100); 282*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x00000400); 283*2f2abcf4SHaojian Zhuang /* bus idle clear */ 284*2f2abcf4SHaojian Zhuang bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VENC); 285*2f2abcf4SHaojian Zhuang /* set venc 645MHz, 1290MHz / 2 */ 286*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV8_REG, 0x07c00040); 287*2f2abcf4SHaojian Zhuang } 288*2f2abcf4SHaojian Zhuang 289*2f2abcf4SHaojian Zhuang static void set_isp_power_up(void) 290*2f2abcf4SHaojian Zhuang { 291*2f2abcf4SHaojian Zhuang /* mtcmos on */ 292*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERPWREN_REG, 0x00000001); 293*2f2abcf4SHaojian Zhuang udelay(100); 294*2f2abcf4SHaojian Zhuang /* clk enable */ 295*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x70007000); 296*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x00100010); 297*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN5_REG, 0x01000010); 298*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x0bf00000); 299*2f2abcf4SHaojian Zhuang udelay(1); 300*2f2abcf4SHaojian Zhuang /* clk disable */ 301*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS5_REG, 0x01000010); 302*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS3_REG, 0x0bf00000); 303*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x70000000); 304*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x00100000); 305*2f2abcf4SHaojian Zhuang udelay(1); 306*2f2abcf4SHaojian Zhuang /* iso disable */ 307*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_ISODIS_REG, 0x00000001); 308*2f2abcf4SHaojian Zhuang /* unreset */ 309*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_ISP_SEC_RSTDIS_REG, 0x0000002f); 310*2f2abcf4SHaojian Zhuang /* clk enable */ 311*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV18_REG, 0x70007000); 312*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x00100010); 313*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN5_REG, 0x01000010); 314*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x0bf00000); 315*2f2abcf4SHaojian Zhuang /* bus idle clear */ 316*2f2abcf4SHaojian Zhuang bus_idle_clear(PMC_NOC_POWER_IDLEREQ_ISP); 317*2f2abcf4SHaojian Zhuang /* csi clk enable */ 318*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN3_REG, 0x00700000); 319*2f2abcf4SHaojian Zhuang } 320*2f2abcf4SHaojian Zhuang 321*2f2abcf4SHaojian Zhuang static void set_ivp_power_up(void) 322*2f2abcf4SHaojian Zhuang { 323*2f2abcf4SHaojian Zhuang /* set ivp ppll0 */ 324*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV0_REG, 0xc0000000); 325*2f2abcf4SHaojian Zhuang /* set ivp 267MHz, 1600MHz / 6 */ 326*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV0_REG, 0x3c001400); 327*2f2abcf4SHaojian Zhuang /* mtcmos on */ 328*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERPWREN_REG, 0x00200000); 329*2f2abcf4SHaojian Zhuang udelay(100); 330*2f2abcf4SHaojian Zhuang /* IVP CRG unreset */ 331*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000001); 332*2f2abcf4SHaojian Zhuang /* clk enable */ 333*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x02000200); 334*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN4_REG, 0x000000a8); 335*2f2abcf4SHaojian Zhuang udelay(1); 336*2f2abcf4SHaojian Zhuang /* clk disable */ 337*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS4_REG, 0x000000a8); 338*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x02000000); 339*2f2abcf4SHaojian Zhuang udelay(1); 340*2f2abcf4SHaojian Zhuang /* iso disable */ 341*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_ISODIS_REG, 0x01000000); 342*2f2abcf4SHaojian Zhuang /* unreset */ 343*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000002); 344*2f2abcf4SHaojian Zhuang /* clk enable */ 345*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV20_REG, 0x02000200); 346*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN4_REG, 0x000000a8); 347*2f2abcf4SHaojian Zhuang /* bus idle clear */ 348*2f2abcf4SHaojian Zhuang bus_idle_clear(PMC_NOC_POWER_IDLEREQ_IVP); 349*2f2abcf4SHaojian Zhuang /* set ivp 533MHz, 1600MHz / 3 */ 350*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV0_REG, 0x3c000800); 351*2f2abcf4SHaojian Zhuang } 352*2f2abcf4SHaojian Zhuang 353*2f2abcf4SHaojian Zhuang static void set_audio_power_up(void) 354*2f2abcf4SHaojian Zhuang { 355*2f2abcf4SHaojian Zhuang unsigned int ret; 356*2f2abcf4SHaojian Zhuang int timeout = 100; 357*2f2abcf4SHaojian Zhuang /* mtcmos on */ 358*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPWREN_REG, 0x00000001); 359*2f2abcf4SHaojian Zhuang udelay(100); 360*2f2abcf4SHaojian Zhuang /* clk enable */ 361*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV19_REG, 0x80108010); 362*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001); 363*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000); 364*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN0_REG, 0x04000000); 365*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN5_REG, 0x00000080); 366*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f); 367*2f2abcf4SHaojian Zhuang udelay(1); 368*2f2abcf4SHaojian Zhuang /* clk disable */ 369*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPERDIS1_REG, 0x0000000f); 370*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPERDIS0_REG, 0x0c000000); 371*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS5_REG, 0x00000080); 372*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS0_REG, 0x04000000); 373*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010000); 374*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV19_REG, 0x80100000); 375*2f2abcf4SHaojian Zhuang udelay(1); 376*2f2abcf4SHaojian Zhuang /* iso disable */ 377*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCISODIS_REG, 0x00000001); 378*2f2abcf4SHaojian Zhuang udelay(1); 379*2f2abcf4SHaojian Zhuang /* unreset */ 380*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_PERRSTDIS1_SEC_REG, 0x00000001); 381*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPERRSTDIS0_REG, 0x00000780); 382*2f2abcf4SHaojian Zhuang /* clk enable */ 383*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV19_REG, 0x80108010); 384*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001); 385*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000); 386*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN0_REG, 0x04000000); 387*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN5_REG, 0x00000080); 388*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f); 389*2f2abcf4SHaojian Zhuang /* bus idle clear */ 390*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPERCTRL7_REG, 0x00040000); 391*2f2abcf4SHaojian Zhuang for (;;) { 392*2f2abcf4SHaojian Zhuang ret = mmio_read_32(SCTRL_SCPERSTAT6_REG); 393*2f2abcf4SHaojian Zhuang if (((ret & (1 << 5)) == 0) && ((ret & (1 << 8)) == 0)) 394*2f2abcf4SHaojian Zhuang break; 395*2f2abcf4SHaojian Zhuang udelay(1); 396*2f2abcf4SHaojian Zhuang timeout--; 397*2f2abcf4SHaojian Zhuang if (timeout <= 0) { 398*2f2abcf4SHaojian Zhuang WARN("%s timeout\n", __func__); 399*2f2abcf4SHaojian Zhuang break; 400*2f2abcf4SHaojian Zhuang } 401*2f2abcf4SHaojian Zhuang } 402*2f2abcf4SHaojian Zhuang mmio_write_32(ASP_CFG_MMBUF_CTRL_REG, 0x00ff0000); 403*2f2abcf4SHaojian Zhuang } 404*2f2abcf4SHaojian Zhuang 405*2f2abcf4SHaojian Zhuang static void set_pcie_power_up(void) 406*2f2abcf4SHaojian Zhuang { 407*2f2abcf4SHaojian Zhuang /* mtcmos on */ 408*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPWREN_REG, 0x00000010); 409*2f2abcf4SHaojian Zhuang udelay(100); 410*2f2abcf4SHaojian Zhuang /* clk enable */ 411*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800); 412*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000); 413*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN7_REG, 0x000003a0); 414*2f2abcf4SHaojian Zhuang udelay(1); 415*2f2abcf4SHaojian Zhuang /* clk disable */ 416*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPERDIS2_REG, 0x00104000); 417*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS7_REG, 0x000003a0); 418*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000000); 419*2f2abcf4SHaojian Zhuang udelay(1); 420*2f2abcf4SHaojian Zhuang /* iso disable */ 421*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCISODIS_REG, 0x00000030); 422*2f2abcf4SHaojian Zhuang /* unreset */ 423*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, 0x8c000000); 424*2f2abcf4SHaojian Zhuang /* clk enable */ 425*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800); 426*2f2abcf4SHaojian Zhuang mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000); 427*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN7_REG, 0x000003a0); 428*2f2abcf4SHaojian Zhuang } 429*2f2abcf4SHaojian Zhuang 430*2f2abcf4SHaojian Zhuang static void ispfunc_enable(void) 431*2f2abcf4SHaojian Zhuang { 432*2f2abcf4SHaojian Zhuang /* enable ispfunc. Otherwise powerup isp_srt causes exception. */ 433*2f2abcf4SHaojian Zhuang mmio_write_32(0xfff35000, 0x00000008); 434*2f2abcf4SHaojian Zhuang mmio_write_32(0xfff35460, 0xc004ffff); 435*2f2abcf4SHaojian Zhuang mmio_write_32(0xfff35030, 0x02000000); 436*2f2abcf4SHaojian Zhuang mdelay(10); 437*2f2abcf4SHaojian Zhuang } 438*2f2abcf4SHaojian Zhuang 439*2f2abcf4SHaojian Zhuang static void isps_control_clock(int flag) 440*2f2abcf4SHaojian Zhuang { 441*2f2abcf4SHaojian Zhuang unsigned int ret; 442*2f2abcf4SHaojian Zhuang 443*2f2abcf4SHaojian Zhuang /* flag: 0 -- disable clock, 1 -- enable clock */ 444*2f2abcf4SHaojian Zhuang if (flag) { 445*2f2abcf4SHaojian Zhuang ret = mmio_read_32(0xe8420364); 446*2f2abcf4SHaojian Zhuang ret |= 1; 447*2f2abcf4SHaojian Zhuang mmio_write_32(0xe8420364, ret); 448*2f2abcf4SHaojian Zhuang } else { 449*2f2abcf4SHaojian Zhuang ret = mmio_read_32(0xe8420364); 450*2f2abcf4SHaojian Zhuang ret &= ~1; 451*2f2abcf4SHaojian Zhuang mmio_write_32(0xe8420364, ret); 452*2f2abcf4SHaojian Zhuang } 453*2f2abcf4SHaojian Zhuang } 454*2f2abcf4SHaojian Zhuang 455*2f2abcf4SHaojian Zhuang static void set_isp_srt_power_up(void) 456*2f2abcf4SHaojian Zhuang { 457*2f2abcf4SHaojian Zhuang unsigned int ret; 458*2f2abcf4SHaojian Zhuang 459*2f2abcf4SHaojian Zhuang ispfunc_enable(); 460*2f2abcf4SHaojian Zhuang /* reset */ 461*2f2abcf4SHaojian Zhuang mmio_write_32(0xe8420374, 0x00000001); 462*2f2abcf4SHaojian Zhuang mmio_write_32(0xe8420350, 0x00000000); 463*2f2abcf4SHaojian Zhuang mmio_write_32(0xe8420358, 0x00000000); 464*2f2abcf4SHaojian Zhuang /* mtcmos on */ 465*2f2abcf4SHaojian Zhuang mmio_write_32(0xfff35150, 0x00400000); 466*2f2abcf4SHaojian Zhuang udelay(100); 467*2f2abcf4SHaojian Zhuang /* clk enable */ 468*2f2abcf4SHaojian Zhuang isps_control_clock(1); 469*2f2abcf4SHaojian Zhuang udelay(1); 470*2f2abcf4SHaojian Zhuang isps_control_clock(0); 471*2f2abcf4SHaojian Zhuang udelay(1); 472*2f2abcf4SHaojian Zhuang /* iso disable */ 473*2f2abcf4SHaojian Zhuang mmio_write_32(0xfff35148, 0x08000000); 474*2f2abcf4SHaojian Zhuang /* unreset */ 475*2f2abcf4SHaojian Zhuang ret = mmio_read_32(0xe8420374); 476*2f2abcf4SHaojian Zhuang ret &= ~0x1; 477*2f2abcf4SHaojian Zhuang mmio_write_32(0xe8420374, ret); 478*2f2abcf4SHaojian Zhuang /* clk enable */ 479*2f2abcf4SHaojian Zhuang isps_control_clock(1); 480*2f2abcf4SHaojian Zhuang /* enable clock gating for accessing csi registers */ 481*2f2abcf4SHaojian Zhuang mmio_write_32(0xe8420010, ~0); 482*2f2abcf4SHaojian Zhuang } 483*2f2abcf4SHaojian Zhuang 484*2f2abcf4SHaojian Zhuang static void hikey960_regulator_enable(void) 485*2f2abcf4SHaojian Zhuang { 486*2f2abcf4SHaojian Zhuang set_vivobus_power_up(); 487*2f2abcf4SHaojian Zhuang hikey960_enable_ppll3(); 488*2f2abcf4SHaojian Zhuang set_dss_power_up(); 489*2f2abcf4SHaojian Zhuang set_vcodec_power_up(); 490*2f2abcf4SHaojian Zhuang set_vdec_power_up(); 491*2f2abcf4SHaojian Zhuang set_venc_power_up(); 492*2f2abcf4SHaojian Zhuang set_isp_power_up(); 493*2f2abcf4SHaojian Zhuang set_ivp_power_up(); 494*2f2abcf4SHaojian Zhuang set_audio_power_up(); 495*2f2abcf4SHaojian Zhuang set_pcie_power_up(); 496*2f2abcf4SHaojian Zhuang set_isp_srt_power_up(); 497*2f2abcf4SHaojian Zhuang } 498*2f2abcf4SHaojian Zhuang 499*2f2abcf4SHaojian Zhuang static void hikey960_ufs_reset(void) 500*2f2abcf4SHaojian Zhuang { 501*2f2abcf4SHaojian Zhuang unsigned int data, mask; 502*2f2abcf4SHaojian Zhuang 503*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERDIS7_REG, 1 << 14); 504*2f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); 505*2f2abcf4SHaojian Zhuang do { 506*2f2abcf4SHaojian Zhuang data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); 507*2f2abcf4SHaojian Zhuang } while (data & BIT_SYSCTRL_REF_CLOCK_EN); 508*2f2abcf4SHaojian Zhuang /* use abb clk */ 509*2f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_UFS_SYSCTRL_REG, BIT_UFS_REFCLK_SRC_SE1); 510*2f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_REFCLK_ISO_EN); 511*2f2abcf4SHaojian Zhuang mmio_write_32(PCTRL_PERI_CTRL3_REG, (1 << 0) | (1 << 16)); 512*2f2abcf4SHaojian Zhuang mdelay(1); 513*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PEREN7_REG, 1 << 14); 514*2f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); 515*2f2abcf4SHaojian Zhuang 516*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTEN3_REG, PERI_UFS_BIT); 517*2f2abcf4SHaojian Zhuang do { 518*2f2abcf4SHaojian Zhuang data = mmio_read_32(CRG_PERRSTSTAT3_REG); 519*2f2abcf4SHaojian Zhuang } while ((data & PERI_UFS_BIT) == 0); 520*2f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_MTCMOS_EN); 521*2f2abcf4SHaojian Zhuang mdelay(1); 522*2f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_PWR_READY); 523*2f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, 524*2f2abcf4SHaojian Zhuang MASK_UFS_DEVICE_RESET); 525*2f2abcf4SHaojian Zhuang /* clear SC_DIV_UFS_PERIBUS */ 526*2f2abcf4SHaojian Zhuang mask = SC_DIV_UFS_PERIBUS << 16; 527*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV17_REG, mask); 528*2f2abcf4SHaojian Zhuang /* set SC_DIV_UFSPHY_CFG(3) */ 529*2f2abcf4SHaojian Zhuang mask = SC_DIV_UFSPHY_CFG_MASK << 16; 530*2f2abcf4SHaojian Zhuang data = SC_DIV_UFSPHY_CFG(3); 531*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_CLKDIV16_REG, mask | data); 532*2f2abcf4SHaojian Zhuang data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); 533*2f2abcf4SHaojian Zhuang data &= ~MASK_SYSCTRL_CFG_CLOCK_FREQ; 534*2f2abcf4SHaojian Zhuang data |= 0x39; 535*2f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_PHY_CLK_CTRL_REG, data); 536*2f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, MASK_SYSCTRL_REF_CLOCK_SEL); 537*2f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_CLOCK_GATE_BYPASS_REG, 538*2f2abcf4SHaojian Zhuang MASK_UFS_CLK_GATE_BYPASS); 539*2f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_UFS_SYSCTRL_REG, MASK_UFS_SYSCTRL_BYPASS); 540*2f2abcf4SHaojian Zhuang 541*2f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_PSW_CLK_CTRL_REG, BIT_SYSCTRL_PSW_CLK_EN); 542*2f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_ISO_CTRL); 543*2f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_PHY_ISO_CTRL); 544*2f2abcf4SHaojian Zhuang mmio_clrbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_LP_ISOL_EN); 545*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, PERI_ARST_UFS_BIT); 546*2f2abcf4SHaojian Zhuang mmio_setbits_32(UFS_SYS_RESET_CTRL_EN_REG, BIT_SYSCTRL_LP_RESET_N); 547*2f2abcf4SHaojian Zhuang mdelay(1); 548*2f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, 549*2f2abcf4SHaojian Zhuang MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET); 550*2f2abcf4SHaojian Zhuang mdelay(20); 551*2f2abcf4SHaojian Zhuang mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, 552*2f2abcf4SHaojian Zhuang 0x03300330); 553*2f2abcf4SHaojian Zhuang 554*2f2abcf4SHaojian Zhuang mmio_write_32(CRG_PERRSTDIS3_REG, PERI_UFS_BIT); 555*2f2abcf4SHaojian Zhuang do { 556*2f2abcf4SHaojian Zhuang data = mmio_read_32(CRG_PERRSTSTAT3_REG); 557*2f2abcf4SHaojian Zhuang } while (data & PERI_UFS_BIT); 558*2f2abcf4SHaojian Zhuang } 559*2f2abcf4SHaojian Zhuang 560*2f2abcf4SHaojian Zhuang static void hikey960_ufs_init(void) 561*2f2abcf4SHaojian Zhuang { 562*2f2abcf4SHaojian Zhuang dw_ufs_params_t ufs_params; 563*2f2abcf4SHaojian Zhuang 564*2f2abcf4SHaojian Zhuang memset(&ufs_params, 0, sizeof(ufs_params)); 565*2f2abcf4SHaojian Zhuang ufs_params.reg_base = UFS_REG_BASE; 566*2f2abcf4SHaojian Zhuang ufs_params.desc_base = HIKEY960_UFS_DESC_BASE; 567*2f2abcf4SHaojian Zhuang ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE; 568*2f2abcf4SHaojian Zhuang 569*2f2abcf4SHaojian Zhuang if ((ufs_params.flags & UFS_FLAGS_SKIPINIT) == 0) 570*2f2abcf4SHaojian Zhuang hikey960_ufs_reset(); 571*2f2abcf4SHaojian Zhuang dw_ufs_init(&ufs_params); 572*2f2abcf4SHaojian Zhuang } 573*2f2abcf4SHaojian Zhuang 574*2f2abcf4SHaojian Zhuang static void hikey960_tzc_init(void) 575*2f2abcf4SHaojian Zhuang { 576*2f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN0_REG, 0x7fbff066); 577*2f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN1_REG, 0xfffff5fc); 578*2f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN2_REG, 0x0007005c); 579*2f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN3_REG, 0x37030700); 580*2f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN4_REG, 0xf63fefae); 581*2f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN5_REG, 0x000410fd); 582*2f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN6_REG, 0x0063ff68); 583*2f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN7_REG, 0x030000f3); 584*2f2abcf4SHaojian Zhuang mmio_write_32(TZC_EN8_REG, 0x00000007); 585*2f2abcf4SHaojian Zhuang } 586*2f2abcf4SHaojian Zhuang 587*2f2abcf4SHaojian Zhuang static void hikey960_peri_init(void) 588*2f2abcf4SHaojian Zhuang { 589*2f2abcf4SHaojian Zhuang /* unreset */ 590*2f2abcf4SHaojian Zhuang mmio_setbits_32(CRG_PERRSTDIS4_REG, 1); 591*2f2abcf4SHaojian Zhuang } 592*2f2abcf4SHaojian Zhuang 593*2f2abcf4SHaojian Zhuang static void hikey960_pinmux_init(void) 594*2f2abcf4SHaojian Zhuang { 595*2f2abcf4SHaojian Zhuang unsigned int id; 596*2f2abcf4SHaojian Zhuang 597*2f2abcf4SHaojian Zhuang hikey960_read_boardid(&id); 598*2f2abcf4SHaojian Zhuang if (id == 5301) { 599*2f2abcf4SHaojian Zhuang /* hikey960 hardware v2 */ 600*2f2abcf4SHaojian Zhuang /* GPIO150: LED */ 601*2f2abcf4SHaojian Zhuang mmio_write_32(IOMG_FIX_006_REG, 0); 602*2f2abcf4SHaojian Zhuang /* GPIO151: LED */ 603*2f2abcf4SHaojian Zhuang mmio_write_32(IOMG_FIX_007_REG, 0); 604*2f2abcf4SHaojian Zhuang /* GPIO189: LED */ 605*2f2abcf4SHaojian Zhuang mmio_write_32(IOMG_AO_011_REG, 0); 606*2f2abcf4SHaojian Zhuang /* GPIO190: LED */ 607*2f2abcf4SHaojian Zhuang mmio_write_32(IOMG_AO_012_REG, 0); 608*2f2abcf4SHaojian Zhuang /* GPIO46 */ 609*2f2abcf4SHaojian Zhuang mmio_write_32(IOMG_044_REG, 0); 610*2f2abcf4SHaojian Zhuang /* GPIO202 */ 611*2f2abcf4SHaojian Zhuang mmio_write_32(IOMG_AO_023_REG, 0); 612*2f2abcf4SHaojian Zhuang /* GPIO206 */ 613*2f2abcf4SHaojian Zhuang mmio_write_32(IOMG_AO_026_REG, 0); 614*2f2abcf4SHaojian Zhuang /* GPIO219 - PD pullup */ 615*2f2abcf4SHaojian Zhuang mmio_write_32(IOMG_AO_039_REG, 0); 616*2f2abcf4SHaojian Zhuang mmio_write_32(IOCG_AO_043_REG, 1 << 0); 617*2f2abcf4SHaojian Zhuang } 618*2f2abcf4SHaojian Zhuang /* GPIO005 - PMU SSI, 10mA */ 619*2f2abcf4SHaojian Zhuang mmio_write_32(IOCG_006_REG, 2 << 4); 620*2f2abcf4SHaojian Zhuang } 621*2f2abcf4SHaojian Zhuang 622*2f2abcf4SHaojian Zhuang /* 623*2f2abcf4SHaojian Zhuang * Function which will perform any remaining platform-specific setup that can 624*2f2abcf4SHaojian Zhuang * occur after the MMU and data cache have been enabled. 625*2f2abcf4SHaojian Zhuang */ 626*2f2abcf4SHaojian Zhuang void bl1_platform_setup(void) 627*2f2abcf4SHaojian Zhuang { 628*2f2abcf4SHaojian Zhuang hikey960_clk_init(); 629*2f2abcf4SHaojian Zhuang hikey960_pmu_init(); 630*2f2abcf4SHaojian Zhuang hikey960_regulator_enable(); 631*2f2abcf4SHaojian Zhuang hikey960_tzc_init(); 632*2f2abcf4SHaojian Zhuang hikey960_peri_init(); 633*2f2abcf4SHaojian Zhuang hikey960_ufs_init(); 634*2f2abcf4SHaojian Zhuang hikey960_pinmux_init(); 635*2f2abcf4SHaojian Zhuang hikey960_io_setup(); 636*2f2abcf4SHaojian Zhuang } 637*2f2abcf4SHaojian Zhuang 638*2f2abcf4SHaojian Zhuang /* 639*2f2abcf4SHaojian Zhuang * The following function checks if Firmware update is needed, 640*2f2abcf4SHaojian Zhuang * by checking if TOC in FIP image is valid or not. 641*2f2abcf4SHaojian Zhuang */ 642*2f2abcf4SHaojian Zhuang unsigned int bl1_plat_get_next_image_id(void) 643*2f2abcf4SHaojian Zhuang { 644*2f2abcf4SHaojian Zhuang unsigned int mode, ret; 645*2f2abcf4SHaojian Zhuang 646*2f2abcf4SHaojian Zhuang mode = mmio_read_32(SCTRL_BAK_DATA0_REG); 647*2f2abcf4SHaojian Zhuang switch (mode & BOOT_MODE_MASK) { 648*2f2abcf4SHaojian Zhuang case BOOT_MODE_RECOVERY: 649*2f2abcf4SHaojian Zhuang ret = NS_BL1U_IMAGE_ID; 650*2f2abcf4SHaojian Zhuang break; 651*2f2abcf4SHaojian Zhuang case BOOT_MODE_NORMAL: 652*2f2abcf4SHaojian Zhuang ret = BL2_IMAGE_ID; 653*2f2abcf4SHaojian Zhuang break; 654*2f2abcf4SHaojian Zhuang default: 655*2f2abcf4SHaojian Zhuang WARN("Invalid boot mode is found:%d\n", mode); 656*2f2abcf4SHaojian Zhuang panic(); 657*2f2abcf4SHaojian Zhuang } 658*2f2abcf4SHaojian Zhuang return ret; 659*2f2abcf4SHaojian Zhuang } 660*2f2abcf4SHaojian Zhuang 661*2f2abcf4SHaojian Zhuang image_desc_t *bl1_plat_get_image_desc(unsigned int image_id) 662*2f2abcf4SHaojian Zhuang { 663*2f2abcf4SHaojian Zhuang unsigned int index = 0; 664*2f2abcf4SHaojian Zhuang 665*2f2abcf4SHaojian Zhuang while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) { 666*2f2abcf4SHaojian Zhuang if (bl1_tbbr_image_descs[index].image_id == image_id) 667*2f2abcf4SHaojian Zhuang return &bl1_tbbr_image_descs[index]; 668*2f2abcf4SHaojian Zhuang index++; 669*2f2abcf4SHaojian Zhuang } 670*2f2abcf4SHaojian Zhuang 671*2f2abcf4SHaojian Zhuang return NULL; 672*2f2abcf4SHaojian Zhuang } 673*2f2abcf4SHaojian Zhuang 674*2f2abcf4SHaojian Zhuang void bl1_plat_set_ep_info(unsigned int image_id, 675*2f2abcf4SHaojian Zhuang entry_point_info_t *ep_info) 676*2f2abcf4SHaojian Zhuang { 677*2f2abcf4SHaojian Zhuang unsigned int data = 0; 678*2f2abcf4SHaojian Zhuang uintptr_t tmp = HIKEY960_NS_TMP_OFFSET; 679*2f2abcf4SHaojian Zhuang 680*2f2abcf4SHaojian Zhuang if (image_id == BL2_IMAGE_ID) 681*2f2abcf4SHaojian Zhuang return; 682*2f2abcf4SHaojian Zhuang /* Copy NS BL1U from 0x1AC1_8000 to 0x1AC9_8000 */ 683*2f2abcf4SHaojian Zhuang memcpy((void *)tmp, (void *)HIKEY960_NS_IMAGE_OFFSET, 684*2f2abcf4SHaojian Zhuang NS_BL1U_SIZE); 685*2f2abcf4SHaojian Zhuang memcpy((void *)NS_BL1U_BASE, (void *)tmp, NS_BL1U_SIZE); 686*2f2abcf4SHaojian Zhuang inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE); 687*2f2abcf4SHaojian Zhuang /* Initialize the GIC driver, cpu and distributor interfaces */ 688*2f2abcf4SHaojian Zhuang gicv2_driver_init(&hikey960_gic_data); 689*2f2abcf4SHaojian Zhuang gicv2_distif_init(); 690*2f2abcf4SHaojian Zhuang gicv2_pcpu_distif_init(); 691*2f2abcf4SHaojian Zhuang gicv2_cpuif_enable(); 692*2f2abcf4SHaojian Zhuang /* CNTFRQ is read-only in EL1 */ 693*2f2abcf4SHaojian Zhuang write_cntfrq_el0(plat_get_syscnt_freq2()); 694*2f2abcf4SHaojian Zhuang data = read_cpacr_el1(); 695*2f2abcf4SHaojian Zhuang do { 696*2f2abcf4SHaojian Zhuang data |= 3 << 20; 697*2f2abcf4SHaojian Zhuang write_cpacr_el1(data); 698*2f2abcf4SHaojian Zhuang data = read_cpacr_el1(); 699*2f2abcf4SHaojian Zhuang } while ((data & (3 << 20)) != (3 << 20)); 700*2f2abcf4SHaojian Zhuang INFO("cpacr_el1:0x%x\n", data); 701*2f2abcf4SHaojian Zhuang 702*2f2abcf4SHaojian Zhuang ep_info->args.arg0 = 0xffff & read_mpidr(); 703*2f2abcf4SHaojian Zhuang ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, 704*2f2abcf4SHaojian Zhuang DISABLE_ALL_EXCEPTIONS); 705*2f2abcf4SHaojian Zhuang } 706