From cab4919955af17eb594c2e2e8de0e54b221854e2 Mon Sep 17 00:00:00 2001 From: Roger Lu Date: Mon, 14 Dec 2020 16:53:22 +0800 Subject: [PATCH] mediatek: mt8192: Add lpm driver Low Power Management (LPM) helps find a suitable configuration for letting system entering idle or suspend with the most resources off. Change-Id: Ie6a7063b666cf338cff5bc972c9025b26de482eb Signed-off-by: Roger Lu --- plat/mediatek/common/lpm/mt_lp_rm.c | 110 ++++++++++++++++++++++++++++ plat/mediatek/common/lpm/mt_lp_rm.h | 42 +++++++++++ plat/mediatek/mt8192/platform.mk | 2 + 3 files changed, 154 insertions(+) create mode 100644 plat/mediatek/common/lpm/mt_lp_rm.c create mode 100644 plat/mediatek/common/lpm/mt_lp_rm.h diff --git a/plat/mediatek/common/lpm/mt_lp_rm.c b/plat/mediatek/common/lpm/mt_lp_rm.c new file mode 100644 index 000000000..f3148fe74 --- /dev/null +++ b/plat/mediatek/common/lpm/mt_lp_rm.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +struct platform_mt_resource_manager { + unsigned int count; + struct mt_resource_manager *plat_rm; +}; + +static struct platform_mt_resource_manager plat_mt_rm; + +int mt_lp_rm_register(struct mt_resource_manager *rm) +{ + unsigned int i; + struct mt_resource_constraint *const *rc; + + if ((rm == NULL) || (rm->consts == NULL) || + (plat_mt_rm.plat_rm != NULL)) { + return MT_RM_STATUS_BAD; + } + + for (i = 0U, rc = rm->consts; *rc != NULL; i++, rc++) { + if ((*rc)->init != NULL) { + (*rc)->init(); + } + } + + plat_mt_rm.plat_rm = rm; + plat_mt_rm.count = i; + + return MT_RM_STATUS_OK; +} + +int mt_lp_rm_reset_constraint(int idx, unsigned int cpuid, int stateid) +{ + struct mt_resource_constraint const *rc = NULL; + + if ((plat_mt_rm.plat_rm == NULL) || (idx < 0) || + (idx >= plat_mt_rm.count)) { + return MT_RM_STATUS_BAD; + } + + rc = plat_mt_rm.plat_rm->consts[idx]; + + if ((rc == NULL) || (rc->reset == NULL)) { + return MT_RM_STATUS_BAD; + } + + return rc->reset(cpuid, stateid); +} + +int mt_lp_rm_find_and_run_constraint(int idx, unsigned int cpuid, + int stateid, void *priv) +{ + int i, res = MT_RM_STATUS_BAD; + struct mt_resource_constraint *const *rc; + struct mt_resource_manager *rm = plat_mt_rm.plat_rm; + + if ((rm == NULL) || (idx < 0) || (idx >= plat_mt_rm.count)) { + return res; + } + + /* If subsys clk/mtcmos is on, add block-resource-off flag */ + if (rm->update != NULL) { + res = rm->update(rm->consts, stateid, priv); + if (res != 0) { + return res; + } + } + + for (i = idx, rc = (rm->consts + idx); *rc != NULL; i++, rc++) { + if (((*rc)->is_valid != NULL) && + ((*rc)->is_valid(cpuid, stateid))) { + if (((*rc)->run != NULL) && + ((*rc)->run(cpuid, stateid) == 0)) { + res = i; + break; + } + } + } + + return res; +} + +int mt_lp_rm_do_update(int stateid, int type, void const *p) +{ + int res = MT_RM_STATUS_BAD; + struct mt_resource_constraint *const *rc; + struct mt_resource_manager *rm = plat_mt_rm.plat_rm; + + if (rm == NULL) { + return res; + } + + for (rc = rm->consts; *rc != NULL; rc++) { + if ((*rc)->update != NULL) { + res = (*rc)->update(stateid, type, p); + if (res != MT_RM_STATUS_OK) { + break; + } + } + } + + return res; +} diff --git a/plat/mediatek/common/lpm/mt_lp_rm.h b/plat/mediatek/common/lpm/mt_lp_rm.h new file mode 100644 index 000000000..39759f1d2 --- /dev/null +++ b/plat/mediatek/common/lpm/mt_lp_rm.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_LP_RM_H +#define MT_LP_RM_H + +#include + +#define MT_RM_STATUS_OK 0 +#define MT_RM_STATUS_BAD -1 + +enum PLAT_MT_LPM_RC_TYPE { + PLAT_RC_UPDATE_CONDITION, + PLAT_RC_UPDATE_REMAIN_IRQS +}; + +struct mt_resource_constraint { + int level; + int (*init)(void); + bool (*is_valid)(unsigned int cpu, int stateid); + int (*update)(int stateid, int type, const void *p); + int (*run)(unsigned int cpu, int stateid); + int (*reset)(unsigned int cpu, int stateid); + unsigned int (*allow)(int stateid); +}; + +struct mt_resource_manager { + int (*update)(struct mt_resource_constraint **con, + int stateid, void *priv); + struct mt_resource_constraint **consts; +}; + +extern int mt_lp_rm_register(struct mt_resource_manager *rm); +extern int mt_lp_rm_find_and_run_constraint(int idx, unsigned int cpuid, + int stateid, void *priv); +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); +#endif /* MT_LP_RM_H */ diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk index a5e7ee26a..9c9b233bb 100644 --- a/plat/mediatek/mt8192/platform.mk +++ b/plat/mediatek/mt8192/platform.mk @@ -8,6 +8,7 @@ MTK_PLAT := plat/mediatek MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ + -I${MTK_PLAT}/common/lpm/ \ -I${MTK_PLAT_SOC}/include/ \ -I${MTK_PLAT_SOC}/drivers/ \ -I${MTK_PLAT_SOC}/drivers/dcm \ @@ -42,6 +43,7 @@ BL31_SOURCES += common/desc_image_load.c \ ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init_v2.c \ ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \ ${MTK_PLAT}/common/drivers/uart/uart.c \ + ${MTK_PLAT}/common/lpm/mt_lp_rm.c \ ${MTK_PLAT}/common/mtk_plat_common.c \ ${MTK_PLAT}/common/mtk_sip_svc.c \ ${MTK_PLAT}/common/params_setup.c \