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