1 /*
2  * Copyright 2024 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/pm/device_runtime.h>
8 #include <zephyr/pm/device.h>
9 #include <zephyr/logging/log.h>
10 #include <main/ipc.h>
11 #include <svc/pm/pm_api.h>
12 #include <zephyr/dt-bindings/power/imx_scu_rsrc.h>
13 
14 LOG_MODULE_REGISTER(nxp_scu_pd);
15 
16 #define DT_DRV_COMPAT nxp_scu_pd
17 
18 struct scu_pd_data {
19 	sc_ipc_t handle;
20 	sc_rsrc_t rsrc;
21 };
22 
scu_pd_pm_action(const struct device * dev,enum pm_device_action action)23 static int scu_pd_pm_action(const struct device *dev,
24 			    enum pm_device_action action)
25 {
26 	int ret;
27 	sc_pm_power_mode_t mode;
28 	struct scu_pd_data *scu_data = dev->data;
29 
30 	LOG_DBG("attempting PM action %d on rsrc %d", action, scu_data->rsrc);
31 
32 	switch (action) {
33 	case PM_DEVICE_ACTION_RESUME:
34 		mode = SC_PM_PW_MODE_ON;
35 		break;
36 	case PM_DEVICE_ACTION_SUSPEND:
37 		mode = SC_PM_PW_MODE_OFF;
38 		break;
39 	case PM_DEVICE_ACTION_TURN_ON:
40 	case PM_DEVICE_ACTION_TURN_OFF:
41 		return 0;
42 	default:
43 		return -ENOTSUP;
44 	}
45 
46 	ret = sc_pm_set_resource_power_mode(scu_data->handle,
47 					    scu_data->rsrc,
48 					    mode);
49 	if (ret != SC_ERR_NONE) {
50 		LOG_ERR("failed to set rsrc %d power mode to %d",
51 			scu_data->rsrc, mode);
52 		return -EIO;
53 	}
54 
55 	return 0;
56 }
57 
scu_pd_init(const struct device * dev)58 static int scu_pd_init(const struct device *dev)
59 {
60 	int ret;
61 	struct scu_pd_data *scu_data = dev->data;
62 
63 	ret = sc_ipc_open(&scu_data->handle, DT_REG_ADDR(DT_NODELABEL(scu_mu)));
64 	if (ret != SC_ERR_NONE) {
65 		return -ENODEV;
66 	}
67 
68 	return pm_device_runtime_enable(dev);
69 }
70 
71 
72 #define SCU_PD_DEVICE_DEFINE(inst)					\
73 									\
74 BUILD_ASSERT(DT_INST_PROP(inst, nxp_resource_id) < IMX_SC_R_LAST,	\
75 	     "invalid resource ID");					\
76 									\
77 static struct scu_pd_data scu_pd_data_##inst = {			\
78 	.rsrc = DT_INST_PROP(inst, nxp_resource_id),			\
79 };									\
80 									\
81 PM_DEVICE_DT_INST_DEFINE(inst, scu_pd_pm_action);			\
82 									\
83 DEVICE_DT_INST_DEFINE(inst, scu_pd_init, PM_DEVICE_DT_INST_GET(inst),	\
84 		      &scu_pd_data_##inst, NULL, PRE_KERNEL_1,		\
85 		      CONFIG_POWER_DOMAIN_NXP_SCU_INIT_PRIORITY,	\
86 		      NULL);
87 
88 DT_INST_FOREACH_STATUS_OKAY(SCU_PD_DEVICE_DEFINE);
89