xref: /rk3399_rockchip-uboot/board/freescale/common/arm_sleep.c (revision 4f66e09bb9fbc47b73f67c3cc08ee2663e8fcdb1)
1a7787b78STang Yuantian /*
2a7787b78STang Yuantian  * Copyright 2014 Freescale Semiconductor, Inc.
3a7787b78STang Yuantian  *
4a7787b78STang Yuantian  * SPDX-License-Identifier:	GPL-2.0+
5a7787b78STang Yuantian  */
6a7787b78STang Yuantian 
7a7787b78STang Yuantian #include <common.h>
8a7787b78STang Yuantian #include <asm/io.h>
9104d6fb6SJan Kiszka #ifndef CONFIG_ARMV7_NONSEC
10a7787b78STang Yuantian #error " Deep sleep needs non-secure mode support. "
11a7787b78STang Yuantian #else
12a7787b78STang Yuantian #include <asm/secure.h>
13a7787b78STang Yuantian #endif
14a7787b78STang Yuantian #include <asm/armv7.h>
15a7787b78STang Yuantian 
16*73fb5838SYork Sun #if defined(CONFIG_ARCH_LS1021A)
17a7787b78STang Yuantian #include <asm/arch/immap_ls102xa.h>
18a7787b78STang Yuantian #endif
19a7787b78STang Yuantian 
20a7787b78STang Yuantian #include "sleep.h"
211fb5ff9aSZhao Qiang #ifdef CONFIG_U_QE
222459afb1SQianyu Gong #include <fsl_qe.h>
231fb5ff9aSZhao Qiang #endif
24a7787b78STang Yuantian 
25a7787b78STang Yuantian DECLARE_GLOBAL_DATA_PTR;
26a7787b78STang Yuantian 
board_mem_sleep_setup(void)27a7787b78STang Yuantian void __weak board_mem_sleep_setup(void)
28a7787b78STang Yuantian {
29a7787b78STang Yuantian }
30a7787b78STang Yuantian 
board_sleep_prepare(void)31a7787b78STang Yuantian void __weak board_sleep_prepare(void)
32a7787b78STang Yuantian {
33a7787b78STang Yuantian }
34a7787b78STang Yuantian 
is_warm_boot(void)35a7787b78STang Yuantian bool is_warm_boot(void)
36a7787b78STang Yuantian {
37a7787b78STang Yuantian 	struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
38a7787b78STang Yuantian 
39a7787b78STang Yuantian 	if (in_be32(&gur->crstsr) & DCFG_CCSR_CRSTSR_WDRFR)
40a7787b78STang Yuantian 		return 1;
41a7787b78STang Yuantian 
42a7787b78STang Yuantian 	return 0;
43a7787b78STang Yuantian }
44a7787b78STang Yuantian 
fsl_dp_disable_console(void)45a7787b78STang Yuantian void fsl_dp_disable_console(void)
46a7787b78STang Yuantian {
47a7787b78STang Yuantian 	gd->flags |= GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE;
48a7787b78STang Yuantian }
49a7787b78STang Yuantian 
50a7787b78STang Yuantian /*
51a7787b78STang Yuantian  * When wakeup from deep sleep, the first 128 bytes space
52a7787b78STang Yuantian  * will be used to do DDR training which corrupts the data
53a7787b78STang Yuantian  * in there. This function will restore them.
54a7787b78STang Yuantian  */
dp_ddr_restore(void)55a7787b78STang Yuantian static void dp_ddr_restore(void)
56a7787b78STang Yuantian {
57a7787b78STang Yuantian 	u64 *src, *dst;
58a7787b78STang Yuantian 	int i;
59a7787b78STang Yuantian 	struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
60a7787b78STang Yuantian 
61a7787b78STang Yuantian 	/* get the address of ddr date from SPARECR3 */
62a7787b78STang Yuantian 	src = (u64 *)in_le32(&scfg->sparecr[2]);
63a7787b78STang Yuantian 	dst = (u64 *)CONFIG_SYS_SDRAM_BASE;
64a7787b78STang Yuantian 
65a7787b78STang Yuantian 	for (i = 0; i < DDR_BUFF_LEN / 8; i++)
66a7787b78STang Yuantian 		*dst++ = *src++;
67a7787b78STang Yuantian }
68a7787b78STang Yuantian 
69*73fb5838SYork Sun #if defined(CONFIG_ARMV7_PSCI) && defined(CONFIG_ARCH_LS1021A)
ls1_psci_resume_fixup(void)70214ffae0SHongbo Zhang void ls1_psci_resume_fixup(void)
71214ffae0SHongbo Zhang {
72214ffae0SHongbo Zhang 	u32 tmp;
73214ffae0SHongbo Zhang 	struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
74214ffae0SHongbo Zhang 
75214ffae0SHongbo Zhang #ifdef QIXIS_BASE
76214ffae0SHongbo Zhang 	void *qixis_base = (void *)QIXIS_BASE;
77214ffae0SHongbo Zhang 
78214ffae0SHongbo Zhang 	/* Pull on PCIe RST# */
79214ffae0SHongbo Zhang 	out_8(qixis_base + QIXIS_RST_FORCE_3, 0);
80214ffae0SHongbo Zhang 
81214ffae0SHongbo Zhang 	/* disable deep sleep signals in FPGA */
82214ffae0SHongbo Zhang 	tmp = in_8(qixis_base + QIXIS_PWR_CTL2);
83214ffae0SHongbo Zhang 	tmp &= ~QIXIS_PWR_CTL2_PCTL;
84214ffae0SHongbo Zhang 	out_8(qixis_base + QIXIS_PWR_CTL2, tmp);
85214ffae0SHongbo Zhang #endif
86214ffae0SHongbo Zhang 
87214ffae0SHongbo Zhang 	/* Disable wakeup interrupt during deep sleep */
88214ffae0SHongbo Zhang 	out_be32(&scfg->pmcintecr, 0);
89214ffae0SHongbo Zhang 	/* Clear PMC interrupt status */
90214ffae0SHongbo Zhang 	out_be32(&scfg->pmcintsr, 0xffffffff);
91214ffae0SHongbo Zhang 
92214ffae0SHongbo Zhang 	/* Disable Warm Device Reset */
93214ffae0SHongbo Zhang 	tmp = in_be32(&scfg->dpslpcr);
94214ffae0SHongbo Zhang 	tmp &= ~SCFG_DPSLPCR_WDRR_EN;
95214ffae0SHongbo Zhang 	out_be32(&scfg->dpslpcr, tmp);
96214ffae0SHongbo Zhang }
97214ffae0SHongbo Zhang #endif
98214ffae0SHongbo Zhang 
dp_resume_prepare(void)99a7787b78STang Yuantian static void dp_resume_prepare(void)
100a7787b78STang Yuantian {
101a7787b78STang Yuantian 	dp_ddr_restore();
102a7787b78STang Yuantian 	board_sleep_prepare();
103a7787b78STang Yuantian 	armv7_init_nonsec();
1041fb5ff9aSZhao Qiang #ifdef CONFIG_U_QE
1051fb5ff9aSZhao Qiang 	u_qe_resume();
1061fb5ff9aSZhao Qiang #endif
107*73fb5838SYork Sun #if defined(CONFIG_ARMV7_PSCI) && defined(CONFIG_ARCH_LS1021A)
108214ffae0SHongbo Zhang 	ls1_psci_resume_fixup();
109214ffae0SHongbo Zhang #endif
110a7787b78STang Yuantian }
111a7787b78STang Yuantian 
fsl_dp_resume(void)112a7787b78STang Yuantian int fsl_dp_resume(void)
113a7787b78STang Yuantian {
114a7787b78STang Yuantian 	u32 start_addr;
115a7787b78STang Yuantian 	void (*kernel_resume)(void);
116a7787b78STang Yuantian 	struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
117a7787b78STang Yuantian 
118a7787b78STang Yuantian 	if (!is_warm_boot())
119a7787b78STang Yuantian 		return 0;
120a7787b78STang Yuantian 
121a7787b78STang Yuantian 	dp_resume_prepare();
122a7787b78STang Yuantian 
123a7787b78STang Yuantian 	/* Get the entry address and jump to kernel */
124214ffae0SHongbo Zhang 	start_addr = in_le32(&scfg->sparecr[3]);
125a7787b78STang Yuantian 	debug("Entry address is 0x%08x\n", start_addr);
126a7787b78STang Yuantian 	kernel_resume = (void (*)(void))start_addr;
127a7787b78STang Yuantian 	secure_ram_addr(_do_nonsec_entry)(kernel_resume, 0, 0, 0);
128a7787b78STang Yuantian 
129a7787b78STang Yuantian 	return 0;
130a7787b78STang Yuantian }
131