feat(mediatek): add new features of LPM
Add new functions and intefaces of LPM to support more interactions
between LPM providers and users.
Change-Id: I8ebbda0c0ef5be3a7a388a38c09424ebf785996f
diff --git a/plat/mediatek/common/lpm/mt_lp_api.c b/plat/mediatek/common/lpm/mt_lp_api.c
new file mode 100644
index 0000000..2a1da6a
--- /dev/null
+++ b/plat/mediatek/common/lpm/mt_lp_api.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lpm/mt_lp_api.h>
+
+int mt_audio_update(int type)
+{
+ int ret, val;
+
+ switch (type) {
+ case AUDIO_AFE_ENTER:
+ case AUDIO_AFE_LEAVE:
+ val = (type == AUDIO_AFE_ENTER) ? 1 : 0;
+ ret = mt_lp_rm_do_update(-1, PLAT_RC_IS_FMAUDIO, &val);
+ break;
+ case AUDIO_DSP_ENTER:
+ case AUDIO_DSP_LEAVE:
+ val = (type == AUDIO_DSP_ENTER) ? 1 : 0;
+ ret = mt_lp_rm_do_update(-1, PLAT_RC_IS_ADSP, &val);
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
+int mtk_usb_update(int type)
+{
+ int ret, val;
+
+ switch (type) {
+ case LPM_USB_ENTER:
+ case LPM_USB_LEAVE:
+ val = (type == LPM_USB_ENTER) ? 1 : 0;
+ ret = mt_lp_rm_do_update(-1, PLAT_RC_IS_USB_INFRA, &val);
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
diff --git a/plat/mediatek/common/lpm/mt_lp_rm.c b/plat/mediatek/common/lpm/mt_lp_rm.c
index 0bafc66..807614a 100644
--- a/plat/mediatek/common/lpm/mt_lp_rm.c
+++ b/plat/mediatek/common/lpm/mt_lp_rm.c
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2020-2023, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
-#include <mt_lp_rm.h>
#include <stddef.h>
+#include <lpm/mt_lp_rm.h>
struct platform_mt_resource_manager {
unsigned int count;
@@ -54,6 +54,29 @@
return rc->reset(cpuid, stateid);
}
+int mt_lp_rm_get_status(unsigned int type, void *priv)
+{
+ int res = 0;
+ struct mt_resource_constraint *const *con;
+ struct mt_resource_manager *rm = plat_mt_rm.plat_rm;
+
+ if ((rm == NULL) || (type >= PLAT_RC_MAX)) {
+ return -1;
+ }
+
+ for (con = rm->consts; *con != NULL; con++) {
+ if ((*con)->get_status == NULL) {
+ continue;
+ }
+ res = (*con)->get_status(type, priv);
+ if (res == MT_RM_STATUS_STOP) {
+ break;
+ }
+ }
+
+ return res;
+}
+
int mt_lp_rm_find_and_run_constraint(int idx, unsigned int cpuid,
int stateid, void *priv)
{
diff --git a/plat/mediatek/common/lpm/mt_lp_rm.h b/plat/mediatek/common/lpm/mt_lp_rm.h
index e93dac3..bda3ba1 100644
--- a/plat/mediatek/common/lpm/mt_lp_rm.h
+++ b/plat/mediatek/common/lpm/mt_lp_rm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2020-2023, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,14 +9,34 @@
#include <stdbool.h>
-#define MT_RM_STATUS_OK 0
-#define MT_RM_STATUS_BAD -1
+#define MT_RM_STATUS_OK (0)
+#define MT_RM_STATUS_BAD (-1)
+#define MT_RM_STATUS_STOP (-2)
enum PLAT_MT_LPM_RC_TYPE {
PLAT_RC_UPDATE_CONDITION,
- PLAT_RC_UPDATE_REMAIN_IRQS
+ PLAT_RC_STATUS,
+ PLAT_RC_UPDATE_REMAIN_IRQS,
+ PLAT_RC_IS_FMAUDIO,
+ PLAT_RC_IS_ADSP,
+ PLAT_RC_ENTER_CNT,
+ PLAT_RC_CLKBUF_STATUS,
+ PLAT_RC_UFS_STATUS,
+ PLAT_RC_IS_USB_PERI,
+ PLAT_RC_IS_USB_INFRA,
+ PLAT_RC_MAX,
};
+enum plat_mt_lpm_hw_ctrl_type {
+ PLAT_AP_MDSRC_REQ,
+ PLAT_AP_MDSRC_ACK,
+ PLAT_AP_IS_MD_SLEEP,
+ PLAT_AP_MDSRC_SETTLE,
+ PLAT_AP_GPUEB_PLL_CONTROL,
+ PLAT_AP_GPUEB_GET_PWR_STATUS,
+ PLAT_AP_HW_CTRL_MAX,
+};
+
struct mt_resource_constraint {
int level;
int (*init)(void);
@@ -24,6 +44,7 @@
int (*update)(int stateid, int type, const void *p);
int (*run)(unsigned int cpu, int stateid);
int (*reset)(unsigned int cpu, int stateid);
+ int (*get_status)(unsigned int type, void *priv);
unsigned int (*allow)(int stateid);
};
@@ -39,4 +60,6 @@
extern int mt_lp_rm_reset_constraint(int constraint_id, unsigned int cpuid,
int stateid);
extern int mt_lp_rm_do_update(int stateid, int type, void const *p);
+extern int mt_lp_rm_get_status(unsigned int type, void *priv);
+
#endif /* MT_LP_RM_H */
diff --git a/plat/mediatek/common/lpm/mt_lp_rq.c b/plat/mediatek/common/lpm/mt_lp_rq.c
new file mode 100644
index 0000000..7b83fed
--- /dev/null
+++ b/plat/mediatek/common/lpm/mt_lp_rq.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/spinlock.h>
+#include <lpm/mt_lp_rqm.h>
+
+struct mt_lp_res_req_m {
+ unsigned int uname[MT_LP_RQ_USER_MAX];
+ unsigned int user_num;
+ unsigned int user_valid;
+ unsigned int resource_num;
+ unsigned int generic_resource_req;
+ unsigned int flag;
+ struct mt_resource_req_manager *plat_rqm;
+};
+
+static struct mt_lp_res_req_m plat_mt_rqm;
+static spinlock_t mt_lp_rq_lock;
+
+static int mt_lp_resource_request(struct mt_lp_resource_user *this, unsigned int resource)
+{
+ int i;
+ struct mt_lp_res_req *const *rs;
+
+ if ((this == NULL) || (resource == 0) || (resource > MT_LP_RQ_ALL)) {
+ ERROR("invalid request(%x)\n", resource);
+ return MT_LP_RQ_STA_BAD;
+ }
+
+ spin_lock(&mt_lp_rq_lock);
+
+ rs = (plat_mt_rqm.plat_rqm)->res;
+ for (i = 0; i < plat_mt_rqm.resource_num; i++) {
+ if ((resource & rs[i]->res_id) != 0) {
+ rs[i]->res_usage |= this->umask;
+ }
+ }
+
+ plat_mt_rqm.flag = MT_LP_RQ_FLAG_NEED_UPDATE;
+ spin_unlock(&mt_lp_rq_lock);
+
+ return MT_LP_RQ_STA_OK;
+}
+
+static int mt_lp_resource_release(struct mt_lp_resource_user *this)
+{
+ int i;
+ struct mt_lp_res_req *const *rs;
+
+ if (this == NULL) {
+ return MT_LP_RQ_STA_BAD;
+ }
+
+ spin_lock(&mt_lp_rq_lock);
+
+ rs = (plat_mt_rqm.plat_rqm)->res;
+ for (i = 0; i < plat_mt_rqm.resource_num; i++) {
+ rs[i]->res_usage &= ~(this->umask);
+ }
+
+ plat_mt_rqm.flag = MT_LP_RQ_FLAG_NEED_UPDATE;
+ spin_unlock(&mt_lp_rq_lock);
+
+ return MT_LP_RQ_STA_OK;
+}
+
+int mt_lp_resource_request_manager_register(struct mt_resource_req_manager *rqm)
+{
+ unsigned int count;
+ struct mt_lp_res_req *const *rs;
+
+ if ((rqm == NULL) || (rqm->res == NULL) || (plat_mt_rqm.plat_rqm != NULL)) {
+ return MT_LP_RQ_STA_BAD;
+ }
+
+ rs = rqm->res;
+ count = 0;
+ while (*rs != NULL) {
+ count++;
+ rs++;
+ }
+
+ plat_mt_rqm.plat_rqm = rqm;
+ plat_mt_rqm.resource_num = count;
+
+ return MT_LP_RQ_STA_OK;
+}
+
+int mt_lp_resource_user_register(char *user, struct mt_lp_resource_user *ru)
+{
+ int i, len;
+ unsigned int uname;
+
+ if ((plat_mt_rqm.plat_rqm == NULL) || (plat_mt_rqm.user_num >= MT_LP_RQ_USER_MAX) ||
+ (user == NULL)) {
+ ru->uid = MT_LP_RQ_USER_INVALID;
+ ru->umask = 0;
+ ru->request = NULL;
+ ru->release = NULL;
+ ERROR("rqm register user invalid\n");
+ return MT_LP_RQ_STA_BAD;
+ }
+
+ len = strnlen(user, MT_LP_RQ_USER_NAME_LEN);
+
+ uname = 0;
+ for (i = 0; i < len; i++) {
+ uname |= (user[i] << (MT_LP_RQ_USER_CHAR_U * i));
+ }
+
+ spin_lock(&mt_lp_rq_lock);
+ i = plat_mt_rqm.user_num;
+ plat_mt_rqm.user_num += 1;
+ plat_mt_rqm.uname[i] = uname;
+ plat_mt_rqm.user_valid |= BIT(i);
+ spin_unlock(&mt_lp_rq_lock);
+
+ ru->umask = BIT(i);
+ ru->uid = i;
+ ru->request = mt_lp_resource_request;
+ ru->release = mt_lp_resource_release;
+ INFO("%s register by %s, uid = %d\n", __func__, user, ru->uid);
+
+ return MT_LP_RQ_STA_OK;
+}
+
+int mt_lp_rq_get_status(int type, void *p)
+{
+ int i;
+ unsigned int update_sta;
+ struct mt_lp_res_req *const *rs;
+ struct resource_req_status *rq_sta = (struct resource_req_status *)p;
+
+ if (plat_mt_rqm.flag != 0) {
+ spin_lock(&mt_lp_rq_lock);
+
+ update_sta = 0;
+ rs = (plat_mt_rqm.plat_rqm)->res;
+ for (i = 0; i < plat_mt_rqm.resource_num; i++) {
+ update_sta |= ((rs[i]->res_usage & plat_mt_rqm.user_valid) != 0) ?
+ rs[i]->res_rq : 0;
+ }
+
+ plat_mt_rqm.generic_resource_req = update_sta;
+ plat_mt_rqm.flag = MT_LP_RQ_FLAG_DONE;
+ spin_unlock(&mt_lp_rq_lock);
+ }
+
+ switch (type) {
+ case PLAT_RQ_REQ_USAGE:
+ rs = (plat_mt_rqm.plat_rqm)->res;
+ rq_sta->val = (rq_sta->id < plat_mt_rqm.resource_num) ?
+ rs[rq_sta->id]->res_usage : plat_mt_rqm.generic_resource_req;
+ break;
+ case PLAT_RQ_USER_NUM:
+ rq_sta->val = plat_mt_rqm.user_num;
+ break;
+ case PLAT_RQ_USER_VALID:
+ rq_sta->val = plat_mt_rqm.user_valid;
+ break;
+ case PLAT_RQ_PER_USER_NAME:
+ rq_sta->val = (rq_sta->id < plat_mt_rqm.user_num) ?
+ plat_mt_rqm.uname[rq_sta->id] : 0;
+ break;
+ case PLAT_RQ_REQ_NUM:
+ rq_sta->val = plat_mt_rqm.resource_num;
+ break;
+ default:
+ break;
+ }
+
+ return MT_LP_RQ_STA_OK;
+}
+
+int mt_lp_rq_update_status(int type, void *p)
+{
+ unsigned int user_mask;
+ struct resource_req_status *rq_sta = (struct resource_req_status *)p;
+
+ switch (type) {
+ case PLAT_RQ_USER_VALID:
+ if (rq_sta->id < plat_mt_rqm.user_num) {
+ user_mask = BIT(rq_sta->id);
+ spin_lock(&mt_lp_rq_lock);
+ plat_mt_rqm.user_valid = (rq_sta->val == 0) ?
+ (plat_mt_rqm.user_valid & ~(user_mask)) :
+ (plat_mt_rqm.user_valid | user_mask);
+ plat_mt_rqm.flag = MT_LP_RQ_FLAG_NEED_UPDATE;
+ spin_unlock(&mt_lp_rq_lock);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return MT_LP_RQ_STA_OK;
+}
diff --git a/plat/mediatek/common/lpm/rules.mk b/plat/mediatek/common/lpm/rules.mk
index 87a212a..eb68e03 100644
--- a/plat/mediatek/common/lpm/rules.mk
+++ b/plat/mediatek/common/lpm/rules.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+# Copyright (c) 2023, MediaTek Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -7,7 +7,10 @@
LOCAL_DIR := $(call GET_LOCAL_DIR)
MODULE := lpm
-LOCAL_SRCS-y := $(LOCAL_DIR)/mt_lp_rm.c
+
+LOCAL_SRCS-y := $(LOCAL_DIR)/mt_lp_api.c
+LOCAL_SRCS-y += $(LOCAL_DIR)/mt_lp_rm.c
+LOCAL_SRCS-y += $(LOCAL_DIR)/mt_lp_rq.c
PLAT_INCLUDES += -I${LOCAL_DIR}
diff --git a/plat/mediatek/include/lpm/mt_lp_api.h b/plat/mediatek/include/lpm/mt_lp_api.h
new file mode 100644
index 0000000..00a2802
--- /dev/null
+++ b/plat/mediatek/include/lpm/mt_lp_api.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_LP_API_H
+#define MT_LP_API_H
+
+#include <lpm/mt_lp_rm.h>
+
+#if MTK_PUBEVENT_ENABLE
+#include <vendor_pubsub_events.h>
+#endif
+
+/* Ufs clk enum for PLAT_RC_CLKBUF_STATUS */
+enum rc_update_ex_ufs_ref_clk {
+ UFS_REF_CLK_OFF = 0,
+ UFS_REF_CLK_ON,
+};
+
+/* Enum for flight mode */
+enum rc_update_ex_flight_mode {
+ FLIGHT_MODE_OFF = 0,
+ FLIGHT_MODE_ON,
+};
+
+struct mt_lpm_pubevent_data {
+ unsigned int u32;
+};
+
+enum mt_lpm_pubevents_id {
+ MT_LPM_PUBEVENTS_BBLPM_ENTER,
+ MT_LPM_PUBEVENTS_BBLPM_LEAVE,
+ MT_LPM_PUBEVENTS_TARGET_CORE,
+ MT_LPM_PUBEVENTS_SYS_POWER_OFF,
+ MT_LPM_PUBEVENTS_SYS_POWER_ON,
+};
+
+struct mt_lp_publish_event {
+ unsigned int id;
+ struct mt_lpm_pubevent_data val;
+};
+
+#if MTK_PUBEVENT_ENABLE
+#define MT_LP_PUBLISH_EVENT(x) ({\
+ PUBLISH_EVENT_ARG(lpm_publish_event, (const void *)(x)); })
+#define MT_LP_SUSPEND_PUBLISH_EVENT(x) ({\
+ PUBLISH_EVENT_ARG(suspend_publish_event, (const void *)(x)); })
+
+#define MT_LP_SUBSCRIBE_SUSPEND(func) SUBSCRIBE_TO_EVENT(suspend_publish_event, func)
+#define MT_LP_SUBSCRIBE_LPM(func) SUBSCRIBE_TO_EVENT(lpm_publish_event, func)
+#else
+#define MT_LP_PUBLISH_EVENT(x) ({ (void)x; })
+#define MT_LP_SUSPEND_PUBLISH_EVENT(x) ({ (void)x; })
+#define MT_LP_SUBSCRIBE_SUSPEND(func)
+#define MT_LP_SUBSCRIBE_LPM(func)
+#endif
+
+/* MTK low power API types for audio */
+enum mt_lp_api_audio_type {
+ AUDIO_AFE_ENTER,
+ AUDIO_AFE_LEAVE,
+ AUDIO_DSP_ENTER,
+ AUDIO_DSP_LEAVE,
+};
+
+/* MTK low power API types for usb */
+enum mt_lp_api_usb_type {
+ LPM_USB_ENTER,
+ LPM_USB_LEAVE,
+};
+
+int mt_audio_update(int type);
+int mtk_usb_update(int type);
+
+#endif /* MT_LP_API_H */
diff --git a/plat/mediatek/include/lpm/mt_lp_rq.h b/plat/mediatek/include/lpm/mt_lp_rq.h
new file mode 100644
index 0000000..2c4908c
--- /dev/null
+++ b/plat/mediatek/include/lpm/mt_lp_rq.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_LP_RQ_H
+#define MT_LP_RQ_H
+
+/* Determine the generic resource request public type */
+#define MT_LP_RQ_XO_FPM BIT(0)
+#define MT_LP_RQ_26M BIT(1)
+#define MT_LP_RQ_INFRA BIT(2)
+#define MT_LP_RQ_SYSPLL BIT(3)
+#define MT_LP_RQ_DRAM BIT(4)
+#define MT_LP_RQ_ALL (0xFFFFFFFF)
+
+struct mt_lp_resource_user {
+ /* Determine the resource user mask */
+ unsigned int umask;
+ /* Determine the resource request user identify */
+ unsigned int uid;
+ /* Request the resource */
+ int (*request)(struct mt_lp_resource_user *this, unsigned int resource);
+ /* Release the resource */
+ int (*release)(struct mt_lp_resource_user *this);
+};
+
+int mt_lp_resource_user_register(char *uname, struct mt_lp_resource_user *ru);
+
+#endif /* MT_LP_RQ_H */
diff --git a/plat/mediatek/include/lpm/mt_lp_rqm.h b/plat/mediatek/include/lpm/mt_lp_rqm.h
new file mode 100644
index 0000000..c30f762
--- /dev/null
+++ b/plat/mediatek/include/lpm/mt_lp_rqm.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_LP_RQM_H
+#define MT_LP_RQM_H
+
+#include "mt_lp_rq.h"
+
+enum plat_mt_lpm_rq_update_type {
+ PLAT_RQ_USER_NUM,
+ PLAT_RQ_USER_VALID,
+ PLAT_RQ_USER_REQ,
+ PLAT_RQ_USER_REL,
+ PLAT_RQ_PER_USER_NAME,
+ PLAT_RQ_REQ_NUM,
+ PLAT_RQ_REQ_USAGE,
+};
+
+/* Determine the request valid */
+#define MT_LP_RQ_VALID (0x1)
+#define MT_LP_RQ_INVALID (0x0)
+
+/* Determine the request user opertions */
+#define MT_LP_RQ_USER_INVALID (-1)
+#define MT_LP_RQ_USER_MAX (32)
+#define MT_LP_RQ_USER_NAME_LEN (4)
+#define MT_LP_RQ_USER_CHAR_U (8)
+
+/* Determine the request update flag */
+#define MT_LP_RQ_FLAG_DONE (0)
+#define MT_LP_RQ_FLAG_NEED_UPDATE BIT(6)
+
+/* Determine the resource update id */
+#define MT_LP_RQ_ID_ALL_USAGE (-1)
+
+/* Determine the return status */
+#define MT_LP_RQ_STA_OK (0)
+#define MT_LP_RQ_STA_BAD (-1)
+
+struct mt_lp_res_req {
+ /* Determine the resource req public identify */
+ const unsigned int res_id;
+ /* Determine the resource bitwise internal control */
+ const unsigned int res_rq;
+ /* Determine the users per bit for current resource usage */
+ unsigned int res_usage;
+};
+
+struct mt_resource_req_manager {
+ /* Determine the set of resources */
+ struct mt_lp_res_req **res;
+};
+
+struct resource_req_status {
+ /* Determine the status id */
+ unsigned int id;
+ /* Determine the status value */
+ unsigned int val;
+};
+
+int mt_lp_resource_request_manager_register(struct mt_resource_req_manager *rqm);
+int mt_lp_rq_update_status(int type, void *p);
+int mt_lp_rq_get_status(int type, void *p);
+
+#endif /* MT_LP_RQM_H */
diff --git a/plat/mediatek/include/lpm/mt_lpm_smc.h b/plat/mediatek/include/lpm/mt_lpm_smc.h
new file mode 100644
index 0000000..0117ca9
--- /dev/null
+++ b/plat/mediatek/include/lpm/mt_lpm_smc.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_LPM_SMC_H
+#define MT_LPM_SMC_H
+
+/*
+ * MTK LPM smc user format:
+ * bit[31:24]: magic number
+ * bit[23:16]: user number
+ * bit[15:00]: user id
+ */
+
+#define MT_LPM_SMC_MAGIC (0xDA000000)
+#define MT_LPM_SMC_MAGIC_MASK (0xFF000000)
+#define MT_LPM_SMC_USER_MASK (0xFF)
+#define MT_LPM_SMC_USER_SHIFT (16)
+
+#define MT_LPM_SMC_USER_ID_MASK (0x0000FFFF)
+
+/*
+ * cpu_pm is used for MCDI to read/write CPC information
+ * spm_dbg is used for spm related debug information
+ * spm is used for spm related settings
+ * cpu_pm_lp is used for MCDI setting irq_remain
+ */
+enum mt_lpm_smc_user_id {
+ MT_LPM_SMC_USER_CPU_PM = 0,
+ MT_LPM_SMC_USER_SPM_DBG,
+ MT_LPM_SMC_USER_SPM,
+ MT_LPM_SMC_USER_CPU_PM_LP,
+ MT_LPM_SMC_USER_SECURE_CPU_PM,
+ MT_LPM_SMC_USER_SECURE_SPM_DBG,
+ MT_LPM_SMC_USER_SECURE_SPM,
+ MT_LPM_SMC_USER_MAX,
+};
+
+#define IS_MT_LPM_SMC(smcid) ((smcid & MT_LPM_SMC_MAGIC_MASK) == MT_LPM_SMC_MAGIC)
+
+/* get real user id */
+#define MT_LPM_SMC_USER(id) ((id >> MT_LPM_SMC_USER_SHIFT) & MT_LPM_SMC_USER_MASK)
+#define MT_LPM_SMC_USER_ID(uid) (uid & MT_LPM_SMC_USER_ID_MASK)
+
+/* sink user id to smc's user id */
+#define MT_LPM_SMC_USER_SINK(user, uid) (((uid & MT_LPM_SMC_USER_ID_MASK) |\
+ ((user & MT_LPM_SMC_USER_MASK) << MT_LPM_SMC_USER_SHIFT)) |\
+ MT_LPM_SMC_MAGIC)
+
+/* sink cpu pm's smc id */
+#define MT_LPM_SMC_USER_ID_CPU_PM(uid) MT_LPM_SMC_USER_SINK(MT_LPM_SMC_USER_CPU_PM, uid)
+/* sink spm's smc id */
+#define MT_LPM_SMC_USER_ID_SPM(uid) MT_LPM_SMC_USER_SINK(MT_LPM_SMC_USER_SPM, uid)
+
+/* sink cpu pm's user id */
+#define MT_LPM_SMC_USER_CPU_PM(uid) MT_LPM_SMC_USER_ID_CPU_PM(uid)
+
+/* sink spm's user id */
+#define MT_LPM_SMC_USER_SPM(uid) MT_LPM_SMC_USER_ID_SPM(uid)
+
+/* behavior */
+#define MT_LPM_SMC_ACT_SET BIT(0)
+#define MT_LPM_SMC_ACT_CLR BIT(1)
+#define MT_LPM_SMC_ACT_GET BIT(2)
+#define MT_LPM_SMC_ACT_PUSH BIT(3)
+#define MT_LPM_SMC_ACT_POP BIT(4)
+#define MT_LPM_SMC_ACT_SUBMIT BIT(5)
+
+/* compatible action for legacy smc from lk */
+#define MT_LPM_SMC_ACT_COMPAT BIT(31)
+
+enum mt_lpm_spmc_compat_id {
+ MT_LPM_SPMC_COMPAT_LK_FW_INIT,
+ MT_LPM_SPMC_COMPAT_LK_MCDI_WDT_DUMP,
+};
+
+#endif /* MT_LPM_SMC_H */