1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 6 #include <linux/iopoll.h> 7 #include <linux/reset.h> 8 9 #include "iris_instance.h" 10 #include "iris_vpu_common.h" 11 #include "iris_vpu_register_defines.h" 12 13 #define AON_WRAPPER_MVP_NOC_RESET_SYNCRST (AON_MVP_NOC_RESET + 0x08) 14 #define CPU_CS_APV_BRIDGE_SYNC_RESET (CPU_BASE_OFFS + 0x174) 15 #define MVP_NOC_RESET_REQ_MASK 0x70103 16 #define VPU_IDLE_BITS 0x7103 17 #define WRAPPER_EFUSE_MONITOR (WRAPPER_BASE_OFFS + 0x08) 18 19 #define APV_CLK_HALT BIT(1) 20 #define CORE_CLK_HALT BIT(0) 21 #define CORE_PWR_ON BIT(1) 22 #define DISABLE_VIDEO_APV_BIT BIT(27) 23 #define DISABLE_VIDEO_VPP1_BIT BIT(28) 24 #define DISABLE_VIDEO_VPP0_BIT BIT(29) 25 26 static int iris_vpu4x_genpd_set_hwmode(struct iris_core *core, bool hw_mode, u32 efuse_value) 27 { 28 int ret; 29 30 ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], hw_mode); 31 if (ret) 32 return ret; 33 34 if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) { 35 ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs 36 [IRIS_VPP0_HW_POWER_DOMAIN], hw_mode); 37 if (ret) 38 goto restore_hw_domain_mode; 39 } 40 41 if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) { 42 ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs 43 [IRIS_VPP1_HW_POWER_DOMAIN], hw_mode); 44 if (ret) 45 goto restore_vpp0_domain_mode; 46 } 47 48 if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) { 49 ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs 50 [IRIS_APV_HW_POWER_DOMAIN], hw_mode); 51 if (ret) 52 goto restore_vpp1_domain_mode; 53 } 54 55 return 0; 56 57 restore_vpp1_domain_mode: 58 if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) 59 dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VPP1_HW_POWER_DOMAIN], 60 !hw_mode); 61 restore_vpp0_domain_mode: 62 if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) 63 dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VPP0_HW_POWER_DOMAIN], 64 !hw_mode); 65 restore_hw_domain_mode: 66 dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], !hw_mode); 67 68 return ret; 69 } 70 71 static int iris_vpu4x_power_on_apv(struct iris_core *core) 72 { 73 int ret; 74 75 ret = iris_enable_power_domains(core, 76 core->pmdomain_tbl->pd_devs[IRIS_APV_HW_POWER_DOMAIN]); 77 if (ret) 78 return ret; 79 80 ret = iris_prepare_enable_clock(core, IRIS_APV_HW_CLK); 81 if (ret) 82 goto disable_apv_hw_power_domain; 83 84 return 0; 85 86 disable_apv_hw_power_domain: 87 iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_APV_HW_POWER_DOMAIN]); 88 89 return ret; 90 } 91 92 static void iris_vpu4x_power_off_apv(struct iris_core *core) 93 { 94 bool handshake_done, handshake_busy; 95 u32 value, count = 0; 96 int ret; 97 98 value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); 99 100 if (value & APV_CLK_HALT) 101 writel(0x0, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); 102 103 do { 104 writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); 105 usleep_range(10, 20); 106 value = readl(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS); 107 108 handshake_done = value & NOC_LPI_STATUS_DONE; 109 handshake_busy = value & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE); 110 111 if (handshake_done || !handshake_busy) 112 break; 113 114 writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); 115 usleep_range(10, 20); 116 117 } while (++count < 1000); 118 119 if (!handshake_done && handshake_busy) 120 dev_err(core->dev, "LPI handshake timeout\n"); 121 122 writel(0x080200, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); 123 ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, 124 value, value & 0x080200, 200, 2000); 125 if (ret) 126 goto disable_clocks_and_power; 127 128 writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_SYNCRST); 129 writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); 130 ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, 131 value, value == 0x0, 200, 2000); 132 if (ret) 133 goto disable_clocks_and_power; 134 135 writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + 136 CPU_CS_APV_BRIDGE_SYNC_RESET); 137 writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_APV_BRIDGE_SYNC_RESET); 138 writel(0x0, core->reg_base + CPU_CS_APV_BRIDGE_SYNC_RESET); 139 140 disable_clocks_and_power: 141 iris_disable_unprepare_clock(core, IRIS_APV_HW_CLK); 142 iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_APV_HW_POWER_DOMAIN]); 143 } 144 145 static void iris_vpu4x_ahb_sync_reset_apv(struct iris_core *core) 146 { 147 writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + 148 CPU_CS_APV_BRIDGE_SYNC_RESET); 149 writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_APV_BRIDGE_SYNC_RESET); 150 writel(0x0, core->reg_base + CPU_CS_APV_BRIDGE_SYNC_RESET); 151 } 152 153 static void iris_vpu4x_ahb_sync_reset_hardware(struct iris_core *core) 154 { 155 writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + 156 CPU_CS_AHB_BRIDGE_SYNC_RESET); 157 writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); 158 writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); 159 } 160 161 static int iris_vpu4x_enable_hardware_clocks(struct iris_core *core, u32 efuse_value) 162 { 163 int ret; 164 165 ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); 166 if (ret) 167 return ret; 168 169 ret = iris_prepare_enable_clock(core, IRIS_HW_FREERUN_CLK); 170 if (ret) 171 goto disable_axi_clock; 172 173 ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); 174 if (ret) 175 goto disable_hw_free_run_clock; 176 177 ret = iris_prepare_enable_clock(core, IRIS_BSE_HW_CLK); 178 if (ret) 179 goto disable_hw_clock; 180 181 if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) { 182 ret = iris_prepare_enable_clock(core, IRIS_VPP0_HW_CLK); 183 if (ret) 184 goto disable_bse_hw_clock; 185 } 186 187 if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) { 188 ret = iris_prepare_enable_clock(core, IRIS_VPP1_HW_CLK); 189 if (ret) 190 goto disable_vpp0_hw_clock; 191 } 192 193 return 0; 194 195 disable_vpp0_hw_clock: 196 if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) 197 iris_disable_unprepare_clock(core, IRIS_VPP0_HW_CLK); 198 disable_bse_hw_clock: 199 iris_disable_unprepare_clock(core, IRIS_BSE_HW_CLK); 200 disable_hw_clock: 201 iris_disable_unprepare_clock(core, IRIS_HW_CLK); 202 disable_hw_free_run_clock: 203 iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); 204 disable_axi_clock: 205 iris_disable_unprepare_clock(core, IRIS_AXI_CLK); 206 207 return ret; 208 } 209 210 static void iris_vpu4x_disable_hardware_clocks(struct iris_core *core, u32 efuse_value) 211 { 212 if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) 213 iris_disable_unprepare_clock(core, IRIS_VPP1_HW_CLK); 214 215 if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) 216 iris_disable_unprepare_clock(core, IRIS_VPP0_HW_CLK); 217 218 iris_disable_unprepare_clock(core, IRIS_BSE_HW_CLK); 219 iris_disable_unprepare_clock(core, IRIS_HW_CLK); 220 iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); 221 iris_disable_unprepare_clock(core, IRIS_AXI_CLK); 222 } 223 224 static int iris_vpu4x_power_on_hardware(struct iris_core *core) 225 { 226 u32 efuse_value = readl(core->reg_base + WRAPPER_EFUSE_MONITOR); 227 int ret; 228 229 ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); 230 if (ret) 231 return ret; 232 233 if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) { 234 ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs 235 [IRIS_VPP0_HW_POWER_DOMAIN]); 236 if (ret) 237 goto disable_hw_power_domain; 238 } 239 240 if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) { 241 ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs 242 [IRIS_VPP1_HW_POWER_DOMAIN]); 243 if (ret) 244 goto disable_vpp0_power_domain; 245 } 246 247 ret = iris_vpu4x_enable_hardware_clocks(core, efuse_value); 248 if (ret) 249 goto disable_vpp1_power_domain; 250 251 if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) { 252 ret = iris_vpu4x_power_on_apv(core); 253 if (ret) 254 goto disable_hw_clocks; 255 256 iris_vpu4x_ahb_sync_reset_apv(core); 257 } 258 259 iris_vpu4x_ahb_sync_reset_hardware(core); 260 261 ret = iris_vpu4x_genpd_set_hwmode(core, true, efuse_value); 262 if (ret) 263 goto disable_apv_power_domain; 264 265 return 0; 266 267 disable_apv_power_domain: 268 if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) 269 iris_vpu4x_power_off_apv(core); 270 disable_hw_clocks: 271 iris_vpu4x_disable_hardware_clocks(core, efuse_value); 272 disable_vpp1_power_domain: 273 if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) 274 iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs 275 [IRIS_VPP1_HW_POWER_DOMAIN]); 276 disable_vpp0_power_domain: 277 if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) 278 iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs 279 [IRIS_VPP0_HW_POWER_DOMAIN]); 280 disable_hw_power_domain: 281 iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); 282 283 return ret; 284 } 285 286 static void iris_vpu4x_power_off_hardware(struct iris_core *core) 287 { 288 u32 efuse_value = readl(core->reg_base + WRAPPER_EFUSE_MONITOR); 289 bool handshake_done, handshake_busy; 290 u32 value, count = 0; 291 int ret; 292 293 iris_vpu4x_genpd_set_hwmode(core, false, efuse_value); 294 295 if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) 296 iris_vpu4x_power_off_apv(core); 297 298 value = readl(core->reg_base + WRAPPER_CORE_POWER_STATUS); 299 300 if (!(value & CORE_PWR_ON)) 301 goto disable_clocks_and_power; 302 303 value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); 304 305 if (value & CORE_CLK_HALT) 306 writel(0x0, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); 307 308 readl_poll_timeout(core->reg_base + VCODEC_SS_IDLE_STATUSN, value, 309 value & VPU_IDLE_BITS, 2000, 20000); 310 311 do { 312 writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); 313 usleep_range(10, 20); 314 value = readl(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS); 315 316 handshake_done = value & NOC_LPI_STATUS_DONE; 317 handshake_busy = value & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE); 318 319 if (handshake_done || !handshake_busy) 320 break; 321 322 writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); 323 usleep_range(10, 20); 324 325 } while (++count < 1000); 326 327 if (!handshake_done && handshake_busy) 328 dev_err(core->dev, "LPI handshake timeout\n"); 329 330 writel(MVP_NOC_RESET_REQ_MASK, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); 331 ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, 332 value, value & MVP_NOC_RESET_REQ_MASK, 200, 2000); 333 if (ret) 334 goto disable_clocks_and_power; 335 336 writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_SYNCRST); 337 writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); 338 ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, 339 value, value == 0x0, 200, 2000); 340 if (ret) 341 goto disable_clocks_and_power; 342 343 writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + 344 CPU_CS_AHB_BRIDGE_SYNC_RESET); 345 writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); 346 writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); 347 348 disable_clocks_and_power: 349 iris_vpu4x_disable_hardware_clocks(core, efuse_value); 350 351 if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) 352 iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs 353 [IRIS_VPP1_HW_POWER_DOMAIN]); 354 355 if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) 356 iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs 357 [IRIS_VPP0_HW_POWER_DOMAIN]); 358 359 iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); 360 } 361 362 const struct vpu_ops iris_vpu4x_ops = { 363 .power_off_hw = iris_vpu4x_power_off_hardware, 364 .power_on_hw = iris_vpu4x_power_on_hardware, 365 .power_off_controller = iris_vpu35_vpu4x_power_off_controller, 366 .power_on_controller = iris_vpu35_vpu4x_power_on_controller, 367 .program_bootup_registers = iris_vpu35_vpu4x_program_bootup_registers, 368 .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, 369 }; 370