1*da8cc41bSWenzhen Yu /*
2*da8cc41bSWenzhen Yu * Copyright (c) 2025, MediaTek Inc. All rights reserved.
3*da8cc41bSWenzhen Yu *
4*da8cc41bSWenzhen Yu * SPDX-License-Identifier: BSD-3-Clause
5*da8cc41bSWenzhen Yu */
6*da8cc41bSWenzhen Yu
7*da8cc41bSWenzhen Yu #include <cdefs.h>
8*da8cc41bSWenzhen Yu
9*da8cc41bSWenzhen Yu #include <lpm_v2/mt_lpm_dispatch.h>
10*da8cc41bSWenzhen Yu
11*da8cc41bSWenzhen Yu /*
12*da8cc41bSWenzhen Yu * Notice, this data don't link to bss section.
13*da8cc41bSWenzhen Yu * It means data structure won't be set as zero.
14*da8cc41bSWenzhen Yu * Please make sure the member will be initialized.
15*da8cc41bSWenzhen Yu */
16*da8cc41bSWenzhen Yu struct mt_dispatch_ctrl mt_dispatcher
17*da8cc41bSWenzhen Yu __section("mt_lpm_s") = {
18*da8cc41bSWenzhen Yu .enable = 0,
19*da8cc41bSWenzhen Yu };
20*da8cc41bSWenzhen Yu
21*da8cc41bSWenzhen Yu struct mt_dispatch_ctrl mt_secure_dispatcher
22*da8cc41bSWenzhen Yu __section("mt_secure_lpm_s") = {
23*da8cc41bSWenzhen Yu .enable = 0,
24*da8cc41bSWenzhen Yu };
25*da8cc41bSWenzhen Yu
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)26*da8cc41bSWenzhen Yu u_register_t invoke_mt_lpm_dispatch(u_register_t x1, u_register_t x2,
27*da8cc41bSWenzhen Yu u_register_t x3, u_register_t x4,
28*da8cc41bSWenzhen Yu void *handle, struct smccc_res *smccc_ret)
29*da8cc41bSWenzhen Yu {
30*da8cc41bSWenzhen Yu uint64_t res = 0;
31*da8cc41bSWenzhen Yu uint32_t user;
32*da8cc41bSWenzhen Yu
33*da8cc41bSWenzhen Yu if (!IS_MT_LPM_SMC(x1))
34*da8cc41bSWenzhen Yu return res;
35*da8cc41bSWenzhen Yu
36*da8cc41bSWenzhen Yu user = MT_LPM_SMC_USER(x1);
37*da8cc41bSWenzhen Yu if ((user < MT_LPM_SMC_USER_MAX) &&
38*da8cc41bSWenzhen Yu (mt_dispatcher.enable & (1 << user))) {
39*da8cc41bSWenzhen Yu res = mt_dispatcher.fn[user](MT_LPM_SMC_USER_ID(x1),
40*da8cc41bSWenzhen Yu x2, x3, x4,
41*da8cc41bSWenzhen Yu handle, smccc_ret);
42*da8cc41bSWenzhen Yu }
43*da8cc41bSWenzhen Yu
44*da8cc41bSWenzhen Yu return res;
45*da8cc41bSWenzhen Yu }
46*da8cc41bSWenzhen Yu DECLARE_SMC_HANDLER(MTK_SIP_MTK_LPM_CONTROL, invoke_mt_lpm_dispatch);
47*da8cc41bSWenzhen Yu
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)48*da8cc41bSWenzhen Yu u_register_t invoke_mt_secure_lpm_dispatch(u_register_t x1, u_register_t x2,
49*da8cc41bSWenzhen Yu u_register_t x3, u_register_t x4,
50*da8cc41bSWenzhen Yu void *handle,
51*da8cc41bSWenzhen Yu struct smccc_res *smccc_ret)
52*da8cc41bSWenzhen Yu {
53*da8cc41bSWenzhen Yu uint64_t res = 0;
54*da8cc41bSWenzhen Yu unsigned int user;
55*da8cc41bSWenzhen Yu
56*da8cc41bSWenzhen Yu if (!IS_MT_LPM_SMC(x1))
57*da8cc41bSWenzhen Yu return res;
58*da8cc41bSWenzhen Yu
59*da8cc41bSWenzhen Yu user = MT_LPM_SMC_USER(x1);
60*da8cc41bSWenzhen Yu if (mt_secure_dispatcher.enable & (1 << user)) {
61*da8cc41bSWenzhen Yu res = mt_secure_dispatcher.fn[user](MT_LPM_SMC_USER_ID(x1), x2,
62*da8cc41bSWenzhen Yu x3, x4, handle, smccc_ret);
63*da8cc41bSWenzhen Yu }
64*da8cc41bSWenzhen Yu
65*da8cc41bSWenzhen Yu return res;
66*da8cc41bSWenzhen Yu }
67*da8cc41bSWenzhen Yu DECLARE_SMC_HANDLER(MTK_SIP_BL_LPM_CONTROL, invoke_mt_secure_lpm_dispatch);
68*da8cc41bSWenzhen Yu
69*da8cc41bSWenzhen Yu /* Check lpm smc user number at compile time */
70*da8cc41bSWenzhen Yu CASSERT(MT_LPM_SMC_USER_MAX <= MTK_DISPATCH_ID_MAX,
71*da8cc41bSWenzhen Yu lpm_smc_user_declare_too_large);
72*da8cc41bSWenzhen Yu
mt_lpm_dispatcher_registry(unsigned int id,mt_lpm_dispatch_fn fn)73*da8cc41bSWenzhen Yu void mt_lpm_dispatcher_registry(unsigned int id, mt_lpm_dispatch_fn fn)
74*da8cc41bSWenzhen Yu {
75*da8cc41bSWenzhen Yu if (id >= MT_LPM_SMC_USER_MAX)
76*da8cc41bSWenzhen Yu return;
77*da8cc41bSWenzhen Yu
78*da8cc41bSWenzhen Yu mt_dispatcher.enable |= BIT(id);
79*da8cc41bSWenzhen Yu mt_dispatcher.fn[id] = fn;
80*da8cc41bSWenzhen Yu }
81*da8cc41bSWenzhen Yu
mt_secure_lpm_dispatcher_registry(unsigned int id,mt_lpm_dispatch_fn fn)82*da8cc41bSWenzhen Yu void mt_secure_lpm_dispatcher_registry(unsigned int id, mt_lpm_dispatch_fn fn)
83*da8cc41bSWenzhen Yu {
84*da8cc41bSWenzhen Yu if (id >= MT_LPM_SMC_USER_MAX)
85*da8cc41bSWenzhen Yu return;
86*da8cc41bSWenzhen Yu
87*da8cc41bSWenzhen Yu mt_secure_dispatcher.enable |= BIT(id);
88*da8cc41bSWenzhen Yu mt_secure_dispatcher.fn[id] = fn;
89*da8cc41bSWenzhen Yu }
90