/* * Copyright (c) 2025, MediaTek Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include struct mt_dispatch_ctrl mt_dispatcher __section("mt_lpm_s") = { .enable = 0, }; struct mt_dispatch_ctrl mt_secure_dispatcher __section("mt_secure_lpm_s") = { .enable = 0, }; u_register_t invoke_mt_lpm_dispatch(u_register_t x1, u_register_t x2, u_register_t x3, u_register_t x4, void *handle, struct smccc_res *smccc_ret) { uint64_t res = 0; uint32_t user; if (!IS_MT_LPM_SMC(x1)) return 0; user = MT_LPM_SMC_USER(x1); if ((user < MT_LPM_SMC_USER_MAX) && (mt_dispatcher.enable & (BIT(user)))) { res = mt_dispatcher.fn[user](MT_LPM_SMC_USER_ID(x1), x2, x3, x4, handle, smccc_ret); } return res; } DECLARE_SMC_HANDLER(MTK_SIP_MTK_LPM_CONTROL, invoke_mt_lpm_dispatch); u_register_t invoke_mt_secure_lpm_dispatch(u_register_t x1, u_register_t x2, u_register_t x3, u_register_t x4, void *handle, struct smccc_res *smccc_ret) { uint64_t res = 0; uint32_t user; if (!IS_MT_LPM_SMC(x1)) return 0; user = MT_LPM_SMC_USER(x1); if (mt_secure_dispatcher.enable & (BIT(user))) { res = mt_secure_dispatcher.fn[user](MT_LPM_SMC_USER_ID(x1), x2, x3, x4, handle, smccc_ret); } return res; } DECLARE_SMC_HANDLER(MTK_SIP_BL_LPM_CONTROL, invoke_mt_secure_lpm_dispatch); /* Check lpm smc user number at compile time */ CASSERT(MT_LPM_SMC_USER_MAX <= MTK_DISPATCH_ID_MAX, lpm_smc_user_declare_too_large); void mt_lpm_dispatcher_registry(unsigned int id, mt_lpm_dispatch_fn fn) { if (id >= MT_LPM_SMC_USER_MAX) return; mt_dispatcher.enable |= BIT(id); mt_dispatcher.fn[id] = fn; } void mt_secure_lpm_dispatcher_registry(unsigned int id, mt_lpm_dispatch_fn fn) { if (id >= MT_LPM_SMC_USER_MAX) return; mt_secure_dispatcher.enable |= BIT(id); mt_secure_dispatcher.fn[id] = fn; }