1*4249a4fbSJacky Bai /* 2*4249a4fbSJacky Bai * Copyright 2024-2025 NXP 3*4249a4fbSJacky Bai * 4*4249a4fbSJacky Bai * SPDX-License-Identifier: BSD-3-Clause 5*4249a4fbSJacky Bai */ 6*4249a4fbSJacky Bai 7*4249a4fbSJacky Bai #include <lib/psci/psci.h> 8*4249a4fbSJacky Bai #include <scmi_imx9.h> 9*4249a4fbSJacky Bai 10*4249a4fbSJacky Bai #include <imx9_psci_common.h> 11*4249a4fbSJacky Bai #include <imx9_sys_sleep.h> 12*4249a4fbSJacky Bai #include <imx_scmi_client.h> 13*4249a4fbSJacky Bai #include <plat_imx8.h> 14*4249a4fbSJacky Bai 15*4249a4fbSJacky Bai uint32_t mask_all[IMR_NUM] = { 16*4249a4fbSJacky Bai 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 17*4249a4fbSJacky Bai 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 18*4249a4fbSJacky Bai 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 19*4249a4fbSJacky Bai 0xffffffff, 0xffffffff, 0xffffffff 20*4249a4fbSJacky Bai }; 21*4249a4fbSJacky Bai 22*4249a4fbSJacky Bai /* 23*4249a4fbSJacky Bai * IRQ masks used to check if any of the below IRQ is 24*4249a4fbSJacky Bai * enabled as the wakeup source: 25*4249a4fbSJacky Bai * lpuart1: 21, flexcan2-5: 40, 42, 44, 46, usdhc1-3: 96, 97, 116 26*4249a4fbSJacky Bai */ 27*4249a4fbSJacky Bai uint32_t wakeup_irq_mask[IMR_NUM] = { 28*4249a4fbSJacky Bai 0x600000, 0x5500, 0xFFC0, 0x100003, 0x0, 0x0, 0x0, 0x0, 29*4249a4fbSJacky Bai 0x0, 0x0, 0x0, 0x80 30*4249a4fbSJacky Bai }; 31*4249a4fbSJacky Bai 32*4249a4fbSJacky Bai struct per_hsk_cfg per_hsk_cfg[] = { 33*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_CAN2, 40U }, 34*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_CAN3, 42U }, 35*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_CAN4, 44U }, 36*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_CAN5, 46U }, 37*4249a4fbSJacky Bai 38*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_LPUART1, 21U }, 39*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_LPUART2, 22U }, 40*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_LPUART3, 74U }, 41*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_LPUART4, 75U }, 42*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_LPUART5, 76U }, 43*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_LPUART6, 77U }, 44*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_LPUART7, 78U }, 45*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_LPUART8, 79U }, 46*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_LPUART9, 80U }, 47*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_LPUART10, 81U }, 48*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_LPUART11, 82U }, 49*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_LPUART12, 83U }, 50*4249a4fbSJacky Bai 51*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_GPIO2, 54U }, 52*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_GPIO3, 56U }, 53*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_GPIO4, 58U }, 54*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_GPIO5, 60U }, 55*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_GPIO6, 62U }, 56*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_GPIO7, 64U }, 57*4249a4fbSJacky Bai }; 58*4249a4fbSJacky Bai 59*4249a4fbSJacky Bai struct gpio_ctx gpios[GPIO_NUM] = { 60*4249a4fbSJacky Bai GPIO_CTX(GPIO2_BASE, 32U), 61*4249a4fbSJacky Bai GPIO_CTX(GPIO3_BASE, 26U), 62*4249a4fbSJacky Bai GPIO_CTX(GPIO4_BASE, 32U), 63*4249a4fbSJacky Bai GPIO_CTX(GPIO5_BASE, 32U), 64*4249a4fbSJacky Bai GPIO_CTX(GPIO6_BASE, 32U), 65*4249a4fbSJacky Bai GPIO_CTX(GPIO7_BASE, 22U), 66*4249a4fbSJacky Bai }; 67*4249a4fbSJacky Bai 68*4249a4fbSJacky Bai struct wdog_ctx wdogs[WDOG_NUM] = { 69*4249a4fbSJacky Bai { WDOG3_BASE }, 70*4249a4fbSJacky Bai { WDOG4_BASE }, 71*4249a4fbSJacky Bai }; 72*4249a4fbSJacky Bai 73*4249a4fbSJacky Bai static const plat_psci_ops_t imx_plat_psci_ops = { 74*4249a4fbSJacky Bai .validate_ns_entrypoint = imx_validate_ns_entrypoint, 75*4249a4fbSJacky Bai .validate_power_state = imx_validate_power_state, 76*4249a4fbSJacky Bai .pwr_domain_on = imx_pwr_domain_on, 77*4249a4fbSJacky Bai .pwr_domain_off = imx_pwr_domain_off, 78*4249a4fbSJacky Bai .pwr_domain_on_finish = imx_pwr_domain_on_finish, 79*4249a4fbSJacky Bai .pwr_domain_suspend = imx_pwr_domain_suspend, 80*4249a4fbSJacky Bai .pwr_domain_suspend_finish = imx_pwr_domain_suspend_finish, 81*4249a4fbSJacky Bai .get_sys_suspend_power_state = imx_get_sys_suspend_power_state, 82*4249a4fbSJacky Bai .pwr_domain_pwr_down = imx_pwr_domain_pwr_down, 83*4249a4fbSJacky Bai .system_reset = imx_system_reset, 84*4249a4fbSJacky Bai .system_off = imx_system_off, 85*4249a4fbSJacky Bai }; 86*4249a4fbSJacky Bai 87*4249a4fbSJacky Bai /* Export the platform specific psci ops */ 88*4249a4fbSJacky Bai int plat_setup_psci_ops(uintptr_t sec_entrypoint, 89*4249a4fbSJacky Bai const plat_psci_ops_t **psci_ops) 90*4249a4fbSJacky Bai { 91*4249a4fbSJacky Bai uint32_t mask = DEBUG_WAKEUP_MASK | EVENT_WAKEUP_MASK; 92*4249a4fbSJacky Bai 93*4249a4fbSJacky Bai /* sec_entrypoint is used for warm reset */ 94*4249a4fbSJacky Bai secure_entrypoint = sec_entrypoint; 95*4249a4fbSJacky Bai imx_set_cpu_boot_entry(0U, secure_entrypoint, SCMI_CPU_VEC_FLAGS_BOOT); 96*4249a4fbSJacky Bai 97*4249a4fbSJacky Bai /* 98*4249a4fbSJacky Bai * Set NON-IRQ wakeup mask for both last core and cluster. 99*4249a4fbSJacky Bai * Disable wakeup on DEBUG_WAKEUP 100*4249a4fbSJacky Bai */ 101*4249a4fbSJacky Bai scmi_core_nonIrq_wake_set(imx9_scmi_handle, IMX9_SCMI_CPU_A55C0, 0U, 1U, mask); 102*4249a4fbSJacky Bai scmi_core_nonIrq_wake_set(imx9_scmi_handle, IMX9_SCMI_CPU_A55P, 0U, 1U, mask); 103*4249a4fbSJacky Bai 104*4249a4fbSJacky Bai /* 105*4249a4fbSJacky Bai * Setup A55 Cluster state for Cpuidle. 106*4249a4fbSJacky Bai */ 107*4249a4fbSJacky Bai struct scmi_lpm_config cpu_lpm_cfg[] = { 108*4249a4fbSJacky Bai { 109*4249a4fbSJacky Bai SCMI_PWR_MIX_SLICE_IDX_A55P, 110*4249a4fbSJacky Bai SCMI_CPU_PD_LPM_ON_RUN, 111*4249a4fbSJacky Bai BIT_32(SCMI_PWR_MEM_SLICE_IDX_A55L3) 112*4249a4fbSJacky Bai }, 113*4249a4fbSJacky Bai { 114*4249a4fbSJacky Bai SCMI_PWR_MIX_SLICE_IDX_NOC, 115*4249a4fbSJacky Bai SCMI_CPU_PD_LPM_ON_ALWAYS, 116*4249a4fbSJacky Bai 0U 117*4249a4fbSJacky Bai }, 118*4249a4fbSJacky Bai { 119*4249a4fbSJacky Bai SCMI_PWR_MIX_SLICE_IDX_WAKEUP, 120*4249a4fbSJacky Bai SCMI_CPU_PD_LPM_ON_ALWAYS, 121*4249a4fbSJacky Bai 0U 122*4249a4fbSJacky Bai } 123*4249a4fbSJacky Bai }; 124*4249a4fbSJacky Bai 125*4249a4fbSJacky Bai /* Set the default LPM state for suspend/hotplug */ 126*4249a4fbSJacky Bai scmi_core_lpm_mode_set(imx9_scmi_handle, 127*4249a4fbSJacky Bai IMX9_SCMI_CPU_A55P, 128*4249a4fbSJacky Bai ARRAY_SIZE(cpu_lpm_cfg), 129*4249a4fbSJacky Bai cpu_lpm_cfg); 130*4249a4fbSJacky Bai 131*4249a4fbSJacky Bai /* Set the LPM state for cpuidle for A55C0 (boot core) */ 132*4249a4fbSJacky Bai cpu_lpm_cfg[0].power_domain = SCMI_PWR_MIX_SLICE_IDX_A55C0; 133*4249a4fbSJacky Bai cpu_lpm_cfg[0].lpmsetting = SCMI_CPU_PD_LPM_ON_RUN; 134*4249a4fbSJacky Bai cpu_lpm_cfg[0].retentionmask = 0U; 135*4249a4fbSJacky Bai scmi_core_lpm_mode_set(imx9_scmi_handle, IMX9_SCMI_CPU_A55C0, 136*4249a4fbSJacky Bai 1U, cpu_lpm_cfg); 137*4249a4fbSJacky Bai 138*4249a4fbSJacky Bai /* 139*4249a4fbSJacky Bai * Set core/custer to GIC wakeup source since NOCMIX is not 140*4249a4fbSJacky Bai * powered down, config the target mode to WAIT 141*4249a4fbSJacky Bai */ 142*4249a4fbSJacky Bai scmi_core_set_sleep_mode(imx9_scmi_handle, IMX9_SCMI_CPU_A55C0, 143*4249a4fbSJacky Bai SCMI_GIC_WAKEUP, SCMI_CPU_SLEEP_WAIT); 144*4249a4fbSJacky Bai 145*4249a4fbSJacky Bai scmi_core_set_sleep_mode(imx9_scmi_handle, IMX9_SCMI_CPU_A55P, 146*4249a4fbSJacky Bai SCMI_GIC_WAKEUP, SCMI_CPU_SLEEP_WAIT); 147*4249a4fbSJacky Bai 148*4249a4fbSJacky Bai /* Enable the wdog3 per handshake */ 149*4249a4fbSJacky Bai struct scmi_per_lpm_config per_lpm[1] = { 150*4249a4fbSJacky Bai { CPU_PER_LPI_IDX_WDOG3, SCMI_CPU_PD_LPM_ON_RUN_WAIT_STOP }, 151*4249a4fbSJacky Bai }; 152*4249a4fbSJacky Bai 153*4249a4fbSJacky Bai scmi_per_lpm_mode_set(imx9_scmi_handle, IMX9_SCMI_CPU_A55P, 154*4249a4fbSJacky Bai 1U, per_lpm); 155*4249a4fbSJacky Bai 156*4249a4fbSJacky Bai *psci_ops = &imx_plat_psci_ops; 157*4249a4fbSJacky Bai 158*4249a4fbSJacky Bai return 0; 159*4249a4fbSJacky Bai } 160