summaryrefslogtreecommitdiff
path: root/arch/arm/mach-stm32mp/psci.c
diff options
context:
space:
mode:
authorPatrice Chotard <patrice.chotard@foss.st.com>2023-10-27 16:43:04 +0200
committerPatrice Chotard <patrice.chotard@foss.st.com>2023-11-13 10:55:38 +0100
commit01a701994b0590b6452516a7c67353359d053c94 (patch)
treeff11e53793948ad6c1fce6c80aa8a1446d92d02f /arch/arm/mach-stm32mp/psci.c
parent970d1673b016ae013839d7bcd69a17601b450304 (diff)
stm32mp2: initial support
Add initial support for STM32MP2 SoCs family. SoCs information are available here : https://www.st.com/content/st_com/en/campaigns/microprocessor-stm32mp2.html Migrate all MP1 related code into stm32mp1/ directory Create stm32mp2 directory dedicated for STM32MP2 SoCs. Common code to MP1, MP13 and MP25 is kept into arch/arm/mach-stm32/mach-stm32mp directory : - boot_params.c - bsec - cmd_stm32key - cmd_stm32prog - dram_init.c - syscon.c - ecdsa_romapi.c For STM32MP2, it also : - adds memory region description needed for ARMv8 MMU. - enables early data cache before relocation. During the transition before/after relocation, the MMU, initially setup at the beginning of DDR, must be setup again at a correct address after relocation. This is done in enables_caches() by disabling cache, force arch.tlb_fillptr to NULL which will force the MMU to be setup again but with a new value for gd->arch.tlb_addr. gd->arch.tlb_addr has been updated after relocation in arm_reserve_mmu(). Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com> Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Diffstat (limited to 'arch/arm/mach-stm32mp/psci.c')
-rw-r--r--arch/arm/mach-stm32mp/psci.c808
1 files changed, 0 insertions, 808 deletions
diff --git a/arch/arm/mach-stm32mp/psci.c b/arch/arm/mach-stm32mp/psci.c
deleted file mode 100644
index 8cdeb0ab3f2..00000000000
--- a/arch/arm/mach-stm32mp/psci.c
+++ /dev/null
@@ -1,808 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
-/*
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
- */
-
-#include <config.h>
-#include <common.h>
-#include <asm/armv7.h>
-#include <asm/cache.h>
-#include <asm/gic.h>
-#include <asm/io.h>
-#include <asm/psci.h>
-#include <asm/secure.h>
-#include <hang.h>
-#include <linux/bitops.h>
-
-/* PWR */
-#define PWR_CR3 0x0c
-#define PWR_MPUCR 0x10
-
-#define PWR_CR3_DDRSREN BIT(10)
-#define PWR_CR3_DDRRETEN BIT(12)
-
-#define PWR_MPUCR_PDDS BIT(0)
-#define PWR_MPUCR_CSTDBYDIS BIT(3)
-#define PWR_MPUCR_CSSF BIT(9)
-
-/* RCC */
-#define RCC_MSSCKSELR 0x48
-#define RCC_DDRITFCR 0xd8
-
-#define RCC_DDRITFCR_DDRC1EN BIT(0)
-#define RCC_DDRITFCR_DDRC1LPEN BIT(1)
-#define RCC_DDRITFCR_DDRC2EN BIT(2)
-#define RCC_DDRITFCR_DDRC2LPEN BIT(3)
-#define RCC_DDRITFCR_DDRPHYCEN BIT(4)
-#define RCC_DDRITFCR_DDRPHYCLPEN BIT(5)
-#define RCC_DDRITFCR_DDRCAPBEN BIT(6)
-#define RCC_DDRITFCR_DDRCAPBLPEN BIT(7)
-#define RCC_DDRITFCR_AXIDCGEN BIT(8)
-#define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9)
-#define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10)
-#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20)
-#define RCC_DDRITFCR_GSKPCTRL BIT(24)
-
-#define RCC_MP_SREQSETR 0x104
-#define RCC_MP_SREQCLRR 0x108
-
-#define RCC_MP_CIER 0x414
-#define RCC_MP_CIFR 0x418
-#define RCC_MP_CIFR_WKUPF BIT(20)
-
-#define RCC_MCUDIVR 0x830
-#define RCC_PLL3CR 0x880
-#define RCC_PLL4CR 0x894
-
-/* SYSCFG */
-#define SYSCFG_CMPCR 0x20
-#define SYSCFG_CMPCR_SW_CTRL BIT(2)
-#define SYSCFG_CMPENSETR 0x24
-#define SYSCFG_CMPENCLRR 0x28
-#define SYSCFG_CMPENR_MPUEN BIT(0)
-
-/* DDR Controller registers offsets */
-#define DDRCTRL_STAT 0x004
-#define DDRCTRL_PWRCTL 0x030
-#define DDRCTRL_PWRTMG 0x034
-#define DDRCTRL_HWLPCTL 0x038
-#define DDRCTRL_DFIMISC 0x1b0
-#define DDRCTRL_SWCTL 0x320
-#define DDRCTRL_SWSTAT 0x324
-#define DDRCTRL_PSTAT 0x3fc
-#define DDRCTRL_PCTRL_0 0x490
-#define DDRCTRL_PCTRL_1 0x540
-
-/* DDR Controller Register fields */
-#define DDRCTRL_STAT_OPERATING_MODE_MASK GENMASK(2, 0)
-#define DDRCTRL_STAT_OPERATING_MODE_NORMAL 0x1
-#define DDRCTRL_STAT_OPERATING_MODE_SR 0x3
-#define DDRCTRL_STAT_SELFREF_TYPE_MASK GENMASK(5, 4)
-#define DDRCTRL_STAT_SELFREF_TYPE_ASR (0x3 << 4)
-#define DDRCTRL_STAT_SELFREF_TYPE_SR (0x2 << 4)
-
-#define DDRCTRL_PWRCTL_SELFREF_EN BIT(0)
-#define DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE BIT(3)
-#define DDRCTRL_PWRCTL_SELFREF_SW BIT(5)
-
-#define DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK GENMASK(23, 16)
-#define DDRCTRL_PWRTMG_SELFREF_TO_X32_0 BIT(16)
-
-#define DDRCTRL_HWLPCTL_HW_LP_EN BIT(0)
-
-#define DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN BIT(0)
-
-#define DDRCTRL_SWCTL_SW_DONE BIT(0)
-
-#define DDRCTRL_SWSTAT_SW_DONE_ACK BIT(0)
-
-#define DDRCTRL_PSTAT_RD_PORT_BUSY_0 BIT(0)
-#define DDRCTRL_PSTAT_RD_PORT_BUSY_1 BIT(1)
-#define DDRCTRL_PSTAT_WR_PORT_BUSY_0 BIT(16)
-#define DDRCTRL_PSTAT_WR_PORT_BUSY_1 BIT(17)
-
-#define DDRCTRL_PCTRL_N_PORT_EN BIT(0)
-
-/* DDR PHY registers offsets */
-#define DDRPHYC_PIR 0x004
-#define DDRPHYC_PGSR 0x00c
-#define DDRPHYC_ACDLLCR 0x014
-#define DDRPHYC_ACIOCR 0x024
-#define DDRPHYC_DXCCR 0x028
-#define DDRPHYC_DSGCR 0x02c
-#define DDRPHYC_ZQ0CR0 0x180
-#define DDRPHYC_DX0DLLCR 0x1cc
-#define DDRPHYC_DX1DLLCR 0x20c
-#define DDRPHYC_DX2DLLCR 0x24c
-#define DDRPHYC_DX3DLLCR 0x28c
-
-/* DDR PHY Register fields */
-#define DDRPHYC_PIR_INIT BIT(0)
-#define DDRPHYC_PIR_DLLSRST BIT(1)
-#define DDRPHYC_PIR_DLLLOCK BIT(2)
-#define DDRPHYC_PIR_ITMSRST BIT(4)
-
-#define DDRPHYC_PGSR_IDONE BIT(0)
-
-#define DDRPHYC_ACDLLCR_DLLSRST BIT(30)
-#define DDRPHYC_ACDLLCR_DLLDIS BIT(31)
-
-#define DDRPHYC_ACIOCR_ACOE BIT(1)
-#define DDRPHYC_ACIOCR_ACPDD BIT(3)
-#define DDRPHYC_ACIOCR_ACPDR BIT(4)
-#define DDRPHYC_ACIOCR_CKPDD_MASK GENMASK(10, 8)
-#define DDRPHYC_ACIOCR_CKPDD_0 BIT(8)
-#define DDRPHYC_ACIOCR_CKPDR_MASK GENMASK(13, 11)
-#define DDRPHYC_ACIOCR_CKPDR_0 BIT(11)
-#define DDRPHYC_ACIOCR_CSPDD_MASK GENMASK(20, 18)
-#define DDRPHYC_ACIOCR_CSPDD_0 BIT(18)
-
-#define DDRPHYC_DXCCR_DXPDD BIT(2)
-#define DDRPHYC_DXCCR_DXPDR BIT(3)
-
-#define DDRPHYC_DSGCR_CKEPDD_MASK GENMASK(19, 16)
-#define DDRPHYC_DSGCR_CKEPDD_0 BIT(16)
-#define DDRPHYC_DSGCR_ODTPDD_MASK GENMASK(23, 20)
-#define DDRPHYC_DSGCR_ODTPDD_0 BIT(20)
-#define DDRPHYC_DSGCR_NL2PD BIT(24)
-#define DDRPHYC_DSGCR_CKOE BIT(28)
-
-#define DDRPHYC_ZQ0CRN_ZQPD BIT(31)
-
-#define DDRPHYC_DXNDLLCR_DLLDIS BIT(31)
-
-#define BOOT_API_A7_CORE0_MAGIC_NUMBER 0xca7face0
-#define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xca7face1
-
-#define MPIDR_AFF0 GENMASK(7, 0)
-
-#define RCC_MP_GRSTCSETR (STM32_RCC_BASE + 0x0404)
-#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0)
-#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4)
-#define RCC_MP_GRSTCSETR_MPUP1RST BIT(5)
-
-/* IWDG */
-#define IWDG_KR 0x00
-#define IWDG_KR_RELOAD_KEY 0xaaaa
-#define IWDG_EWCR 0x14
-#define IWDG_EWCR_EWIC BIT(14)
-
-#define STM32MP1_PSCI_NR_CPUS 2
-#if STM32MP1_PSCI_NR_CPUS > CONFIG_ARMV7_PSCI_NR_CPUS
-#error "invalid value for CONFIG_ARMV7_PSCI_NR_CPUS"
-#endif
-
-u8 psci_state[STM32MP1_PSCI_NR_CPUS] __secure_data = {
- PSCI_AFFINITY_LEVEL_ON,
- PSCI_AFFINITY_LEVEL_OFF};
-
-static u32 __secure_data cntfrq;
-
-static u32 __secure cp15_read_cntfrq(void)
-{
- u32 frq;
-
- asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (frq));
-
- return frq;
-}
-
-static void __secure cp15_write_cntfrq(u32 frq)
-{
- asm volatile ("mcr p15, 0, %0, c14, c0, 0" : : "r" (frq));
-}
-
-static inline void psci_set_state(int cpu, u8 state)
-{
- psci_state[cpu] = state;
- dsb();
- isb();
-}
-
-static u32 __secure stm32mp_get_gicd_base_address(void)
-{
- u32 periphbase;
-
- /* get the GIC base address from the CBAR register */
- asm("mrc p15, 4, %0, c15, c0, 0\n" : "=r" (periphbase));
-
- return (periphbase & CBAR_MASK) + GIC_DIST_OFFSET;
-}
-
-static void __secure stm32mp_raise_sgi0(int cpu)
-{
- u32 gic_dist_addr;
-
- gic_dist_addr = stm32mp_get_gicd_base_address();
-
- /* ask cpu with SGI0 */
- writel((BIT(cpu) << 16), gic_dist_addr + GICD_SGIR);
-}
-
-void __secure psci_arch_cpu_entry(void)
-{
- u32 cpu = psci_get_cpu_id();
-
- psci_set_state(cpu, PSCI_AFFINITY_LEVEL_ON);
-
- /* write the saved cntfrq */
- cp15_write_cntfrq(cntfrq);
-
- /* reset magic in TAMP register */
- writel(0xFFFFFFFF, TAMP_BACKUP_MAGIC_NUMBER);
-}
-
-s32 __secure psci_features(u32 function_id, u32 psci_fid)
-{
- switch (psci_fid) {
- case ARM_PSCI_0_2_FN_PSCI_VERSION:
- case ARM_PSCI_0_2_FN_CPU_OFF:
- case ARM_PSCI_0_2_FN_CPU_ON:
- case ARM_PSCI_0_2_FN_AFFINITY_INFO:
- case ARM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
- case ARM_PSCI_0_2_FN_SYSTEM_OFF:
- case ARM_PSCI_0_2_FN_SYSTEM_RESET:
- case ARM_PSCI_1_0_FN_SYSTEM_SUSPEND:
- return 0x0;
- }
- return ARM_PSCI_RET_NI;
-}
-
-u32 __secure psci_version(void)
-{
- return ARM_PSCI_VER_1_0;
-}
-
-s32 __secure psci_affinity_info(u32 function_id, u32 target_affinity,
- u32 lowest_affinity_level)
-{
- u32 cpu = target_affinity & MPIDR_AFF0;
-
- if (lowest_affinity_level > 0)
- return ARM_PSCI_RET_INVAL;
-
- if (target_affinity & ~MPIDR_AFF0)
- return ARM_PSCI_RET_INVAL;
-
- if (cpu >= STM32MP1_PSCI_NR_CPUS)
- return ARM_PSCI_RET_INVAL;
-
- return psci_state[cpu];
-}
-
-u32 __secure psci_migrate_info_type(void)
-{
- /*
- * in Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf
- * return 2 = Trusted OS is either not present or does not require
- * migration, system of this type does not require the caller
- * to use the MIGRATE function.
- * MIGRATE function calls return NOT_SUPPORTED.
- */
- return 2;
-}
-
-s32 __secure psci_cpu_on(u32 function_id, u32 target_cpu, u32 pc,
- u32 context_id)
-{
- u32 cpu = target_cpu & MPIDR_AFF0;
-
- if (target_cpu & ~MPIDR_AFF0)
- return ARM_PSCI_RET_INVAL;
-
- if (cpu >= STM32MP1_PSCI_NR_CPUS)
- return ARM_PSCI_RET_INVAL;
-
- if (psci_state[cpu] == PSCI_AFFINITY_LEVEL_ON)
- return ARM_PSCI_RET_ALREADY_ON;
-
- /* read and save cntfrq of current cpu to write on target cpu */
- cntfrq = cp15_read_cntfrq();
-
- /* reset magic in TAMP register */
- if (readl(TAMP_BACKUP_MAGIC_NUMBER))
- writel(0xFFFFFFFF, TAMP_BACKUP_MAGIC_NUMBER);
- /*
- * ROM code need a first SGI0 after core reset
- * core is ready when magic is set to 0 in ROM code
- */
- while (readl(TAMP_BACKUP_MAGIC_NUMBER))
- stm32mp_raise_sgi0(cpu);
-
- /* store target PC and context id*/
- psci_save(cpu, pc, context_id);
-
- /* write entrypoint in backup RAM register */
- writel((u32)&psci_cpu_entry, TAMP_BACKUP_BRANCH_ADDRESS);
- psci_set_state(cpu, PSCI_AFFINITY_LEVEL_ON_PENDING);
-
- /* write magic number in backup register */
- if (cpu == 0x01)
- writel(BOOT_API_A7_CORE1_MAGIC_NUMBER,
- TAMP_BACKUP_MAGIC_NUMBER);
- else
- writel(BOOT_API_A7_CORE0_MAGIC_NUMBER,
- TAMP_BACKUP_MAGIC_NUMBER);
-
- /* Generate an IT to start the core */
- stm32mp_raise_sgi0(cpu);
-
- return ARM_PSCI_RET_SUCCESS;
-}
-
-s32 __secure psci_cpu_off(void)
-{
- u32 cpu;
-
- cpu = psci_get_cpu_id();
-
- psci_cpu_off_common();
- psci_set_state(cpu, PSCI_AFFINITY_LEVEL_OFF);
-
- /* reset core: wfi is managed by BootRom */
- if (cpu == 0x01)
- writel(RCC_MP_GRSTCSETR_MPUP1RST, RCC_MP_GRSTCSETR);
- else
- writel(RCC_MP_GRSTCSETR_MPUP0RST, RCC_MP_GRSTCSETR);
-
- /* just waiting reset */
- while (1)
- wfi();
-}
-
-void __secure psci_system_reset(void)
-{
- /* System reset */
- writel(RCC_MP_GRSTCSETR_MPSYSRST, RCC_MP_GRSTCSETR);
- /* just waiting reset */
- while (1)
- wfi();
-}
-
-void __secure psci_system_off(void)
-{
- /* System Off is not managed, waiting user power off
- * TODO: handle I2C write in PMIC Main Control register bit 0 = SWOFF
- */
- while (1)
- wfi();
-}
-
-static void __secure secure_udelay(unsigned int delay)
-{
- u32 freq = cp15_read_cntfrq() / 1000000;
- u64 start, end;
-
- delay *= freq;
-
- asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (start));
- for (;;) {
- asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (end));
- if ((end - start) > delay)
- break;
- }
-}
-
-static int __secure secure_waitbits(u32 reg, u32 mask, u32 val)
-{
- u32 freq = cp15_read_cntfrq() / 1000000;
- u32 delay = 500 * freq; /* 500 us */
- u64 start, end;
- u32 tmp;
-
- asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (start));
- for (;;) {
- tmp = readl(reg);
- tmp &= mask;
- if ((tmp & val) == val)
- return 0;
- asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (end));
- if ((end - start) > delay)
- return -ETIMEDOUT;
- }
-}
-
-static void __secure ddr_sr_mode_ssr(u32 *saved_pwrctl)
-{
- setbits_le32(STM32_RCC_BASE + RCC_DDRITFCR,
- RCC_DDRITFCR_DDRC1LPEN | RCC_DDRITFCR_DDRC1EN |
- RCC_DDRITFCR_DDRC2LPEN | RCC_DDRITFCR_DDRC2EN |
- RCC_DDRITFCR_DDRCAPBLPEN | RCC_DDRITFCR_DDRPHYCAPBLPEN |
- RCC_DDRITFCR_DDRCAPBEN | RCC_DDRITFCR_DDRPHYCAPBEN |
- RCC_DDRITFCR_DDRPHYCEN);
-
- clrbits_le32(STM32_RCC_BASE + RCC_DDRITFCR,
- RCC_DDRITFCR_AXIDCGEN | RCC_DDRITFCR_DDRCKMOD_MASK);
-
- /* Disable HW LP interface of uMCTL2 */
- clrbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_HWLPCTL,
- DDRCTRL_HWLPCTL_HW_LP_EN);
-
- /* Configure Automatic LP modes of uMCTL2 */
- clrsetbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_PWRTMG,
- DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK,
- DDRCTRL_PWRTMG_SELFREF_TO_X32_0);
-
- /* Save PWRCTL register to restart ASR after suspend (if applicable) */
- *saved_pwrctl = readl(STM32_DDRCTRL_BASE + DDRCTRL_PWRCTL);
-
- /*
- * Disable Clock disable with LP modes
- * (used in RUN mode for LPDDR2 with specific timing).
- */
- clrbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_PWRCTL,
- DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE);
-
- /* Disable automatic Self-Refresh mode */
- clrbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_PWRCTL,
- DDRCTRL_PWRCTL_SELFREF_EN);
-}
-
-static void __secure ddr_sr_mode_restore(u32 saved_pwrctl)
-{
- saved_pwrctl &= DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE |
- DDRCTRL_PWRCTL_SELFREF_EN;
-
- /* Restore ASR mode in case it was enabled before suspend. */
- setbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_PWRCTL, saved_pwrctl);
-}
-
-static int __secure ddr_sw_self_refresh_in(void)
-{
- int ret;
-
- clrbits_le32(STM32_RCC_BASE + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN);
-
- /* Blocks AXI ports from taking anymore transactions */
- clrbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_PCTRL_0,
- DDRCTRL_PCTRL_N_PORT_EN);
- clrbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_PCTRL_1,
- DDRCTRL_PCTRL_N_PORT_EN);
-
- /*
- * Waits unit all AXI ports are idle
- * Poll PSTAT.rd_port_busy_n = 0
- * Poll PSTAT.wr_port_busy_n = 0
- */
- ret = secure_waitbits(STM32_DDRCTRL_BASE + DDRCTRL_PSTAT,
- DDRCTRL_PSTAT_RD_PORT_BUSY_0 |
- DDRCTRL_PSTAT_RD_PORT_BUSY_1 |
- DDRCTRL_PSTAT_WR_PORT_BUSY_0 |
- DDRCTRL_PSTAT_WR_PORT_BUSY_1, 0);
- if (ret)
- goto pstat_failed;
-
- /* SW Self-Refresh entry */
- setbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_PWRCTL, DDRCTRL_PWRCTL_SELFREF_SW);
-
- /*
- * Wait operating mode change in self-refresh mode
- * with STAT.operating_mode[1:0]==11.
- * Ensure transition to self-refresh was due to software
- * by checking also that STAT.selfref_type[1:0]=2.
- */
- ret = secure_waitbits(STM32_DDRCTRL_BASE + DDRCTRL_STAT,
- DDRCTRL_STAT_OPERATING_MODE_MASK |
- DDRCTRL_STAT_SELFREF_TYPE_MASK,
- DDRCTRL_STAT_OPERATING_MODE_SR |
- DDRCTRL_STAT_SELFREF_TYPE_SR);
- if (ret)
- goto selfref_sw_failed;
-
- /* IOs powering down (PUBL registers) */
- setbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDD);
- setbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDR);
-
- clrsetbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ACIOCR,
- DDRPHYC_ACIOCR_CKPDD_MASK,
- DDRPHYC_ACIOCR_CKPDD_0);
-
- clrsetbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ACIOCR,
- DDRPHYC_ACIOCR_CKPDR_MASK,
- DDRPHYC_ACIOCR_CKPDR_0);
-
- clrsetbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ACIOCR,
- DDRPHYC_ACIOCR_CSPDD_MASK,
- DDRPHYC_ACIOCR_CSPDD_0);
-
- /* Disable command/address output driver */
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACOE);
-
- setbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDD);
-
- setbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR);
-
- clrsetbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DSGCR,
- DDRPHYC_DSGCR_ODTPDD_MASK,
- DDRPHYC_DSGCR_ODTPDD_0);
-
- setbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DSGCR, DDRPHYC_DSGCR_NL2PD);
-
- clrsetbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DSGCR,
- DDRPHYC_DSGCR_CKEPDD_MASK,
- DDRPHYC_DSGCR_CKEPDD_0);
-
- /* Disable PZQ cell (PUBL register) */
- setbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ZQ0CR0, DDRPHYC_ZQ0CRN_ZQPD);
-
- /* Set latch */
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DSGCR, DDRPHYC_DSGCR_CKOE);
-
- /* Additional delay to avoid early latch */
- secure_udelay(10);
-
- /* Activate sw retention in PWRCTRL */
- setbits_le32(STM32_PWR_BASE + PWR_CR3, PWR_CR3_DDRRETEN);
-
- /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */
- setbits_le32(STM32_RCC_BASE + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL);
-
- /* Disable all DLLs: GLITCH window */
- setbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ACDLLCR, DDRPHYC_ACDLLCR_DLLDIS);
-
- setbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DX0DLLCR, DDRPHYC_DXNDLLCR_DLLDIS);
-
- setbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DX1DLLCR, DDRPHYC_DXNDLLCR_DLLDIS);
-
- setbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DX2DLLCR, DDRPHYC_DXNDLLCR_DLLDIS);
-
- setbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DX3DLLCR, DDRPHYC_DXNDLLCR_DLLDIS);
-
- /* Switch controller clocks (uMCTL2/PUBL) to DLL output clock */
- clrbits_le32(STM32_RCC_BASE + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL);
-
- /* Deactivate all DDR clocks */
- clrbits_le32(STM32_RCC_BASE + RCC_DDRITFCR,
- RCC_DDRITFCR_DDRC1EN | RCC_DDRITFCR_DDRC2EN |
- RCC_DDRITFCR_DDRCAPBEN | RCC_DDRITFCR_DDRPHYCAPBEN);
-
- return 0;
-
-selfref_sw_failed:
- /* This bit should be cleared to restore DDR in its previous state */
- clrbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_PWRCTL,
- DDRCTRL_PWRCTL_SELFREF_SW);
-
-pstat_failed:
- setbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_PCTRL_0,
- DDRCTRL_PCTRL_N_PORT_EN);
- setbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_PCTRL_1,
- DDRCTRL_PCTRL_N_PORT_EN);
-
- return -EINVAL;
-};
-
-static void __secure ddr_sw_self_refresh_exit(void)
-{
- int ret;
-
- /* Enable all clocks */
- setbits_le32(STM32_RCC_BASE + RCC_DDRITFCR,
- RCC_DDRITFCR_DDRC1EN | RCC_DDRITFCR_DDRC2EN |
- RCC_DDRITFCR_DDRPHYCEN | RCC_DDRITFCR_DDRPHYCAPBEN |
- RCC_DDRITFCR_DDRCAPBEN);
-
- /* Handshake */
- clrbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_SWCTL, DDRCTRL_SWCTL_SW_DONE);
-
- /* Mask dfi_init_complete_en */
- clrbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_DFIMISC,
- DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
-
- /* Ack */
- setbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_SWCTL, DDRCTRL_SWCTL_SW_DONE);
- ret = secure_waitbits(STM32_DDRCTRL_BASE + DDRCTRL_SWSTAT,
- DDRCTRL_SWSTAT_SW_DONE_ACK,
- DDRCTRL_SWSTAT_SW_DONE_ACK);
- if (ret)
- hang();
-
- /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */
- setbits_le32(STM32_RCC_BASE + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL);
-
- /* Enable all DLLs: GLITCH window */
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ACDLLCR,
- DDRPHYC_ACDLLCR_DLLDIS);
-
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DX0DLLCR, DDRPHYC_DXNDLLCR_DLLDIS);
-
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DX1DLLCR, DDRPHYC_DXNDLLCR_DLLDIS);
-
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DX2DLLCR, DDRPHYC_DXNDLLCR_DLLDIS);
-
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DX3DLLCR, DDRPHYC_DXNDLLCR_DLLDIS);
-
- /* Additional delay to avoid early DLL clock switch */
- secure_udelay(50);
-
- /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */
- clrbits_le32(STM32_RCC_BASE + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL);
-
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ACDLLCR, DDRPHYC_ACDLLCR_DLLSRST);
-
- secure_udelay(10);
-
- setbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ACDLLCR, DDRPHYC_ACDLLCR_DLLSRST);
-
- /* PHY partial init: (DLL lock and ITM reset) */
- writel(DDRPHYC_PIR_DLLSRST | DDRPHYC_PIR_DLLLOCK |
- DDRPHYC_PIR_ITMSRST | DDRPHYC_PIR_INIT,
- STM32_DDRPHYC_BASE + DDRPHYC_PIR);
-
- /* Need to wait at least 10 clock cycles before accessing PGSR */
- secure_udelay(1);
-
- /* Pool end of init */
- ret = secure_waitbits(STM32_DDRPHYC_BASE + DDRPHYC_PGSR,
- DDRPHYC_PGSR_IDONE, DDRPHYC_PGSR_IDONE);
- if (ret)
- hang();
-
- /* Handshake */
- clrbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_SWCTL, DDRCTRL_SWCTL_SW_DONE);
-
- /* Unmask dfi_init_complete_en to uMCTL2 */
- setbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_DFIMISC, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
-
- /* Ack */
- setbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_SWCTL, DDRCTRL_SWCTL_SW_DONE);
- ret = secure_waitbits(STM32_DDRCTRL_BASE + DDRCTRL_SWSTAT,
- DDRCTRL_SWSTAT_SW_DONE_ACK,
- DDRCTRL_SWSTAT_SW_DONE_ACK);
- if (ret)
- hang();
-
- /* Deactivate sw retention in PWR */
- clrbits_le32(STM32_PWR_BASE + PWR_CR3, PWR_CR3_DDRRETEN);
-
- /* Enable PZQ cell (PUBL register) */
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ZQ0CR0, DDRPHYC_ZQ0CRN_ZQPD);
-
- /* Enable pad drivers */
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDD);
-
- /* Enable command/address output driver */
- setbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACOE);
-
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_CKPDD_MASK);
-
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_CSPDD_MASK);
-
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDD);
-
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR);
-
- /* Release latch */
- setbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DSGCR, DDRPHYC_DSGCR_CKOE);
-
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DSGCR, DDRPHYC_DSGCR_ODTPDD_MASK);
-
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DSGCR, DDRPHYC_DSGCR_NL2PD);
-
- clrbits_le32(STM32_DDRPHYC_BASE + DDRPHYC_DSGCR, DDRPHYC_DSGCR_CKEPDD_MASK);
-
- /* Remove selfrefresh */
- clrbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_PWRCTL, DDRCTRL_PWRCTL_SELFREF_SW);
-
- /* Wait operating_mode == normal */
- ret = secure_waitbits(STM32_DDRCTRL_BASE + DDRCTRL_STAT,
- DDRCTRL_STAT_OPERATING_MODE_MASK,
- DDRCTRL_STAT_OPERATING_MODE_NORMAL);
- if (ret)
- hang();
-
- /* AXI ports are no longer blocked from taking transactions */
- setbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_PCTRL_0, DDRCTRL_PCTRL_N_PORT_EN);
- setbits_le32(STM32_DDRCTRL_BASE + DDRCTRL_PCTRL_1, DDRCTRL_PCTRL_N_PORT_EN);
-
- setbits_le32(STM32_RCC_BASE + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN);
-}
-
-void __secure psci_system_suspend(u32 __always_unused function_id,
- u32 ep, u32 context_id)
-{
- u32 saved_mcudivr, saved_pll3cr, saved_pll4cr, saved_mssckselr;
- u32 gicd_addr = stm32mp_get_gicd_base_address();
- bool iwdg1_wake = false;
- bool iwdg2_wake = false;
- bool other_wake = false;
- u32 saved_pwrctl, reg;
- u32 gic_enabled[8];
- u32 irqs;
- int i;
-
- /* Cache enable mask of all 256 SPI */
- for (i = 0; i < ARRAY_SIZE(gic_enabled); i++)
- gic_enabled[i] = readl(gicd_addr + GICD_ISENABLERn + 0x4 + 4 * i);
-
- /* Disable IO compensation */
-
- /* Place current APSRC/ANSRC into RAPSRC/RANSRC */
- reg = readl(STM32_SYSCFG_BASE + SYSCFG_CMPCR);
- reg >>= 8;
- reg &= 0xff << 16;
- reg |= SYSCFG_CMPCR_SW_CTRL;
- writel(reg, STM32_SYSCFG_BASE + SYSCFG_CMPCR);
- writel(SYSCFG_CMPENR_MPUEN, STM32_SYSCFG_BASE + SYSCFG_CMPENCLRR);
-
- writel(RCC_MP_CIFR_WKUPF, STM32_RCC_BASE + RCC_MP_CIFR);
- setbits_le32(STM32_RCC_BASE + RCC_MP_CIER, RCC_MP_CIFR_WKUPF);
-
- setbits_le32(STM32_PWR_BASE + PWR_MPUCR,
- PWR_MPUCR_CSSF | PWR_MPUCR_CSTDBYDIS);
-
- saved_mcudivr = readl(STM32_RCC_BASE + RCC_MCUDIVR);
- saved_pll3cr = readl(STM32_RCC_BASE + RCC_PLL3CR);
- saved_pll4cr = readl(STM32_RCC_BASE + RCC_PLL4CR);
- saved_mssckselr = readl(STM32_RCC_BASE + RCC_MSSCKSELR);
-
- psci_v7_flush_dcache_all();
- ddr_sr_mode_ssr(&saved_pwrctl);
- ddr_sw_self_refresh_in();
- setbits_le32(STM32_PWR_BASE + PWR_CR3, PWR_CR3_DDRSREN);
- writel(0x3, STM32_RCC_BASE + RCC_MP_SREQSETR);
-
- /* Ping the IWDG before entering suspend */
- iwdg1_wake = !!(gic_enabled[4] & BIT(22)); /* SPI 150 */
- iwdg2_wake = !!(gic_enabled[4] & BIT(23)); /* SPI 151 */
-
- for (;;) {
- /* Ping IWDG1 and ACK pretimer IRQ */
- if (iwdg1_wake) {
- writel(IWDG_KR_RELOAD_KEY, STM32_IWDG1_BASE + IWDG_KR);
- writel(IWDG_EWCR_EWIC, STM32_IWDG1_BASE + IWDG_EWCR);
- }
-
- /* Ping IWDG2 and ACK pretimer IRQ */
- if (iwdg2_wake) {
- writel(IWDG_KR_RELOAD_KEY, STM32_IWDG2_BASE + IWDG_KR);
- writel(IWDG_EWCR_EWIC, STM32_IWDG2_BASE + IWDG_EWCR);
- }
-
- iwdg1_wake = false;
- iwdg2_wake = false;
-
- /* Zzz, enter stop mode */
- asm volatile(
- "isb\n"
- "dsb\n"
- "wfi\n");
-
- /* Determine the wake up source */
- for (i = 0; i < ARRAY_SIZE(gic_enabled); i++) {
- irqs = readl(gicd_addr + GICR_IGROUPMODRn + 0x4 + 4 * i);
- irqs &= gic_enabled[i];
- if (!irqs)
- continue;
-
- /* Test whether IWDG pretimeout triggered the wake up. */
- if (i == 4) { /* SPI Num 128..159 */
- iwdg1_wake = !!(irqs & BIT(22)); /* SPI 150 */
- iwdg2_wake = !!(irqs & BIT(23)); /* SPI 151 */
- irqs &= ~(BIT(22) | BIT(23));
- }
-
- /* Test whether there is any other wake up trigger. */
- if (irqs) {
- other_wake = true;
- break;
- }
- }
-
- /* Other wake up triggers pending, let OS deal with all of it. */
- if (other_wake)
- break;
- }
-
- writel(0x3, STM32_RCC_BASE + RCC_MP_SREQCLRR);
- ddr_sw_self_refresh_exit();
- ddr_sr_mode_restore(saved_pwrctl);
-
- writel(saved_mcudivr, STM32_RCC_BASE + RCC_MCUDIVR);
- writel(saved_pll3cr, STM32_RCC_BASE + RCC_PLL3CR);
- writel(saved_pll4cr, STM32_RCC_BASE + RCC_PLL4CR);
- writel(saved_mssckselr, STM32_RCC_BASE + RCC_MSSCKSELR);
-
- writel(SYSCFG_CMPENR_MPUEN, STM32_SYSCFG_BASE + SYSCFG_CMPENSETR);
- clrbits_le32(STM32_SYSCFG_BASE + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
-}