xref: /rk3399_ARM-atf/plat/mediatek/drivers/ufs/ufs_ctrl.c (revision 31a69d9ae79c57d349bb04444a5bbd6267957c87)
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>
11*31a69d9aSYidi Lin #include <lpm_v2/mt_lp_api.h>
12*31a69d9aSYidi 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 
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 
44*31a69d9aSYidi Lin /* SPM resource control */
45*31a69d9aSYidi Lin #define RSC_MEM			(MT_LP_RQ_DRAM | MT_LP_RQ_EMI)
46*31a69d9aSYidi Lin #define RSC_PMIC		MT_LP_RQ_PMIC
47*31a69d9aSYidi Lin 
48*31a69d9aSYidi Lin static int ufs_rsc_ctrl(unsigned int rsc, bool hold)
49*31a69d9aSYidi Lin {
50*31a69d9aSYidi Lin 	static struct mt_lp_resource_user ufs_res_user;
51*31a69d9aSYidi Lin 	int ret = -1;
52*31a69d9aSYidi Lin 
53*31a69d9aSYidi Lin 	if (!ufs_res_user.uid) {
54*31a69d9aSYidi Lin 		ret = mt_lp_resource_user_register("UFS", &ufs_res_user);
55*31a69d9aSYidi Lin 
56*31a69d9aSYidi Lin 		if (ret) {
57*31a69d9aSYidi Lin 			WARN("%s: register lp resource failed\n", __func__);
58*31a69d9aSYidi Lin 			return ret;
59*31a69d9aSYidi Lin 		}
60*31a69d9aSYidi Lin 	}
61*31a69d9aSYidi Lin 
62*31a69d9aSYidi Lin 	if (hold)
63*31a69d9aSYidi Lin 		ret = ufs_res_user.request(&ufs_res_user, rsc);
64*31a69d9aSYidi Lin 	else
65*31a69d9aSYidi Lin 		ret = ufs_res_user.release(&ufs_res_user);
66*31a69d9aSYidi Lin 
67*31a69d9aSYidi Lin 	VERBOSE("%s: rsc=%d, hold=%d\n", __func__, rsc, hold);
68*31a69d9aSYidi Lin 
69*31a69d9aSYidi Lin 	if (ret)
70*31a69d9aSYidi Lin 		WARN("%s: RSC_%d %s failed\n", __func__, rsc, hold ? "request" : "release");
71*31a69d9aSYidi Lin 
72*31a69d9aSYidi Lin 	return ret;
73*31a69d9aSYidi Lin }
74*31a69d9aSYidi Lin 
75*31a69d9aSYidi Lin int ufs_rsc_ctrl_mem(bool hold)
76*31a69d9aSYidi Lin {
77*31a69d9aSYidi Lin 	return ufs_rsc_ctrl(RSC_MEM, hold);
78*31a69d9aSYidi Lin }
79*31a69d9aSYidi Lin 
80*31a69d9aSYidi Lin int ufs_rcs_ctrl_pmic(bool hold)
81*31a69d9aSYidi Lin {
82*31a69d9aSYidi Lin 	return ufs_rsc_ctrl(RSC_PMIC, hold);
83*31a69d9aSYidi Lin }
84*31a69d9aSYidi Lin 
85*31a69d9aSYidi Lin /* UFS clock status */
86*31a69d9aSYidi Lin static uint32_t ufs_clk_sta = UFS_REF_CLK_ON;
87*31a69d9aSYidi Lin 
88*31a69d9aSYidi Lin bool ufs_is_clk_status_off(void)
89*31a69d9aSYidi Lin {
90*31a69d9aSYidi Lin 	return ufs_clk_sta == UFS_REF_CLK_OFF;
91*31a69d9aSYidi Lin }
92*31a69d9aSYidi Lin 
93*31a69d9aSYidi Lin void ufs_set_clk_status(bool on)
94*31a69d9aSYidi Lin {
95*31a69d9aSYidi Lin 	if (on)
96*31a69d9aSYidi Lin 		ufs_clk_sta = UFS_REF_CLK_ON;
97*31a69d9aSYidi Lin 	else
98*31a69d9aSYidi Lin 		ufs_clk_sta = UFS_REF_CLK_OFF;
99*31a69d9aSYidi Lin }
100*31a69d9aSYidi Lin 
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:
112*31a69d9aSYidi Lin 		ufs_mphy_va09_cg_ctrl(!!x2);
11357c73515SYidi Lin 		break;
11457c73515SYidi Lin 	case UFS_MTK_SIP_DEVICE_RESET:
115*31a69d9aSYidi 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:
136*31a69d9aSYidi Lin #if defined(CONFIG_MTK_MTCMOS)
137*31a69d9aSYidi Lin 		ufs_mtcmos_ctrl(!!x2);
138*31a69d9aSYidi 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 
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