xref: /rk3399_ARM-atf/plat/hisilicon/hikey960/hikey960_bl2_setup.c (revision 19b731e810399145ee085cfe25411f91bbb0625b)
17cb09cb4SHaojian Zhuang /*
2d2128731SHaojian Zhuang  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
37cb09cb4SHaojian Zhuang  *
47cb09cb4SHaojian Zhuang  * SPDX-License-Identifier: BSD-3-Clause
57cb09cb4SHaojian Zhuang  */
67cb09cb4SHaojian Zhuang 
77cb09cb4SHaojian Zhuang #include <arch_helpers.h>
87cb09cb4SHaojian Zhuang #include <assert.h>
97cb09cb4SHaojian Zhuang #include <bl_common.h>
107cb09cb4SHaojian Zhuang #include <console.h>
117cb09cb4SHaojian Zhuang #include <debug.h>
12d2128731SHaojian Zhuang #include <delay_timer.h>
132de0c5ccSVictor Chong #include <desc_image_load.h>
14d2128731SHaojian Zhuang #include <dw_ufs.h>
157cb09cb4SHaojian Zhuang #include <errno.h>
167cb09cb4SHaojian Zhuang #include <generic_delay_timer.h>
177cb09cb4SHaojian Zhuang #include <hi3660.h>
187cb09cb4SHaojian Zhuang #include <mmio.h>
19b16bb16eSVictor Chong #ifdef SPD_opteed
20b16bb16eSVictor Chong #include <optee_utils.h>
21b16bb16eSVictor Chong #endif
227cb09cb4SHaojian Zhuang #include <platform_def.h>
237cb09cb4SHaojian Zhuang #include <string.h>
247cb09cb4SHaojian Zhuang #include <ufs.h>
257cb09cb4SHaojian Zhuang 
267cb09cb4SHaojian Zhuang #include "hikey960_def.h"
277cb09cb4SHaojian Zhuang #include "hikey960_private.h"
287cb09cb4SHaojian Zhuang 
297cb09cb4SHaojian Zhuang /*
307cb09cb4SHaojian Zhuang  * The next 2 constants identify the extents of the code & RO data region.
317cb09cb4SHaojian Zhuang  * These addresses are used by the MMU setup code and therefore they must be
327cb09cb4SHaojian Zhuang  * page-aligned.  It is the responsibility of the linker script to ensure that
337cb09cb4SHaojian Zhuang  * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
347cb09cb4SHaojian Zhuang  */
357cb09cb4SHaojian Zhuang #define BL2_RO_BASE (unsigned long)(&__RO_START__)
367cb09cb4SHaojian Zhuang #define BL2_RO_LIMIT (unsigned long)(&__RO_END__)
377cb09cb4SHaojian Zhuang 
38d2128731SHaojian Zhuang #define BL2_RW_BASE		(BL2_RO_LIMIT)
39d2128731SHaojian Zhuang 
407cb09cb4SHaojian Zhuang /*
417cb09cb4SHaojian Zhuang  * The next 2 constants identify the extents of the coherent memory region.
427cb09cb4SHaojian Zhuang  * These addresses are used by the MMU setup code and therefore they must be
437cb09cb4SHaojian Zhuang  * page-aligned.  It is the responsibility of the linker script to ensure that
447cb09cb4SHaojian Zhuang  * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
457cb09cb4SHaojian Zhuang  * page-aligned addresses.
467cb09cb4SHaojian Zhuang  */
477cb09cb4SHaojian Zhuang #define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
487cb09cb4SHaojian Zhuang #define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
497cb09cb4SHaojian Zhuang 
50d2128731SHaojian Zhuang static meminfo_t bl2_el3_tzram_layout;
517cb09cb4SHaojian Zhuang extern int load_lpm3(void);
527cb09cb4SHaojian Zhuang 
53d2128731SHaojian Zhuang enum {
54d2128731SHaojian Zhuang 	BOOT_MODE_RECOVERY = 0,
55d2128731SHaojian Zhuang 	BOOT_MODE_NORMAL,
56d2128731SHaojian Zhuang 	BOOT_MODE_MASK = 1,
57d2128731SHaojian Zhuang };
58d2128731SHaojian Zhuang 
592de0c5ccSVictor Chong /*******************************************************************************
602de0c5ccSVictor Chong  * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
612de0c5ccSVictor Chong  * Return 0 on success, -1 otherwise.
622de0c5ccSVictor Chong  ******************************************************************************/
632de0c5ccSVictor Chong int plat_hikey960_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info)
647cb09cb4SHaojian Zhuang {
657cb09cb4SHaojian Zhuang 	int i;
667cb09cb4SHaojian Zhuang 	int *buf;
677cb09cb4SHaojian Zhuang 
682de0c5ccSVictor Chong 	assert(scp_bl2_image_info->image_size < SCP_BL2_SIZE);
697cb09cb4SHaojian Zhuang 
707cb09cb4SHaojian Zhuang 	INFO("BL2: Initiating SCP_BL2 transfer to SCP\n");
717cb09cb4SHaojian Zhuang 
727cb09cb4SHaojian Zhuang 	INFO("BL2: SCP_BL2: 0x%lx@0x%x\n",
737cb09cb4SHaojian Zhuang 	     scp_bl2_image_info->image_base,
747cb09cb4SHaojian Zhuang 	     scp_bl2_image_info->image_size);
757cb09cb4SHaojian Zhuang 
767cb09cb4SHaojian Zhuang 	buf = (int *)scp_bl2_image_info->image_base;
777cb09cb4SHaojian Zhuang 
787cb09cb4SHaojian Zhuang 	INFO("BL2: SCP_BL2 HEAD:\n");
797cb09cb4SHaojian Zhuang 	for (i = 0; i < 64; i += 4)
807cb09cb4SHaojian Zhuang 		INFO("BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x\n",
817cb09cb4SHaojian Zhuang 			buf[i], buf[i+1], buf[i+2], buf[i+3]);
827cb09cb4SHaojian Zhuang 
837cb09cb4SHaojian Zhuang 	buf = (int *)(scp_bl2_image_info->image_base +
847cb09cb4SHaojian Zhuang 		      scp_bl2_image_info->image_size - 256);
857cb09cb4SHaojian Zhuang 
867cb09cb4SHaojian Zhuang 	INFO("BL2: SCP_BL2 TAIL:\n");
877cb09cb4SHaojian Zhuang 	for (i = 0; i < 64; i += 4)
887cb09cb4SHaojian Zhuang 		INFO("BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x\n",
897cb09cb4SHaojian Zhuang 			buf[i], buf[i+1], buf[i+2], buf[i+3]);
907cb09cb4SHaojian Zhuang 
917cb09cb4SHaojian Zhuang 	INFO("BL2: SCP_BL2 transferred to SCP\n");
927cb09cb4SHaojian Zhuang 
937cb09cb4SHaojian Zhuang 	load_lpm3();
947cb09cb4SHaojian Zhuang 	(void)buf;
957cb09cb4SHaojian Zhuang 
967cb09cb4SHaojian Zhuang 	return 0;
977cb09cb4SHaojian Zhuang }
987cb09cb4SHaojian Zhuang 
99d2128731SHaojian Zhuang static void hikey960_ufs_reset(void)
100d2128731SHaojian Zhuang {
101d2128731SHaojian Zhuang 	unsigned int data, mask;
102d2128731SHaojian Zhuang 
103d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS7_REG, 1 << 14);
104d2128731SHaojian Zhuang 	mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN);
105d2128731SHaojian Zhuang 	do {
106d2128731SHaojian Zhuang 		data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG);
107d2128731SHaojian Zhuang 	} while (data & BIT_SYSCTRL_REF_CLOCK_EN);
108d2128731SHaojian Zhuang 	/* use abb clk */
109d2128731SHaojian Zhuang 	mmio_clrbits_32(UFS_SYS_UFS_SYSCTRL_REG, BIT_UFS_REFCLK_SRC_SE1);
110d2128731SHaojian Zhuang 	mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_REFCLK_ISO_EN);
111d2128731SHaojian Zhuang 	mmio_write_32(PCTRL_PERI_CTRL3_REG, (1 << 0) | (1 << 16));
112d2128731SHaojian Zhuang 	mdelay(1);
113d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN7_REG, 1 << 14);
114d2128731SHaojian Zhuang 	mmio_setbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN);
115d2128731SHaojian Zhuang 
116d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTEN3_REG, PERI_UFS_BIT);
117d2128731SHaojian Zhuang 	do {
118d2128731SHaojian Zhuang 		data = mmio_read_32(CRG_PERRSTSTAT3_REG);
119d2128731SHaojian Zhuang 	} while ((data & PERI_UFS_BIT) == 0);
120d2128731SHaojian Zhuang 	mmio_setbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_MTCMOS_EN);
121d2128731SHaojian Zhuang 	mdelay(1);
122d2128731SHaojian Zhuang 	mmio_setbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_PWR_READY);
123d2128731SHaojian Zhuang 	mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG,
124d2128731SHaojian Zhuang 		      MASK_UFS_DEVICE_RESET);
125d2128731SHaojian Zhuang 	/* clear SC_DIV_UFS_PERIBUS */
126d2128731SHaojian Zhuang 	mask = SC_DIV_UFS_PERIBUS << 16;
127d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV17_REG, mask);
128d2128731SHaojian Zhuang 	/* set SC_DIV_UFSPHY_CFG(3) */
129d2128731SHaojian Zhuang 	mask = SC_DIV_UFSPHY_CFG_MASK << 16;
130d2128731SHaojian Zhuang 	data = SC_DIV_UFSPHY_CFG(3);
131d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV16_REG, mask | data);
132d2128731SHaojian Zhuang 	data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG);
133d2128731SHaojian Zhuang 	data &= ~MASK_SYSCTRL_CFG_CLOCK_FREQ;
134d2128731SHaojian Zhuang 	data |= 0x39;
135d2128731SHaojian Zhuang 	mmio_write_32(UFS_SYS_PHY_CLK_CTRL_REG, data);
136d2128731SHaojian Zhuang 	mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, MASK_SYSCTRL_REF_CLOCK_SEL);
137d2128731SHaojian Zhuang 	mmio_setbits_32(UFS_SYS_CLOCK_GATE_BYPASS_REG,
138d2128731SHaojian Zhuang 			MASK_UFS_CLK_GATE_BYPASS);
139d2128731SHaojian Zhuang 	mmio_setbits_32(UFS_SYS_UFS_SYSCTRL_REG, MASK_UFS_SYSCTRL_BYPASS);
140d2128731SHaojian Zhuang 
141d2128731SHaojian Zhuang 	mmio_setbits_32(UFS_SYS_PSW_CLK_CTRL_REG, BIT_SYSCTRL_PSW_CLK_EN);
142d2128731SHaojian Zhuang 	mmio_clrbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_ISO_CTRL);
143d2128731SHaojian Zhuang 	mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_PHY_ISO_CTRL);
144d2128731SHaojian Zhuang 	mmio_clrbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_LP_ISOL_EN);
145d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS3_REG, PERI_ARST_UFS_BIT);
146d2128731SHaojian Zhuang 	mmio_setbits_32(UFS_SYS_RESET_CTRL_EN_REG, BIT_SYSCTRL_LP_RESET_N);
147d2128731SHaojian Zhuang 	mdelay(1);
148d2128731SHaojian Zhuang 	mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG,
149d2128731SHaojian Zhuang 		      MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET);
150d2128731SHaojian Zhuang 	mdelay(20);
151d2128731SHaojian Zhuang 	mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG,
152d2128731SHaojian Zhuang 		      0x03300330);
153d2128731SHaojian Zhuang 
154d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS3_REG, PERI_UFS_BIT);
155d2128731SHaojian Zhuang 	do {
156d2128731SHaojian Zhuang 		data = mmio_read_32(CRG_PERRSTSTAT3_REG);
157d2128731SHaojian Zhuang 	} while (data & PERI_UFS_BIT);
158d2128731SHaojian Zhuang }
159d2128731SHaojian Zhuang 
160*19b731e8SHaojian Zhuang static void hikey960_init_ufs(void)
1612de0c5ccSVictor Chong {
162d2128731SHaojian Zhuang 	dw_ufs_params_t ufs_params;
1632de0c5ccSVictor Chong 
1642de0c5ccSVictor Chong 	memset(&ufs_params, 0, sizeof(ufs_params_t));
1652de0c5ccSVictor Chong 	ufs_params.reg_base = UFS_REG_BASE;
1662de0c5ccSVictor Chong 	ufs_params.desc_base = HIKEY960_UFS_DESC_BASE;
1672de0c5ccSVictor Chong 	ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE;
168d2128731SHaojian Zhuang 	hikey960_ufs_reset();
169d2128731SHaojian Zhuang 	dw_ufs_init(&ufs_params);
1702de0c5ccSVictor Chong }
1712de0c5ccSVictor Chong 
1722de0c5ccSVictor Chong /*******************************************************************************
1732de0c5ccSVictor Chong  * Gets SPSR for BL32 entry
1742de0c5ccSVictor Chong  ******************************************************************************/
1752de0c5ccSVictor Chong uint32_t hikey960_get_spsr_for_bl32_entry(void)
1762de0c5ccSVictor Chong {
1772de0c5ccSVictor Chong 	/*
1782de0c5ccSVictor Chong 	 * The Secure Payload Dispatcher service is responsible for
1792de0c5ccSVictor Chong 	 * setting the SPSR prior to entry into the BL3-2 image.
1802de0c5ccSVictor Chong 	 */
1812de0c5ccSVictor Chong 	return 0;
1822de0c5ccSVictor Chong }
1832de0c5ccSVictor Chong 
1842de0c5ccSVictor Chong /*******************************************************************************
1852de0c5ccSVictor Chong  * Gets SPSR for BL33 entry
1862de0c5ccSVictor Chong  ******************************************************************************/
1872de0c5ccSVictor Chong #ifndef AARCH32
1882de0c5ccSVictor Chong uint32_t hikey960_get_spsr_for_bl33_entry(void)
1892de0c5ccSVictor Chong {
1902de0c5ccSVictor Chong 	unsigned int mode;
1912de0c5ccSVictor Chong 	uint32_t spsr;
1922de0c5ccSVictor Chong 
1932de0c5ccSVictor Chong 	/* Figure out what mode we enter the non-secure world in */
1942de0c5ccSVictor Chong 	mode = EL_IMPLEMENTED(2) ? MODE_EL2 : MODE_EL1;
1952de0c5ccSVictor Chong 
1962de0c5ccSVictor Chong 	/*
1972de0c5ccSVictor Chong 	 * TODO: Consider the possibility of specifying the SPSR in
1982de0c5ccSVictor Chong 	 * the FIP ToC and allowing the platform to have a say as
1992de0c5ccSVictor Chong 	 * well.
2002de0c5ccSVictor Chong 	 */
2012de0c5ccSVictor Chong 	spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
2022de0c5ccSVictor Chong 	return spsr;
2032de0c5ccSVictor Chong }
2042de0c5ccSVictor Chong #else
2052de0c5ccSVictor Chong uint32_t hikey960_get_spsr_for_bl33_entry(void)
2062de0c5ccSVictor Chong {
2072de0c5ccSVictor Chong 	unsigned int hyp_status, mode, spsr;
2082de0c5ccSVictor Chong 
2092de0c5ccSVictor Chong 	hyp_status = GET_VIRT_EXT(read_id_pfr1());
2102de0c5ccSVictor Chong 
2112de0c5ccSVictor Chong 	mode = (hyp_status) ? MODE32_hyp : MODE32_svc;
2122de0c5ccSVictor Chong 
2132de0c5ccSVictor Chong 	/*
2142de0c5ccSVictor Chong 	 * TODO: Consider the possibility of specifying the SPSR in
2152de0c5ccSVictor Chong 	 * the FIP ToC and allowing the platform to have a say as
2162de0c5ccSVictor Chong 	 * well.
2172de0c5ccSVictor Chong 	 */
2182de0c5ccSVictor Chong 	spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1,
2192de0c5ccSVictor Chong 			SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
2202de0c5ccSVictor Chong 	return spsr;
2212de0c5ccSVictor Chong }
2222de0c5ccSVictor Chong #endif /* AARCH32 */
2232de0c5ccSVictor Chong 
2242de0c5ccSVictor Chong int hikey960_bl2_handle_post_image_load(unsigned int image_id)
2252de0c5ccSVictor Chong {
2262de0c5ccSVictor Chong 	int err = 0;
2272de0c5ccSVictor Chong 	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
228b16bb16eSVictor Chong #ifdef SPD_opteed
229b16bb16eSVictor Chong 	bl_mem_params_node_t *pager_mem_params = NULL;
230b16bb16eSVictor Chong 	bl_mem_params_node_t *paged_mem_params = NULL;
231b16bb16eSVictor Chong #endif
2322de0c5ccSVictor Chong 	assert(bl_mem_params);
2332de0c5ccSVictor Chong 
2342de0c5ccSVictor Chong 	switch (image_id) {
2352de0c5ccSVictor Chong #ifdef AARCH64
2362de0c5ccSVictor Chong 	case BL32_IMAGE_ID:
237b16bb16eSVictor Chong #ifdef SPD_opteed
238b16bb16eSVictor Chong 		pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
239b16bb16eSVictor Chong 		assert(pager_mem_params);
240b16bb16eSVictor Chong 
241b16bb16eSVictor Chong 		paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
242b16bb16eSVictor Chong 		assert(paged_mem_params);
243b16bb16eSVictor Chong 
244b16bb16eSVictor Chong 		err = parse_optee_header(&bl_mem_params->ep_info,
245b16bb16eSVictor Chong 				&pager_mem_params->image_info,
246b16bb16eSVictor Chong 				&paged_mem_params->image_info);
247b16bb16eSVictor Chong 		if (err != 0) {
248b16bb16eSVictor Chong 			WARN("OPTEE header parse error.\n");
249b16bb16eSVictor Chong 		}
250b16bb16eSVictor Chong #endif
2512de0c5ccSVictor Chong 		bl_mem_params->ep_info.spsr = hikey960_get_spsr_for_bl32_entry();
2522de0c5ccSVictor Chong 		break;
2532de0c5ccSVictor Chong #endif
2542de0c5ccSVictor Chong 
2552de0c5ccSVictor Chong 	case BL33_IMAGE_ID:
2562de0c5ccSVictor Chong 		/* BL33 expects to receive the primary CPU MPID (through r0) */
2572de0c5ccSVictor Chong 		bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
2582de0c5ccSVictor Chong 		bl_mem_params->ep_info.spsr = hikey960_get_spsr_for_bl33_entry();
2592de0c5ccSVictor Chong 		break;
2602de0c5ccSVictor Chong 
2612de0c5ccSVictor Chong #ifdef SCP_BL2_BASE
2622de0c5ccSVictor Chong 	case SCP_BL2_IMAGE_ID:
2632de0c5ccSVictor Chong 		/* The subsequent handling of SCP_BL2 is platform specific */
2642de0c5ccSVictor Chong 		err = plat_hikey960_bl2_handle_scp_bl2(&bl_mem_params->image_info);
2652de0c5ccSVictor Chong 		if (err) {
2662de0c5ccSVictor Chong 			WARN("Failure in platform-specific handling of SCP_BL2 image.\n");
2672de0c5ccSVictor Chong 		}
2682de0c5ccSVictor Chong 		break;
2692de0c5ccSVictor Chong #endif
2702de0c5ccSVictor Chong 	}
2712de0c5ccSVictor Chong 
2722de0c5ccSVictor Chong 	return err;
2732de0c5ccSVictor Chong }
2742de0c5ccSVictor Chong 
275d2128731SHaojian Zhuang static void hikey960_clk_init(void)
276d2128731SHaojian Zhuang {
277d2128731SHaojian Zhuang 	/* change ldi0 sel to ppll2 */
278d2128731SHaojian Zhuang 	mmio_write_32(0xfff350b4, 0xf0002000);
279d2128731SHaojian Zhuang 	/* ldi0 20' */
280d2128731SHaojian Zhuang 	mmio_write_32(0xfff350bc, 0xfc004c00);
281d2128731SHaojian Zhuang }
282d2128731SHaojian Zhuang 
283d2128731SHaojian Zhuang static void hikey960_pmu_init(void)
284d2128731SHaojian Zhuang {
285d2128731SHaojian Zhuang 	/* clear np_xo_abb_dig_START bit in PMIC_CLK_TOP_CTRL7 register */
286d2128731SHaojian Zhuang 	mmio_clrbits_32(PMU_SSI0_CLK_TOP_CTRL7_REG, NP_XO_ABB_DIG);
287d2128731SHaojian Zhuang }
288d2128731SHaojian Zhuang 
289d2128731SHaojian Zhuang static void hikey960_enable_ppll3(void)
290d2128731SHaojian Zhuang {
291d2128731SHaojian Zhuang 	/* enable ppll3 */
292d2128731SHaojian Zhuang 	mmio_write_32(PMC_PPLL3_CTRL0_REG, 0x4904305);
293d2128731SHaojian Zhuang 	mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x2300000);
294d2128731SHaojian Zhuang 	mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x6300000);
295d2128731SHaojian Zhuang }
296d2128731SHaojian Zhuang 
297d2128731SHaojian Zhuang static void bus_idle_clear(unsigned int value)
298d2128731SHaojian Zhuang {
299d2128731SHaojian Zhuang 	unsigned int pmc_value, value1, value2;
300d2128731SHaojian Zhuang 	int timeout = 100;
301d2128731SHaojian Zhuang 
302d2128731SHaojian Zhuang 	pmc_value = value << 16;
303d2128731SHaojian Zhuang 	pmc_value &= ~value;
304d2128731SHaojian Zhuang 	mmio_write_32(PMC_NOC_POWER_IDLEREQ_REG, pmc_value);
305d2128731SHaojian Zhuang 
306d2128731SHaojian Zhuang 	for (;;) {
307d2128731SHaojian Zhuang 		value1 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLEACK_REG);
308d2128731SHaojian Zhuang 		value2 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLE_REG);
309d2128731SHaojian Zhuang 		if (((value1 & value) == 0) && ((value2 & value) == 0))
310d2128731SHaojian Zhuang 			break;
311d2128731SHaojian Zhuang 		udelay(1);
312d2128731SHaojian Zhuang 		timeout--;
313d2128731SHaojian Zhuang 		if (timeout <= 0) {
314d2128731SHaojian Zhuang 			WARN("%s timeout\n", __func__);
315d2128731SHaojian Zhuang 			break;
316d2128731SHaojian Zhuang 		}
317d2128731SHaojian Zhuang 	}
318d2128731SHaojian Zhuang }
319d2128731SHaojian Zhuang 
320d2128731SHaojian Zhuang static void set_vivobus_power_up(void)
321d2128731SHaojian Zhuang {
322d2128731SHaojian Zhuang 	/* clk enable */
323d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x00020002);
324d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN0_REG, 0x00001000);
325d2128731SHaojian Zhuang }
326d2128731SHaojian Zhuang 
327d2128731SHaojian Zhuang static void set_dss_power_up(void)
328d2128731SHaojian Zhuang {
329d2128731SHaojian Zhuang 	/* set edc0 133MHz = 1600MHz / 12 */
330d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV5_REG, 0x003f000b);
331d2128731SHaojian Zhuang 	/* set ldi0 ppl0 */
332d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV3_REG, 0xf0001000);
333d2128731SHaojian Zhuang 	/* set ldi0 133MHz, 1600MHz / 12 */
334d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV5_REG, 0xfc002c00);
335d2128731SHaojian Zhuang 	/* mtcmos on */
336d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERPWREN_REG, 0x00000020);
337d2128731SHaojian Zhuang 	udelay(100);
338d2128731SHaojian Zhuang 	/* DISP CRG */
339d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000010);
340d2128731SHaojian Zhuang 	/* clk enable */
341d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x01400140);
342d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN0_REG, 0x00002000);
343d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x0003b000);
344d2128731SHaojian Zhuang 	udelay(1);
345d2128731SHaojian Zhuang 	/* clk disable */
346d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS3_REG, 0x0003b000);
347d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS0_REG, 0x00002000);
348d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x01400000);
349d2128731SHaojian Zhuang 	udelay(1);
350d2128731SHaojian Zhuang 	/* iso disable */
351d2128731SHaojian Zhuang 	mmio_write_32(CRG_ISODIS_REG, 0x00000040);
352d2128731SHaojian Zhuang 	/* unreset */
353d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000006);
354d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000c00);
355d2128731SHaojian Zhuang 	/* clk enable */
356d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x01400140);
357d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN0_REG, 0x00002000);
358d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x0003b000);
359d2128731SHaojian Zhuang 	/* bus idle clear */
360d2128731SHaojian Zhuang 	bus_idle_clear(PMC_NOC_POWER_IDLEREQ_DSS);
361d2128731SHaojian Zhuang 	/* set edc0 400MHz for 2K 1600MHz / 4 */
362d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV5_REG, 0x003f0003);
363d2128731SHaojian Zhuang 	/* set ldi 266MHz, 1600MHz / 6 */
364d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV5_REG, 0xfc001400);
365d2128731SHaojian Zhuang }
366d2128731SHaojian Zhuang 
367d2128731SHaojian Zhuang static void set_vcodec_power_up(void)
368d2128731SHaojian Zhuang {
369d2128731SHaojian Zhuang 	/* clk enable */
370d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x00040004);
371d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN0_REG, 0x00000060);
372d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN2_REG, 0x10000000);
373d2128731SHaojian Zhuang 	/* unreset */
374d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS0_REG, 0x00000018);
375d2128731SHaojian Zhuang 	/* bus idle clear */
376d2128731SHaojian Zhuang 	bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VCODEC);
377d2128731SHaojian Zhuang }
378d2128731SHaojian Zhuang 
379d2128731SHaojian Zhuang static void set_vdec_power_up(void)
380d2128731SHaojian Zhuang {
381d2128731SHaojian Zhuang 	/* mtcmos on */
382d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERPWREN_REG, 0x00000004);
383d2128731SHaojian Zhuang 	udelay(100);
384d2128731SHaojian Zhuang 	/* clk enable */
385d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x80008000);
386d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN2_REG, 0x20080000);
387d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x00000800);
388d2128731SHaojian Zhuang 	udelay(1);
389d2128731SHaojian Zhuang 	/* clk disable */
390d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS3_REG, 0x00000800);
391d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS2_REG, 0x20080000);
392d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x80000000);
393d2128731SHaojian Zhuang 	udelay(1);
394d2128731SHaojian Zhuang 	/* iso disable */
395d2128731SHaojian Zhuang 	mmio_write_32(CRG_ISODIS_REG, 0x00000004);
396d2128731SHaojian Zhuang 	/* unreset */
397d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000200);
398d2128731SHaojian Zhuang 	/* clk enable */
399d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x80008000);
400d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN2_REG, 0x20080000);
401d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x00000800);
402d2128731SHaojian Zhuang 	/* bus idle clear */
403d2128731SHaojian Zhuang 	bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VDEC);
404d2128731SHaojian Zhuang }
405d2128731SHaojian Zhuang 
406d2128731SHaojian Zhuang static void set_venc_power_up(void)
407d2128731SHaojian Zhuang {
408d2128731SHaojian Zhuang 	/* set venc ppll3 */
409d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV8_REG, 0x18001000);
410d2128731SHaojian Zhuang 	/* set venc 258MHz, 1290MHz / 5 */
411d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV8_REG, 0x07c00100);
412d2128731SHaojian Zhuang 	/* mtcmos on */
413d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERPWREN_REG, 0x00000002);
414d2128731SHaojian Zhuang 	udelay(100);
415d2128731SHaojian Zhuang 	/* clk enable */
416d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV19_REG, 0x00010001);
417d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN2_REG, 0x40000100);
418d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x00000400);
419d2128731SHaojian Zhuang 	udelay(1);
420d2128731SHaojian Zhuang 	/* clk disable */
421d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS3_REG, 0x00000400);
422d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS2_REG, 0x40000100);
423d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV19_REG, 0x00010000);
424d2128731SHaojian Zhuang 	udelay(1);
425d2128731SHaojian Zhuang 	/* iso disable */
426d2128731SHaojian Zhuang 	mmio_write_32(CRG_ISODIS_REG, 0x00000002);
427d2128731SHaojian Zhuang 	/* unreset */
428d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000100);
429d2128731SHaojian Zhuang 	/* clk enable */
430d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV19_REG, 0x00010001);
431d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN2_REG, 0x40000100);
432d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x00000400);
433d2128731SHaojian Zhuang 	/* bus idle clear */
434d2128731SHaojian Zhuang 	bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VENC);
435d2128731SHaojian Zhuang 	/* set venc 645MHz, 1290MHz / 2 */
436d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV8_REG, 0x07c00040);
437d2128731SHaojian Zhuang }
438d2128731SHaojian Zhuang 
439d2128731SHaojian Zhuang static void set_isp_power_up(void)
440d2128731SHaojian Zhuang {
441d2128731SHaojian Zhuang 	/* mtcmos on */
442d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERPWREN_REG, 0x00000001);
443d2128731SHaojian Zhuang 	udelay(100);
444d2128731SHaojian Zhuang 	/* clk enable */
445d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x70007000);
446d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x00100010);
447d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN5_REG, 0x01000010);
448d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x0bf00000);
449d2128731SHaojian Zhuang 	udelay(1);
450d2128731SHaojian Zhuang 	/* clk disable */
451d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS5_REG, 0x01000010);
452d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS3_REG, 0x0bf00000);
453d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x70000000);
454d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x00100000);
455d2128731SHaojian Zhuang 	udelay(1);
456d2128731SHaojian Zhuang 	/* iso disable */
457d2128731SHaojian Zhuang 	mmio_write_32(CRG_ISODIS_REG, 0x00000001);
458d2128731SHaojian Zhuang 	/* unreset */
459d2128731SHaojian Zhuang 	mmio_write_32(CRG_ISP_SEC_RSTDIS_REG, 0x0000002f);
460d2128731SHaojian Zhuang 	/* clk enable */
461d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x70007000);
462d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x00100010);
463d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN5_REG, 0x01000010);
464d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x0bf00000);
465d2128731SHaojian Zhuang 	/* bus idle clear */
466d2128731SHaojian Zhuang 	bus_idle_clear(PMC_NOC_POWER_IDLEREQ_ISP);
467d2128731SHaojian Zhuang 	/* csi clk enable */
468d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x00700000);
469d2128731SHaojian Zhuang }
470d2128731SHaojian Zhuang 
471d2128731SHaojian Zhuang static void set_ivp_power_up(void)
472d2128731SHaojian Zhuang {
473d2128731SHaojian Zhuang 	/* set ivp ppll0 */
474d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV0_REG, 0xc0000000);
475d2128731SHaojian Zhuang 	/* set ivp 267MHz, 1600MHz / 6 */
476d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV0_REG, 0x3c001400);
477d2128731SHaojian Zhuang 	/* mtcmos on */
478d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERPWREN_REG, 0x00200000);
479d2128731SHaojian Zhuang 	udelay(100);
480d2128731SHaojian Zhuang 	/* IVP CRG unreset */
481d2128731SHaojian Zhuang 	mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000001);
482d2128731SHaojian Zhuang 	/* clk enable */
483d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x02000200);
484d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN4_REG, 0x000000a8);
485d2128731SHaojian Zhuang 	udelay(1);
486d2128731SHaojian Zhuang 	/* clk disable */
487d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS4_REG, 0x000000a8);
488d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x02000000);
489d2128731SHaojian Zhuang 	udelay(1);
490d2128731SHaojian Zhuang 	/* iso disable */
491d2128731SHaojian Zhuang 	mmio_write_32(CRG_ISODIS_REG, 0x01000000);
492d2128731SHaojian Zhuang 	/* unreset */
493d2128731SHaojian Zhuang 	mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000002);
494d2128731SHaojian Zhuang 	/* clk enable */
495d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x02000200);
496d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN4_REG, 0x000000a8);
497d2128731SHaojian Zhuang 	/* bus idle clear */
498d2128731SHaojian Zhuang 	bus_idle_clear(PMC_NOC_POWER_IDLEREQ_IVP);
499d2128731SHaojian Zhuang 	/* set ivp 533MHz, 1600MHz / 3 */
500d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV0_REG, 0x3c000800);
501d2128731SHaojian Zhuang }
502d2128731SHaojian Zhuang 
503d2128731SHaojian Zhuang static void set_audio_power_up(void)
504d2128731SHaojian Zhuang {
505d2128731SHaojian Zhuang 	unsigned int ret;
506d2128731SHaojian Zhuang 	int timeout = 100;
507d2128731SHaojian Zhuang 	/* mtcmos on */
508d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPWREN_REG, 0x00000001);
509d2128731SHaojian Zhuang 	udelay(100);
510d2128731SHaojian Zhuang 	/* clk enable */
511d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV19_REG, 0x80108010);
512d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001);
513d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000);
514d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN0_REG, 0x04000000);
515d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN5_REG, 0x00000080);
516d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f);
517d2128731SHaojian Zhuang 	udelay(1);
518d2128731SHaojian Zhuang 	/* clk disable */
519d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPERDIS1_REG, 0x0000000f);
520d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPERDIS0_REG, 0x0c000000);
521d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS5_REG, 0x00000080);
522d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS0_REG, 0x04000000);
523d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010000);
524d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV19_REG, 0x80100000);
525d2128731SHaojian Zhuang 	udelay(1);
526d2128731SHaojian Zhuang 	/* iso disable */
527d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCISODIS_REG, 0x00000001);
528d2128731SHaojian Zhuang 	udelay(1);
529d2128731SHaojian Zhuang 	/* unreset */
530d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_PERRSTDIS1_SEC_REG, 0x00000001);
531d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPERRSTDIS0_REG, 0x00000780);
532d2128731SHaojian Zhuang 	/* clk enable */
533d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV19_REG, 0x80108010);
534d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001);
535d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000);
536d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN0_REG, 0x04000000);
537d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN5_REG, 0x00000080);
538d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f);
539d2128731SHaojian Zhuang 	/* bus idle clear */
540d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPERCTRL7_REG, 0x00040000);
541d2128731SHaojian Zhuang 	for (;;) {
542d2128731SHaojian Zhuang 		ret = mmio_read_32(SCTRL_SCPERSTAT6_REG);
543d2128731SHaojian Zhuang 		if (((ret & (1 << 5)) == 0) && ((ret & (1 << 8)) == 0))
544d2128731SHaojian Zhuang 			break;
545d2128731SHaojian Zhuang 		udelay(1);
546d2128731SHaojian Zhuang 		timeout--;
547d2128731SHaojian Zhuang 		if (timeout <= 0) {
548d2128731SHaojian Zhuang 			WARN("%s timeout\n", __func__);
549d2128731SHaojian Zhuang 			break;
550d2128731SHaojian Zhuang 		}
551d2128731SHaojian Zhuang 	}
552d2128731SHaojian Zhuang 	mmio_write_32(ASP_CFG_MMBUF_CTRL_REG, 0x00ff0000);
553d2128731SHaojian Zhuang }
554d2128731SHaojian Zhuang 
555d2128731SHaojian Zhuang static void set_pcie_power_up(void)
556d2128731SHaojian Zhuang {
557d2128731SHaojian Zhuang 	/* mtcmos on */
558d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPWREN_REG, 0x00000010);
559d2128731SHaojian Zhuang 	udelay(100);
560d2128731SHaojian Zhuang 	/* clk enable */
561d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800);
562d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000);
563d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN7_REG, 0x000003a0);
564d2128731SHaojian Zhuang 	udelay(1);
565d2128731SHaojian Zhuang 	/* clk disable */
566d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPERDIS2_REG, 0x00104000);
567d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS7_REG, 0x000003a0);
568d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000000);
569d2128731SHaojian Zhuang 	udelay(1);
570d2128731SHaojian Zhuang 	/* iso disable */
571d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCISODIS_REG, 0x00000030);
572d2128731SHaojian Zhuang 	/* unreset */
573d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS3_REG, 0x8c000000);
574d2128731SHaojian Zhuang 	/* clk enable */
575d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800);
576d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000);
577d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN7_REG, 0x000003a0);
578d2128731SHaojian Zhuang }
579d2128731SHaojian Zhuang 
580d2128731SHaojian Zhuang static void ispfunc_enable(void)
581d2128731SHaojian Zhuang {
582d2128731SHaojian Zhuang 	/* enable ispfunc. Otherwise powerup isp_srt causes exception. */
583d2128731SHaojian Zhuang 	mmio_write_32(0xfff35000, 0x00000008);
584d2128731SHaojian Zhuang 	mmio_write_32(0xfff35460, 0xc004ffff);
585d2128731SHaojian Zhuang 	mmio_write_32(0xfff35030, 0x02000000);
586d2128731SHaojian Zhuang 	mdelay(10);
587d2128731SHaojian Zhuang }
588d2128731SHaojian Zhuang 
589d2128731SHaojian Zhuang static void isps_control_clock(int flag)
590d2128731SHaojian Zhuang {
591d2128731SHaojian Zhuang 	unsigned int ret;
592d2128731SHaojian Zhuang 
593d2128731SHaojian Zhuang 	/* flag: 0 -- disable clock, 1 -- enable clock */
594d2128731SHaojian Zhuang 	if (flag) {
595d2128731SHaojian Zhuang 		ret = mmio_read_32(0xe8420364);
596d2128731SHaojian Zhuang 		ret |= 1;
597d2128731SHaojian Zhuang 		mmio_write_32(0xe8420364, ret);
598d2128731SHaojian Zhuang 	} else {
599d2128731SHaojian Zhuang 		ret = mmio_read_32(0xe8420364);
600d2128731SHaojian Zhuang 		ret &= ~1;
601d2128731SHaojian Zhuang 		mmio_write_32(0xe8420364, ret);
602d2128731SHaojian Zhuang 	}
603d2128731SHaojian Zhuang }
604d2128731SHaojian Zhuang 
605d2128731SHaojian Zhuang static void set_isp_srt_power_up(void)
606d2128731SHaojian Zhuang {
607d2128731SHaojian Zhuang 	unsigned int ret;
608d2128731SHaojian Zhuang 
609d2128731SHaojian Zhuang 	ispfunc_enable();
610d2128731SHaojian Zhuang 	/* reset */
611d2128731SHaojian Zhuang 	mmio_write_32(0xe8420374, 0x00000001);
612d2128731SHaojian Zhuang 	mmio_write_32(0xe8420350, 0x00000000);
613d2128731SHaojian Zhuang 	mmio_write_32(0xe8420358, 0x00000000);
614d2128731SHaojian Zhuang 	/* mtcmos on */
615d2128731SHaojian Zhuang 	mmio_write_32(0xfff35150, 0x00400000);
616d2128731SHaojian Zhuang 	udelay(100);
617d2128731SHaojian Zhuang 	/* clk enable */
618d2128731SHaojian Zhuang 	isps_control_clock(1);
619d2128731SHaojian Zhuang 	udelay(1);
620d2128731SHaojian Zhuang 	isps_control_clock(0);
621d2128731SHaojian Zhuang 	udelay(1);
622d2128731SHaojian Zhuang 	/* iso disable */
623d2128731SHaojian Zhuang 	mmio_write_32(0xfff35148, 0x08000000);
624d2128731SHaojian Zhuang 	/* unreset */
625d2128731SHaojian Zhuang 	ret = mmio_read_32(0xe8420374);
626d2128731SHaojian Zhuang 	ret &= ~0x1;
627d2128731SHaojian Zhuang 	mmio_write_32(0xe8420374, ret);
628d2128731SHaojian Zhuang 	/* clk enable */
629d2128731SHaojian Zhuang 	isps_control_clock(1);
630d2128731SHaojian Zhuang 	/* enable clock gating for accessing csi registers */
631d2128731SHaojian Zhuang 	mmio_write_32(0xe8420010, ~0);
632d2128731SHaojian Zhuang }
633d2128731SHaojian Zhuang 
634d2128731SHaojian Zhuang static void hikey960_regulator_enable(void)
635d2128731SHaojian Zhuang {
636d2128731SHaojian Zhuang 	set_vivobus_power_up();
637d2128731SHaojian Zhuang 	hikey960_enable_ppll3();
638d2128731SHaojian Zhuang 	set_dss_power_up();
639d2128731SHaojian Zhuang 	set_vcodec_power_up();
640d2128731SHaojian Zhuang 	set_vdec_power_up();
641d2128731SHaojian Zhuang 	set_venc_power_up();
642d2128731SHaojian Zhuang 	set_isp_power_up();
643d2128731SHaojian Zhuang 	set_ivp_power_up();
644d2128731SHaojian Zhuang 	set_audio_power_up();
645d2128731SHaojian Zhuang 	set_pcie_power_up();
646d2128731SHaojian Zhuang 	set_isp_srt_power_up();
647d2128731SHaojian Zhuang }
648d2128731SHaojian Zhuang 
649d2128731SHaojian Zhuang static void hikey960_tzc_init(void)
650d2128731SHaojian Zhuang {
651d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN0_REG, 0x7fbff066);
652d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN1_REG, 0xfffff5fc);
653d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN2_REG, 0x0007005c);
654d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN3_REG, 0x37030700);
655d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN4_REG, 0xf63fefae);
656d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN5_REG, 0x000410fd);
657d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN6_REG, 0x0063ff68);
658d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN7_REG, 0x030000f3);
659d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN8_REG, 0x00000007);
660d2128731SHaojian Zhuang }
661d2128731SHaojian Zhuang 
662d2128731SHaojian Zhuang static void hikey960_peri_init(void)
663d2128731SHaojian Zhuang {
664d2128731SHaojian Zhuang 	/* unreset */
665d2128731SHaojian Zhuang 	mmio_setbits_32(CRG_PERRSTDIS4_REG, 1);
666d2128731SHaojian Zhuang }
667d2128731SHaojian Zhuang 
668d2128731SHaojian Zhuang static void hikey960_pinmux_init(void)
669d2128731SHaojian Zhuang {
670d2128731SHaojian Zhuang 	unsigned int id;
671d2128731SHaojian Zhuang 
672d2128731SHaojian Zhuang 	hikey960_read_boardid(&id);
673d2128731SHaojian Zhuang 	if (id == 5301) {
674d2128731SHaojian Zhuang 		/* hikey960 hardware v2 */
675d2128731SHaojian Zhuang 		/* GPIO150: LED */
676d2128731SHaojian Zhuang 		mmio_write_32(IOMG_FIX_006_REG, 0);
677d2128731SHaojian Zhuang 		/* GPIO151: LED */
678d2128731SHaojian Zhuang 		mmio_write_32(IOMG_FIX_007_REG, 0);
679d2128731SHaojian Zhuang 		/* GPIO189: LED */
680d2128731SHaojian Zhuang 		mmio_write_32(IOMG_AO_011_REG, 0);
681d2128731SHaojian Zhuang 		/* GPIO190: LED */
682d2128731SHaojian Zhuang 		mmio_write_32(IOMG_AO_012_REG, 0);
683d2128731SHaojian Zhuang 		/* GPIO46 */
684d2128731SHaojian Zhuang 		mmio_write_32(IOMG_044_REG, 0);
685d2128731SHaojian Zhuang 		/* GPIO202 */
686d2128731SHaojian Zhuang 		mmio_write_32(IOMG_AO_023_REG, 0);
687d2128731SHaojian Zhuang 		/* GPIO206 */
688d2128731SHaojian Zhuang 		mmio_write_32(IOMG_AO_026_REG, 0);
689d2128731SHaojian Zhuang 		/* GPIO219 - PD pullup */
690d2128731SHaojian Zhuang 		mmio_write_32(IOMG_AO_039_REG, 0);
691d2128731SHaojian Zhuang 		mmio_write_32(IOCG_AO_043_REG, 1 << 0);
692d2128731SHaojian Zhuang 	}
693d2128731SHaojian Zhuang 	/* GPIO005 - PMU SSI, 10mA */
694d2128731SHaojian Zhuang 	mmio_write_32(IOCG_006_REG, 2 << 4);
695d2128731SHaojian Zhuang }
696d2128731SHaojian Zhuang 
6972de0c5ccSVictor Chong /*******************************************************************************
6982de0c5ccSVictor Chong  * This function can be used by the platforms to update/use image
6992de0c5ccSVictor Chong  * information for given `image_id`.
7002de0c5ccSVictor Chong  ******************************************************************************/
7012de0c5ccSVictor Chong int bl2_plat_handle_post_image_load(unsigned int image_id)
7022de0c5ccSVictor Chong {
7032de0c5ccSVictor Chong 	return hikey960_bl2_handle_post_image_load(image_id);
7042de0c5ccSVictor Chong }
7052de0c5ccSVictor Chong 
706d2128731SHaojian Zhuang void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2,
707d2128731SHaojian Zhuang 				  u_register_t arg3, u_register_t arg4)
7087cb09cb4SHaojian Zhuang {
7097cb09cb4SHaojian Zhuang 	unsigned int id, uart_base;
7107cb09cb4SHaojian Zhuang 
7117cb09cb4SHaojian Zhuang 	generic_delay_timer_init();
7127cb09cb4SHaojian Zhuang 	hikey960_read_boardid(&id);
7137cb09cb4SHaojian Zhuang 	if (id == 5300)
7147cb09cb4SHaojian Zhuang 		uart_base = PL011_UART5_BASE;
7157cb09cb4SHaojian Zhuang 	else
7167cb09cb4SHaojian Zhuang 		uart_base = PL011_UART6_BASE;
7177cb09cb4SHaojian Zhuang 	/* Initialize the console to provide early debug support */
7187cb09cb4SHaojian Zhuang 	console_init(uart_base, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE);
719d2128731SHaojian Zhuang 	/*
720d2128731SHaojian Zhuang 	 * Allow BL2 to see the whole Trusted RAM.
721d2128731SHaojian Zhuang 	 */
722d2128731SHaojian Zhuang 	bl2_el3_tzram_layout.total_base = BL2_RW_BASE;
723d2128731SHaojian Zhuang 	bl2_el3_tzram_layout.total_size = BL31_LIMIT - BL2_RW_BASE;
7247cb09cb4SHaojian Zhuang }
7257cb09cb4SHaojian Zhuang 
726d2128731SHaojian Zhuang void bl2_el3_plat_arch_setup(void)
7277cb09cb4SHaojian Zhuang {
728d2128731SHaojian Zhuang 	hikey960_init_mmu_el3(bl2_el3_tzram_layout.total_base,
729d2128731SHaojian Zhuang 			      bl2_el3_tzram_layout.total_size,
7307cb09cb4SHaojian Zhuang 			      BL2_RO_BASE,
7317cb09cb4SHaojian Zhuang 			      BL2_RO_LIMIT,
7327cb09cb4SHaojian Zhuang 			      BL2_COHERENT_RAM_BASE,
7337cb09cb4SHaojian Zhuang 			      BL2_COHERENT_RAM_LIMIT);
7347cb09cb4SHaojian Zhuang }
7357cb09cb4SHaojian Zhuang 
7367cb09cb4SHaojian Zhuang void bl2_platform_setup(void)
7377cb09cb4SHaojian Zhuang {
7387cb09cb4SHaojian Zhuang 	/* disable WDT0 */
7397cb09cb4SHaojian Zhuang 	if (mmio_read_32(WDT0_REG_BASE + WDT_LOCK_OFFSET) == WDT_LOCKED) {
7407cb09cb4SHaojian Zhuang 		mmio_write_32(WDT0_REG_BASE + WDT_LOCK_OFFSET, WDT_UNLOCK);
7417cb09cb4SHaojian Zhuang 		mmio_write_32(WDT0_REG_BASE + WDT_CONTROL_OFFSET, 0);
7427cb09cb4SHaojian Zhuang 		mmio_write_32(WDT0_REG_BASE + WDT_LOCK_OFFSET, 0);
7437cb09cb4SHaojian Zhuang 	}
744d2128731SHaojian Zhuang 	hikey960_clk_init();
745d2128731SHaojian Zhuang 	hikey960_pmu_init();
746d2128731SHaojian Zhuang 	hikey960_regulator_enable();
747d2128731SHaojian Zhuang 	hikey960_tzc_init();
748d2128731SHaojian Zhuang 	hikey960_peri_init();
749d2128731SHaojian Zhuang 	hikey960_pinmux_init();
750*19b731e8SHaojian Zhuang 	hikey960_init_ufs();
751*19b731e8SHaojian Zhuang 	hikey960_io_setup();
7527cb09cb4SHaojian Zhuang }
753