157c73515SYidi Lin /*
257c73515SYidi Lin * Copyright (c) 2025, MediaTek Inc. All rights reserved.
357c73515SYidi Lin *
457c73515SYidi Lin * SPDX-License-Identifier: BSD-3-Clause
557c73515SYidi Lin */
657c73515SYidi Lin
757c73515SYidi Lin #include <common/debug.h>
857c73515SYidi Lin
957c73515SYidi Lin /* MTK header */
1057c73515SYidi Lin #include <drivers/pmic/pmic_swap_api.h>
1131a69d9aSYidi Lin #include <lpm_v2/mt_lp_api.h>
1231a69d9aSYidi Lin #include <lpm_v2/mt_lp_rq.h>
1357c73515SYidi Lin #include <mtk_bl31_interface.h>
1457c73515SYidi Lin #include <mtk_sip_svc.h>
1557c73515SYidi Lin
1657c73515SYidi Lin /* UFS generic control flags */
1757c73515SYidi Lin #define UFS_MTK_SIP_VA09_PWR_CTRL BIT(0)
1857c73515SYidi Lin #define UFS_MTK_SIP_DEVICE_RESET BIT(1)
1957c73515SYidi Lin #define UFS_MTK_SIP_CRYPTO_CTRL BIT(2)
2057c73515SYidi Lin #define UFS_MTK_SIP_REF_CLK_NOTIFICATION BIT(3)
2157c73515SYidi Lin #define UFS_MTK_SIP_SRAM_PWR_CTRL BIT(5)
2257c73515SYidi Lin #define UFS_MTK_SIP_GET_VCC_INFO BIT(6)
2357c73515SYidi Lin #define UFS_MTK_SIP_DEVICE_PWR_CTRL BIT(7)
2457c73515SYidi Lin #define UFS_MTK_SIP_MPHY_CTRL BIT(8)
2557c73515SYidi Lin #define UFS_MTK_SIP_MTCMOS_CTRL BIT(9)
2657c73515SYidi Lin
2757c73515SYidi Lin enum {
2857c73515SYidi Lin VCC_NONE = 0,
2957c73515SYidi Lin VCC_1,
3057c73515SYidi Lin VCC_2,
3157c73515SYidi Lin };
3257c73515SYidi Lin
ufs_get_vcc_info(struct smccc_res * smccc_ret)3357c73515SYidi Lin static void ufs_get_vcc_info(struct smccc_res *smccc_ret)
3457c73515SYidi Lin {
3557c73515SYidi Lin if (smccc_ret == NULL)
3657c73515SYidi Lin return;
3757c73515SYidi Lin
3857c73515SYidi Lin if (is_second_pmic_pp_swap())
3957c73515SYidi Lin smccc_ret->a1 = VCC_2;
4057c73515SYidi Lin else
4157c73515SYidi Lin smccc_ret->a1 = VCC_1;
4257c73515SYidi Lin }
4357c73515SYidi Lin
4431a69d9aSYidi Lin /* SPM resource control */
4531a69d9aSYidi Lin #define RSC_MEM (MT_LP_RQ_DRAM | MT_LP_RQ_EMI)
4631a69d9aSYidi Lin #define RSC_PMIC MT_LP_RQ_PMIC
4731a69d9aSYidi Lin
ufs_rsc_ctrl(unsigned int rsc,bool hold)4831a69d9aSYidi Lin static int ufs_rsc_ctrl(unsigned int rsc, bool hold)
4931a69d9aSYidi Lin {
5031a69d9aSYidi Lin static struct mt_lp_resource_user ufs_res_user;
5131a69d9aSYidi Lin int ret = -1;
5231a69d9aSYidi Lin
5331a69d9aSYidi Lin if (!ufs_res_user.uid) {
5431a69d9aSYidi Lin ret = mt_lp_resource_user_register("UFS", &ufs_res_user);
5531a69d9aSYidi Lin
5631a69d9aSYidi Lin if (ret) {
5731a69d9aSYidi Lin WARN("%s: register lp resource failed\n", __func__);
5831a69d9aSYidi Lin return ret;
5931a69d9aSYidi Lin }
6031a69d9aSYidi Lin }
6131a69d9aSYidi Lin
6231a69d9aSYidi Lin if (hold)
6331a69d9aSYidi Lin ret = ufs_res_user.request(&ufs_res_user, rsc);
6431a69d9aSYidi Lin else
6531a69d9aSYidi Lin ret = ufs_res_user.release(&ufs_res_user);
6631a69d9aSYidi Lin
6731a69d9aSYidi Lin VERBOSE("%s: rsc=%d, hold=%d\n", __func__, rsc, hold);
6831a69d9aSYidi Lin
6931a69d9aSYidi Lin if (ret)
7031a69d9aSYidi Lin WARN("%s: RSC_%d %s failed\n", __func__, rsc, hold ? "request" : "release");
7131a69d9aSYidi Lin
7231a69d9aSYidi Lin return ret;
7331a69d9aSYidi Lin }
7431a69d9aSYidi Lin
ufs_rsc_ctrl_mem(bool hold)7531a69d9aSYidi Lin int ufs_rsc_ctrl_mem(bool hold)
7631a69d9aSYidi Lin {
7731a69d9aSYidi Lin return ufs_rsc_ctrl(RSC_MEM, hold);
7831a69d9aSYidi Lin }
7931a69d9aSYidi Lin
ufs_rsc_ctrl_pmic(bool hold)80*260e18b1SCloud Zhang int ufs_rsc_ctrl_pmic(bool hold)
8131a69d9aSYidi Lin {
8231a69d9aSYidi Lin return ufs_rsc_ctrl(RSC_PMIC, hold);
8331a69d9aSYidi Lin }
8431a69d9aSYidi Lin
8531a69d9aSYidi Lin /* UFS clock status */
8631a69d9aSYidi Lin static uint32_t ufs_clk_sta = UFS_REF_CLK_ON;
8731a69d9aSYidi Lin
ufs_is_clk_status_off(void)8831a69d9aSYidi Lin bool ufs_is_clk_status_off(void)
8931a69d9aSYidi Lin {
9031a69d9aSYidi Lin return ufs_clk_sta == UFS_REF_CLK_OFF;
9131a69d9aSYidi Lin }
9231a69d9aSYidi Lin
ufs_set_clk_status(bool on)9331a69d9aSYidi Lin void ufs_set_clk_status(bool on)
9431a69d9aSYidi Lin {
9531a69d9aSYidi Lin if (on)
9631a69d9aSYidi Lin ufs_clk_sta = UFS_REF_CLK_ON;
9731a69d9aSYidi Lin else
9831a69d9aSYidi Lin ufs_clk_sta = UFS_REF_CLK_OFF;
9931a69d9aSYidi Lin }
10031a69d9aSYidi Lin
ufs_knl_ctrl(u_register_t x1,u_register_t x2,u_register_t x3,u_register_t x4,void * handle,struct smccc_res * smccc_ret)10157c73515SYidi Lin static u_register_t ufs_knl_ctrl(u_register_t x1,
10257c73515SYidi Lin u_register_t x2,
10357c73515SYidi Lin u_register_t x3,
10457c73515SYidi Lin u_register_t x4,
10557c73515SYidi Lin void *handle,
10657c73515SYidi Lin struct smccc_res *smccc_ret)
10757c73515SYidi Lin {
10857c73515SYidi Lin uint64_t ret = 0;
10957c73515SYidi Lin
11057c73515SYidi Lin switch (x1) {
11157c73515SYidi Lin case UFS_MTK_SIP_VA09_PWR_CTRL:
11231a69d9aSYidi Lin ufs_mphy_va09_cg_ctrl(!!x2);
11357c73515SYidi Lin break;
11457c73515SYidi Lin case UFS_MTK_SIP_DEVICE_RESET:
11531a69d9aSYidi Lin ufs_device_reset_ctrl(!!x2);
11657c73515SYidi Lin break;
11757c73515SYidi Lin case UFS_MTK_SIP_CRYPTO_CTRL:
11857c73515SYidi Lin ufs_crypto_hie_init();
11957c73515SYidi Lin break;
12057c73515SYidi Lin case UFS_MTK_SIP_REF_CLK_NOTIFICATION:
12157c73515SYidi Lin ufs_ref_clk_status(x2, x3);
12257c73515SYidi Lin break;
12357c73515SYidi Lin case UFS_MTK_SIP_SRAM_PWR_CTRL:
12457c73515SYidi Lin ufs_sram_pwr_ctrl(x2);
12557c73515SYidi Lin break;
12657c73515SYidi Lin case UFS_MTK_SIP_GET_VCC_INFO:
12757c73515SYidi Lin ufs_get_vcc_info(smccc_ret);
12857c73515SYidi Lin break;
12957c73515SYidi Lin case UFS_MTK_SIP_DEVICE_PWR_CTRL:
13057c73515SYidi Lin ufs_device_pwr_ctrl(x2, x3);
13157c73515SYidi Lin break;
13257c73515SYidi Lin case UFS_MTK_SIP_MPHY_CTRL:
13357c73515SYidi Lin ufs_mphy_ctrl(x2);
13457c73515SYidi Lin break;
13557c73515SYidi Lin case UFS_MTK_SIP_MTCMOS_CTRL:
13631a69d9aSYidi Lin #if defined(CONFIG_MTK_MTCMOS)
13731a69d9aSYidi Lin ufs_mtcmos_ctrl(!!x2);
13831a69d9aSYidi Lin #endif
13957c73515SYidi Lin break;
14057c73515SYidi Lin default:
14157c73515SYidi Lin ret = -1;
14257c73515SYidi Lin WARN("[UFS] invalid argument 0x%lx from kernel\n", x1);
14357c73515SYidi Lin break;
14457c73515SYidi Lin }
14557c73515SYidi Lin
14657c73515SYidi Lin return ret;
14757c73515SYidi Lin }
14857c73515SYidi Lin
ufs_bl_ctrl(u_register_t x1,u_register_t x2,u_register_t x3,u_register_t x4,void * handle,struct smccc_res * smccc_ret)14957c73515SYidi Lin static u_register_t ufs_bl_ctrl(u_register_t x1,
15057c73515SYidi Lin u_register_t x2,
15157c73515SYidi Lin u_register_t x3,
15257c73515SYidi Lin u_register_t x4,
15357c73515SYidi Lin void *handle,
15457c73515SYidi Lin struct smccc_res *smccc_ret)
15557c73515SYidi Lin {
15657c73515SYidi Lin uint64_t ret = 0;
15757c73515SYidi Lin
15857c73515SYidi Lin switch (x1) {
15957c73515SYidi Lin case UFS_MTK_SIP_DEVICE_RESET:
16057c73515SYidi Lin ufs_device_reset_ctrl(x2);
16157c73515SYidi Lin break;
16257c73515SYidi Lin default:
16357c73515SYidi Lin ret = -1;
16457c73515SYidi Lin WARN("[UFS] invalid argument 0x%lx from bootloader\n", x1);
16557c73515SYidi Lin break;
16657c73515SYidi Lin }
16757c73515SYidi Lin
16857c73515SYidi Lin return ret;
16957c73515SYidi Lin }
17057c73515SYidi Lin
17157c73515SYidi Lin DECLARE_SMC_HANDLER(MTK_SIP_KERNEL_UFS_CONTROL, ufs_knl_ctrl);
17257c73515SYidi Lin DECLARE_SMC_HANDLER(MTK_SIP_BL_UFS_CONTROL, ufs_bl_ctrl);
173