xref: /rk3399_ARM-atf/plat/hisilicon/hikey960/hikey960_bl2_setup.c (revision d2128731a93e0bd1c3580d045232cf9a984db606)
17cb09cb4SHaojian Zhuang /*
2*d2128731SHaojian 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>
12*d2128731SHaojian Zhuang #include <delay_timer.h>
132de0c5ccSVictor Chong #include <desc_image_load.h>
14*d2128731SHaojian 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 
38*d2128731SHaojian Zhuang #define BL2_RW_BASE		(BL2_RO_LIMIT)
39*d2128731SHaojian 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 
50*d2128731SHaojian Zhuang static meminfo_t bl2_el3_tzram_layout;
517cb09cb4SHaojian Zhuang extern int load_lpm3(void);
527cb09cb4SHaojian Zhuang 
53*d2128731SHaojian Zhuang enum {
54*d2128731SHaojian Zhuang 	BOOT_MODE_RECOVERY = 0,
55*d2128731SHaojian Zhuang 	BOOT_MODE_NORMAL,
56*d2128731SHaojian Zhuang 	BOOT_MODE_MASK = 1,
57*d2128731SHaojian Zhuang };
58*d2128731SHaojian 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 
99*d2128731SHaojian Zhuang static void hikey960_ufs_reset(void)
100*d2128731SHaojian Zhuang {
101*d2128731SHaojian Zhuang 	unsigned int data, mask;
102*d2128731SHaojian Zhuang 
103*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS7_REG, 1 << 14);
104*d2128731SHaojian Zhuang 	mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN);
105*d2128731SHaojian Zhuang 	do {
106*d2128731SHaojian Zhuang 		data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG);
107*d2128731SHaojian Zhuang 	} while (data & BIT_SYSCTRL_REF_CLOCK_EN);
108*d2128731SHaojian Zhuang 	/* use abb clk */
109*d2128731SHaojian Zhuang 	mmio_clrbits_32(UFS_SYS_UFS_SYSCTRL_REG, BIT_UFS_REFCLK_SRC_SE1);
110*d2128731SHaojian Zhuang 	mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_REFCLK_ISO_EN);
111*d2128731SHaojian Zhuang 	mmio_write_32(PCTRL_PERI_CTRL3_REG, (1 << 0) | (1 << 16));
112*d2128731SHaojian Zhuang 	mdelay(1);
113*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN7_REG, 1 << 14);
114*d2128731SHaojian Zhuang 	mmio_setbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN);
115*d2128731SHaojian Zhuang 
116*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTEN3_REG, PERI_UFS_BIT);
117*d2128731SHaojian Zhuang 	do {
118*d2128731SHaojian Zhuang 		data = mmio_read_32(CRG_PERRSTSTAT3_REG);
119*d2128731SHaojian Zhuang 	} while ((data & PERI_UFS_BIT) == 0);
120*d2128731SHaojian Zhuang 	mmio_setbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_MTCMOS_EN);
121*d2128731SHaojian Zhuang 	mdelay(1);
122*d2128731SHaojian Zhuang 	mmio_setbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_PWR_READY);
123*d2128731SHaojian Zhuang 	mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG,
124*d2128731SHaojian Zhuang 		      MASK_UFS_DEVICE_RESET);
125*d2128731SHaojian Zhuang 	/* clear SC_DIV_UFS_PERIBUS */
126*d2128731SHaojian Zhuang 	mask = SC_DIV_UFS_PERIBUS << 16;
127*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV17_REG, mask);
128*d2128731SHaojian Zhuang 	/* set SC_DIV_UFSPHY_CFG(3) */
129*d2128731SHaojian Zhuang 	mask = SC_DIV_UFSPHY_CFG_MASK << 16;
130*d2128731SHaojian Zhuang 	data = SC_DIV_UFSPHY_CFG(3);
131*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV16_REG, mask | data);
132*d2128731SHaojian Zhuang 	data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG);
133*d2128731SHaojian Zhuang 	data &= ~MASK_SYSCTRL_CFG_CLOCK_FREQ;
134*d2128731SHaojian Zhuang 	data |= 0x39;
135*d2128731SHaojian Zhuang 	mmio_write_32(UFS_SYS_PHY_CLK_CTRL_REG, data);
136*d2128731SHaojian Zhuang 	mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, MASK_SYSCTRL_REF_CLOCK_SEL);
137*d2128731SHaojian Zhuang 	mmio_setbits_32(UFS_SYS_CLOCK_GATE_BYPASS_REG,
138*d2128731SHaojian Zhuang 			MASK_UFS_CLK_GATE_BYPASS);
139*d2128731SHaojian Zhuang 	mmio_setbits_32(UFS_SYS_UFS_SYSCTRL_REG, MASK_UFS_SYSCTRL_BYPASS);
140*d2128731SHaojian Zhuang 
141*d2128731SHaojian Zhuang 	mmio_setbits_32(UFS_SYS_PSW_CLK_CTRL_REG, BIT_SYSCTRL_PSW_CLK_EN);
142*d2128731SHaojian Zhuang 	mmio_clrbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_ISO_CTRL);
143*d2128731SHaojian Zhuang 	mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_PHY_ISO_CTRL);
144*d2128731SHaojian Zhuang 	mmio_clrbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_LP_ISOL_EN);
145*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS3_REG, PERI_ARST_UFS_BIT);
146*d2128731SHaojian Zhuang 	mmio_setbits_32(UFS_SYS_RESET_CTRL_EN_REG, BIT_SYSCTRL_LP_RESET_N);
147*d2128731SHaojian Zhuang 	mdelay(1);
148*d2128731SHaojian Zhuang 	mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG,
149*d2128731SHaojian Zhuang 		      MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET);
150*d2128731SHaojian Zhuang 	mdelay(20);
151*d2128731SHaojian Zhuang 	mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG,
152*d2128731SHaojian Zhuang 		      0x03300330);
153*d2128731SHaojian Zhuang 
154*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS3_REG, PERI_UFS_BIT);
155*d2128731SHaojian Zhuang 	do {
156*d2128731SHaojian Zhuang 		data = mmio_read_32(CRG_PERRSTSTAT3_REG);
157*d2128731SHaojian Zhuang 	} while (data & PERI_UFS_BIT);
158*d2128731SHaojian Zhuang }
159*d2128731SHaojian Zhuang 
1602de0c5ccSVictor Chong void hikey960_init_ufs(void)
1612de0c5ccSVictor Chong {
162*d2128731SHaojian 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;
168*d2128731SHaojian Zhuang 	hikey960_ufs_reset();
169*d2128731SHaojian 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 
275*d2128731SHaojian Zhuang static void hikey960_clk_init(void)
276*d2128731SHaojian Zhuang {
277*d2128731SHaojian Zhuang 	/* change ldi0 sel to ppll2 */
278*d2128731SHaojian Zhuang 	mmio_write_32(0xfff350b4, 0xf0002000);
279*d2128731SHaojian Zhuang 	/* ldi0 20' */
280*d2128731SHaojian Zhuang 	mmio_write_32(0xfff350bc, 0xfc004c00);
281*d2128731SHaojian Zhuang }
282*d2128731SHaojian Zhuang 
283*d2128731SHaojian Zhuang static void hikey960_pmu_init(void)
284*d2128731SHaojian Zhuang {
285*d2128731SHaojian Zhuang 	/* clear np_xo_abb_dig_START bit in PMIC_CLK_TOP_CTRL7 register */
286*d2128731SHaojian Zhuang 	mmio_clrbits_32(PMU_SSI0_CLK_TOP_CTRL7_REG, NP_XO_ABB_DIG);
287*d2128731SHaojian Zhuang }
288*d2128731SHaojian Zhuang 
289*d2128731SHaojian Zhuang static void hikey960_enable_ppll3(void)
290*d2128731SHaojian Zhuang {
291*d2128731SHaojian Zhuang 	/* enable ppll3 */
292*d2128731SHaojian Zhuang 	mmio_write_32(PMC_PPLL3_CTRL0_REG, 0x4904305);
293*d2128731SHaojian Zhuang 	mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x2300000);
294*d2128731SHaojian Zhuang 	mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x6300000);
295*d2128731SHaojian Zhuang }
296*d2128731SHaojian Zhuang 
297*d2128731SHaojian Zhuang static void bus_idle_clear(unsigned int value)
298*d2128731SHaojian Zhuang {
299*d2128731SHaojian Zhuang 	unsigned int pmc_value, value1, value2;
300*d2128731SHaojian Zhuang 	int timeout = 100;
301*d2128731SHaojian Zhuang 
302*d2128731SHaojian Zhuang 	pmc_value = value << 16;
303*d2128731SHaojian Zhuang 	pmc_value &= ~value;
304*d2128731SHaojian Zhuang 	mmio_write_32(PMC_NOC_POWER_IDLEREQ_REG, pmc_value);
305*d2128731SHaojian Zhuang 
306*d2128731SHaojian Zhuang 	for (;;) {
307*d2128731SHaojian Zhuang 		value1 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLEACK_REG);
308*d2128731SHaojian Zhuang 		value2 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLE_REG);
309*d2128731SHaojian Zhuang 		if (((value1 & value) == 0) && ((value2 & value) == 0))
310*d2128731SHaojian Zhuang 			break;
311*d2128731SHaojian Zhuang 		udelay(1);
312*d2128731SHaojian Zhuang 		timeout--;
313*d2128731SHaojian Zhuang 		if (timeout <= 0) {
314*d2128731SHaojian Zhuang 			WARN("%s timeout\n", __func__);
315*d2128731SHaojian Zhuang 			break;
316*d2128731SHaojian Zhuang 		}
317*d2128731SHaojian Zhuang 	}
318*d2128731SHaojian Zhuang }
319*d2128731SHaojian Zhuang 
320*d2128731SHaojian Zhuang static void set_vivobus_power_up(void)
321*d2128731SHaojian Zhuang {
322*d2128731SHaojian Zhuang 	/* clk enable */
323*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x00020002);
324*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN0_REG, 0x00001000);
325*d2128731SHaojian Zhuang }
326*d2128731SHaojian Zhuang 
327*d2128731SHaojian Zhuang static void set_dss_power_up(void)
328*d2128731SHaojian Zhuang {
329*d2128731SHaojian Zhuang 	/* set edc0 133MHz = 1600MHz / 12 */
330*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV5_REG, 0x003f000b);
331*d2128731SHaojian Zhuang 	/* set ldi0 ppl0 */
332*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV3_REG, 0xf0001000);
333*d2128731SHaojian Zhuang 	/* set ldi0 133MHz, 1600MHz / 12 */
334*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV5_REG, 0xfc002c00);
335*d2128731SHaojian Zhuang 	/* mtcmos on */
336*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERPWREN_REG, 0x00000020);
337*d2128731SHaojian Zhuang 	udelay(100);
338*d2128731SHaojian Zhuang 	/* DISP CRG */
339*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000010);
340*d2128731SHaojian Zhuang 	/* clk enable */
341*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x01400140);
342*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN0_REG, 0x00002000);
343*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x0003b000);
344*d2128731SHaojian Zhuang 	udelay(1);
345*d2128731SHaojian Zhuang 	/* clk disable */
346*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS3_REG, 0x0003b000);
347*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS0_REG, 0x00002000);
348*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x01400000);
349*d2128731SHaojian Zhuang 	udelay(1);
350*d2128731SHaojian Zhuang 	/* iso disable */
351*d2128731SHaojian Zhuang 	mmio_write_32(CRG_ISODIS_REG, 0x00000040);
352*d2128731SHaojian Zhuang 	/* unreset */
353*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000006);
354*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000c00);
355*d2128731SHaojian Zhuang 	/* clk enable */
356*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x01400140);
357*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN0_REG, 0x00002000);
358*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x0003b000);
359*d2128731SHaojian Zhuang 	/* bus idle clear */
360*d2128731SHaojian Zhuang 	bus_idle_clear(PMC_NOC_POWER_IDLEREQ_DSS);
361*d2128731SHaojian Zhuang 	/* set edc0 400MHz for 2K 1600MHz / 4 */
362*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV5_REG, 0x003f0003);
363*d2128731SHaojian Zhuang 	/* set ldi 266MHz, 1600MHz / 6 */
364*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV5_REG, 0xfc001400);
365*d2128731SHaojian Zhuang }
366*d2128731SHaojian Zhuang 
367*d2128731SHaojian Zhuang static void set_vcodec_power_up(void)
368*d2128731SHaojian Zhuang {
369*d2128731SHaojian Zhuang 	/* clk enable */
370*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x00040004);
371*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN0_REG, 0x00000060);
372*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN2_REG, 0x10000000);
373*d2128731SHaojian Zhuang 	/* unreset */
374*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS0_REG, 0x00000018);
375*d2128731SHaojian Zhuang 	/* bus idle clear */
376*d2128731SHaojian Zhuang 	bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VCODEC);
377*d2128731SHaojian Zhuang }
378*d2128731SHaojian Zhuang 
379*d2128731SHaojian Zhuang static void set_vdec_power_up(void)
380*d2128731SHaojian Zhuang {
381*d2128731SHaojian Zhuang 	/* mtcmos on */
382*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERPWREN_REG, 0x00000004);
383*d2128731SHaojian Zhuang 	udelay(100);
384*d2128731SHaojian Zhuang 	/* clk enable */
385*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x80008000);
386*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN2_REG, 0x20080000);
387*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x00000800);
388*d2128731SHaojian Zhuang 	udelay(1);
389*d2128731SHaojian Zhuang 	/* clk disable */
390*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS3_REG, 0x00000800);
391*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS2_REG, 0x20080000);
392*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x80000000);
393*d2128731SHaojian Zhuang 	udelay(1);
394*d2128731SHaojian Zhuang 	/* iso disable */
395*d2128731SHaojian Zhuang 	mmio_write_32(CRG_ISODIS_REG, 0x00000004);
396*d2128731SHaojian Zhuang 	/* unreset */
397*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000200);
398*d2128731SHaojian Zhuang 	/* clk enable */
399*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x80008000);
400*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN2_REG, 0x20080000);
401*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x00000800);
402*d2128731SHaojian Zhuang 	/* bus idle clear */
403*d2128731SHaojian Zhuang 	bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VDEC);
404*d2128731SHaojian Zhuang }
405*d2128731SHaojian Zhuang 
406*d2128731SHaojian Zhuang static void set_venc_power_up(void)
407*d2128731SHaojian Zhuang {
408*d2128731SHaojian Zhuang 	/* set venc ppll3 */
409*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV8_REG, 0x18001000);
410*d2128731SHaojian Zhuang 	/* set venc 258MHz, 1290MHz / 5 */
411*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV8_REG, 0x07c00100);
412*d2128731SHaojian Zhuang 	/* mtcmos on */
413*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERPWREN_REG, 0x00000002);
414*d2128731SHaojian Zhuang 	udelay(100);
415*d2128731SHaojian Zhuang 	/* clk enable */
416*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV19_REG, 0x00010001);
417*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN2_REG, 0x40000100);
418*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x00000400);
419*d2128731SHaojian Zhuang 	udelay(1);
420*d2128731SHaojian Zhuang 	/* clk disable */
421*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS3_REG, 0x00000400);
422*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS2_REG, 0x40000100);
423*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV19_REG, 0x00010000);
424*d2128731SHaojian Zhuang 	udelay(1);
425*d2128731SHaojian Zhuang 	/* iso disable */
426*d2128731SHaojian Zhuang 	mmio_write_32(CRG_ISODIS_REG, 0x00000002);
427*d2128731SHaojian Zhuang 	/* unreset */
428*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000100);
429*d2128731SHaojian Zhuang 	/* clk enable */
430*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV19_REG, 0x00010001);
431*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN2_REG, 0x40000100);
432*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x00000400);
433*d2128731SHaojian Zhuang 	/* bus idle clear */
434*d2128731SHaojian Zhuang 	bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VENC);
435*d2128731SHaojian Zhuang 	/* set venc 645MHz, 1290MHz / 2 */
436*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV8_REG, 0x07c00040);
437*d2128731SHaojian Zhuang }
438*d2128731SHaojian Zhuang 
439*d2128731SHaojian Zhuang static void set_isp_power_up(void)
440*d2128731SHaojian Zhuang {
441*d2128731SHaojian Zhuang 	/* mtcmos on */
442*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERPWREN_REG, 0x00000001);
443*d2128731SHaojian Zhuang 	udelay(100);
444*d2128731SHaojian Zhuang 	/* clk enable */
445*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x70007000);
446*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x00100010);
447*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN5_REG, 0x01000010);
448*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x0bf00000);
449*d2128731SHaojian Zhuang 	udelay(1);
450*d2128731SHaojian Zhuang 	/* clk disable */
451*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS5_REG, 0x01000010);
452*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS3_REG, 0x0bf00000);
453*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x70000000);
454*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x00100000);
455*d2128731SHaojian Zhuang 	udelay(1);
456*d2128731SHaojian Zhuang 	/* iso disable */
457*d2128731SHaojian Zhuang 	mmio_write_32(CRG_ISODIS_REG, 0x00000001);
458*d2128731SHaojian Zhuang 	/* unreset */
459*d2128731SHaojian Zhuang 	mmio_write_32(CRG_ISP_SEC_RSTDIS_REG, 0x0000002f);
460*d2128731SHaojian Zhuang 	/* clk enable */
461*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV18_REG, 0x70007000);
462*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x00100010);
463*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN5_REG, 0x01000010);
464*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x0bf00000);
465*d2128731SHaojian Zhuang 	/* bus idle clear */
466*d2128731SHaojian Zhuang 	bus_idle_clear(PMC_NOC_POWER_IDLEREQ_ISP);
467*d2128731SHaojian Zhuang 	/* csi clk enable */
468*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN3_REG, 0x00700000);
469*d2128731SHaojian Zhuang }
470*d2128731SHaojian Zhuang 
471*d2128731SHaojian Zhuang static void set_ivp_power_up(void)
472*d2128731SHaojian Zhuang {
473*d2128731SHaojian Zhuang 	/* set ivp ppll0 */
474*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV0_REG, 0xc0000000);
475*d2128731SHaojian Zhuang 	/* set ivp 267MHz, 1600MHz / 6 */
476*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV0_REG, 0x3c001400);
477*d2128731SHaojian Zhuang 	/* mtcmos on */
478*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERPWREN_REG, 0x00200000);
479*d2128731SHaojian Zhuang 	udelay(100);
480*d2128731SHaojian Zhuang 	/* IVP CRG unreset */
481*d2128731SHaojian Zhuang 	mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000001);
482*d2128731SHaojian Zhuang 	/* clk enable */
483*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x02000200);
484*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN4_REG, 0x000000a8);
485*d2128731SHaojian Zhuang 	udelay(1);
486*d2128731SHaojian Zhuang 	/* clk disable */
487*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS4_REG, 0x000000a8);
488*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x02000000);
489*d2128731SHaojian Zhuang 	udelay(1);
490*d2128731SHaojian Zhuang 	/* iso disable */
491*d2128731SHaojian Zhuang 	mmio_write_32(CRG_ISODIS_REG, 0x01000000);
492*d2128731SHaojian Zhuang 	/* unreset */
493*d2128731SHaojian Zhuang 	mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000002);
494*d2128731SHaojian Zhuang 	/* clk enable */
495*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV20_REG, 0x02000200);
496*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN4_REG, 0x000000a8);
497*d2128731SHaojian Zhuang 	/* bus idle clear */
498*d2128731SHaojian Zhuang 	bus_idle_clear(PMC_NOC_POWER_IDLEREQ_IVP);
499*d2128731SHaojian Zhuang 	/* set ivp 533MHz, 1600MHz / 3 */
500*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV0_REG, 0x3c000800);
501*d2128731SHaojian Zhuang }
502*d2128731SHaojian Zhuang 
503*d2128731SHaojian Zhuang static void set_audio_power_up(void)
504*d2128731SHaojian Zhuang {
505*d2128731SHaojian Zhuang 	unsigned int ret;
506*d2128731SHaojian Zhuang 	int timeout = 100;
507*d2128731SHaojian Zhuang 	/* mtcmos on */
508*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPWREN_REG, 0x00000001);
509*d2128731SHaojian Zhuang 	udelay(100);
510*d2128731SHaojian Zhuang 	/* clk enable */
511*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV19_REG, 0x80108010);
512*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001);
513*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000);
514*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN0_REG, 0x04000000);
515*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN5_REG, 0x00000080);
516*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f);
517*d2128731SHaojian Zhuang 	udelay(1);
518*d2128731SHaojian Zhuang 	/* clk disable */
519*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPERDIS1_REG, 0x0000000f);
520*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPERDIS0_REG, 0x0c000000);
521*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS5_REG, 0x00000080);
522*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS0_REG, 0x04000000);
523*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010000);
524*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV19_REG, 0x80100000);
525*d2128731SHaojian Zhuang 	udelay(1);
526*d2128731SHaojian Zhuang 	/* iso disable */
527*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCISODIS_REG, 0x00000001);
528*d2128731SHaojian Zhuang 	udelay(1);
529*d2128731SHaojian Zhuang 	/* unreset */
530*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_PERRSTDIS1_SEC_REG, 0x00000001);
531*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPERRSTDIS0_REG, 0x00000780);
532*d2128731SHaojian Zhuang 	/* clk enable */
533*d2128731SHaojian Zhuang 	mmio_write_32(CRG_CLKDIV19_REG, 0x80108010);
534*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001);
535*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000);
536*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN0_REG, 0x04000000);
537*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN5_REG, 0x00000080);
538*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f);
539*d2128731SHaojian Zhuang 	/* bus idle clear */
540*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPERCTRL7_REG, 0x00040000);
541*d2128731SHaojian Zhuang 	for (;;) {
542*d2128731SHaojian Zhuang 		ret = mmio_read_32(SCTRL_SCPERSTAT6_REG);
543*d2128731SHaojian Zhuang 		if (((ret & (1 << 5)) == 0) && ((ret & (1 << 8)) == 0))
544*d2128731SHaojian Zhuang 			break;
545*d2128731SHaojian Zhuang 		udelay(1);
546*d2128731SHaojian Zhuang 		timeout--;
547*d2128731SHaojian Zhuang 		if (timeout <= 0) {
548*d2128731SHaojian Zhuang 			WARN("%s timeout\n", __func__);
549*d2128731SHaojian Zhuang 			break;
550*d2128731SHaojian Zhuang 		}
551*d2128731SHaojian Zhuang 	}
552*d2128731SHaojian Zhuang 	mmio_write_32(ASP_CFG_MMBUF_CTRL_REG, 0x00ff0000);
553*d2128731SHaojian Zhuang }
554*d2128731SHaojian Zhuang 
555*d2128731SHaojian Zhuang static void set_pcie_power_up(void)
556*d2128731SHaojian Zhuang {
557*d2128731SHaojian Zhuang 	/* mtcmos on */
558*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPWREN_REG, 0x00000010);
559*d2128731SHaojian Zhuang 	udelay(100);
560*d2128731SHaojian Zhuang 	/* clk enable */
561*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800);
562*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000);
563*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN7_REG, 0x000003a0);
564*d2128731SHaojian Zhuang 	udelay(1);
565*d2128731SHaojian Zhuang 	/* clk disable */
566*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPERDIS2_REG, 0x00104000);
567*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERDIS7_REG, 0x000003a0);
568*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000000);
569*d2128731SHaojian Zhuang 	udelay(1);
570*d2128731SHaojian Zhuang 	/* iso disable */
571*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCISODIS_REG, 0x00000030);
572*d2128731SHaojian Zhuang 	/* unreset */
573*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS3_REG, 0x8c000000);
574*d2128731SHaojian Zhuang 	/* clk enable */
575*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800);
576*d2128731SHaojian Zhuang 	mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000);
577*d2128731SHaojian Zhuang 	mmio_write_32(CRG_PEREN7_REG, 0x000003a0);
578*d2128731SHaojian Zhuang }
579*d2128731SHaojian Zhuang 
580*d2128731SHaojian Zhuang static void ispfunc_enable(void)
581*d2128731SHaojian Zhuang {
582*d2128731SHaojian Zhuang 	/* enable ispfunc. Otherwise powerup isp_srt causes exception. */
583*d2128731SHaojian Zhuang 	mmio_write_32(0xfff35000, 0x00000008);
584*d2128731SHaojian Zhuang 	mmio_write_32(0xfff35460, 0xc004ffff);
585*d2128731SHaojian Zhuang 	mmio_write_32(0xfff35030, 0x02000000);
586*d2128731SHaojian Zhuang 	mdelay(10);
587*d2128731SHaojian Zhuang }
588*d2128731SHaojian Zhuang 
589*d2128731SHaojian Zhuang static void isps_control_clock(int flag)
590*d2128731SHaojian Zhuang {
591*d2128731SHaojian Zhuang 	unsigned int ret;
592*d2128731SHaojian Zhuang 
593*d2128731SHaojian Zhuang 	/* flag: 0 -- disable clock, 1 -- enable clock */
594*d2128731SHaojian Zhuang 	if (flag) {
595*d2128731SHaojian Zhuang 		ret = mmio_read_32(0xe8420364);
596*d2128731SHaojian Zhuang 		ret |= 1;
597*d2128731SHaojian Zhuang 		mmio_write_32(0xe8420364, ret);
598*d2128731SHaojian Zhuang 	} else {
599*d2128731SHaojian Zhuang 		ret = mmio_read_32(0xe8420364);
600*d2128731SHaojian Zhuang 		ret &= ~1;
601*d2128731SHaojian Zhuang 		mmio_write_32(0xe8420364, ret);
602*d2128731SHaojian Zhuang 	}
603*d2128731SHaojian Zhuang }
604*d2128731SHaojian Zhuang 
605*d2128731SHaojian Zhuang static void set_isp_srt_power_up(void)
606*d2128731SHaojian Zhuang {
607*d2128731SHaojian Zhuang 	unsigned int ret;
608*d2128731SHaojian Zhuang 
609*d2128731SHaojian Zhuang 	ispfunc_enable();
610*d2128731SHaojian Zhuang 	/* reset */
611*d2128731SHaojian Zhuang 	mmio_write_32(0xe8420374, 0x00000001);
612*d2128731SHaojian Zhuang 	mmio_write_32(0xe8420350, 0x00000000);
613*d2128731SHaojian Zhuang 	mmio_write_32(0xe8420358, 0x00000000);
614*d2128731SHaojian Zhuang 	/* mtcmos on */
615*d2128731SHaojian Zhuang 	mmio_write_32(0xfff35150, 0x00400000);
616*d2128731SHaojian Zhuang 	udelay(100);
617*d2128731SHaojian Zhuang 	/* clk enable */
618*d2128731SHaojian Zhuang 	isps_control_clock(1);
619*d2128731SHaojian Zhuang 	udelay(1);
620*d2128731SHaojian Zhuang 	isps_control_clock(0);
621*d2128731SHaojian Zhuang 	udelay(1);
622*d2128731SHaojian Zhuang 	/* iso disable */
623*d2128731SHaojian Zhuang 	mmio_write_32(0xfff35148, 0x08000000);
624*d2128731SHaojian Zhuang 	/* unreset */
625*d2128731SHaojian Zhuang 	ret = mmio_read_32(0xe8420374);
626*d2128731SHaojian Zhuang 	ret &= ~0x1;
627*d2128731SHaojian Zhuang 	mmio_write_32(0xe8420374, ret);
628*d2128731SHaojian Zhuang 	/* clk enable */
629*d2128731SHaojian Zhuang 	isps_control_clock(1);
630*d2128731SHaojian Zhuang 	/* enable clock gating for accessing csi registers */
631*d2128731SHaojian Zhuang 	mmio_write_32(0xe8420010, ~0);
632*d2128731SHaojian Zhuang }
633*d2128731SHaojian Zhuang 
634*d2128731SHaojian Zhuang static void hikey960_regulator_enable(void)
635*d2128731SHaojian Zhuang {
636*d2128731SHaojian Zhuang 	set_vivobus_power_up();
637*d2128731SHaojian Zhuang 	hikey960_enable_ppll3();
638*d2128731SHaojian Zhuang 	set_dss_power_up();
639*d2128731SHaojian Zhuang 	set_vcodec_power_up();
640*d2128731SHaojian Zhuang 	set_vdec_power_up();
641*d2128731SHaojian Zhuang 	set_venc_power_up();
642*d2128731SHaojian Zhuang 	set_isp_power_up();
643*d2128731SHaojian Zhuang 	set_ivp_power_up();
644*d2128731SHaojian Zhuang 	set_audio_power_up();
645*d2128731SHaojian Zhuang 	set_pcie_power_up();
646*d2128731SHaojian Zhuang 	set_isp_srt_power_up();
647*d2128731SHaojian Zhuang }
648*d2128731SHaojian Zhuang 
649*d2128731SHaojian Zhuang static void hikey960_tzc_init(void)
650*d2128731SHaojian Zhuang {
651*d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN0_REG, 0x7fbff066);
652*d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN1_REG, 0xfffff5fc);
653*d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN2_REG, 0x0007005c);
654*d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN3_REG, 0x37030700);
655*d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN4_REG, 0xf63fefae);
656*d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN5_REG, 0x000410fd);
657*d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN6_REG, 0x0063ff68);
658*d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN7_REG, 0x030000f3);
659*d2128731SHaojian Zhuang 	mmio_write_32(TZC_EN8_REG, 0x00000007);
660*d2128731SHaojian Zhuang }
661*d2128731SHaojian Zhuang 
662*d2128731SHaojian Zhuang static void hikey960_peri_init(void)
663*d2128731SHaojian Zhuang {
664*d2128731SHaojian Zhuang 	/* unreset */
665*d2128731SHaojian Zhuang 	mmio_setbits_32(CRG_PERRSTDIS4_REG, 1);
666*d2128731SHaojian Zhuang }
667*d2128731SHaojian Zhuang 
668*d2128731SHaojian Zhuang static void hikey960_pinmux_init(void)
669*d2128731SHaojian Zhuang {
670*d2128731SHaojian Zhuang 	unsigned int id;
671*d2128731SHaojian Zhuang 
672*d2128731SHaojian Zhuang 	hikey960_read_boardid(&id);
673*d2128731SHaojian Zhuang 	if (id == 5301) {
674*d2128731SHaojian Zhuang 		/* hikey960 hardware v2 */
675*d2128731SHaojian Zhuang 		/* GPIO150: LED */
676*d2128731SHaojian Zhuang 		mmio_write_32(IOMG_FIX_006_REG, 0);
677*d2128731SHaojian Zhuang 		/* GPIO151: LED */
678*d2128731SHaojian Zhuang 		mmio_write_32(IOMG_FIX_007_REG, 0);
679*d2128731SHaojian Zhuang 		/* GPIO189: LED */
680*d2128731SHaojian Zhuang 		mmio_write_32(IOMG_AO_011_REG, 0);
681*d2128731SHaojian Zhuang 		/* GPIO190: LED */
682*d2128731SHaojian Zhuang 		mmio_write_32(IOMG_AO_012_REG, 0);
683*d2128731SHaojian Zhuang 		/* GPIO46 */
684*d2128731SHaojian Zhuang 		mmio_write_32(IOMG_044_REG, 0);
685*d2128731SHaojian Zhuang 		/* GPIO202 */
686*d2128731SHaojian Zhuang 		mmio_write_32(IOMG_AO_023_REG, 0);
687*d2128731SHaojian Zhuang 		/* GPIO206 */
688*d2128731SHaojian Zhuang 		mmio_write_32(IOMG_AO_026_REG, 0);
689*d2128731SHaojian Zhuang 		/* GPIO219 - PD pullup */
690*d2128731SHaojian Zhuang 		mmio_write_32(IOMG_AO_039_REG, 0);
691*d2128731SHaojian Zhuang 		mmio_write_32(IOCG_AO_043_REG, 1 << 0);
692*d2128731SHaojian Zhuang 	}
693*d2128731SHaojian Zhuang 	/* GPIO005 - PMU SSI, 10mA */
694*d2128731SHaojian Zhuang 	mmio_write_32(IOCG_006_REG, 2 << 4);
695*d2128731SHaojian Zhuang }
696*d2128731SHaojian 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 
706*d2128731SHaojian Zhuang void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2,
707*d2128731SHaojian 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);
719*d2128731SHaojian Zhuang 	/*
720*d2128731SHaojian Zhuang 	 * Allow BL2 to see the whole Trusted RAM.
721*d2128731SHaojian Zhuang 	 */
722*d2128731SHaojian Zhuang 	bl2_el3_tzram_layout.total_base = BL2_RW_BASE;
723*d2128731SHaojian Zhuang 	bl2_el3_tzram_layout.total_size = BL31_LIMIT - BL2_RW_BASE;
7247cb09cb4SHaojian Zhuang }
7257cb09cb4SHaojian Zhuang 
726*d2128731SHaojian Zhuang void bl2_el3_plat_arch_setup(void)
7277cb09cb4SHaojian Zhuang {
728*d2128731SHaojian Zhuang 	hikey960_init_mmu_el3(bl2_el3_tzram_layout.total_base,
729*d2128731SHaojian 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 	}
744*d2128731SHaojian Zhuang 	hikey960_clk_init();
745*d2128731SHaojian Zhuang 	hikey960_pmu_init();
746*d2128731SHaojian Zhuang 	hikey960_regulator_enable();
747*d2128731SHaojian Zhuang 	hikey960_tzc_init();
748*d2128731SHaojian Zhuang 	hikey960_peri_init();
749*d2128731SHaojian Zhuang 	hikey960_pinmux_init();
7507cb09cb4SHaojian Zhuang }
751