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 RTFF_SAVE BIT(24) 24 #define RTFF_NRESTORE BIT(25) 25 #define RTFF_CLK_DIS BIT(26) 26 #define RTFF_SAVE_FLAG BIT(27) 27 #define PWR_ACK BIT(30) 28 #define PWR_ACK_2ND BIT(31) 29 30 #define UFS0_SRAM_PDN BIT(8) 31 #define UFS0_SRAM_PDN_ACK BIT(12) 32 33 #define POWERON_CONFIG_EN (SPM_BASE + 0x0) 34 #define UFS0_PWR_CON (SPM_BASE + 0xE2C) 35 #define UFS0_PHY_PWR_CON (SPM_BASE + 0xE30) 36 37 #define SPM_BUS_PROTECT_EN_SET (SPM_BASE + 0x90DC) 38 #define SPM_BUS_PROTECT_EN_CLR (SPM_BASE + 0x90E0) 39 #define SPM_BUS_PROTECT_CG_EN_SET (SPM_BASE + 0x90F4) 40 #define SPM_BUS_PROTECT_CG_EN_CLR (SPM_BASE + 0x90F8) 41 #define SPM_BUS_PROTECT_RDY_STA (SPM_BASE + 0x9208) 42 43 #define UFS0_PROT_STEP1_MASK BIT(11) 44 #define UFS0_PHY_PROT_STEP1_MASK BIT(12) 45 46 enum { 47 RELEASE_BUS_PROTECT, 48 SET_BUS_PROTECT 49 }; 50 51 #define MTCMOS_TIMEOUT_US 500 52 53 #define MTCMOS_ETIMEDOUT 25 54 55 static spinlock_t mtcmos_ctrl_lock; 56 57 static int mtcmos_wait_for_state(uint32_t reg, uint32_t mask, bool is_set) 58 { 59 uint32_t retry = MTCMOS_TIMEOUT_US; 60 uint32_t expect = is_set ? mask : 0; 61 62 do { 63 if ((mmio_read_32(reg) & mask) == expect) 64 return 0; 65 udelay(1); 66 retry--; 67 } while (retry); 68 69 ERROR("%s(0x%x, 0x%x, %d) timeout, reg_val=0x%x\n", 70 __func__, reg, mask, is_set, mmio_read_32(reg)); 71 72 return -MTCMOS_ETIMEDOUT; 73 } 74 75 76 static int spm_mtcmos_ctrl_bus_prot(int state, uint32_t mask) 77 { 78 mmio_write_32(SPM_BUS_PROTECT_CG_EN_SET, mask); 79 80 if (state == SET_BUS_PROTECT) { 81 mmio_write_32(SPM_BUS_PROTECT_EN_SET, mask); 82 if (mtcmos_wait_for_state(SPM_BUS_PROTECT_RDY_STA, mask, 83 true)) 84 return -MTCMOS_ETIMEDOUT; 85 } else if (state == RELEASE_BUS_PROTECT) { 86 mmio_write_32(SPM_BUS_PROTECT_EN_CLR, mask); 87 } 88 89 mmio_write_32(SPM_BUS_PROTECT_CG_EN_CLR, mask); 90 91 return 0; 92 } 93 94 static int spm_mtcmos_ctrl(enum mtcmos_state state, uintptr_t reg, uint32_t mask) 95 { 96 int ret = 0; 97 98 spin_lock(&mtcmos_ctrl_lock); 99 100 mmio_write_32(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | BIT(0)); 101 102 if (state == STA_POWER_DOWN) { 103 ret = spm_mtcmos_ctrl_bus_prot(SET_BUS_PROTECT, mask); 104 if (ret) 105 goto exit; 106 107 if (reg == UFS0_PWR_CON) { 108 mmio_setbits_32(reg, UFS0_SRAM_PDN); 109 ret = mtcmos_wait_for_state(reg, UFS0_SRAM_PDN_ACK, 110 true); 111 if (ret) 112 goto exit; 113 } 114 115 mmio_setbits_32(reg, RTFF_CLK_DIS); 116 mmio_setbits_32(reg, RTFF_SAVE); 117 mmio_clrbits_32(reg, RTFF_SAVE); 118 mmio_clrbits_32(reg, RTFF_CLK_DIS); 119 mmio_setbits_32(reg, RTFF_SAVE_FLAG); 120 121 mmio_setbits_32(reg, PWR_ISO); 122 mmio_setbits_32(reg, PWR_CLK_DIS); 123 mmio_clrbits_32(reg, PWR_RST_B); 124 125 mmio_clrbits_32(reg, PWR_ON); 126 ret = mtcmos_wait_for_state(reg, PWR_ACK, false); 127 if (ret) 128 goto exit; 129 130 mmio_clrbits_32(reg, PWR_ON_2ND); 131 ret = mtcmos_wait_for_state(reg, PWR_ACK_2ND, false); 132 if (ret) 133 goto exit; 134 } else if (state == STA_POWER_ON) { 135 mmio_setbits_32(reg, PWR_ON); 136 ret = mtcmos_wait_for_state(reg, PWR_ACK, true); 137 if (ret) 138 goto exit; 139 140 udelay(50); 141 142 mmio_setbits_32(reg, PWR_ON_2ND); 143 ret = mtcmos_wait_for_state(reg, PWR_ACK_2ND, true); 144 if (ret) 145 goto exit; 146 147 mmio_clrbits_32(reg, PWR_CLK_DIS); 148 mmio_clrbits_32(reg, PWR_ISO); 149 udelay(10); 150 mmio_setbits_32(reg, PWR_RST_B); 151 152 if ((mmio_read_32(reg) & RTFF_SAVE_FLAG) == RTFF_SAVE_FLAG) { 153 mmio_setbits_32(reg, RTFF_CLK_DIS); 154 mmio_clrbits_32(reg, RTFF_NRESTORE); 155 mmio_setbits_32(reg, RTFF_NRESTORE); 156 mmio_clrbits_32(reg, RTFF_CLK_DIS); 157 } 158 159 if (reg == UFS0_PWR_CON) { 160 mmio_clrbits_32(UFS0_PWR_CON, UFS0_SRAM_PDN); 161 ret = mtcmos_wait_for_state(UFS0_PWR_CON, 162 UFS0_SRAM_PDN_ACK, 163 false); 164 if (ret) 165 goto exit; 166 } 167 168 spm_mtcmos_ctrl_bus_prot(RELEASE_BUS_PROTECT, mask); 169 } 170 171 exit: 172 spin_unlock(&mtcmos_ctrl_lock); 173 return ret; 174 } 175 176 int spm_mtcmos_ctrl_ufs0(enum mtcmos_state state) 177 { 178 return spm_mtcmos_ctrl(state, UFS0_PWR_CON, UFS0_PROT_STEP1_MASK); 179 } 180 181 int spm_mtcmos_ctrl_ufs0_phy(enum mtcmos_state state) 182 { 183 return spm_mtcmos_ctrl(state, UFS0_PHY_PWR_CON, 184 UFS0_PHY_PROT_STEP1_MASK); 185 } 186