1 /* 2 * Copyright (c) 2025, MediaTek Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 #include <stdint.h> 7 8 #include <common/debug.h> 9 #include <drivers/delay_timer.h> 10 #include <lib/mmio.h> 11 #include <lib/spinlock.h> 12 #include <platform_def.h> 13 14 #include <mtcmos.h> 15 16 #define SPM_PROJECT_CODE 0xB16 17 18 #define PWR_RST_B BIT(0) 19 #define PWR_ISO BIT(1) 20 #define PWR_ON BIT(2) 21 #define PWR_ON_2ND BIT(3) 22 #define PWR_CLK_DIS BIT(4) 23 #define PWR_ACK BIT(30) 24 #define PWR_ACK_2ND BIT(31) 25 26 #define SRAM_PDN BIT(8) 27 #define SRAM_PDN_ACK BIT(12) 28 29 #define MTCMOS_TIMEOUT_US 500 30 31 #define MTCMOS_ETIMEDOUT 25 32 33 static spinlock_t mtcmos_ctrl_lock; 34 35 static int mtcmos_wait_for_state(uint32_t reg, uint32_t mask, bool is_set) 36 { 37 uint32_t retry = MTCMOS_TIMEOUT_US; 38 uint32_t expect = is_set ? mask : 0; 39 40 do { 41 if ((mmio_read_32(reg) & mask) == expect) 42 return 0; 43 udelay(1); 44 retry--; 45 } while (retry); 46 47 ERROR("%s(0x%x, 0x%x, %d) timeout, reg_val=0x%x\n", 48 __func__, reg, mask, is_set, mmio_read_32(reg)); 49 50 return -MTCMOS_ETIMEDOUT; 51 } 52 53 54 static int spm_mtcmos_ctrl_bus_prot(const struct bus_protect *bp_table, uint32_t bp_steps) 55 { 56 int i; 57 58 for (i = 0; i < bp_steps; i++) { 59 mmio_write_32(bp_table[i].en_addr, bp_table[i].mask); 60 if (bp_table[i].rdy_addr) { 61 if (mtcmos_wait_for_state(bp_table[i].rdy_addr, bp_table[i].mask, true)) 62 return -MTCMOS_ETIMEDOUT; 63 } 64 } 65 return 0; 66 } 67 68 69 static int spm_mtcmos_ctrl(enum mtcmos_state state, uintptr_t reg, 70 bool has_sram, int *rtff_save_flag, 71 const struct bus_protect *bp_table, uint32_t bp_steps) 72 { 73 int ret = 0; 74 75 spin_lock(&mtcmos_ctrl_lock); 76 77 mmio_write_32(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | BIT(0)); 78 79 if (state == STA_POWER_DOWN) { 80 ret = spm_mtcmos_ctrl_bus_prot(bp_table, bp_steps); 81 if (ret) 82 goto exit; 83 84 if (has_sram) { 85 mmio_setbits_32(reg, SRAM_PDN); 86 ret = mtcmos_wait_for_state(reg, SRAM_PDN_ACK, true); 87 if (ret) 88 goto exit; 89 } 90 91 mmio_setbits_32(reg, RTFF_CLK_DIS); 92 mmio_setbits_32(reg, RTFF_SAVE); 93 mmio_clrbits_32(reg, RTFF_SAVE); 94 mmio_clrbits_32(reg, RTFF_CLK_DIS); 95 #ifdef RTFF_SAVE_FLAG 96 mmio_setbits_32(reg, RTFF_SAVE_FLAG); 97 #endif 98 *rtff_save_flag = 1; 99 100 101 mmio_setbits_32(reg, PWR_ISO); 102 mmio_setbits_32(reg, PWR_CLK_DIS); 103 mmio_clrbits_32(reg, PWR_RST_B); 104 105 mmio_clrbits_32(reg, PWR_ON); 106 ret = mtcmos_wait_for_state(reg, PWR_ACK, false); 107 if (ret) 108 goto exit; 109 110 mmio_clrbits_32(reg, PWR_ON_2ND); 111 ret = mtcmos_wait_for_state(reg, PWR_ACK_2ND, false); 112 if (ret) 113 goto exit; 114 } else if (state == STA_POWER_ON) { 115 mmio_setbits_32(reg, PWR_ON); 116 ret = mtcmos_wait_for_state(reg, PWR_ACK, true); 117 if (ret) 118 goto exit; 119 120 udelay(50); 121 122 mmio_setbits_32(reg, PWR_ON_2ND); 123 ret = mtcmos_wait_for_state(reg, PWR_ACK_2ND, true); 124 if (ret) 125 goto exit; 126 127 mmio_clrbits_32(reg, PWR_CLK_DIS); 128 mmio_clrbits_32(reg, PWR_ISO); 129 udelay(10); 130 mmio_setbits_32(reg, PWR_RST_B); 131 132 133 if (*rtff_save_flag == 1) { 134 mmio_setbits_32(reg, RTFF_CLK_DIS); 135 mmio_clrbits_32(reg, RTFF_NRESTORE); 136 mmio_setbits_32(reg, RTFF_NRESTORE); 137 mmio_clrbits_32(reg, RTFF_CLK_DIS); 138 #ifdef RTFF_SAVE_FLAG 139 mmio_clrbits_32(reg, RTFF_SAVE_FLAG); 140 #endif 141 *rtff_save_flag = 0; 142 } 143 144 if (has_sram) { 145 mmio_clrbits_32(reg, SRAM_PDN); 146 ret = mtcmos_wait_for_state(reg, SRAM_PDN_ACK, false); 147 if (ret) 148 goto exit; 149 } 150 151 spm_mtcmos_ctrl_bus_prot(bp_table, bp_steps); 152 } 153 154 exit: 155 spin_unlock(&mtcmos_ctrl_lock); 156 return ret; 157 } 158 159 int spm_mtcmos_ctrl_ufs0(enum mtcmos_state state) 160 { 161 static int rtff_save_flag; 162 const struct bus_protect *bp_table; 163 uint32_t bp_steps; 164 165 if (state == STA_POWER_DOWN) { 166 bp_table = &ufs0_bus_prot_set_table[0]; 167 bp_steps = ARRAY_SIZE(ufs0_bus_prot_set_table); 168 } else { 169 bp_table = &ufs0_bus_prot_clr_table[0]; 170 bp_steps = ARRAY_SIZE(ufs0_bus_prot_clr_table); 171 } 172 173 return spm_mtcmos_ctrl(state, UFS0_PWR_CON, false, &rtff_save_flag, 174 bp_table, bp_steps); 175 } 176 177 int spm_mtcmos_ctrl_ufs0_phy(enum mtcmos_state state) 178 { 179 static int rtff_save_flag; 180 const struct bus_protect *bp_table; 181 uint32_t bp_steps; 182 183 if (state == STA_POWER_DOWN) { 184 bp_table = &ufs0_phy_bus_prot_set_table[0]; 185 bp_steps = ARRAY_SIZE(ufs0_phy_bus_prot_set_table); 186 } else { 187 bp_table = &ufs0_phy_bus_prot_clr_table[0]; 188 bp_steps = ARRAY_SIZE(ufs0_phy_bus_prot_clr_table); 189 } 190 191 return spm_mtcmos_ctrl(state, UFS0_PHY_PWR_CON, true, &rtff_save_flag, 192 bp_table, bp_steps); 193 } 194