1*08b167e9SHaojian Zhuang /* 2*08b167e9SHaojian Zhuang * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3*08b167e9SHaojian Zhuang * 4*08b167e9SHaojian Zhuang * SPDX-License-Identifier: BSD-3-Clause 5*08b167e9SHaojian Zhuang */ 6*08b167e9SHaojian Zhuang 7*08b167e9SHaojian Zhuang #include <arch_helpers.h> 8*08b167e9SHaojian Zhuang #include <assert.h> 9*08b167e9SHaojian Zhuang #include <bl_common.h> 10*08b167e9SHaojian Zhuang #include <console.h> 11*08b167e9SHaojian Zhuang #include <debug.h> 12*08b167e9SHaojian Zhuang #include <dw_mmc.h> 13*08b167e9SHaojian Zhuang #include <emmc.h> 14*08b167e9SHaojian Zhuang #include <errno.h> 15*08b167e9SHaojian Zhuang #include <gpio.h> 16*08b167e9SHaojian Zhuang #include <hi6220.h> 17*08b167e9SHaojian Zhuang #include <hi6553.h> 18*08b167e9SHaojian Zhuang #include <mmio.h> 19*08b167e9SHaojian Zhuang #include <pl061_gpio.h> 20*08b167e9SHaojian Zhuang #include <platform.h> 21*08b167e9SHaojian Zhuang #include <platform_def.h> 22*08b167e9SHaojian Zhuang #include <sp804_delay_timer.h> 23*08b167e9SHaojian Zhuang #include <string.h> 24*08b167e9SHaojian Zhuang #include <tbbr/tbbr_img_desc.h> 25*08b167e9SHaojian Zhuang 26*08b167e9SHaojian Zhuang #include "../../bl1/bl1_private.h" 27*08b167e9SHaojian Zhuang #include "hikey_def.h" 28*08b167e9SHaojian Zhuang #include "hikey_private.h" 29*08b167e9SHaojian Zhuang 30*08b167e9SHaojian Zhuang /* 31*08b167e9SHaojian Zhuang * Declarations of linker defined symbols which will help us find the layout 32*08b167e9SHaojian Zhuang * of trusted RAM 33*08b167e9SHaojian Zhuang */ 34*08b167e9SHaojian Zhuang extern unsigned long __COHERENT_RAM_START__; 35*08b167e9SHaojian Zhuang extern unsigned long __COHERENT_RAM_END__; 36*08b167e9SHaojian Zhuang 37*08b167e9SHaojian Zhuang /* 38*08b167e9SHaojian Zhuang * The next 2 constants identify the extents of the coherent memory region. 39*08b167e9SHaojian Zhuang * These addresses are used by the MMU setup code and therefore they must be 40*08b167e9SHaojian Zhuang * page-aligned. It is the responsibility of the linker script to ensure that 41*08b167e9SHaojian Zhuang * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to 42*08b167e9SHaojian Zhuang * page-aligned addresses. 43*08b167e9SHaojian Zhuang */ 44*08b167e9SHaojian Zhuang #define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) 45*08b167e9SHaojian Zhuang #define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) 46*08b167e9SHaojian Zhuang 47*08b167e9SHaojian Zhuang /* Data structure which holds the extents of the trusted RAM for BL1 */ 48*08b167e9SHaojian Zhuang static meminfo_t bl1_tzram_layout; 49*08b167e9SHaojian Zhuang 50*08b167e9SHaojian Zhuang enum { 51*08b167e9SHaojian Zhuang BOOT_NORMAL = 0, 52*08b167e9SHaojian Zhuang BOOT_USB_DOWNLOAD, 53*08b167e9SHaojian Zhuang BOOT_UART_DOWNLOAD, 54*08b167e9SHaojian Zhuang }; 55*08b167e9SHaojian Zhuang 56*08b167e9SHaojian Zhuang meminfo_t *bl1_plat_sec_mem_layout(void) 57*08b167e9SHaojian Zhuang { 58*08b167e9SHaojian Zhuang return &bl1_tzram_layout; 59*08b167e9SHaojian Zhuang } 60*08b167e9SHaojian Zhuang 61*08b167e9SHaojian Zhuang /* 62*08b167e9SHaojian Zhuang * Perform any BL1 specific platform actions. 63*08b167e9SHaojian Zhuang */ 64*08b167e9SHaojian Zhuang void bl1_early_platform_setup(void) 65*08b167e9SHaojian Zhuang { 66*08b167e9SHaojian Zhuang const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE; 67*08b167e9SHaojian Zhuang 68*08b167e9SHaojian Zhuang /* Initialize the console to provide early debug support */ 69*08b167e9SHaojian Zhuang console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE); 70*08b167e9SHaojian Zhuang 71*08b167e9SHaojian Zhuang /* Allow BL1 to see the whole Trusted RAM */ 72*08b167e9SHaojian Zhuang bl1_tzram_layout.total_base = BL1_RW_BASE; 73*08b167e9SHaojian Zhuang bl1_tzram_layout.total_size = BL1_RW_SIZE; 74*08b167e9SHaojian Zhuang 75*08b167e9SHaojian Zhuang /* Calculate how much RAM BL1 is using and how much remains free */ 76*08b167e9SHaojian Zhuang bl1_tzram_layout.free_base = BL1_RW_BASE; 77*08b167e9SHaojian Zhuang bl1_tzram_layout.free_size = BL1_RW_SIZE; 78*08b167e9SHaojian Zhuang reserve_mem(&bl1_tzram_layout.free_base, 79*08b167e9SHaojian Zhuang &bl1_tzram_layout.free_size, 80*08b167e9SHaojian Zhuang BL1_RAM_BASE, 81*08b167e9SHaojian Zhuang bl1_size); 82*08b167e9SHaojian Zhuang 83*08b167e9SHaojian Zhuang INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT, 84*08b167e9SHaojian Zhuang bl1_size); 85*08b167e9SHaojian Zhuang } 86*08b167e9SHaojian Zhuang 87*08b167e9SHaojian Zhuang /* 88*08b167e9SHaojian Zhuang * Perform the very early platform specific architecture setup here. At the 89*08b167e9SHaojian Zhuang * moment this only does basic initialization. Later architectural setup 90*08b167e9SHaojian Zhuang * (bl1_arch_setup()) does not do anything platform specific. 91*08b167e9SHaojian Zhuang */ 92*08b167e9SHaojian Zhuang void bl1_plat_arch_setup(void) 93*08b167e9SHaojian Zhuang { 94*08b167e9SHaojian Zhuang hikey_init_mmu_el3(bl1_tzram_layout.total_base, 95*08b167e9SHaojian Zhuang bl1_tzram_layout.total_size, 96*08b167e9SHaojian Zhuang BL1_RO_BASE, 97*08b167e9SHaojian Zhuang BL1_RO_LIMIT, 98*08b167e9SHaojian Zhuang BL1_COHERENT_RAM_BASE, 99*08b167e9SHaojian Zhuang BL1_COHERENT_RAM_LIMIT); 100*08b167e9SHaojian Zhuang } 101*08b167e9SHaojian Zhuang 102*08b167e9SHaojian Zhuang static void hikey_sp804_init(void) 103*08b167e9SHaojian Zhuang { 104*08b167e9SHaojian Zhuang uint32_t data; 105*08b167e9SHaojian Zhuang 106*08b167e9SHaojian Zhuang /* select the clock of dual timer0 */ 107*08b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_TIMER_EN0); 108*08b167e9SHaojian Zhuang while (data & 3) { 109*08b167e9SHaojian Zhuang data &= ~3; 110*08b167e9SHaojian Zhuang data |= 3 << 16; 111*08b167e9SHaojian Zhuang mmio_write_32(AO_SC_TIMER_EN0, data); 112*08b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_TIMER_EN0); 113*08b167e9SHaojian Zhuang } 114*08b167e9SHaojian Zhuang /* enable the pclk of dual timer0 */ 115*08b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4); 116*08b167e9SHaojian Zhuang while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)) { 117*08b167e9SHaojian Zhuang mmio_write_32(AO_SC_PERIPH_CLKEN4, PCLK_TIMER1 | PCLK_TIMER0); 118*08b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4); 119*08b167e9SHaojian Zhuang } 120*08b167e9SHaojian Zhuang /* reset dual timer0 */ 121*08b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); 122*08b167e9SHaojian Zhuang mmio_write_32(AO_SC_PERIPH_RSTEN4, PCLK_TIMER1 | PCLK_TIMER0); 123*08b167e9SHaojian Zhuang do { 124*08b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); 125*08b167e9SHaojian Zhuang } while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)); 126*08b167e9SHaojian Zhuang /* unreset dual timer0 */ 127*08b167e9SHaojian Zhuang mmio_write_32(AO_SC_PERIPH_RSTDIS4, PCLK_TIMER1 | PCLK_TIMER0); 128*08b167e9SHaojian Zhuang do { 129*08b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); 130*08b167e9SHaojian Zhuang } while ((data & PCLK_TIMER1) || (data & PCLK_TIMER0)); 131*08b167e9SHaojian Zhuang 132*08b167e9SHaojian Zhuang sp804_timer_init(SP804_TIMER0_BASE, 10, 192); 133*08b167e9SHaojian Zhuang } 134*08b167e9SHaojian Zhuang 135*08b167e9SHaojian Zhuang static void hikey_gpio_init(void) 136*08b167e9SHaojian Zhuang { 137*08b167e9SHaojian Zhuang pl061_gpio_init(); 138*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO0_BASE, 0); 139*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO1_BASE, 1); 140*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO2_BASE, 2); 141*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO3_BASE, 3); 142*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO4_BASE, 4); 143*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO5_BASE, 5); 144*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO6_BASE, 6); 145*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO7_BASE, 7); 146*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO8_BASE, 8); 147*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO9_BASE, 9); 148*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO10_BASE, 10); 149*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO11_BASE, 11); 150*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO12_BASE, 12); 151*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO13_BASE, 13); 152*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO14_BASE, 14); 153*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO15_BASE, 15); 154*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO16_BASE, 16); 155*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO17_BASE, 17); 156*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO18_BASE, 18); 157*08b167e9SHaojian Zhuang pl061_gpio_register(GPIO19_BASE, 19); 158*08b167e9SHaojian Zhuang 159*08b167e9SHaojian Zhuang /* Power on indicator LED (USER_LED1). */ 160*08b167e9SHaojian Zhuang gpio_set_direction(32, GPIO_DIR_OUT); /* LED1 */ 161*08b167e9SHaojian Zhuang gpio_set_value(32, GPIO_LEVEL_HIGH); 162*08b167e9SHaojian Zhuang gpio_set_direction(33, GPIO_DIR_OUT); /* LED2 */ 163*08b167e9SHaojian Zhuang gpio_set_value(33, GPIO_LEVEL_LOW); 164*08b167e9SHaojian Zhuang gpio_set_direction(34, GPIO_DIR_OUT); /* LED3 */ 165*08b167e9SHaojian Zhuang gpio_set_direction(35, GPIO_DIR_OUT); /* LED4 */ 166*08b167e9SHaojian Zhuang } 167*08b167e9SHaojian Zhuang 168*08b167e9SHaojian Zhuang static void hikey_pmussi_init(void) 169*08b167e9SHaojian Zhuang { 170*08b167e9SHaojian Zhuang uint32_t data; 171*08b167e9SHaojian Zhuang 172*08b167e9SHaojian Zhuang /* Initialize PWR_HOLD GPIO */ 173*08b167e9SHaojian Zhuang gpio_set_direction(0, GPIO_DIR_OUT); 174*08b167e9SHaojian Zhuang gpio_set_value(0, GPIO_LEVEL_LOW); 175*08b167e9SHaojian Zhuang 176*08b167e9SHaojian Zhuang /* 177*08b167e9SHaojian Zhuang * After reset, PMUSSI stays in reset mode. 178*08b167e9SHaojian Zhuang * Now make it out of reset. 179*08b167e9SHaojian Zhuang */ 180*08b167e9SHaojian Zhuang mmio_write_32(AO_SC_PERIPH_RSTDIS4, 181*08b167e9SHaojian Zhuang AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N); 182*08b167e9SHaojian Zhuang do { 183*08b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); 184*08b167e9SHaojian Zhuang } while (data & AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N); 185*08b167e9SHaojian Zhuang 186*08b167e9SHaojian Zhuang /* Set PMUSSI clock latency for read operation. */ 187*08b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_MCU_SUBSYS_CTRL3); 188*08b167e9SHaojian Zhuang data &= ~AO_SC_MCU_SUBSYS_CTRL3_RCLK_MASK; 189*08b167e9SHaojian Zhuang data |= AO_SC_MCU_SUBSYS_CTRL3_RCLK_3; 190*08b167e9SHaojian Zhuang mmio_write_32(AO_SC_MCU_SUBSYS_CTRL3, data); 191*08b167e9SHaojian Zhuang 192*08b167e9SHaojian Zhuang /* enable PMUSSI clock */ 193*08b167e9SHaojian Zhuang data = AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_CCPU | 194*08b167e9SHaojian Zhuang AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_MCU; 195*08b167e9SHaojian Zhuang mmio_write_32(AO_SC_PERIPH_CLKEN5, data); 196*08b167e9SHaojian Zhuang data = AO_SC_PERIPH_CLKEN4_PCLK_PMUSSI; 197*08b167e9SHaojian Zhuang mmio_write_32(AO_SC_PERIPH_CLKEN4, data); 198*08b167e9SHaojian Zhuang 199*08b167e9SHaojian Zhuang gpio_set_value(0, GPIO_LEVEL_HIGH); 200*08b167e9SHaojian Zhuang } 201*08b167e9SHaojian Zhuang 202*08b167e9SHaojian Zhuang static void hikey_hi6553_init(void) 203*08b167e9SHaojian Zhuang { 204*08b167e9SHaojian Zhuang uint8_t data; 205*08b167e9SHaojian Zhuang 206*08b167e9SHaojian Zhuang mmio_write_8(HI6553_PERI_EN_MARK, 0x1e); 207*08b167e9SHaojian Zhuang mmio_write_8(HI6553_NP_REG_ADJ1, 0); 208*08b167e9SHaojian Zhuang data = DISABLE6_XO_CLK_CONN | DISABLE6_XO_CLK_NFC | 209*08b167e9SHaojian Zhuang DISABLE6_XO_CLK_RF1 | DISABLE6_XO_CLK_RF2; 210*08b167e9SHaojian Zhuang mmio_write_8(HI6553_DISABLE6_XO_CLK, data); 211*08b167e9SHaojian Zhuang 212*08b167e9SHaojian Zhuang /* configure BUCK0 & BUCK1 */ 213*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK01_CTRL2, 0x5e); 214*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK0_CTRL7, 0x10); 215*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK1_CTRL7, 0x10); 216*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK0_CTRL5, 0x1e); 217*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK1_CTRL5, 0x1e); 218*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK0_CTRL1, 0xfc); 219*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK1_CTRL1, 0xfc); 220*08b167e9SHaojian Zhuang 221*08b167e9SHaojian Zhuang /* configure BUCK2 */ 222*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK2_REG1, 0x4f); 223*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK2_REG5, 0x99); 224*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK2_REG6, 0x45); 225*08b167e9SHaojian Zhuang mdelay(1); 226*08b167e9SHaojian Zhuang mmio_write_8(HI6553_VSET_BUCK2_ADJ, 0x22); 227*08b167e9SHaojian Zhuang mdelay(1); 228*08b167e9SHaojian Zhuang 229*08b167e9SHaojian Zhuang /* configure BUCK3 */ 230*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK3_REG3, 0x02); 231*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK3_REG5, 0x99); 232*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK3_REG6, 0x41); 233*08b167e9SHaojian Zhuang mmio_write_8(HI6553_VSET_BUCK3_ADJ, 0x02); 234*08b167e9SHaojian Zhuang mdelay(1); 235*08b167e9SHaojian Zhuang 236*08b167e9SHaojian Zhuang /* configure BUCK4 */ 237*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK4_REG2, 0x9a); 238*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK4_REG5, 0x99); 239*08b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK4_REG6, 0x45); 240*08b167e9SHaojian Zhuang 241*08b167e9SHaojian Zhuang /* configure LDO20 */ 242*08b167e9SHaojian Zhuang mmio_write_8(HI6553_LDO20_REG_ADJ, 0x50); 243*08b167e9SHaojian Zhuang 244*08b167e9SHaojian Zhuang mmio_write_8(HI6553_NP_REG_CHG, 0x0f); 245*08b167e9SHaojian Zhuang mmio_write_8(HI6553_CLK_TOP0, 0x06); 246*08b167e9SHaojian Zhuang mmio_write_8(HI6553_CLK_TOP3, 0xc0); 247*08b167e9SHaojian Zhuang mmio_write_8(HI6553_CLK_TOP4, 0x00); 248*08b167e9SHaojian Zhuang 249*08b167e9SHaojian Zhuang /* configure LDO7 & LDO10 for SD slot */ 250*08b167e9SHaojian Zhuang /* enable LDO7 */ 251*08b167e9SHaojian Zhuang data = mmio_read_8(HI6553_LDO7_REG_ADJ); 252*08b167e9SHaojian Zhuang data = (data & 0xf8) | 0x2; 253*08b167e9SHaojian Zhuang mmio_write_8(HI6553_LDO7_REG_ADJ, data); 254*08b167e9SHaojian Zhuang mdelay(5); 255*08b167e9SHaojian Zhuang mmio_write_8(HI6553_ENABLE2_LDO1_8, 1 << 6); 256*08b167e9SHaojian Zhuang mdelay(5); 257*08b167e9SHaojian Zhuang /* enable LDO10 */ 258*08b167e9SHaojian Zhuang data = mmio_read_8(HI6553_LDO10_REG_ADJ); 259*08b167e9SHaojian Zhuang data = (data & 0xf8) | 0x5; 260*08b167e9SHaojian Zhuang mmio_write_8(HI6553_LDO10_REG_ADJ, data); 261*08b167e9SHaojian Zhuang mdelay(5); 262*08b167e9SHaojian Zhuang mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 1); 263*08b167e9SHaojian Zhuang mdelay(5); 264*08b167e9SHaojian Zhuang /* enable LDO15 */ 265*08b167e9SHaojian Zhuang data = mmio_read_8(HI6553_LDO15_REG_ADJ); 266*08b167e9SHaojian Zhuang data = (data & 0xf8) | 0x4; 267*08b167e9SHaojian Zhuang mmio_write_8(HI6553_LDO15_REG_ADJ, data); 268*08b167e9SHaojian Zhuang mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 6); 269*08b167e9SHaojian Zhuang mdelay(5); 270*08b167e9SHaojian Zhuang /* enable LDO19 */ 271*08b167e9SHaojian Zhuang data = mmio_read_8(HI6553_LDO19_REG_ADJ); 272*08b167e9SHaojian Zhuang data |= 0x7; 273*08b167e9SHaojian Zhuang mmio_write_8(HI6553_LDO19_REG_ADJ, data); 274*08b167e9SHaojian Zhuang mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 2); 275*08b167e9SHaojian Zhuang mdelay(5); 276*08b167e9SHaojian Zhuang /* enable LDO21 */ 277*08b167e9SHaojian Zhuang data = mmio_read_8(HI6553_LDO21_REG_ADJ); 278*08b167e9SHaojian Zhuang data = (data & 0xf8) | 0x3; 279*08b167e9SHaojian Zhuang mmio_write_8(HI6553_LDO21_REG_ADJ, data); 280*08b167e9SHaojian Zhuang mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 4); 281*08b167e9SHaojian Zhuang mdelay(5); 282*08b167e9SHaojian Zhuang /* enable LDO22 */ 283*08b167e9SHaojian Zhuang data = mmio_read_8(HI6553_LDO22_REG_ADJ); 284*08b167e9SHaojian Zhuang data = (data & 0xf8) | 0x7; 285*08b167e9SHaojian Zhuang mmio_write_8(HI6553_LDO22_REG_ADJ, data); 286*08b167e9SHaojian Zhuang mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 5); 287*08b167e9SHaojian Zhuang mdelay(5); 288*08b167e9SHaojian Zhuang 289*08b167e9SHaojian Zhuang /* select 32.764KHz */ 290*08b167e9SHaojian Zhuang mmio_write_8(HI6553_CLK19M2_600_586_EN, 0x01); 291*08b167e9SHaojian Zhuang } 292*08b167e9SHaojian Zhuang 293*08b167e9SHaojian Zhuang static void init_mmc0_pll(void) 294*08b167e9SHaojian Zhuang { 295*08b167e9SHaojian Zhuang unsigned int data; 296*08b167e9SHaojian Zhuang 297*08b167e9SHaojian Zhuang /* select SYSPLL as the source of MMC0 */ 298*08b167e9SHaojian Zhuang /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */ 299*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_CLK_SEL0, 1 << 5 | 1 << 21); 300*08b167e9SHaojian Zhuang do { 301*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_CLK_SEL0); 302*08b167e9SHaojian Zhuang } while (!(data & (1 << 5))); 303*08b167e9SHaojian Zhuang /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */ 304*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_CLK_SEL0, 1 << 29); 305*08b167e9SHaojian Zhuang do { 306*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_CLK_SEL0); 307*08b167e9SHaojian Zhuang } while (data & (1 << 13)); 308*08b167e9SHaojian Zhuang 309*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 0)); 310*08b167e9SHaojian Zhuang do { 311*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 312*08b167e9SHaojian Zhuang } while (!(data & (1 << 0))); 313*08b167e9SHaojian Zhuang 314*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKEN12); 315*08b167e9SHaojian Zhuang data |= 1 << 1; 316*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN12, data); 317*08b167e9SHaojian Zhuang 318*08b167e9SHaojian Zhuang do { 319*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_CLKCFG8BIT1, (1 << 7) | 0xb); 320*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_CLKCFG8BIT1); 321*08b167e9SHaojian Zhuang } while ((data & 0xb) != 0xb); 322*08b167e9SHaojian Zhuang } 323*08b167e9SHaojian Zhuang 324*08b167e9SHaojian Zhuang static void reset_mmc0_clk(void) 325*08b167e9SHaojian Zhuang { 326*08b167e9SHaojian Zhuang unsigned int data; 327*08b167e9SHaojian Zhuang 328*08b167e9SHaojian Zhuang /* disable mmc0 bus clock */ 329*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0); 330*08b167e9SHaojian Zhuang do { 331*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 332*08b167e9SHaojian Zhuang } while (data & PERI_CLK0_MMC0); 333*08b167e9SHaojian Zhuang /* enable mmc0 bus clock */ 334*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0); 335*08b167e9SHaojian Zhuang do { 336*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 337*08b167e9SHaojian Zhuang } while (!(data & PERI_CLK0_MMC0)); 338*08b167e9SHaojian Zhuang /* reset mmc0 clock domain */ 339*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0); 340*08b167e9SHaojian Zhuang 341*08b167e9SHaojian Zhuang /* bypass mmc0 clock phase */ 342*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CTRL2); 343*08b167e9SHaojian Zhuang data |= 3; 344*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CTRL2, data); 345*08b167e9SHaojian Zhuang 346*08b167e9SHaojian Zhuang /* disable low power */ 347*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CTRL13); 348*08b167e9SHaojian Zhuang data |= 1 << 3; 349*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CTRL13, data); 350*08b167e9SHaojian Zhuang do { 351*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); 352*08b167e9SHaojian Zhuang } while (!(data & PERI_RST0_MMC0)); 353*08b167e9SHaojian Zhuang 354*08b167e9SHaojian Zhuang /* unreset mmc0 clock domain */ 355*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0); 356*08b167e9SHaojian Zhuang do { 357*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); 358*08b167e9SHaojian Zhuang } while (data & PERI_RST0_MMC0); 359*08b167e9SHaojian Zhuang } 360*08b167e9SHaojian Zhuang 361*08b167e9SHaojian Zhuang static void init_media_clk(void) 362*08b167e9SHaojian Zhuang { 363*08b167e9SHaojian Zhuang unsigned int data, value; 364*08b167e9SHaojian Zhuang 365*08b167e9SHaojian Zhuang data = mmio_read_32(PMCTRL_MEDPLLCTRL); 366*08b167e9SHaojian Zhuang data |= 1; 367*08b167e9SHaojian Zhuang mmio_write_32(PMCTRL_MEDPLLCTRL, data); 368*08b167e9SHaojian Zhuang 369*08b167e9SHaojian Zhuang for (;;) { 370*08b167e9SHaojian Zhuang data = mmio_read_32(PMCTRL_MEDPLLCTRL); 371*08b167e9SHaojian Zhuang value = 1 << 28; 372*08b167e9SHaojian Zhuang if ((data & value) == value) 373*08b167e9SHaojian Zhuang break; 374*08b167e9SHaojian Zhuang } 375*08b167e9SHaojian Zhuang 376*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKEN12); 377*08b167e9SHaojian Zhuang data = 1 << 10; 378*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN12, data); 379*08b167e9SHaojian Zhuang } 380*08b167e9SHaojian Zhuang 381*08b167e9SHaojian Zhuang static void init_mmc1_pll(void) 382*08b167e9SHaojian Zhuang { 383*08b167e9SHaojian Zhuang uint32_t data; 384*08b167e9SHaojian Zhuang 385*08b167e9SHaojian Zhuang /* select SYSPLL as the source of MMC1 */ 386*08b167e9SHaojian Zhuang /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */ 387*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_CLK_SEL0, 1 << 11 | 1 << 27); 388*08b167e9SHaojian Zhuang do { 389*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_CLK_SEL0); 390*08b167e9SHaojian Zhuang } while (!(data & (1 << 11))); 391*08b167e9SHaojian Zhuang /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */ 392*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_CLK_SEL0, 1 << 30); 393*08b167e9SHaojian Zhuang do { 394*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_CLK_SEL0); 395*08b167e9SHaojian Zhuang } while (data & (1 << 14)); 396*08b167e9SHaojian Zhuang 397*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 1)); 398*08b167e9SHaojian Zhuang do { 399*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 400*08b167e9SHaojian Zhuang } while (!(data & (1 << 1))); 401*08b167e9SHaojian Zhuang 402*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKEN12); 403*08b167e9SHaojian Zhuang data |= 1 << 2; 404*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN12, data); 405*08b167e9SHaojian Zhuang 406*08b167e9SHaojian Zhuang do { 407*08b167e9SHaojian Zhuang /* 1.2GHz / 50 = 24MHz */ 408*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_CLKCFG8BIT2, 0x31 | (1 << 7)); 409*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_CLKCFG8BIT2); 410*08b167e9SHaojian Zhuang } while ((data & 0x31) != 0x31); 411*08b167e9SHaojian Zhuang } 412*08b167e9SHaojian Zhuang 413*08b167e9SHaojian Zhuang static void reset_mmc1_clk(void) 414*08b167e9SHaojian Zhuang { 415*08b167e9SHaojian Zhuang unsigned int data; 416*08b167e9SHaojian Zhuang 417*08b167e9SHaojian Zhuang /* disable mmc1 bus clock */ 418*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC1); 419*08b167e9SHaojian Zhuang do { 420*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 421*08b167e9SHaojian Zhuang } while (data & PERI_CLK0_MMC1); 422*08b167e9SHaojian Zhuang /* enable mmc1 bus clock */ 423*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC1); 424*08b167e9SHaojian Zhuang do { 425*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 426*08b167e9SHaojian Zhuang } while (!(data & PERI_CLK0_MMC1)); 427*08b167e9SHaojian Zhuang /* reset mmc1 clock domain */ 428*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC1); 429*08b167e9SHaojian Zhuang 430*08b167e9SHaojian Zhuang /* bypass mmc1 clock phase */ 431*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CTRL2); 432*08b167e9SHaojian Zhuang data |= 3 << 2; 433*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CTRL2, data); 434*08b167e9SHaojian Zhuang 435*08b167e9SHaojian Zhuang /* disable low power */ 436*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CTRL13); 437*08b167e9SHaojian Zhuang data |= 1 << 4; 438*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CTRL13, data); 439*08b167e9SHaojian Zhuang do { 440*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); 441*08b167e9SHaojian Zhuang } while (!(data & PERI_RST0_MMC1)); 442*08b167e9SHaojian Zhuang 443*08b167e9SHaojian Zhuang /* unreset mmc0 clock domain */ 444*08b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC1); 445*08b167e9SHaojian Zhuang do { 446*08b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); 447*08b167e9SHaojian Zhuang } while (data & PERI_RST0_MMC1); 448*08b167e9SHaojian Zhuang } 449*08b167e9SHaojian Zhuang 450*08b167e9SHaojian Zhuang /* Initialize PLL of both eMMC and SD controllers. */ 451*08b167e9SHaojian Zhuang static void hikey_mmc_pll_init(void) 452*08b167e9SHaojian Zhuang { 453*08b167e9SHaojian Zhuang init_mmc0_pll(); 454*08b167e9SHaojian Zhuang reset_mmc0_clk(); 455*08b167e9SHaojian Zhuang init_media_clk(); 456*08b167e9SHaojian Zhuang 457*08b167e9SHaojian Zhuang dsb(); 458*08b167e9SHaojian Zhuang 459*08b167e9SHaojian Zhuang init_mmc1_pll(); 460*08b167e9SHaojian Zhuang reset_mmc1_clk(); 461*08b167e9SHaojian Zhuang } 462*08b167e9SHaojian Zhuang 463*08b167e9SHaojian Zhuang /* 464*08b167e9SHaojian Zhuang * Function which will perform any remaining platform-specific setup that can 465*08b167e9SHaojian Zhuang * occur after the MMU and data cache have been enabled. 466*08b167e9SHaojian Zhuang */ 467*08b167e9SHaojian Zhuang void bl1_platform_setup(void) 468*08b167e9SHaojian Zhuang { 469*08b167e9SHaojian Zhuang dw_mmc_params_t params; 470*08b167e9SHaojian Zhuang 471*08b167e9SHaojian Zhuang assert((HIKEY_BL1_MMC_DESC_BASE >= SRAM_BASE) && 472*08b167e9SHaojian Zhuang ((SRAM_BASE + SRAM_SIZE) >= 473*08b167e9SHaojian Zhuang (HIKEY_BL1_MMC_DATA_BASE + HIKEY_BL1_MMC_DATA_SIZE))); 474*08b167e9SHaojian Zhuang hikey_sp804_init(); 475*08b167e9SHaojian Zhuang hikey_gpio_init(); 476*08b167e9SHaojian Zhuang hikey_pmussi_init(); 477*08b167e9SHaojian Zhuang hikey_hi6553_init(); 478*08b167e9SHaojian Zhuang 479*08b167e9SHaojian Zhuang hikey_mmc_pll_init(); 480*08b167e9SHaojian Zhuang 481*08b167e9SHaojian Zhuang memset(¶ms, 0, sizeof(dw_mmc_params_t)); 482*08b167e9SHaojian Zhuang params.reg_base = DWMMC0_BASE; 483*08b167e9SHaojian Zhuang params.desc_base = HIKEY_BL1_MMC_DESC_BASE; 484*08b167e9SHaojian Zhuang params.desc_size = 1 << 20; 485*08b167e9SHaojian Zhuang params.clk_rate = 24 * 1000 * 1000; 486*08b167e9SHaojian Zhuang params.bus_width = EMMC_BUS_WIDTH_8; 487*08b167e9SHaojian Zhuang params.flags = EMMC_FLAG_CMD23; 488*08b167e9SHaojian Zhuang dw_mmc_init(¶ms); 489*08b167e9SHaojian Zhuang 490*08b167e9SHaojian Zhuang hikey_io_setup(); 491*08b167e9SHaojian Zhuang } 492*08b167e9SHaojian Zhuang 493*08b167e9SHaojian Zhuang /* 494*08b167e9SHaojian Zhuang * The following function checks if Firmware update is needed, 495*08b167e9SHaojian Zhuang * by checking if TOC in FIP image is valid or not. 496*08b167e9SHaojian Zhuang */ 497*08b167e9SHaojian Zhuang unsigned int bl1_plat_get_next_image_id(void) 498*08b167e9SHaojian Zhuang { 499*08b167e9SHaojian Zhuang int32_t boot_mode; 500*08b167e9SHaojian Zhuang unsigned int ret; 501*08b167e9SHaojian Zhuang 502*08b167e9SHaojian Zhuang boot_mode = mmio_read_32(ONCHIPROM_PARAM_BASE); 503*08b167e9SHaojian Zhuang switch (boot_mode) { 504*08b167e9SHaojian Zhuang case BOOT_NORMAL: 505*08b167e9SHaojian Zhuang ret = BL2_IMAGE_ID; 506*08b167e9SHaojian Zhuang break; 507*08b167e9SHaojian Zhuang case BOOT_USB_DOWNLOAD: 508*08b167e9SHaojian Zhuang case BOOT_UART_DOWNLOAD: 509*08b167e9SHaojian Zhuang ret = NS_BL1U_IMAGE_ID; 510*08b167e9SHaojian Zhuang break; 511*08b167e9SHaojian Zhuang default: 512*08b167e9SHaojian Zhuang WARN("Invalid boot mode is found:%d\n", boot_mode); 513*08b167e9SHaojian Zhuang panic(); 514*08b167e9SHaojian Zhuang } 515*08b167e9SHaojian Zhuang return ret; 516*08b167e9SHaojian Zhuang } 517*08b167e9SHaojian Zhuang 518*08b167e9SHaojian Zhuang image_desc_t *bl1_plat_get_image_desc(unsigned int image_id) 519*08b167e9SHaojian Zhuang { 520*08b167e9SHaojian Zhuang unsigned int index = 0; 521*08b167e9SHaojian Zhuang 522*08b167e9SHaojian Zhuang while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) { 523*08b167e9SHaojian Zhuang if (bl1_tbbr_image_descs[index].image_id == image_id) 524*08b167e9SHaojian Zhuang return &bl1_tbbr_image_descs[index]; 525*08b167e9SHaojian Zhuang 526*08b167e9SHaojian Zhuang index++; 527*08b167e9SHaojian Zhuang } 528*08b167e9SHaojian Zhuang 529*08b167e9SHaojian Zhuang return NULL; 530*08b167e9SHaojian Zhuang } 531*08b167e9SHaojian Zhuang 532*08b167e9SHaojian Zhuang void bl1_plat_set_ep_info(unsigned int image_id, 533*08b167e9SHaojian Zhuang entry_point_info_t *ep_info) 534*08b167e9SHaojian Zhuang { 535*08b167e9SHaojian Zhuang unsigned int data = 0; 536*08b167e9SHaojian Zhuang 537*08b167e9SHaojian Zhuang if (image_id == BL2_IMAGE_ID) 538*08b167e9SHaojian Zhuang return; 539*08b167e9SHaojian Zhuang inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE); 540*08b167e9SHaojian Zhuang __asm__ volatile ("mrs %0, cpacr_el1" : "=r"(data)); 541*08b167e9SHaojian Zhuang do { 542*08b167e9SHaojian Zhuang data |= 3 << 20; 543*08b167e9SHaojian Zhuang __asm__ volatile ("msr cpacr_el1, %0" : : "r"(data)); 544*08b167e9SHaojian Zhuang __asm__ volatile ("mrs %0, cpacr_el1" : "=r"(data)); 545*08b167e9SHaojian Zhuang } while ((data & (3 << 20)) != (3 << 20)); 546*08b167e9SHaojian Zhuang INFO("cpacr_el1:0x%x\n", data); 547*08b167e9SHaojian Zhuang 548*08b167e9SHaojian Zhuang ep_info->args.arg0 = 0xffff & read_mpidr(); 549*08b167e9SHaojian Zhuang ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, 550*08b167e9SHaojian Zhuang DISABLE_ALL_EXCEPTIONS); 551*08b167e9SHaojian Zhuang } 552