108b167e9SHaojian Zhuang /* 208b167e9SHaojian Zhuang * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 308b167e9SHaojian Zhuang * 408b167e9SHaojian Zhuang * SPDX-License-Identifier: BSD-3-Clause 508b167e9SHaojian Zhuang */ 608b167e9SHaojian Zhuang 708b167e9SHaojian Zhuang #include <arch_helpers.h> 808b167e9SHaojian Zhuang #include <assert.h> 908b167e9SHaojian Zhuang #include <bl_common.h> 1008b167e9SHaojian Zhuang #include <console.h> 1108b167e9SHaojian Zhuang #include <debug.h> 1208b167e9SHaojian Zhuang #include <dw_mmc.h> 1308b167e9SHaojian Zhuang #include <emmc.h> 1408b167e9SHaojian Zhuang #include <errno.h> 1508b167e9SHaojian Zhuang #include <gpio.h> 1608b167e9SHaojian Zhuang #include <hi6220.h> 1708b167e9SHaojian Zhuang #include <hi6553.h> 1808b167e9SHaojian Zhuang #include <mmio.h> 1908b167e9SHaojian Zhuang #include <pl061_gpio.h> 2008b167e9SHaojian Zhuang #include <platform.h> 2108b167e9SHaojian Zhuang #include <platform_def.h> 2208b167e9SHaojian Zhuang #include <sp804_delay_timer.h> 2308b167e9SHaojian Zhuang #include <string.h> 2408b167e9SHaojian Zhuang #include <tbbr/tbbr_img_desc.h> 2508b167e9SHaojian Zhuang 2608b167e9SHaojian Zhuang #include "../../bl1/bl1_private.h" 2708b167e9SHaojian Zhuang #include "hikey_def.h" 2808b167e9SHaojian Zhuang #include "hikey_private.h" 2908b167e9SHaojian Zhuang 3008b167e9SHaojian Zhuang /* 3108b167e9SHaojian Zhuang * Declarations of linker defined symbols which will help us find the layout 3208b167e9SHaojian Zhuang * of trusted RAM 3308b167e9SHaojian Zhuang */ 3408b167e9SHaojian Zhuang extern unsigned long __COHERENT_RAM_START__; 3508b167e9SHaojian Zhuang extern unsigned long __COHERENT_RAM_END__; 3608b167e9SHaojian Zhuang 3708b167e9SHaojian Zhuang /* 3808b167e9SHaojian Zhuang * The next 2 constants identify the extents of the coherent memory region. 3908b167e9SHaojian Zhuang * These addresses are used by the MMU setup code and therefore they must be 4008b167e9SHaojian Zhuang * page-aligned. It is the responsibility of the linker script to ensure that 4108b167e9SHaojian Zhuang * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to 4208b167e9SHaojian Zhuang * page-aligned addresses. 4308b167e9SHaojian Zhuang */ 4408b167e9SHaojian Zhuang #define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) 4508b167e9SHaojian Zhuang #define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) 4608b167e9SHaojian Zhuang 4708b167e9SHaojian Zhuang /* Data structure which holds the extents of the trusted RAM for BL1 */ 4808b167e9SHaojian Zhuang static meminfo_t bl1_tzram_layout; 4908b167e9SHaojian Zhuang 5008b167e9SHaojian Zhuang enum { 5108b167e9SHaojian Zhuang BOOT_NORMAL = 0, 5208b167e9SHaojian Zhuang BOOT_USB_DOWNLOAD, 5308b167e9SHaojian Zhuang BOOT_UART_DOWNLOAD, 5408b167e9SHaojian Zhuang }; 5508b167e9SHaojian Zhuang 5608b167e9SHaojian Zhuang meminfo_t *bl1_plat_sec_mem_layout(void) 5708b167e9SHaojian Zhuang { 5808b167e9SHaojian Zhuang return &bl1_tzram_layout; 5908b167e9SHaojian Zhuang } 6008b167e9SHaojian Zhuang 6108b167e9SHaojian Zhuang /* 6208b167e9SHaojian Zhuang * Perform any BL1 specific platform actions. 6308b167e9SHaojian Zhuang */ 6408b167e9SHaojian Zhuang void bl1_early_platform_setup(void) 6508b167e9SHaojian Zhuang { 6608b167e9SHaojian Zhuang const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE; 6708b167e9SHaojian Zhuang 6808b167e9SHaojian Zhuang /* Initialize the console to provide early debug support */ 6908b167e9SHaojian Zhuang console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE); 7008b167e9SHaojian Zhuang 7108b167e9SHaojian Zhuang /* Allow BL1 to see the whole Trusted RAM */ 7208b167e9SHaojian Zhuang bl1_tzram_layout.total_base = BL1_RW_BASE; 7308b167e9SHaojian Zhuang bl1_tzram_layout.total_size = BL1_RW_SIZE; 7408b167e9SHaojian Zhuang 7508b167e9SHaojian Zhuang /* Calculate how much RAM BL1 is using and how much remains free */ 7608b167e9SHaojian Zhuang bl1_tzram_layout.free_base = BL1_RW_BASE; 7708b167e9SHaojian Zhuang bl1_tzram_layout.free_size = BL1_RW_SIZE; 7808b167e9SHaojian Zhuang reserve_mem(&bl1_tzram_layout.free_base, 7908b167e9SHaojian Zhuang &bl1_tzram_layout.free_size, 8008b167e9SHaojian Zhuang BL1_RAM_BASE, 8108b167e9SHaojian Zhuang bl1_size); 8208b167e9SHaojian Zhuang 8308b167e9SHaojian Zhuang INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT, 8408b167e9SHaojian Zhuang bl1_size); 8508b167e9SHaojian Zhuang } 8608b167e9SHaojian Zhuang 8708b167e9SHaojian Zhuang /* 8808b167e9SHaojian Zhuang * Perform the very early platform specific architecture setup here. At the 8908b167e9SHaojian Zhuang * moment this only does basic initialization. Later architectural setup 9008b167e9SHaojian Zhuang * (bl1_arch_setup()) does not do anything platform specific. 9108b167e9SHaojian Zhuang */ 9208b167e9SHaojian Zhuang void bl1_plat_arch_setup(void) 9308b167e9SHaojian Zhuang { 9408b167e9SHaojian Zhuang hikey_init_mmu_el3(bl1_tzram_layout.total_base, 9508b167e9SHaojian Zhuang bl1_tzram_layout.total_size, 9608b167e9SHaojian Zhuang BL1_RO_BASE, 9708b167e9SHaojian Zhuang BL1_RO_LIMIT, 9808b167e9SHaojian Zhuang BL1_COHERENT_RAM_BASE, 9908b167e9SHaojian Zhuang BL1_COHERENT_RAM_LIMIT); 10008b167e9SHaojian Zhuang } 10108b167e9SHaojian Zhuang 10208b167e9SHaojian Zhuang static void hikey_sp804_init(void) 10308b167e9SHaojian Zhuang { 10408b167e9SHaojian Zhuang uint32_t data; 10508b167e9SHaojian Zhuang 10608b167e9SHaojian Zhuang /* select the clock of dual timer0 */ 10708b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_TIMER_EN0); 10808b167e9SHaojian Zhuang while (data & 3) { 10908b167e9SHaojian Zhuang data &= ~3; 11008b167e9SHaojian Zhuang data |= 3 << 16; 11108b167e9SHaojian Zhuang mmio_write_32(AO_SC_TIMER_EN0, data); 11208b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_TIMER_EN0); 11308b167e9SHaojian Zhuang } 11408b167e9SHaojian Zhuang /* enable the pclk of dual timer0 */ 11508b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4); 11608b167e9SHaojian Zhuang while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)) { 11708b167e9SHaojian Zhuang mmio_write_32(AO_SC_PERIPH_CLKEN4, PCLK_TIMER1 | PCLK_TIMER0); 11808b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4); 11908b167e9SHaojian Zhuang } 12008b167e9SHaojian Zhuang /* reset dual timer0 */ 12108b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); 12208b167e9SHaojian Zhuang mmio_write_32(AO_SC_PERIPH_RSTEN4, PCLK_TIMER1 | PCLK_TIMER0); 12308b167e9SHaojian Zhuang do { 12408b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); 12508b167e9SHaojian Zhuang } while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)); 12608b167e9SHaojian Zhuang /* unreset dual timer0 */ 12708b167e9SHaojian Zhuang mmio_write_32(AO_SC_PERIPH_RSTDIS4, PCLK_TIMER1 | PCLK_TIMER0); 12808b167e9SHaojian Zhuang do { 12908b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); 13008b167e9SHaojian Zhuang } while ((data & PCLK_TIMER1) || (data & PCLK_TIMER0)); 13108b167e9SHaojian Zhuang 13208b167e9SHaojian Zhuang sp804_timer_init(SP804_TIMER0_BASE, 10, 192); 13308b167e9SHaojian Zhuang } 13408b167e9SHaojian Zhuang 13508b167e9SHaojian Zhuang static void hikey_gpio_init(void) 13608b167e9SHaojian Zhuang { 13708b167e9SHaojian Zhuang pl061_gpio_init(); 13808b167e9SHaojian Zhuang pl061_gpio_register(GPIO0_BASE, 0); 13908b167e9SHaojian Zhuang pl061_gpio_register(GPIO1_BASE, 1); 14008b167e9SHaojian Zhuang pl061_gpio_register(GPIO2_BASE, 2); 14108b167e9SHaojian Zhuang pl061_gpio_register(GPIO3_BASE, 3); 14208b167e9SHaojian Zhuang pl061_gpio_register(GPIO4_BASE, 4); 14308b167e9SHaojian Zhuang pl061_gpio_register(GPIO5_BASE, 5); 14408b167e9SHaojian Zhuang pl061_gpio_register(GPIO6_BASE, 6); 14508b167e9SHaojian Zhuang pl061_gpio_register(GPIO7_BASE, 7); 14608b167e9SHaojian Zhuang pl061_gpio_register(GPIO8_BASE, 8); 14708b167e9SHaojian Zhuang pl061_gpio_register(GPIO9_BASE, 9); 14808b167e9SHaojian Zhuang pl061_gpio_register(GPIO10_BASE, 10); 14908b167e9SHaojian Zhuang pl061_gpio_register(GPIO11_BASE, 11); 15008b167e9SHaojian Zhuang pl061_gpio_register(GPIO12_BASE, 12); 15108b167e9SHaojian Zhuang pl061_gpio_register(GPIO13_BASE, 13); 15208b167e9SHaojian Zhuang pl061_gpio_register(GPIO14_BASE, 14); 15308b167e9SHaojian Zhuang pl061_gpio_register(GPIO15_BASE, 15); 15408b167e9SHaojian Zhuang pl061_gpio_register(GPIO16_BASE, 16); 15508b167e9SHaojian Zhuang pl061_gpio_register(GPIO17_BASE, 17); 15608b167e9SHaojian Zhuang pl061_gpio_register(GPIO18_BASE, 18); 15708b167e9SHaojian Zhuang pl061_gpio_register(GPIO19_BASE, 19); 15808b167e9SHaojian Zhuang 15908b167e9SHaojian Zhuang /* Power on indicator LED (USER_LED1). */ 16008b167e9SHaojian Zhuang gpio_set_direction(32, GPIO_DIR_OUT); /* LED1 */ 16108b167e9SHaojian Zhuang gpio_set_value(32, GPIO_LEVEL_HIGH); 16208b167e9SHaojian Zhuang gpio_set_direction(33, GPIO_DIR_OUT); /* LED2 */ 16308b167e9SHaojian Zhuang gpio_set_value(33, GPIO_LEVEL_LOW); 16408b167e9SHaojian Zhuang gpio_set_direction(34, GPIO_DIR_OUT); /* LED3 */ 16508b167e9SHaojian Zhuang gpio_set_direction(35, GPIO_DIR_OUT); /* LED4 */ 16608b167e9SHaojian Zhuang } 16708b167e9SHaojian Zhuang 16808b167e9SHaojian Zhuang static void hikey_pmussi_init(void) 16908b167e9SHaojian Zhuang { 17008b167e9SHaojian Zhuang uint32_t data; 17108b167e9SHaojian Zhuang 17208b167e9SHaojian Zhuang /* Initialize PWR_HOLD GPIO */ 17308b167e9SHaojian Zhuang gpio_set_direction(0, GPIO_DIR_OUT); 17408b167e9SHaojian Zhuang gpio_set_value(0, GPIO_LEVEL_LOW); 17508b167e9SHaojian Zhuang 17608b167e9SHaojian Zhuang /* 17708b167e9SHaojian Zhuang * After reset, PMUSSI stays in reset mode. 17808b167e9SHaojian Zhuang * Now make it out of reset. 17908b167e9SHaojian Zhuang */ 18008b167e9SHaojian Zhuang mmio_write_32(AO_SC_PERIPH_RSTDIS4, 18108b167e9SHaojian Zhuang AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N); 18208b167e9SHaojian Zhuang do { 18308b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); 18408b167e9SHaojian Zhuang } while (data & AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N); 18508b167e9SHaojian Zhuang 18608b167e9SHaojian Zhuang /* Set PMUSSI clock latency for read operation. */ 18708b167e9SHaojian Zhuang data = mmio_read_32(AO_SC_MCU_SUBSYS_CTRL3); 18808b167e9SHaojian Zhuang data &= ~AO_SC_MCU_SUBSYS_CTRL3_RCLK_MASK; 18908b167e9SHaojian Zhuang data |= AO_SC_MCU_SUBSYS_CTRL3_RCLK_3; 19008b167e9SHaojian Zhuang mmio_write_32(AO_SC_MCU_SUBSYS_CTRL3, data); 19108b167e9SHaojian Zhuang 19208b167e9SHaojian Zhuang /* enable PMUSSI clock */ 19308b167e9SHaojian Zhuang data = AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_CCPU | 19408b167e9SHaojian Zhuang AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_MCU; 19508b167e9SHaojian Zhuang mmio_write_32(AO_SC_PERIPH_CLKEN5, data); 19608b167e9SHaojian Zhuang data = AO_SC_PERIPH_CLKEN4_PCLK_PMUSSI; 19708b167e9SHaojian Zhuang mmio_write_32(AO_SC_PERIPH_CLKEN4, data); 19808b167e9SHaojian Zhuang 19908b167e9SHaojian Zhuang gpio_set_value(0, GPIO_LEVEL_HIGH); 20008b167e9SHaojian Zhuang } 20108b167e9SHaojian Zhuang 20208b167e9SHaojian Zhuang static void hikey_hi6553_init(void) 20308b167e9SHaojian Zhuang { 20408b167e9SHaojian Zhuang uint8_t data; 20508b167e9SHaojian Zhuang 20608b167e9SHaojian Zhuang mmio_write_8(HI6553_PERI_EN_MARK, 0x1e); 20708b167e9SHaojian Zhuang mmio_write_8(HI6553_NP_REG_ADJ1, 0); 20808b167e9SHaojian Zhuang data = DISABLE6_XO_CLK_CONN | DISABLE6_XO_CLK_NFC | 20908b167e9SHaojian Zhuang DISABLE6_XO_CLK_RF1 | DISABLE6_XO_CLK_RF2; 21008b167e9SHaojian Zhuang mmio_write_8(HI6553_DISABLE6_XO_CLK, data); 21108b167e9SHaojian Zhuang 21208b167e9SHaojian Zhuang /* configure BUCK0 & BUCK1 */ 21308b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK01_CTRL2, 0x5e); 21408b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK0_CTRL7, 0x10); 21508b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK1_CTRL7, 0x10); 21608b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK0_CTRL5, 0x1e); 21708b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK1_CTRL5, 0x1e); 21808b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK0_CTRL1, 0xfc); 21908b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK1_CTRL1, 0xfc); 22008b167e9SHaojian Zhuang 22108b167e9SHaojian Zhuang /* configure BUCK2 */ 22208b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK2_REG1, 0x4f); 22308b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK2_REG5, 0x99); 22408b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK2_REG6, 0x45); 22508b167e9SHaojian Zhuang mdelay(1); 22608b167e9SHaojian Zhuang mmio_write_8(HI6553_VSET_BUCK2_ADJ, 0x22); 22708b167e9SHaojian Zhuang mdelay(1); 22808b167e9SHaojian Zhuang 22908b167e9SHaojian Zhuang /* configure BUCK3 */ 23008b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK3_REG3, 0x02); 23108b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK3_REG5, 0x99); 23208b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK3_REG6, 0x41); 23308b167e9SHaojian Zhuang mmio_write_8(HI6553_VSET_BUCK3_ADJ, 0x02); 23408b167e9SHaojian Zhuang mdelay(1); 23508b167e9SHaojian Zhuang 23608b167e9SHaojian Zhuang /* configure BUCK4 */ 23708b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK4_REG2, 0x9a); 23808b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK4_REG5, 0x99); 23908b167e9SHaojian Zhuang mmio_write_8(HI6553_BUCK4_REG6, 0x45); 24008b167e9SHaojian Zhuang 24108b167e9SHaojian Zhuang /* configure LDO20 */ 24208b167e9SHaojian Zhuang mmio_write_8(HI6553_LDO20_REG_ADJ, 0x50); 24308b167e9SHaojian Zhuang 24408b167e9SHaojian Zhuang mmio_write_8(HI6553_NP_REG_CHG, 0x0f); 24508b167e9SHaojian Zhuang mmio_write_8(HI6553_CLK_TOP0, 0x06); 24608b167e9SHaojian Zhuang mmio_write_8(HI6553_CLK_TOP3, 0xc0); 24708b167e9SHaojian Zhuang mmio_write_8(HI6553_CLK_TOP4, 0x00); 24808b167e9SHaojian Zhuang 24908b167e9SHaojian Zhuang /* configure LDO7 & LDO10 for SD slot */ 25008b167e9SHaojian Zhuang /* enable LDO7 */ 25108b167e9SHaojian Zhuang data = mmio_read_8(HI6553_LDO7_REG_ADJ); 25208b167e9SHaojian Zhuang data = (data & 0xf8) | 0x2; 25308b167e9SHaojian Zhuang mmio_write_8(HI6553_LDO7_REG_ADJ, data); 25408b167e9SHaojian Zhuang mdelay(5); 25508b167e9SHaojian Zhuang mmio_write_8(HI6553_ENABLE2_LDO1_8, 1 << 6); 25608b167e9SHaojian Zhuang mdelay(5); 25708b167e9SHaojian Zhuang /* enable LDO10 */ 25808b167e9SHaojian Zhuang data = mmio_read_8(HI6553_LDO10_REG_ADJ); 25908b167e9SHaojian Zhuang data = (data & 0xf8) | 0x5; 26008b167e9SHaojian Zhuang mmio_write_8(HI6553_LDO10_REG_ADJ, data); 26108b167e9SHaojian Zhuang mdelay(5); 26208b167e9SHaojian Zhuang mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 1); 26308b167e9SHaojian Zhuang mdelay(5); 26408b167e9SHaojian Zhuang /* enable LDO15 */ 26508b167e9SHaojian Zhuang data = mmio_read_8(HI6553_LDO15_REG_ADJ); 26608b167e9SHaojian Zhuang data = (data & 0xf8) | 0x4; 26708b167e9SHaojian Zhuang mmio_write_8(HI6553_LDO15_REG_ADJ, data); 26808b167e9SHaojian Zhuang mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 6); 26908b167e9SHaojian Zhuang mdelay(5); 27008b167e9SHaojian Zhuang /* enable LDO19 */ 27108b167e9SHaojian Zhuang data = mmio_read_8(HI6553_LDO19_REG_ADJ); 27208b167e9SHaojian Zhuang data |= 0x7; 27308b167e9SHaojian Zhuang mmio_write_8(HI6553_LDO19_REG_ADJ, data); 27408b167e9SHaojian Zhuang mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 2); 27508b167e9SHaojian Zhuang mdelay(5); 27608b167e9SHaojian Zhuang /* enable LDO21 */ 27708b167e9SHaojian Zhuang data = mmio_read_8(HI6553_LDO21_REG_ADJ); 27808b167e9SHaojian Zhuang data = (data & 0xf8) | 0x3; 27908b167e9SHaojian Zhuang mmio_write_8(HI6553_LDO21_REG_ADJ, data); 28008b167e9SHaojian Zhuang mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 4); 28108b167e9SHaojian Zhuang mdelay(5); 28208b167e9SHaojian Zhuang /* enable LDO22 */ 28308b167e9SHaojian Zhuang data = mmio_read_8(HI6553_LDO22_REG_ADJ); 28408b167e9SHaojian Zhuang data = (data & 0xf8) | 0x7; 28508b167e9SHaojian Zhuang mmio_write_8(HI6553_LDO22_REG_ADJ, data); 28608b167e9SHaojian Zhuang mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 5); 28708b167e9SHaojian Zhuang mdelay(5); 28808b167e9SHaojian Zhuang 28908b167e9SHaojian Zhuang /* select 32.764KHz */ 29008b167e9SHaojian Zhuang mmio_write_8(HI6553_CLK19M2_600_586_EN, 0x01); 291*c9e8774cSLeo Yan 292*c9e8774cSLeo Yan /* Disable vbus_det interrupts */ 293*c9e8774cSLeo Yan data = mmio_read_8(HI6553_IRQ2_MASK); 294*c9e8774cSLeo Yan data = data | 0x3; 295*c9e8774cSLeo Yan mmio_write_8(HI6553_IRQ2_MASK, data); 29608b167e9SHaojian Zhuang } 29708b167e9SHaojian Zhuang 29808b167e9SHaojian Zhuang static void init_mmc0_pll(void) 29908b167e9SHaojian Zhuang { 30008b167e9SHaojian Zhuang unsigned int data; 30108b167e9SHaojian Zhuang 30208b167e9SHaojian Zhuang /* select SYSPLL as the source of MMC0 */ 30308b167e9SHaojian Zhuang /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */ 30408b167e9SHaojian Zhuang mmio_write_32(PERI_SC_CLK_SEL0, 1 << 5 | 1 << 21); 30508b167e9SHaojian Zhuang do { 30608b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_CLK_SEL0); 30708b167e9SHaojian Zhuang } while (!(data & (1 << 5))); 30808b167e9SHaojian Zhuang /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */ 30908b167e9SHaojian Zhuang mmio_write_32(PERI_SC_CLK_SEL0, 1 << 29); 31008b167e9SHaojian Zhuang do { 31108b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_CLK_SEL0); 31208b167e9SHaojian Zhuang } while (data & (1 << 13)); 31308b167e9SHaojian Zhuang 31408b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 0)); 31508b167e9SHaojian Zhuang do { 31608b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 31708b167e9SHaojian Zhuang } while (!(data & (1 << 0))); 31808b167e9SHaojian Zhuang 31908b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKEN12); 32008b167e9SHaojian Zhuang data |= 1 << 1; 32108b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN12, data); 32208b167e9SHaojian Zhuang 32308b167e9SHaojian Zhuang do { 32408b167e9SHaojian Zhuang mmio_write_32(PERI_SC_CLKCFG8BIT1, (1 << 7) | 0xb); 32508b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_CLKCFG8BIT1); 32608b167e9SHaojian Zhuang } while ((data & 0xb) != 0xb); 32708b167e9SHaojian Zhuang } 32808b167e9SHaojian Zhuang 32908b167e9SHaojian Zhuang static void reset_mmc0_clk(void) 33008b167e9SHaojian Zhuang { 33108b167e9SHaojian Zhuang unsigned int data; 33208b167e9SHaojian Zhuang 33308b167e9SHaojian Zhuang /* disable mmc0 bus clock */ 33408b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0); 33508b167e9SHaojian Zhuang do { 33608b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 33708b167e9SHaojian Zhuang } while (data & PERI_CLK0_MMC0); 33808b167e9SHaojian Zhuang /* enable mmc0 bus clock */ 33908b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0); 34008b167e9SHaojian Zhuang do { 34108b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 34208b167e9SHaojian Zhuang } while (!(data & PERI_CLK0_MMC0)); 34308b167e9SHaojian Zhuang /* reset mmc0 clock domain */ 34408b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0); 34508b167e9SHaojian Zhuang 34608b167e9SHaojian Zhuang /* bypass mmc0 clock phase */ 34708b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CTRL2); 34808b167e9SHaojian Zhuang data |= 3; 34908b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CTRL2, data); 35008b167e9SHaojian Zhuang 35108b167e9SHaojian Zhuang /* disable low power */ 35208b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CTRL13); 35308b167e9SHaojian Zhuang data |= 1 << 3; 35408b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CTRL13, data); 35508b167e9SHaojian Zhuang do { 35608b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); 35708b167e9SHaojian Zhuang } while (!(data & PERI_RST0_MMC0)); 35808b167e9SHaojian Zhuang 35908b167e9SHaojian Zhuang /* unreset mmc0 clock domain */ 36008b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0); 36108b167e9SHaojian Zhuang do { 36208b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); 36308b167e9SHaojian Zhuang } while (data & PERI_RST0_MMC0); 36408b167e9SHaojian Zhuang } 36508b167e9SHaojian Zhuang 36608b167e9SHaojian Zhuang static void init_media_clk(void) 36708b167e9SHaojian Zhuang { 36808b167e9SHaojian Zhuang unsigned int data, value; 36908b167e9SHaojian Zhuang 37008b167e9SHaojian Zhuang data = mmio_read_32(PMCTRL_MEDPLLCTRL); 37108b167e9SHaojian Zhuang data |= 1; 37208b167e9SHaojian Zhuang mmio_write_32(PMCTRL_MEDPLLCTRL, data); 37308b167e9SHaojian Zhuang 37408b167e9SHaojian Zhuang for (;;) { 37508b167e9SHaojian Zhuang data = mmio_read_32(PMCTRL_MEDPLLCTRL); 37608b167e9SHaojian Zhuang value = 1 << 28; 37708b167e9SHaojian Zhuang if ((data & value) == value) 37808b167e9SHaojian Zhuang break; 37908b167e9SHaojian Zhuang } 38008b167e9SHaojian Zhuang 38108b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKEN12); 38208b167e9SHaojian Zhuang data = 1 << 10; 38308b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN12, data); 38408b167e9SHaojian Zhuang } 38508b167e9SHaojian Zhuang 38608b167e9SHaojian Zhuang static void init_mmc1_pll(void) 38708b167e9SHaojian Zhuang { 38808b167e9SHaojian Zhuang uint32_t data; 38908b167e9SHaojian Zhuang 39008b167e9SHaojian Zhuang /* select SYSPLL as the source of MMC1 */ 39108b167e9SHaojian Zhuang /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */ 39208b167e9SHaojian Zhuang mmio_write_32(PERI_SC_CLK_SEL0, 1 << 11 | 1 << 27); 39308b167e9SHaojian Zhuang do { 39408b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_CLK_SEL0); 39508b167e9SHaojian Zhuang } while (!(data & (1 << 11))); 39608b167e9SHaojian Zhuang /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */ 39708b167e9SHaojian Zhuang mmio_write_32(PERI_SC_CLK_SEL0, 1 << 30); 39808b167e9SHaojian Zhuang do { 39908b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_CLK_SEL0); 40008b167e9SHaojian Zhuang } while (data & (1 << 14)); 40108b167e9SHaojian Zhuang 40208b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 1)); 40308b167e9SHaojian Zhuang do { 40408b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 40508b167e9SHaojian Zhuang } while (!(data & (1 << 1))); 40608b167e9SHaojian Zhuang 40708b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKEN12); 40808b167e9SHaojian Zhuang data |= 1 << 2; 40908b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN12, data); 41008b167e9SHaojian Zhuang 41108b167e9SHaojian Zhuang do { 41208b167e9SHaojian Zhuang /* 1.2GHz / 50 = 24MHz */ 41308b167e9SHaojian Zhuang mmio_write_32(PERI_SC_CLKCFG8BIT2, 0x31 | (1 << 7)); 41408b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_CLKCFG8BIT2); 41508b167e9SHaojian Zhuang } while ((data & 0x31) != 0x31); 41608b167e9SHaojian Zhuang } 41708b167e9SHaojian Zhuang 41808b167e9SHaojian Zhuang static void reset_mmc1_clk(void) 41908b167e9SHaojian Zhuang { 42008b167e9SHaojian Zhuang unsigned int data; 42108b167e9SHaojian Zhuang 42208b167e9SHaojian Zhuang /* disable mmc1 bus clock */ 42308b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC1); 42408b167e9SHaojian Zhuang do { 42508b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 42608b167e9SHaojian Zhuang } while (data & PERI_CLK0_MMC1); 42708b167e9SHaojian Zhuang /* enable mmc1 bus clock */ 42808b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC1); 42908b167e9SHaojian Zhuang do { 43008b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); 43108b167e9SHaojian Zhuang } while (!(data & PERI_CLK0_MMC1)); 43208b167e9SHaojian Zhuang /* reset mmc1 clock domain */ 43308b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC1); 43408b167e9SHaojian Zhuang 43508b167e9SHaojian Zhuang /* bypass mmc1 clock phase */ 43608b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CTRL2); 43708b167e9SHaojian Zhuang data |= 3 << 2; 43808b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CTRL2, data); 43908b167e9SHaojian Zhuang 44008b167e9SHaojian Zhuang /* disable low power */ 44108b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_CTRL13); 44208b167e9SHaojian Zhuang data |= 1 << 4; 44308b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_CTRL13, data); 44408b167e9SHaojian Zhuang do { 44508b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); 44608b167e9SHaojian Zhuang } while (!(data & PERI_RST0_MMC1)); 44708b167e9SHaojian Zhuang 44808b167e9SHaojian Zhuang /* unreset mmc0 clock domain */ 44908b167e9SHaojian Zhuang mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC1); 45008b167e9SHaojian Zhuang do { 45108b167e9SHaojian Zhuang data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); 45208b167e9SHaojian Zhuang } while (data & PERI_RST0_MMC1); 45308b167e9SHaojian Zhuang } 45408b167e9SHaojian Zhuang 45508b167e9SHaojian Zhuang /* Initialize PLL of both eMMC and SD controllers. */ 45608b167e9SHaojian Zhuang static void hikey_mmc_pll_init(void) 45708b167e9SHaojian Zhuang { 45808b167e9SHaojian Zhuang init_mmc0_pll(); 45908b167e9SHaojian Zhuang reset_mmc0_clk(); 46008b167e9SHaojian Zhuang init_media_clk(); 46108b167e9SHaojian Zhuang 46208b167e9SHaojian Zhuang dsb(); 46308b167e9SHaojian Zhuang 46408b167e9SHaojian Zhuang init_mmc1_pll(); 46508b167e9SHaojian Zhuang reset_mmc1_clk(); 46608b167e9SHaojian Zhuang } 46708b167e9SHaojian Zhuang 46808b167e9SHaojian Zhuang /* 46908b167e9SHaojian Zhuang * Function which will perform any remaining platform-specific setup that can 47008b167e9SHaojian Zhuang * occur after the MMU and data cache have been enabled. 47108b167e9SHaojian Zhuang */ 47208b167e9SHaojian Zhuang void bl1_platform_setup(void) 47308b167e9SHaojian Zhuang { 47408b167e9SHaojian Zhuang dw_mmc_params_t params; 47508b167e9SHaojian Zhuang 47608b167e9SHaojian Zhuang assert((HIKEY_BL1_MMC_DESC_BASE >= SRAM_BASE) && 47708b167e9SHaojian Zhuang ((SRAM_BASE + SRAM_SIZE) >= 47808b167e9SHaojian Zhuang (HIKEY_BL1_MMC_DATA_BASE + HIKEY_BL1_MMC_DATA_SIZE))); 47908b167e9SHaojian Zhuang hikey_sp804_init(); 48008b167e9SHaojian Zhuang hikey_gpio_init(); 48108b167e9SHaojian Zhuang hikey_pmussi_init(); 48208b167e9SHaojian Zhuang hikey_hi6553_init(); 48308b167e9SHaojian Zhuang 48408b167e9SHaojian Zhuang hikey_mmc_pll_init(); 48508b167e9SHaojian Zhuang 48608b167e9SHaojian Zhuang memset(¶ms, 0, sizeof(dw_mmc_params_t)); 48708b167e9SHaojian Zhuang params.reg_base = DWMMC0_BASE; 48808b167e9SHaojian Zhuang params.desc_base = HIKEY_BL1_MMC_DESC_BASE; 48908b167e9SHaojian Zhuang params.desc_size = 1 << 20; 49008b167e9SHaojian Zhuang params.clk_rate = 24 * 1000 * 1000; 49108b167e9SHaojian Zhuang params.bus_width = EMMC_BUS_WIDTH_8; 49208b167e9SHaojian Zhuang params.flags = EMMC_FLAG_CMD23; 49308b167e9SHaojian Zhuang dw_mmc_init(¶ms); 49408b167e9SHaojian Zhuang 49508b167e9SHaojian Zhuang hikey_io_setup(); 49608b167e9SHaojian Zhuang } 49708b167e9SHaojian Zhuang 49808b167e9SHaojian Zhuang /* 49908b167e9SHaojian Zhuang * The following function checks if Firmware update is needed, 50008b167e9SHaojian Zhuang * by checking if TOC in FIP image is valid or not. 50108b167e9SHaojian Zhuang */ 50208b167e9SHaojian Zhuang unsigned int bl1_plat_get_next_image_id(void) 50308b167e9SHaojian Zhuang { 50408b167e9SHaojian Zhuang int32_t boot_mode; 50508b167e9SHaojian Zhuang unsigned int ret; 50608b167e9SHaojian Zhuang 50708b167e9SHaojian Zhuang boot_mode = mmio_read_32(ONCHIPROM_PARAM_BASE); 50808b167e9SHaojian Zhuang switch (boot_mode) { 50908b167e9SHaojian Zhuang case BOOT_NORMAL: 51008b167e9SHaojian Zhuang ret = BL2_IMAGE_ID; 51108b167e9SHaojian Zhuang break; 51208b167e9SHaojian Zhuang case BOOT_USB_DOWNLOAD: 51308b167e9SHaojian Zhuang case BOOT_UART_DOWNLOAD: 51408b167e9SHaojian Zhuang ret = NS_BL1U_IMAGE_ID; 51508b167e9SHaojian Zhuang break; 51608b167e9SHaojian Zhuang default: 51708b167e9SHaojian Zhuang WARN("Invalid boot mode is found:%d\n", boot_mode); 51808b167e9SHaojian Zhuang panic(); 51908b167e9SHaojian Zhuang } 52008b167e9SHaojian Zhuang return ret; 52108b167e9SHaojian Zhuang } 52208b167e9SHaojian Zhuang 52308b167e9SHaojian Zhuang image_desc_t *bl1_plat_get_image_desc(unsigned int image_id) 52408b167e9SHaojian Zhuang { 52508b167e9SHaojian Zhuang unsigned int index = 0; 52608b167e9SHaojian Zhuang 52708b167e9SHaojian Zhuang while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) { 52808b167e9SHaojian Zhuang if (bl1_tbbr_image_descs[index].image_id == image_id) 52908b167e9SHaojian Zhuang return &bl1_tbbr_image_descs[index]; 53008b167e9SHaojian Zhuang 53108b167e9SHaojian Zhuang index++; 53208b167e9SHaojian Zhuang } 53308b167e9SHaojian Zhuang 53408b167e9SHaojian Zhuang return NULL; 53508b167e9SHaojian Zhuang } 53608b167e9SHaojian Zhuang 53708b167e9SHaojian Zhuang void bl1_plat_set_ep_info(unsigned int image_id, 53808b167e9SHaojian Zhuang entry_point_info_t *ep_info) 53908b167e9SHaojian Zhuang { 54008b167e9SHaojian Zhuang unsigned int data = 0; 54108b167e9SHaojian Zhuang 54208b167e9SHaojian Zhuang if (image_id == BL2_IMAGE_ID) 54308b167e9SHaojian Zhuang return; 54408b167e9SHaojian Zhuang inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE); 54508b167e9SHaojian Zhuang __asm__ volatile ("mrs %0, cpacr_el1" : "=r"(data)); 54608b167e9SHaojian Zhuang do { 54708b167e9SHaojian Zhuang data |= 3 << 20; 54808b167e9SHaojian Zhuang __asm__ volatile ("msr cpacr_el1, %0" : : "r"(data)); 54908b167e9SHaojian Zhuang __asm__ volatile ("mrs %0, cpacr_el1" : "=r"(data)); 55008b167e9SHaojian Zhuang } while ((data & (3 << 20)) != (3 << 20)); 55108b167e9SHaojian Zhuang INFO("cpacr_el1:0x%x\n", data); 55208b167e9SHaojian Zhuang 55308b167e9SHaojian Zhuang ep_info->args.arg0 = 0xffff & read_mpidr(); 55408b167e9SHaojian Zhuang ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, 55508b167e9SHaojian Zhuang DISABLE_ALL_EXCEPTIONS); 55608b167e9SHaojian Zhuang } 557