1 /*
2 * Copyright (c) 2025, MediaTek Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <common/debug.h>
8
9 /* MTK header */
10 #include <drivers/pmic/pmic_swap_api.h>
11 #include <lpm_v2/mt_lp_api.h>
12 #include <lpm_v2/mt_lp_rq.h>
13 #include <mtk_bl31_interface.h>
14 #include <mtk_sip_svc.h>
15
16 /* UFS generic control flags */
17 #define UFS_MTK_SIP_VA09_PWR_CTRL BIT(0)
18 #define UFS_MTK_SIP_DEVICE_RESET BIT(1)
19 #define UFS_MTK_SIP_CRYPTO_CTRL BIT(2)
20 #define UFS_MTK_SIP_REF_CLK_NOTIFICATION BIT(3)
21 #define UFS_MTK_SIP_SRAM_PWR_CTRL BIT(5)
22 #define UFS_MTK_SIP_GET_VCC_INFO BIT(6)
23 #define UFS_MTK_SIP_DEVICE_PWR_CTRL BIT(7)
24 #define UFS_MTK_SIP_MPHY_CTRL BIT(8)
25 #define UFS_MTK_SIP_MTCMOS_CTRL BIT(9)
26
27 enum {
28 VCC_NONE = 0,
29 VCC_1,
30 VCC_2,
31 };
32
ufs_get_vcc_info(struct smccc_res * smccc_ret)33 static void ufs_get_vcc_info(struct smccc_res *smccc_ret)
34 {
35 if (smccc_ret == NULL)
36 return;
37
38 if (is_second_pmic_pp_swap())
39 smccc_ret->a1 = VCC_2;
40 else
41 smccc_ret->a1 = VCC_1;
42 }
43
44 /* SPM resource control */
45 #define RSC_MEM (MT_LP_RQ_DRAM | MT_LP_RQ_EMI)
46 #define RSC_PMIC MT_LP_RQ_PMIC
47
ufs_rsc_ctrl(unsigned int rsc,bool hold)48 static int ufs_rsc_ctrl(unsigned int rsc, bool hold)
49 {
50 static struct mt_lp_resource_user ufs_res_user;
51 int ret = -1;
52
53 if (!ufs_res_user.uid) {
54 ret = mt_lp_resource_user_register("UFS", &ufs_res_user);
55
56 if (ret) {
57 WARN("%s: register lp resource failed\n", __func__);
58 return ret;
59 }
60 }
61
62 if (hold)
63 ret = ufs_res_user.request(&ufs_res_user, rsc);
64 else
65 ret = ufs_res_user.release(&ufs_res_user);
66
67 VERBOSE("%s: rsc=%d, hold=%d\n", __func__, rsc, hold);
68
69 if (ret)
70 WARN("%s: RSC_%d %s failed\n", __func__, rsc, hold ? "request" : "release");
71
72 return ret;
73 }
74
ufs_rsc_ctrl_mem(bool hold)75 int ufs_rsc_ctrl_mem(bool hold)
76 {
77 return ufs_rsc_ctrl(RSC_MEM, hold);
78 }
79
ufs_rsc_ctrl_pmic(bool hold)80 int ufs_rsc_ctrl_pmic(bool hold)
81 {
82 return ufs_rsc_ctrl(RSC_PMIC, hold);
83 }
84
85 /* UFS clock status */
86 static uint32_t ufs_clk_sta = UFS_REF_CLK_ON;
87
ufs_is_clk_status_off(void)88 bool ufs_is_clk_status_off(void)
89 {
90 return ufs_clk_sta == UFS_REF_CLK_OFF;
91 }
92
ufs_set_clk_status(bool on)93 void ufs_set_clk_status(bool on)
94 {
95 if (on)
96 ufs_clk_sta = UFS_REF_CLK_ON;
97 else
98 ufs_clk_sta = UFS_REF_CLK_OFF;
99 }
100
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)101 static u_register_t ufs_knl_ctrl(u_register_t x1,
102 u_register_t x2,
103 u_register_t x3,
104 u_register_t x4,
105 void *handle,
106 struct smccc_res *smccc_ret)
107 {
108 uint64_t ret = 0;
109
110 switch (x1) {
111 case UFS_MTK_SIP_VA09_PWR_CTRL:
112 ufs_mphy_va09_cg_ctrl(!!x2);
113 break;
114 case UFS_MTK_SIP_DEVICE_RESET:
115 ufs_device_reset_ctrl(!!x2);
116 break;
117 case UFS_MTK_SIP_CRYPTO_CTRL:
118 ufs_crypto_hie_init();
119 break;
120 case UFS_MTK_SIP_REF_CLK_NOTIFICATION:
121 ufs_ref_clk_status(x2, x3);
122 break;
123 case UFS_MTK_SIP_SRAM_PWR_CTRL:
124 ufs_sram_pwr_ctrl(x2);
125 break;
126 case UFS_MTK_SIP_GET_VCC_INFO:
127 ufs_get_vcc_info(smccc_ret);
128 break;
129 case UFS_MTK_SIP_DEVICE_PWR_CTRL:
130 ufs_device_pwr_ctrl(x2, x3);
131 break;
132 case UFS_MTK_SIP_MPHY_CTRL:
133 ufs_mphy_ctrl(x2);
134 break;
135 case UFS_MTK_SIP_MTCMOS_CTRL:
136 #if defined(CONFIG_MTK_MTCMOS)
137 ufs_mtcmos_ctrl(!!x2);
138 #endif
139 break;
140 default:
141 ret = -1;
142 WARN("[UFS] invalid argument 0x%lx from kernel\n", x1);
143 break;
144 }
145
146 return ret;
147 }
148
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)149 static u_register_t ufs_bl_ctrl(u_register_t x1,
150 u_register_t x2,
151 u_register_t x3,
152 u_register_t x4,
153 void *handle,
154 struct smccc_res *smccc_ret)
155 {
156 uint64_t ret = 0;
157
158 switch (x1) {
159 case UFS_MTK_SIP_DEVICE_RESET:
160 ufs_device_reset_ctrl(x2);
161 break;
162 default:
163 ret = -1;
164 WARN("[UFS] invalid argument 0x%lx from bootloader\n", x1);
165 break;
166 }
167
168 return ret;
169 }
170
171 DECLARE_SMC_HANDLER(MTK_SIP_KERNEL_UFS_CONTROL, ufs_knl_ctrl);
172 DECLARE_SMC_HANDLER(MTK_SIP_BL_UFS_CONTROL, ufs_bl_ctrl);
173