diff --git a/drivers/power_domain/CMakeLists.txt b/drivers/power_domain/CMakeLists.txt index 27b07c945f1..dedd7a50dff 100644 --- a/drivers/power_domain/CMakeLists.txt +++ b/drivers/power_domain/CMakeLists.txt @@ -6,3 +6,4 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_GPIO power_domain_gpio.c) zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_GPIO_MONITOR power_domain_gpio_monitor.c) zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_INTEL_ADSP power_domain_intel_adsp.c) +zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_NXP_SCU power_domain_nxp_scu.c) diff --git a/drivers/power_domain/Kconfig b/drivers/power_domain/Kconfig index 647d7036679..f29057acf5c 100644 --- a/drivers/power_domain/Kconfig +++ b/drivers/power_domain/Kconfig @@ -73,4 +73,21 @@ config POWER_DOMAIN_GPIO_MONITOR_INIT_PRIORITY endif #POWER_DOMAIN_GPIO_MONITOR +config POWER_DOMAIN_NXP_SCU + bool "NXP SCU-managed PD driver" + default y + depends on DT_HAS_NXP_SCU_PD_ENABLED + help + Enable support for NXPs SCU-managed power domain driver. + +if POWER_DOMAIN_NXP_SCU + +config POWER_DOMAIN_NXP_SCU_INIT_PRIORITY + int "NXP SCU-managed PD driver init priority" + default 10 + help + NXP SCU-managed PD driver initialization priority. + +endif #POWER_DOMAIN_NXP_SCU + endif diff --git a/drivers/power_domain/power_domain_nxp_scu.c b/drivers/power_domain/power_domain_nxp_scu.c new file mode 100644 index 00000000000..2ed162359fd --- /dev/null +++ b/drivers/power_domain/power_domain_nxp_scu.c @@ -0,0 +1,88 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include
+#include +#include + +LOG_MODULE_REGISTER(nxp_scu_pd); + +#define DT_DRV_COMPAT nxp_scu_pd + +struct scu_pd_data { + sc_ipc_t handle; + sc_rsrc_t rsrc; +}; + +static int scu_pd_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret; + sc_pm_power_mode_t mode; + struct scu_pd_data *scu_data = dev->data; + + LOG_DBG("attempting PM action %d on rsrc %d", action, scu_data->rsrc); + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + mode = SC_PM_PW_MODE_ON; + break; + case PM_DEVICE_ACTION_SUSPEND: + mode = SC_PM_PW_MODE_OFF; + break; + case PM_DEVICE_ACTION_TURN_ON: + case PM_DEVICE_ACTION_TURN_OFF: + return 0; + default: + return -ENOTSUP; + } + + ret = sc_pm_set_resource_power_mode(scu_data->handle, + scu_data->rsrc, + mode); + if (ret != SC_ERR_NONE) { + LOG_ERR("failed to set rsrc %d power mode to %d", + scu_data->rsrc, mode); + return -EIO; + } + + return 0; +} + +static int scu_pd_init(const struct device *dev) +{ + int ret; + struct scu_pd_data *scu_data = dev->data; + + ret = sc_ipc_open(&scu_data->handle, DT_REG_ADDR(DT_NODELABEL(scu_mu))); + if (ret != SC_ERR_NONE) { + return -ENODEV; + } + + return pm_device_runtime_enable(dev); +} + + +#define SCU_PD_DEVICE_DEFINE(inst) \ + \ +BUILD_ASSERT(DT_INST_PROP(inst, nxp_resource_id) < IMX_SC_R_LAST, \ + "invalid resource ID"); \ + \ +static struct scu_pd_data scu_pd_data_##inst = { \ + .rsrc = DT_INST_PROP(inst, nxp_resource_id), \ +}; \ + \ +PM_DEVICE_DT_INST_DEFINE(inst, scu_pd_pm_action); \ + \ +DEVICE_DT_INST_DEFINE(inst, scu_pd_init, PM_DEVICE_DT_INST_GET(inst), \ + &scu_pd_data_##inst, NULL, PRE_KERNEL_1, \ + CONFIG_POWER_DOMAIN_NXP_SCU_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(SCU_PD_DEVICE_DEFINE);