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 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 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 7531a69d9aSYidi Lin int ufs_rsc_ctrl_mem(bool hold) 7631a69d9aSYidi Lin { 7731a69d9aSYidi Lin return ufs_rsc_ctrl(RSC_MEM, hold); 7831a69d9aSYidi Lin } 7931a69d9aSYidi Lin 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 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 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 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 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