1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2014 Freescale Semiconductor, Inc.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <asm/io.h>
9*4882a593Smuzhiyun #ifndef CONFIG_ARMV7_NONSEC
10*4882a593Smuzhiyun #error " Deep sleep needs non-secure mode support. "
11*4882a593Smuzhiyun #else
12*4882a593Smuzhiyun #include <asm/secure.h>
13*4882a593Smuzhiyun #endif
14*4882a593Smuzhiyun #include <asm/armv7.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #if defined(CONFIG_ARCH_LS1021A)
17*4882a593Smuzhiyun #include <asm/arch/immap_ls102xa.h>
18*4882a593Smuzhiyun #endif
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include "sleep.h"
21*4882a593Smuzhiyun #ifdef CONFIG_U_QE
22*4882a593Smuzhiyun #include <fsl_qe.h>
23*4882a593Smuzhiyun #endif
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
26*4882a593Smuzhiyun
board_mem_sleep_setup(void)27*4882a593Smuzhiyun void __weak board_mem_sleep_setup(void)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun }
30*4882a593Smuzhiyun
board_sleep_prepare(void)31*4882a593Smuzhiyun void __weak board_sleep_prepare(void)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun }
34*4882a593Smuzhiyun
is_warm_boot(void)35*4882a593Smuzhiyun bool is_warm_boot(void)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun if (in_be32(&gur->crstsr) & DCFG_CCSR_CRSTSR_WDRFR)
40*4882a593Smuzhiyun return 1;
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun return 0;
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun
fsl_dp_disable_console(void)45*4882a593Smuzhiyun void fsl_dp_disable_console(void)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun gd->flags |= GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE;
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /*
51*4882a593Smuzhiyun * When wakeup from deep sleep, the first 128 bytes space
52*4882a593Smuzhiyun * will be used to do DDR training which corrupts the data
53*4882a593Smuzhiyun * in there. This function will restore them.
54*4882a593Smuzhiyun */
dp_ddr_restore(void)55*4882a593Smuzhiyun static void dp_ddr_restore(void)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun u64 *src, *dst;
58*4882a593Smuzhiyun int i;
59*4882a593Smuzhiyun struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /* get the address of ddr date from SPARECR3 */
62*4882a593Smuzhiyun src = (u64 *)in_le32(&scfg->sparecr[2]);
63*4882a593Smuzhiyun dst = (u64 *)CONFIG_SYS_SDRAM_BASE;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun for (i = 0; i < DDR_BUFF_LEN / 8; i++)
66*4882a593Smuzhiyun *dst++ = *src++;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun #if defined(CONFIG_ARMV7_PSCI) && defined(CONFIG_ARCH_LS1021A)
ls1_psci_resume_fixup(void)70*4882a593Smuzhiyun void ls1_psci_resume_fixup(void)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun u32 tmp;
73*4882a593Smuzhiyun struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun #ifdef QIXIS_BASE
76*4882a593Smuzhiyun void *qixis_base = (void *)QIXIS_BASE;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun /* Pull on PCIe RST# */
79*4882a593Smuzhiyun out_8(qixis_base + QIXIS_RST_FORCE_3, 0);
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun /* disable deep sleep signals in FPGA */
82*4882a593Smuzhiyun tmp = in_8(qixis_base + QIXIS_PWR_CTL2);
83*4882a593Smuzhiyun tmp &= ~QIXIS_PWR_CTL2_PCTL;
84*4882a593Smuzhiyun out_8(qixis_base + QIXIS_PWR_CTL2, tmp);
85*4882a593Smuzhiyun #endif
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun /* Disable wakeup interrupt during deep sleep */
88*4882a593Smuzhiyun out_be32(&scfg->pmcintecr, 0);
89*4882a593Smuzhiyun /* Clear PMC interrupt status */
90*4882a593Smuzhiyun out_be32(&scfg->pmcintsr, 0xffffffff);
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /* Disable Warm Device Reset */
93*4882a593Smuzhiyun tmp = in_be32(&scfg->dpslpcr);
94*4882a593Smuzhiyun tmp &= ~SCFG_DPSLPCR_WDRR_EN;
95*4882a593Smuzhiyun out_be32(&scfg->dpslpcr, tmp);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun #endif
98*4882a593Smuzhiyun
dp_resume_prepare(void)99*4882a593Smuzhiyun static void dp_resume_prepare(void)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun dp_ddr_restore();
102*4882a593Smuzhiyun board_sleep_prepare();
103*4882a593Smuzhiyun armv7_init_nonsec();
104*4882a593Smuzhiyun #ifdef CONFIG_U_QE
105*4882a593Smuzhiyun u_qe_resume();
106*4882a593Smuzhiyun #endif
107*4882a593Smuzhiyun #if defined(CONFIG_ARMV7_PSCI) && defined(CONFIG_ARCH_LS1021A)
108*4882a593Smuzhiyun ls1_psci_resume_fixup();
109*4882a593Smuzhiyun #endif
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
fsl_dp_resume(void)112*4882a593Smuzhiyun int fsl_dp_resume(void)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun u32 start_addr;
115*4882a593Smuzhiyun void (*kernel_resume)(void);
116*4882a593Smuzhiyun struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun if (!is_warm_boot())
119*4882a593Smuzhiyun return 0;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun dp_resume_prepare();
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun /* Get the entry address and jump to kernel */
124*4882a593Smuzhiyun start_addr = in_le32(&scfg->sparecr[3]);
125*4882a593Smuzhiyun debug("Entry address is 0x%08x\n", start_addr);
126*4882a593Smuzhiyun kernel_resume = (void (*)(void))start_addr;
127*4882a593Smuzhiyun secure_ram_addr(_do_nonsec_entry)(kernel_resume, 0, 0, 0);
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun return 0;
130*4882a593Smuzhiyun }
131