xref: /rk3399_ARM-atf/plat/hisilicon/hikey/hikey_bl2_setup.c (revision a628b1ab2aa8fa7ca9ffe4e05d714c50e8d83792)
132e9fc1aSHaojian Zhuang /*
2103c213cSHaojian Zhuang  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
332e9fc1aSHaojian Zhuang  *
432e9fc1aSHaojian Zhuang  * SPDX-License-Identifier: BSD-3-Clause
532e9fc1aSHaojian Zhuang  */
632e9fc1aSHaojian Zhuang 
732e9fc1aSHaojian Zhuang #include <arch_helpers.h>
832e9fc1aSHaojian Zhuang #include <assert.h>
932e9fc1aSHaojian Zhuang #include <bl_common.h>
1032e9fc1aSHaojian Zhuang #include <console.h>
1132e9fc1aSHaojian Zhuang #include <debug.h>
122de0c5ccSVictor Chong #include <desc_image_load.h>
1332e9fc1aSHaojian Zhuang #include <dw_mmc.h>
1432e9fc1aSHaojian Zhuang #include <emmc.h>
1532e9fc1aSHaojian Zhuang #include <errno.h>
16*a628b1abSHaojian Zhuang #include <gpio.h>
1732e9fc1aSHaojian Zhuang #include <hi6220.h>
18*a628b1abSHaojian Zhuang #include <hi6553.h>
1932e9fc1aSHaojian Zhuang #include <hisi_mcu.h>
2032e9fc1aSHaojian Zhuang #include <hisi_sram_map.h>
2132e9fc1aSHaojian Zhuang #include <mmio.h>
22b16bb16eSVictor Chong #ifdef SPD_opteed
23b16bb16eSVictor Chong #include <optee_utils.h>
24b16bb16eSVictor Chong #endif
25*a628b1abSHaojian Zhuang #include <pl061_gpio.h>
26*a628b1abSHaojian Zhuang #include <platform.h>
2732e9fc1aSHaojian Zhuang #include <platform_def.h>
2832e9fc1aSHaojian Zhuang #include <sp804_delay_timer.h>
2932e9fc1aSHaojian Zhuang #include <string.h>
3032e9fc1aSHaojian Zhuang 
3132e9fc1aSHaojian Zhuang #include "hikey_def.h"
3232e9fc1aSHaojian Zhuang #include "hikey_private.h"
3332e9fc1aSHaojian Zhuang 
3432e9fc1aSHaojian Zhuang /*
3532e9fc1aSHaojian Zhuang  * The next 2 constants identify the extents of the code & RO data region.
3632e9fc1aSHaojian Zhuang  * These addresses are used by the MMU setup code and therefore they must be
3732e9fc1aSHaojian Zhuang  * page-aligned.  It is the responsibility of the linker script to ensure that
3832e9fc1aSHaojian Zhuang  * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
3932e9fc1aSHaojian Zhuang  */
4032e9fc1aSHaojian Zhuang #define BL2_RO_BASE (unsigned long)(&__RO_START__)
4132e9fc1aSHaojian Zhuang #define BL2_RO_LIMIT (unsigned long)(&__RO_END__)
4232e9fc1aSHaojian Zhuang 
43*a628b1abSHaojian Zhuang #define BL2_RW_BASE		(BL2_RO_LIMIT)
44*a628b1abSHaojian Zhuang 
4532e9fc1aSHaojian Zhuang /*
4632e9fc1aSHaojian Zhuang  * The next 2 constants identify the extents of the coherent memory region.
4732e9fc1aSHaojian Zhuang  * These addresses are used by the MMU setup code and therefore they must be
4832e9fc1aSHaojian Zhuang  * page-aligned.  It is the responsibility of the linker script to ensure that
4932e9fc1aSHaojian Zhuang  * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
5032e9fc1aSHaojian Zhuang  * page-aligned addresses.
5132e9fc1aSHaojian Zhuang  */
5232e9fc1aSHaojian Zhuang #define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
5332e9fc1aSHaojian Zhuang #define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
5432e9fc1aSHaojian Zhuang 
55*a628b1abSHaojian Zhuang static meminfo_t bl2_el3_tzram_layout;
56*a628b1abSHaojian Zhuang 
57*a628b1abSHaojian Zhuang enum {
58*a628b1abSHaojian Zhuang 	BOOT_MODE_RECOVERY = 0,
59*a628b1abSHaojian Zhuang 	BOOT_MODE_NORMAL,
60*a628b1abSHaojian Zhuang 	BOOT_MODE_MASK = 1,
61*a628b1abSHaojian Zhuang };
6232e9fc1aSHaojian Zhuang 
632de0c5ccSVictor Chong /*******************************************************************************
642de0c5ccSVictor Chong  * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
652de0c5ccSVictor Chong  * Return 0 on success, -1 otherwise.
662de0c5ccSVictor Chong  ******************************************************************************/
672de0c5ccSVictor Chong int plat_hikey_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info)
6832e9fc1aSHaojian Zhuang {
6932e9fc1aSHaojian Zhuang 	/* Enable MCU SRAM */
7032e9fc1aSHaojian Zhuang 	hisi_mcu_enable_sram();
7132e9fc1aSHaojian Zhuang 
7232e9fc1aSHaojian Zhuang 	/* Load MCU binary into SRAM */
7332e9fc1aSHaojian Zhuang 	hisi_mcu_load_image(scp_bl2_image_info->image_base,
7432e9fc1aSHaojian Zhuang 			    scp_bl2_image_info->image_size);
7532e9fc1aSHaojian Zhuang 	/* Let MCU running */
7632e9fc1aSHaojian Zhuang 	hisi_mcu_start_run();
7732e9fc1aSHaojian Zhuang 
7832e9fc1aSHaojian Zhuang 	INFO("%s: MCU PC is at 0x%x\n",
7932e9fc1aSHaojian Zhuang 	     __func__, mmio_read_32(AO_SC_MCU_SUBSYS_STAT2));
8032e9fc1aSHaojian Zhuang 	INFO("%s: AO_SC_PERIPH_CLKSTAT4 is 0x%x\n",
8132e9fc1aSHaojian Zhuang 	     __func__, mmio_read_32(AO_SC_PERIPH_CLKSTAT4));
8232e9fc1aSHaojian Zhuang 	return 0;
8332e9fc1aSHaojian Zhuang }
8432e9fc1aSHaojian Zhuang 
852de0c5ccSVictor Chong /*******************************************************************************
862de0c5ccSVictor Chong  * Gets SPSR for BL32 entry
872de0c5ccSVictor Chong  ******************************************************************************/
882de0c5ccSVictor Chong uint32_t hikey_get_spsr_for_bl32_entry(void)
892de0c5ccSVictor Chong {
902de0c5ccSVictor Chong 	/*
912de0c5ccSVictor Chong 	 * The Secure Payload Dispatcher service is responsible for
922de0c5ccSVictor Chong 	 * setting the SPSR prior to entry into the BL3-2 image.
932de0c5ccSVictor Chong 	 */
942de0c5ccSVictor Chong 	return 0;
952de0c5ccSVictor Chong }
962de0c5ccSVictor Chong 
972de0c5ccSVictor Chong /*******************************************************************************
982de0c5ccSVictor Chong  * Gets SPSR for BL33 entry
992de0c5ccSVictor Chong  ******************************************************************************/
1002de0c5ccSVictor Chong #ifndef AARCH32
1012de0c5ccSVictor Chong uint32_t hikey_get_spsr_for_bl33_entry(void)
1022de0c5ccSVictor Chong {
1032de0c5ccSVictor Chong 	unsigned int mode;
1042de0c5ccSVictor Chong 	uint32_t spsr;
1052de0c5ccSVictor Chong 
1062de0c5ccSVictor Chong 	/* Figure out what mode we enter the non-secure world in */
1072de0c5ccSVictor Chong 	mode = EL_IMPLEMENTED(2) ? MODE_EL2 : MODE_EL1;
1082de0c5ccSVictor Chong 
1092de0c5ccSVictor Chong 	/*
1102de0c5ccSVictor Chong 	 * TODO: Consider the possibility of specifying the SPSR in
1112de0c5ccSVictor Chong 	 * the FIP ToC and allowing the platform to have a say as
1122de0c5ccSVictor Chong 	 * well.
1132de0c5ccSVictor Chong 	 */
1142de0c5ccSVictor Chong 	spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
1152de0c5ccSVictor Chong 	return spsr;
1162de0c5ccSVictor Chong }
1172de0c5ccSVictor Chong #else
1182de0c5ccSVictor Chong uint32_t hikey_get_spsr_for_bl33_entry(void)
1192de0c5ccSVictor Chong {
1202de0c5ccSVictor Chong 	unsigned int hyp_status, mode, spsr;
1212de0c5ccSVictor Chong 
1222de0c5ccSVictor Chong 	hyp_status = GET_VIRT_EXT(read_id_pfr1());
1232de0c5ccSVictor Chong 
1242de0c5ccSVictor Chong 	mode = (hyp_status) ? MODE32_hyp : MODE32_svc;
1252de0c5ccSVictor Chong 
1262de0c5ccSVictor Chong 	/*
1272de0c5ccSVictor Chong 	 * TODO: Consider the possibility of specifying the SPSR in
1282de0c5ccSVictor Chong 	 * the FIP ToC and allowing the platform to have a say as
1292de0c5ccSVictor Chong 	 * well.
1302de0c5ccSVictor Chong 	 */
1312de0c5ccSVictor Chong 	spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1,
1322de0c5ccSVictor Chong 			SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
1332de0c5ccSVictor Chong 	return spsr;
1342de0c5ccSVictor Chong }
1352de0c5ccSVictor Chong #endif /* AARCH32 */
1362de0c5ccSVictor Chong 
1372de0c5ccSVictor Chong int hikey_bl2_handle_post_image_load(unsigned int image_id)
1382de0c5ccSVictor Chong {
1392de0c5ccSVictor Chong 	int err = 0;
1402de0c5ccSVictor Chong 	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
141b16bb16eSVictor Chong #ifdef SPD_opteed
142b16bb16eSVictor Chong 	bl_mem_params_node_t *pager_mem_params = NULL;
143b16bb16eSVictor Chong 	bl_mem_params_node_t *paged_mem_params = NULL;
144b16bb16eSVictor Chong #endif
1452de0c5ccSVictor Chong 	assert(bl_mem_params);
1462de0c5ccSVictor Chong 
1472de0c5ccSVictor Chong 	switch (image_id) {
1482de0c5ccSVictor Chong #ifdef AARCH64
1492de0c5ccSVictor Chong 	case BL32_IMAGE_ID:
150b16bb16eSVictor Chong #ifdef SPD_opteed
151b16bb16eSVictor Chong 		pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
152b16bb16eSVictor Chong 		assert(pager_mem_params);
153b16bb16eSVictor Chong 
154b16bb16eSVictor Chong 		paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
155b16bb16eSVictor Chong 		assert(paged_mem_params);
156b16bb16eSVictor Chong 
157b16bb16eSVictor Chong 		err = parse_optee_header(&bl_mem_params->ep_info,
158b16bb16eSVictor Chong 				&pager_mem_params->image_info,
159b16bb16eSVictor Chong 				&paged_mem_params->image_info);
160b16bb16eSVictor Chong 		if (err != 0) {
161b16bb16eSVictor Chong 			WARN("OPTEE header parse error.\n");
162b16bb16eSVictor Chong 		}
163b16bb16eSVictor Chong #endif
1642de0c5ccSVictor Chong 		bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl32_entry();
1652de0c5ccSVictor Chong 		break;
1662de0c5ccSVictor Chong #endif
1672de0c5ccSVictor Chong 
1682de0c5ccSVictor Chong 	case BL33_IMAGE_ID:
1692de0c5ccSVictor Chong 		/* BL33 expects to receive the primary CPU MPID (through r0) */
1702de0c5ccSVictor Chong 		bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
1712de0c5ccSVictor Chong 		bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl33_entry();
1722de0c5ccSVictor Chong 		break;
1732de0c5ccSVictor Chong 
1742de0c5ccSVictor Chong #ifdef SCP_BL2_BASE
1752de0c5ccSVictor Chong 	case SCP_BL2_IMAGE_ID:
1762de0c5ccSVictor Chong 		/* The subsequent handling of SCP_BL2 is platform specific */
1772de0c5ccSVictor Chong 		err = plat_hikey_bl2_handle_scp_bl2(&bl_mem_params->image_info);
1782de0c5ccSVictor Chong 		if (err) {
1792de0c5ccSVictor Chong 			WARN("Failure in platform-specific handling of SCP_BL2 image.\n");
1802de0c5ccSVictor Chong 		}
1812de0c5ccSVictor Chong 		break;
1822de0c5ccSVictor Chong #endif
1832de0c5ccSVictor Chong 	}
1842de0c5ccSVictor Chong 
1852de0c5ccSVictor Chong 	return err;
1862de0c5ccSVictor Chong }
1872de0c5ccSVictor Chong 
1882de0c5ccSVictor Chong /*******************************************************************************
1892de0c5ccSVictor Chong  * This function can be used by the platforms to update/use image
1902de0c5ccSVictor Chong  * information for given `image_id`.
1912de0c5ccSVictor Chong  ******************************************************************************/
1922de0c5ccSVictor Chong int bl2_plat_handle_post_image_load(unsigned int image_id)
1932de0c5ccSVictor Chong {
1942de0c5ccSVictor Chong 	return hikey_bl2_handle_post_image_load(image_id);
1952de0c5ccSVictor Chong }
1962de0c5ccSVictor Chong 
19732e9fc1aSHaojian Zhuang static void reset_dwmmc_clk(void)
19832e9fc1aSHaojian Zhuang {
19932e9fc1aSHaojian Zhuang 	unsigned int data;
20032e9fc1aSHaojian Zhuang 
20132e9fc1aSHaojian Zhuang 	/* disable mmc0 bus clock */
20232e9fc1aSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0);
20332e9fc1aSHaojian Zhuang 	do {
20432e9fc1aSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
20532e9fc1aSHaojian Zhuang 	} while (data & PERI_CLK0_MMC0);
20632e9fc1aSHaojian Zhuang 	/* enable mmc0 bus clock */
20732e9fc1aSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0);
20832e9fc1aSHaojian Zhuang 	do {
20932e9fc1aSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
21032e9fc1aSHaojian Zhuang 	} while (!(data & PERI_CLK0_MMC0));
21132e9fc1aSHaojian Zhuang 	/* reset mmc0 clock domain */
21232e9fc1aSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0);
21332e9fc1aSHaojian Zhuang 
21432e9fc1aSHaojian Zhuang 	/* bypass mmc0 clock phase */
21532e9fc1aSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
21632e9fc1aSHaojian Zhuang 	data |= 3;
21732e9fc1aSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
21832e9fc1aSHaojian Zhuang 
21932e9fc1aSHaojian Zhuang 	/* disable low power */
22032e9fc1aSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
22132e9fc1aSHaojian Zhuang 	data |= 1 << 3;
22232e9fc1aSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
22332e9fc1aSHaojian Zhuang 	do {
22432e9fc1aSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
22532e9fc1aSHaojian Zhuang 	} while (!(data & PERI_RST0_MMC0));
22632e9fc1aSHaojian Zhuang 
22732e9fc1aSHaojian Zhuang 	/* unreset mmc0 clock domain */
22832e9fc1aSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0);
22932e9fc1aSHaojian Zhuang 	do {
23032e9fc1aSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
23132e9fc1aSHaojian Zhuang 	} while (data & PERI_RST0_MMC0);
23232e9fc1aSHaojian Zhuang }
23332e9fc1aSHaojian Zhuang 
23432e9fc1aSHaojian Zhuang static void hikey_boardid_init(void)
23532e9fc1aSHaojian Zhuang {
23632e9fc1aSHaojian Zhuang 	u_register_t midr;
23732e9fc1aSHaojian Zhuang 
23832e9fc1aSHaojian Zhuang 	midr = read_midr();
23932e9fc1aSHaojian Zhuang 	mmio_write_32(MEMORY_AXI_CHIP_ADDR, midr);
24032e9fc1aSHaojian Zhuang 	INFO("[BDID] [%x] midr: 0x%x\n", MEMORY_AXI_CHIP_ADDR,
24132e9fc1aSHaojian Zhuang 	     (unsigned int)midr);
24232e9fc1aSHaojian Zhuang 
24332e9fc1aSHaojian Zhuang 	mmio_write_32(MEMORY_AXI_BOARD_TYPE_ADDR, 0);
24432e9fc1aSHaojian Zhuang 	mmio_write_32(MEMORY_AXI_BOARD_ID_ADDR, 0x2b);
24532e9fc1aSHaojian Zhuang 
24632e9fc1aSHaojian Zhuang 	mmio_write_32(ACPU_ARM64_FLAGA, 0x1234);
24732e9fc1aSHaojian Zhuang 	mmio_write_32(ACPU_ARM64_FLAGB, 0x5678);
24832e9fc1aSHaojian Zhuang }
24932e9fc1aSHaojian Zhuang 
25032e9fc1aSHaojian Zhuang static void hikey_sd_init(void)
25132e9fc1aSHaojian Zhuang {
25232e9fc1aSHaojian Zhuang 	/* switch pinmux to SD */
25332e9fc1aSHaojian Zhuang 	mmio_write_32(IOMG_SD_CLK, IOMG_MUX_FUNC0);
25432e9fc1aSHaojian Zhuang 	mmio_write_32(IOMG_SD_CMD, IOMG_MUX_FUNC0);
25532e9fc1aSHaojian Zhuang 	mmio_write_32(IOMG_SD_DATA0, IOMG_MUX_FUNC0);
25632e9fc1aSHaojian Zhuang 	mmio_write_32(IOMG_SD_DATA1, IOMG_MUX_FUNC0);
25732e9fc1aSHaojian Zhuang 	mmio_write_32(IOMG_SD_DATA2, IOMG_MUX_FUNC0);
25832e9fc1aSHaojian Zhuang 	mmio_write_32(IOMG_SD_DATA3, IOMG_MUX_FUNC0);
25932e9fc1aSHaojian Zhuang 
26032e9fc1aSHaojian Zhuang 	mmio_write_32(IOCG_SD_CLK, IOCG_INPUT_16MA);
26132e9fc1aSHaojian Zhuang 	mmio_write_32(IOCG_SD_CMD, IOCG_INPUT_12MA);
26232e9fc1aSHaojian Zhuang 	mmio_write_32(IOCG_SD_DATA0, IOCG_INPUT_12MA);
26332e9fc1aSHaojian Zhuang 	mmio_write_32(IOCG_SD_DATA1, IOCG_INPUT_12MA);
26432e9fc1aSHaojian Zhuang 	mmio_write_32(IOCG_SD_DATA2, IOCG_INPUT_12MA);
26532e9fc1aSHaojian Zhuang 	mmio_write_32(IOCG_SD_DATA3, IOCG_INPUT_12MA);
26632e9fc1aSHaojian Zhuang 
26732e9fc1aSHaojian Zhuang 	/* set SD Card detect as nopull */
26832e9fc1aSHaojian Zhuang 	mmio_write_32(IOCG_GPIO8, 0);
26932e9fc1aSHaojian Zhuang }
27032e9fc1aSHaojian Zhuang 
27132e9fc1aSHaojian Zhuang static void hikey_jumper_init(void)
27232e9fc1aSHaojian Zhuang {
27332e9fc1aSHaojian Zhuang 	/* set jumper detect as nopull */
27432e9fc1aSHaojian Zhuang 	mmio_write_32(IOCG_GPIO24, 0);
27532e9fc1aSHaojian Zhuang 	/* set jumper detect as GPIO */
27632e9fc1aSHaojian Zhuang 	mmio_write_32(IOMG_GPIO24, IOMG_MUX_FUNC0);
27732e9fc1aSHaojian Zhuang }
27832e9fc1aSHaojian Zhuang 
279*a628b1abSHaojian Zhuang static void hikey_sp804_init(void)
280*a628b1abSHaojian Zhuang {
281*a628b1abSHaojian Zhuang 	uint32_t data;
282*a628b1abSHaojian Zhuang 
283*a628b1abSHaojian Zhuang 	/* select the clock of dual timer0 */
284*a628b1abSHaojian Zhuang 	data = mmio_read_32(AO_SC_TIMER_EN0);
285*a628b1abSHaojian Zhuang 	while (data & 3) {
286*a628b1abSHaojian Zhuang 		data &= ~3;
287*a628b1abSHaojian Zhuang 		data |= 3 << 16;
288*a628b1abSHaojian Zhuang 		mmio_write_32(AO_SC_TIMER_EN0, data);
289*a628b1abSHaojian Zhuang 		data = mmio_read_32(AO_SC_TIMER_EN0);
290*a628b1abSHaojian Zhuang 	}
291*a628b1abSHaojian Zhuang 	/* enable the pclk of dual timer0 */
292*a628b1abSHaojian Zhuang 	data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4);
293*a628b1abSHaojian Zhuang 	while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)) {
294*a628b1abSHaojian Zhuang 		mmio_write_32(AO_SC_PERIPH_CLKEN4, PCLK_TIMER1 | PCLK_TIMER0);
295*a628b1abSHaojian Zhuang 		data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4);
296*a628b1abSHaojian Zhuang 	}
297*a628b1abSHaojian Zhuang 	/* reset dual timer0 */
298*a628b1abSHaojian Zhuang 	data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
299*a628b1abSHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_RSTEN4, PCLK_TIMER1 | PCLK_TIMER0);
300*a628b1abSHaojian Zhuang 	do {
301*a628b1abSHaojian Zhuang 		data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
302*a628b1abSHaojian Zhuang 	} while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0));
303*a628b1abSHaojian Zhuang 	/* unreset dual timer0 */
304*a628b1abSHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_RSTDIS4, PCLK_TIMER1 | PCLK_TIMER0);
305*a628b1abSHaojian Zhuang 	do {
306*a628b1abSHaojian Zhuang 		data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
307*a628b1abSHaojian Zhuang 	} while ((data & PCLK_TIMER1) || (data & PCLK_TIMER0));
308*a628b1abSHaojian Zhuang 
309*a628b1abSHaojian Zhuang 	sp804_timer_init(SP804_TIMER0_BASE, 10, 192);
310*a628b1abSHaojian Zhuang }
311*a628b1abSHaojian Zhuang 
312*a628b1abSHaojian Zhuang static void hikey_gpio_init(void)
313*a628b1abSHaojian Zhuang {
314*a628b1abSHaojian Zhuang 	pl061_gpio_init();
315*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO0_BASE, 0);
316*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO1_BASE, 1);
317*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO2_BASE, 2);
318*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO3_BASE, 3);
319*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO4_BASE, 4);
320*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO5_BASE, 5);
321*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO6_BASE, 6);
322*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO7_BASE, 7);
323*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO8_BASE, 8);
324*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO9_BASE, 9);
325*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO10_BASE, 10);
326*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO11_BASE, 11);
327*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO12_BASE, 12);
328*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO13_BASE, 13);
329*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO14_BASE, 14);
330*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO15_BASE, 15);
331*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO16_BASE, 16);
332*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO17_BASE, 17);
333*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO18_BASE, 18);
334*a628b1abSHaojian Zhuang 	pl061_gpio_register(GPIO19_BASE, 19);
335*a628b1abSHaojian Zhuang 
336*a628b1abSHaojian Zhuang 	/* Power on indicator LED (USER_LED1). */
337*a628b1abSHaojian Zhuang 	gpio_set_direction(32, GPIO_DIR_OUT);	/* LED1 */
338*a628b1abSHaojian Zhuang 	gpio_set_value(32, GPIO_LEVEL_HIGH);
339*a628b1abSHaojian Zhuang 	gpio_set_direction(33, GPIO_DIR_OUT);	/* LED2 */
340*a628b1abSHaojian Zhuang 	gpio_set_value(33, GPIO_LEVEL_LOW);
341*a628b1abSHaojian Zhuang 	gpio_set_direction(34, GPIO_DIR_OUT);	/* LED3 */
342*a628b1abSHaojian Zhuang 	gpio_set_direction(35, GPIO_DIR_OUT);	/* LED4 */
343*a628b1abSHaojian Zhuang }
344*a628b1abSHaojian Zhuang 
345*a628b1abSHaojian Zhuang static void hikey_pmussi_init(void)
346*a628b1abSHaojian Zhuang {
347*a628b1abSHaojian Zhuang 	uint32_t data;
348*a628b1abSHaojian Zhuang 
349*a628b1abSHaojian Zhuang 	/* Initialize PWR_HOLD GPIO */
350*a628b1abSHaojian Zhuang 	gpio_set_direction(0, GPIO_DIR_OUT);
351*a628b1abSHaojian Zhuang 	gpio_set_value(0, GPIO_LEVEL_LOW);
352*a628b1abSHaojian Zhuang 
353*a628b1abSHaojian Zhuang 	/*
354*a628b1abSHaojian Zhuang 	 * After reset, PMUSSI stays in reset mode.
355*a628b1abSHaojian Zhuang 	 * Now make it out of reset.
356*a628b1abSHaojian Zhuang 	 */
357*a628b1abSHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_RSTDIS4,
358*a628b1abSHaojian Zhuang 		      AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N);
359*a628b1abSHaojian Zhuang 	do {
360*a628b1abSHaojian Zhuang 		data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
361*a628b1abSHaojian Zhuang 	} while (data & AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N);
362*a628b1abSHaojian Zhuang 
363*a628b1abSHaojian Zhuang 	/* Set PMUSSI clock latency for read operation. */
364*a628b1abSHaojian Zhuang 	data = mmio_read_32(AO_SC_MCU_SUBSYS_CTRL3);
365*a628b1abSHaojian Zhuang 	data &= ~AO_SC_MCU_SUBSYS_CTRL3_RCLK_MASK;
366*a628b1abSHaojian Zhuang 	data |= AO_SC_MCU_SUBSYS_CTRL3_RCLK_3;
367*a628b1abSHaojian Zhuang 	mmio_write_32(AO_SC_MCU_SUBSYS_CTRL3, data);
368*a628b1abSHaojian Zhuang 
369*a628b1abSHaojian Zhuang 	/* enable PMUSSI clock */
370*a628b1abSHaojian Zhuang 	data = AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_CCPU |
371*a628b1abSHaojian Zhuang 	       AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_MCU;
372*a628b1abSHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_CLKEN5, data);
373*a628b1abSHaojian Zhuang 	data = AO_SC_PERIPH_CLKEN4_PCLK_PMUSSI;
374*a628b1abSHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_CLKEN4, data);
375*a628b1abSHaojian Zhuang 
376*a628b1abSHaojian Zhuang 	gpio_set_value(0, GPIO_LEVEL_HIGH);
377*a628b1abSHaojian Zhuang }
378*a628b1abSHaojian Zhuang 
379*a628b1abSHaojian Zhuang static void hikey_hi6553_init(void)
380*a628b1abSHaojian Zhuang {
381*a628b1abSHaojian Zhuang 	uint8_t data;
382*a628b1abSHaojian Zhuang 
383*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_PERI_EN_MARK, 0x1e);
384*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_NP_REG_ADJ1, 0);
385*a628b1abSHaojian Zhuang 	data = DISABLE6_XO_CLK_CONN | DISABLE6_XO_CLK_NFC |
386*a628b1abSHaojian Zhuang 		DISABLE6_XO_CLK_RF1 | DISABLE6_XO_CLK_RF2;
387*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_DISABLE6_XO_CLK, data);
388*a628b1abSHaojian Zhuang 
389*a628b1abSHaojian Zhuang 	/* configure BUCK0 & BUCK1 */
390*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK01_CTRL2, 0x5e);
391*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK0_CTRL7, 0x10);
392*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK1_CTRL7, 0x10);
393*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK0_CTRL5, 0x1e);
394*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK1_CTRL5, 0x1e);
395*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK0_CTRL1, 0xfc);
396*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK1_CTRL1, 0xfc);
397*a628b1abSHaojian Zhuang 
398*a628b1abSHaojian Zhuang 	/* configure BUCK2 */
399*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK2_REG1, 0x4f);
400*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK2_REG5, 0x99);
401*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK2_REG6, 0x45);
402*a628b1abSHaojian Zhuang 	mdelay(1);
403*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_VSET_BUCK2_ADJ, 0x22);
404*a628b1abSHaojian Zhuang 	mdelay(1);
405*a628b1abSHaojian Zhuang 
406*a628b1abSHaojian Zhuang 	/* configure BUCK3 */
407*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK3_REG3, 0x02);
408*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK3_REG5, 0x99);
409*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK3_REG6, 0x41);
410*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_VSET_BUCK3_ADJ, 0x02);
411*a628b1abSHaojian Zhuang 	mdelay(1);
412*a628b1abSHaojian Zhuang 
413*a628b1abSHaojian Zhuang 	/* configure BUCK4 */
414*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK4_REG2, 0x9a);
415*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK4_REG5, 0x99);
416*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_BUCK4_REG6, 0x45);
417*a628b1abSHaojian Zhuang 
418*a628b1abSHaojian Zhuang 	/* configure LDO20 */
419*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_LDO20_REG_ADJ, 0x50);
420*a628b1abSHaojian Zhuang 
421*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_NP_REG_CHG, 0x0f);
422*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_CLK_TOP0, 0x06);
423*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_CLK_TOP3, 0xc0);
424*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_CLK_TOP4, 0x00);
425*a628b1abSHaojian Zhuang 
426*a628b1abSHaojian Zhuang 	/* configure LDO7 & LDO10 for SD slot */
427*a628b1abSHaojian Zhuang 	/* enable LDO7 */
428*a628b1abSHaojian Zhuang 	data = mmio_read_8(HI6553_LDO7_REG_ADJ);
429*a628b1abSHaojian Zhuang 	data = (data & 0xf8) | 0x2;
430*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_LDO7_REG_ADJ, data);
431*a628b1abSHaojian Zhuang 	mdelay(5);
432*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_ENABLE2_LDO1_8, 1 << 6);
433*a628b1abSHaojian Zhuang 	mdelay(5);
434*a628b1abSHaojian Zhuang 	/* enable LDO10 */
435*a628b1abSHaojian Zhuang 	data = mmio_read_8(HI6553_LDO10_REG_ADJ);
436*a628b1abSHaojian Zhuang 	data = (data & 0xf8) | 0x5;
437*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_LDO10_REG_ADJ, data);
438*a628b1abSHaojian Zhuang 	mdelay(5);
439*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 1);
440*a628b1abSHaojian Zhuang 	mdelay(5);
441*a628b1abSHaojian Zhuang 	/* enable LDO15 */
442*a628b1abSHaojian Zhuang 	data = mmio_read_8(HI6553_LDO15_REG_ADJ);
443*a628b1abSHaojian Zhuang 	data = (data & 0xf8) | 0x4;
444*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_LDO15_REG_ADJ, data);
445*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 6);
446*a628b1abSHaojian Zhuang 	mdelay(5);
447*a628b1abSHaojian Zhuang 	/* enable LDO19 */
448*a628b1abSHaojian Zhuang 	data = mmio_read_8(HI6553_LDO19_REG_ADJ);
449*a628b1abSHaojian Zhuang 	data |= 0x7;
450*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_LDO19_REG_ADJ, data);
451*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 2);
452*a628b1abSHaojian Zhuang 	mdelay(5);
453*a628b1abSHaojian Zhuang 	/* enable LDO21 */
454*a628b1abSHaojian Zhuang 	data = mmio_read_8(HI6553_LDO21_REG_ADJ);
455*a628b1abSHaojian Zhuang 	data = (data & 0xf8) | 0x3;
456*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_LDO21_REG_ADJ, data);
457*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 4);
458*a628b1abSHaojian Zhuang 	mdelay(5);
459*a628b1abSHaojian Zhuang 	/* enable LDO22 */
460*a628b1abSHaojian Zhuang 	data = mmio_read_8(HI6553_LDO22_REG_ADJ);
461*a628b1abSHaojian Zhuang 	data = (data & 0xf8) | 0x7;
462*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_LDO22_REG_ADJ, data);
463*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 5);
464*a628b1abSHaojian Zhuang 	mdelay(5);
465*a628b1abSHaojian Zhuang 
466*a628b1abSHaojian Zhuang 	/* select 32.764KHz */
467*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_CLK19M2_600_586_EN, 0x01);
468*a628b1abSHaojian Zhuang 
469*a628b1abSHaojian Zhuang 	/* Disable vbus_det interrupts */
470*a628b1abSHaojian Zhuang 	data = mmio_read_8(HI6553_IRQ2_MASK);
471*a628b1abSHaojian Zhuang 	data = data | 0x3;
472*a628b1abSHaojian Zhuang 	mmio_write_8(HI6553_IRQ2_MASK, data);
473*a628b1abSHaojian Zhuang }
474*a628b1abSHaojian Zhuang 
475*a628b1abSHaojian Zhuang static void init_mmc0_pll(void)
476*a628b1abSHaojian Zhuang {
477*a628b1abSHaojian Zhuang 	unsigned int data;
478*a628b1abSHaojian Zhuang 
479*a628b1abSHaojian Zhuang 	/* select SYSPLL as the source of MMC0 */
480*a628b1abSHaojian Zhuang 	/* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
481*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_CLK_SEL0, 1 << 5 | 1 << 21);
482*a628b1abSHaojian Zhuang 	do {
483*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLK_SEL0);
484*a628b1abSHaojian Zhuang 	} while (!(data & (1 << 5)));
485*a628b1abSHaojian Zhuang 	/* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
486*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_CLK_SEL0, 1 << 29);
487*a628b1abSHaojian Zhuang 	do {
488*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLK_SEL0);
489*a628b1abSHaojian Zhuang 	} while (data & (1 << 13));
490*a628b1abSHaojian Zhuang 
491*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 0));
492*a628b1abSHaojian Zhuang 	do {
493*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
494*a628b1abSHaojian Zhuang 	} while (!(data & (1 << 0)));
495*a628b1abSHaojian Zhuang 
496*a628b1abSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
497*a628b1abSHaojian Zhuang 	data |= 1 << 1;
498*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
499*a628b1abSHaojian Zhuang 
500*a628b1abSHaojian Zhuang 	do {
501*a628b1abSHaojian Zhuang 		mmio_write_32(PERI_SC_CLKCFG8BIT1, (1 << 7) | 0xb);
502*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLKCFG8BIT1);
503*a628b1abSHaojian Zhuang 	} while ((data & 0xb) != 0xb);
504*a628b1abSHaojian Zhuang }
505*a628b1abSHaojian Zhuang 
506*a628b1abSHaojian Zhuang static void reset_mmc0_clk(void)
507*a628b1abSHaojian Zhuang {
508*a628b1abSHaojian Zhuang 	unsigned int data;
509*a628b1abSHaojian Zhuang 
510*a628b1abSHaojian Zhuang 	/* disable mmc0 bus clock */
511*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0);
512*a628b1abSHaojian Zhuang 	do {
513*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
514*a628b1abSHaojian Zhuang 	} while (data & PERI_CLK0_MMC0);
515*a628b1abSHaojian Zhuang 	/* enable mmc0 bus clock */
516*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0);
517*a628b1abSHaojian Zhuang 	do {
518*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
519*a628b1abSHaojian Zhuang 	} while (!(data & PERI_CLK0_MMC0));
520*a628b1abSHaojian Zhuang 	/* reset mmc0 clock domain */
521*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0);
522*a628b1abSHaojian Zhuang 
523*a628b1abSHaojian Zhuang 	/* bypass mmc0 clock phase */
524*a628b1abSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
525*a628b1abSHaojian Zhuang 	data |= 3;
526*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
527*a628b1abSHaojian Zhuang 
528*a628b1abSHaojian Zhuang 	/* disable low power */
529*a628b1abSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
530*a628b1abSHaojian Zhuang 	data |= 1 << 3;
531*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
532*a628b1abSHaojian Zhuang 	do {
533*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
534*a628b1abSHaojian Zhuang 	} while (!(data & PERI_RST0_MMC0));
535*a628b1abSHaojian Zhuang 
536*a628b1abSHaojian Zhuang 	/* unreset mmc0 clock domain */
537*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0);
538*a628b1abSHaojian Zhuang 	do {
539*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
540*a628b1abSHaojian Zhuang 	} while (data & PERI_RST0_MMC0);
541*a628b1abSHaojian Zhuang }
542*a628b1abSHaojian Zhuang 
543*a628b1abSHaojian Zhuang static void init_media_clk(void)
544*a628b1abSHaojian Zhuang {
545*a628b1abSHaojian Zhuang 	unsigned int data, value;
546*a628b1abSHaojian Zhuang 
547*a628b1abSHaojian Zhuang 	data = mmio_read_32(PMCTRL_MEDPLLCTRL);
548*a628b1abSHaojian Zhuang 	data |= 1;
549*a628b1abSHaojian Zhuang 	mmio_write_32(PMCTRL_MEDPLLCTRL, data);
550*a628b1abSHaojian Zhuang 
551*a628b1abSHaojian Zhuang 	for (;;) {
552*a628b1abSHaojian Zhuang 		data = mmio_read_32(PMCTRL_MEDPLLCTRL);
553*a628b1abSHaojian Zhuang 		value = 1 << 28;
554*a628b1abSHaojian Zhuang 		if ((data & value) == value)
555*a628b1abSHaojian Zhuang 			break;
556*a628b1abSHaojian Zhuang 	}
557*a628b1abSHaojian Zhuang 
558*a628b1abSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
559*a628b1abSHaojian Zhuang 	data = 1 << 10;
560*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
561*a628b1abSHaojian Zhuang }
562*a628b1abSHaojian Zhuang 
563*a628b1abSHaojian Zhuang static void init_mmc1_pll(void)
564*a628b1abSHaojian Zhuang {
565*a628b1abSHaojian Zhuang 	uint32_t data;
566*a628b1abSHaojian Zhuang 
567*a628b1abSHaojian Zhuang 	/* select SYSPLL as the source of MMC1 */
568*a628b1abSHaojian Zhuang 	/* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
569*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_CLK_SEL0, 1 << 11 | 1 << 27);
570*a628b1abSHaojian Zhuang 	do {
571*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLK_SEL0);
572*a628b1abSHaojian Zhuang 	} while (!(data & (1 << 11)));
573*a628b1abSHaojian Zhuang 	/* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
574*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_CLK_SEL0, 1 << 30);
575*a628b1abSHaojian Zhuang 	do {
576*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLK_SEL0);
577*a628b1abSHaojian Zhuang 	} while (data & (1 << 14));
578*a628b1abSHaojian Zhuang 
579*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 1));
580*a628b1abSHaojian Zhuang 	do {
581*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
582*a628b1abSHaojian Zhuang 	} while (!(data & (1 << 1)));
583*a628b1abSHaojian Zhuang 
584*a628b1abSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
585*a628b1abSHaojian Zhuang 	data |= 1 << 2;
586*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
587*a628b1abSHaojian Zhuang 
588*a628b1abSHaojian Zhuang 	do {
589*a628b1abSHaojian Zhuang 		/* 1.2GHz / 50 = 24MHz */
590*a628b1abSHaojian Zhuang 		mmio_write_32(PERI_SC_CLKCFG8BIT2, 0x31 | (1 << 7));
591*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLKCFG8BIT2);
592*a628b1abSHaojian Zhuang 	} while ((data & 0x31) != 0x31);
593*a628b1abSHaojian Zhuang }
594*a628b1abSHaojian Zhuang 
595*a628b1abSHaojian Zhuang static void reset_mmc1_clk(void)
596*a628b1abSHaojian Zhuang {
597*a628b1abSHaojian Zhuang 	unsigned int data;
598*a628b1abSHaojian Zhuang 
599*a628b1abSHaojian Zhuang 	/* disable mmc1 bus clock */
600*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC1);
601*a628b1abSHaojian Zhuang 	do {
602*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
603*a628b1abSHaojian Zhuang 	} while (data & PERI_CLK0_MMC1);
604*a628b1abSHaojian Zhuang 	/* enable mmc1 bus clock */
605*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC1);
606*a628b1abSHaojian Zhuang 	do {
607*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
608*a628b1abSHaojian Zhuang 	} while (!(data & PERI_CLK0_MMC1));
609*a628b1abSHaojian Zhuang 	/* reset mmc1 clock domain */
610*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC1);
611*a628b1abSHaojian Zhuang 
612*a628b1abSHaojian Zhuang 	/* bypass mmc1 clock phase */
613*a628b1abSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
614*a628b1abSHaojian Zhuang 	data |= 3 << 2;
615*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
616*a628b1abSHaojian Zhuang 
617*a628b1abSHaojian Zhuang 	/* disable low power */
618*a628b1abSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
619*a628b1abSHaojian Zhuang 	data |= 1 << 4;
620*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
621*a628b1abSHaojian Zhuang 	do {
622*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
623*a628b1abSHaojian Zhuang 	} while (!(data & PERI_RST0_MMC1));
624*a628b1abSHaojian Zhuang 
625*a628b1abSHaojian Zhuang 	/* unreset mmc0 clock domain */
626*a628b1abSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC1);
627*a628b1abSHaojian Zhuang 	do {
628*a628b1abSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
629*a628b1abSHaojian Zhuang 	} while (data & PERI_RST0_MMC1);
630*a628b1abSHaojian Zhuang }
631*a628b1abSHaojian Zhuang 
632*a628b1abSHaojian Zhuang /* Initialize PLL of both eMMC and SD controllers. */
633*a628b1abSHaojian Zhuang static void hikey_mmc_pll_init(void)
634*a628b1abSHaojian Zhuang {
635*a628b1abSHaojian Zhuang 	init_mmc0_pll();
636*a628b1abSHaojian Zhuang 	reset_mmc0_clk();
637*a628b1abSHaojian Zhuang 	init_media_clk();
638*a628b1abSHaojian Zhuang 
639*a628b1abSHaojian Zhuang 	dsb();
640*a628b1abSHaojian Zhuang 
641*a628b1abSHaojian Zhuang 	init_mmc1_pll();
642*a628b1abSHaojian Zhuang 	reset_mmc1_clk();
643*a628b1abSHaojian Zhuang }
644*a628b1abSHaojian Zhuang 
645*a628b1abSHaojian Zhuang static void hikey_rtc_init(void)
646*a628b1abSHaojian Zhuang {
647*a628b1abSHaojian Zhuang 	uint32_t data;
648*a628b1abSHaojian Zhuang 
649*a628b1abSHaojian Zhuang 	data = mmio_read_32(AO_SC_PERIPH_CLKEN4);
650*a628b1abSHaojian Zhuang 	data |= AO_SC_PERIPH_RSTDIS4_RESET_RTC0_N;
651*a628b1abSHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_CLKEN4, data);
652*a628b1abSHaojian Zhuang }
653*a628b1abSHaojian Zhuang 
654*a628b1abSHaojian Zhuang void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2,
655*a628b1abSHaojian Zhuang 				  u_register_t arg3, u_register_t arg4)
656*a628b1abSHaojian Zhuang {
657*a628b1abSHaojian Zhuang 	/* Initialize the console to provide early debug support */
658*a628b1abSHaojian Zhuang 	console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE);
659*a628b1abSHaojian Zhuang 	/*
660*a628b1abSHaojian Zhuang 	 * Allow BL2 to see the whole Trusted RAM.
661*a628b1abSHaojian Zhuang 	 */
662*a628b1abSHaojian Zhuang 	bl2_el3_tzram_layout.total_base = BL2_RW_BASE;
663*a628b1abSHaojian Zhuang 	bl2_el3_tzram_layout.total_size = BL31_LIMIT - BL2_RW_BASE;
664*a628b1abSHaojian Zhuang }
665*a628b1abSHaojian Zhuang 
666*a628b1abSHaojian Zhuang void bl2_el3_plat_arch_setup(void)
667*a628b1abSHaojian Zhuang {
668*a628b1abSHaojian Zhuang 	hikey_init_mmu_el3(bl2_el3_tzram_layout.total_base,
669*a628b1abSHaojian Zhuang 			   bl2_el3_tzram_layout.total_size,
670*a628b1abSHaojian Zhuang 			   BL2_RO_BASE,
671*a628b1abSHaojian Zhuang 			   BL2_RO_LIMIT,
672*a628b1abSHaojian Zhuang 			   BL2_COHERENT_RAM_BASE,
673*a628b1abSHaojian Zhuang 			   BL2_COHERENT_RAM_LIMIT);
674*a628b1abSHaojian Zhuang }
675*a628b1abSHaojian Zhuang 
676*a628b1abSHaojian Zhuang void bl2_platform_setup(void)
67732e9fc1aSHaojian Zhuang {
67832e9fc1aSHaojian Zhuang 	dw_mmc_params_t params;
67932e9fc1aSHaojian Zhuang 
680*a628b1abSHaojian Zhuang 	hikey_sp804_init();
681*a628b1abSHaojian Zhuang 	hikey_gpio_init();
682*a628b1abSHaojian Zhuang 	hikey_pmussi_init();
683*a628b1abSHaojian Zhuang 	hikey_hi6553_init();
68432e9fc1aSHaojian Zhuang 
685*a628b1abSHaojian Zhuang 	dsb();
686*a628b1abSHaojian Zhuang 	hikey_ddr_init();
687*a628b1abSHaojian Zhuang 	hikey_security_setup();
68832e9fc1aSHaojian Zhuang 
68932e9fc1aSHaojian Zhuang 	/* Clear SRAM since it'll be used by MCU right now. */
69032e9fc1aSHaojian Zhuang 	memset((void *)SRAM_BASE, 0, SRAM_SIZE);
691a9b3021eSHaojian Zhuang 	clean_dcache_range(SRAM_BASE, SRAM_SIZE);
69232e9fc1aSHaojian Zhuang 
69332e9fc1aSHaojian Zhuang 	hikey_boardid_init();
69432e9fc1aSHaojian Zhuang 	init_acpu_dvfs();
695*a628b1abSHaojian Zhuang 	hikey_rtc_init();
69632e9fc1aSHaojian Zhuang 	hikey_sd_init();
69732e9fc1aSHaojian Zhuang 	hikey_jumper_init();
69832e9fc1aSHaojian Zhuang 
699*a628b1abSHaojian Zhuang 	hikey_mmc_pll_init();
700*a628b1abSHaojian Zhuang 
70132e9fc1aSHaojian Zhuang 	reset_dwmmc_clk();
70232e9fc1aSHaojian Zhuang 	memset(&params, 0, sizeof(dw_mmc_params_t));
70332e9fc1aSHaojian Zhuang 	params.reg_base = DWMMC0_BASE;
70432e9fc1aSHaojian Zhuang 	params.desc_base = HIKEY_MMC_DESC_BASE;
70532e9fc1aSHaojian Zhuang 	params.desc_size = 1 << 20;
70632e9fc1aSHaojian Zhuang 	params.clk_rate = 24 * 1000 * 1000;
70732e9fc1aSHaojian Zhuang 	params.bus_width = EMMC_BUS_WIDTH_8;
70832e9fc1aSHaojian Zhuang 	params.flags = EMMC_FLAG_CMD23;
70932e9fc1aSHaojian Zhuang 	dw_mmc_init(&params);
71032e9fc1aSHaojian Zhuang 
71132e9fc1aSHaojian Zhuang 	hikey_io_setup();
71232e9fc1aSHaojian Zhuang }
713