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