162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2020-2023 Intel Corporation 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include "ivpu_drv.h" 762306a36Sopenharmony_ci#include "ivpu_fw.h" 862306a36Sopenharmony_ci#include "ivpu_hw_37xx_reg.h" 962306a36Sopenharmony_ci#include "ivpu_hw_reg_io.h" 1062306a36Sopenharmony_ci#include "ivpu_hw.h" 1162306a36Sopenharmony_ci#include "ivpu_ipc.h" 1262306a36Sopenharmony_ci#include "ivpu_mmu.h" 1362306a36Sopenharmony_ci#include "ivpu_pm.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define TILE_FUSE_ENABLE_BOTH 0x0 1662306a36Sopenharmony_ci#define TILE_SKU_BOTH_MTL 0x3630 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* Work point configuration values */ 1962306a36Sopenharmony_ci#define CONFIG_1_TILE 0x01 2062306a36Sopenharmony_ci#define CONFIG_2_TILE 0x02 2162306a36Sopenharmony_ci#define PLL_RATIO_5_3 0x01 2262306a36Sopenharmony_ci#define PLL_RATIO_4_3 0x02 2362306a36Sopenharmony_ci#define WP_CONFIG(tile, ratio) (((tile) << 8) | (ratio)) 2462306a36Sopenharmony_ci#define WP_CONFIG_1_TILE_5_3_RATIO WP_CONFIG(CONFIG_1_TILE, PLL_RATIO_5_3) 2562306a36Sopenharmony_ci#define WP_CONFIG_1_TILE_4_3_RATIO WP_CONFIG(CONFIG_1_TILE, PLL_RATIO_4_3) 2662306a36Sopenharmony_ci#define WP_CONFIG_2_TILE_5_3_RATIO WP_CONFIG(CONFIG_2_TILE, PLL_RATIO_5_3) 2762306a36Sopenharmony_ci#define WP_CONFIG_2_TILE_4_3_RATIO WP_CONFIG(CONFIG_2_TILE, PLL_RATIO_4_3) 2862306a36Sopenharmony_ci#define WP_CONFIG_0_TILE_PLL_OFF WP_CONFIG(0, 0) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define PLL_REF_CLK_FREQ (50 * 1000000) 3162306a36Sopenharmony_ci#define PLL_SIMULATION_FREQ (10 * 1000000) 3262306a36Sopenharmony_ci#define PLL_DEFAULT_EPP_VALUE 0x80 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define TIM_SAFE_ENABLE 0xf1d0dead 3562306a36Sopenharmony_ci#define TIM_WATCHDOG_RESET_VALUE 0xffffffff 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define TIMEOUT_US (150 * USEC_PER_MSEC) 3862306a36Sopenharmony_ci#define PWR_ISLAND_STATUS_TIMEOUT_US (5 * USEC_PER_MSEC) 3962306a36Sopenharmony_ci#define PLL_TIMEOUT_US (1500 * USEC_PER_MSEC) 4062306a36Sopenharmony_ci#define IDLE_TIMEOUT_US (500 * USEC_PER_MSEC) 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define ICB_0_IRQ_MASK ((REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT)) | \ 4362306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT)) | \ 4462306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT)) | \ 4562306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT)) | \ 4662306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT)) | \ 4762306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT)) | \ 4862306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT))) 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#define ICB_1_IRQ_MASK ((REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_2_INT)) | \ 5162306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_3_INT)) | \ 5262306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_4_INT))) 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define ICB_0_1_IRQ_MASK ((((u64)ICB_1_IRQ_MASK) << 32) | ICB_0_IRQ_MASK) 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#define BUTTRESS_IRQ_MASK ((REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR)) | \ 5762306a36Sopenharmony_ci (REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, UFI_ERR))) 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#define BUTTRESS_ALL_IRQ_MASK (BUTTRESS_IRQ_MASK | \ 6062306a36Sopenharmony_ci (REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE))) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define BUTTRESS_IRQ_ENABLE_MASK ((u32)~BUTTRESS_IRQ_MASK) 6362306a36Sopenharmony_ci#define BUTTRESS_IRQ_DISABLE_MASK ((u32)-1) 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci#define ITF_FIREWALL_VIOLATION_MASK ((REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_ROM_CMX)) | \ 6662306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_DBG)) | \ 6762306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_CTRL)) | \ 6862306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, DEC400)) | \ 6962306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_NCE)) | \ 7062306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI)) | \ 7162306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI_CMX))) 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic char *ivpu_platform_to_str(u32 platform) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci switch (platform) { 7662306a36Sopenharmony_ci case IVPU_PLATFORM_SILICON: 7762306a36Sopenharmony_ci return "IVPU_PLATFORM_SILICON"; 7862306a36Sopenharmony_ci case IVPU_PLATFORM_SIMICS: 7962306a36Sopenharmony_ci return "IVPU_PLATFORM_SIMICS"; 8062306a36Sopenharmony_ci case IVPU_PLATFORM_FPGA: 8162306a36Sopenharmony_ci return "IVPU_PLATFORM_FPGA"; 8262306a36Sopenharmony_ci default: 8362306a36Sopenharmony_ci return "Invalid platform"; 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic void ivpu_hw_read_platform(struct ivpu_device *vdev) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci u32 gen_ctrl = REGV_RD32(VPU_37XX_HOST_SS_GEN_CTRL); 9062306a36Sopenharmony_ci u32 platform = REG_GET_FLD(VPU_37XX_HOST_SS_GEN_CTRL, PS, gen_ctrl); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci if (platform == IVPU_PLATFORM_SIMICS || platform == IVPU_PLATFORM_FPGA) 9362306a36Sopenharmony_ci vdev->platform = platform; 9462306a36Sopenharmony_ci else 9562306a36Sopenharmony_ci vdev->platform = IVPU_PLATFORM_SILICON; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci ivpu_dbg(vdev, MISC, "Platform type: %s (%d)\n", 9862306a36Sopenharmony_ci ivpu_platform_to_str(vdev->platform), vdev->platform); 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic void ivpu_hw_wa_init(struct ivpu_device *vdev) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci vdev->wa.punit_disabled = ivpu_is_fpga(vdev); 10462306a36Sopenharmony_ci vdev->wa.clear_runtime_mem = false; 10562306a36Sopenharmony_ci vdev->wa.d3hot_after_power_off = true; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, BUTTRESS_ALL_IRQ_MASK); 10862306a36Sopenharmony_ci if (REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) == BUTTRESS_ALL_IRQ_MASK) { 10962306a36Sopenharmony_ci /* Writing 1s does not clear the interrupt status register */ 11062306a36Sopenharmony_ci vdev->wa.interrupt_clear_with_0 = true; 11162306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, 0x0); 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci IVPU_PRINT_WA(punit_disabled); 11562306a36Sopenharmony_ci IVPU_PRINT_WA(clear_runtime_mem); 11662306a36Sopenharmony_ci IVPU_PRINT_WA(d3hot_after_power_off); 11762306a36Sopenharmony_ci IVPU_PRINT_WA(interrupt_clear_with_0); 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic void ivpu_hw_timeouts_init(struct ivpu_device *vdev) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci if (ivpu_is_simics(vdev) || ivpu_is_fpga(vdev)) { 12362306a36Sopenharmony_ci vdev->timeout.boot = 100000; 12462306a36Sopenharmony_ci vdev->timeout.jsm = 50000; 12562306a36Sopenharmony_ci vdev->timeout.tdr = 2000000; 12662306a36Sopenharmony_ci vdev->timeout.reschedule_suspend = 1000; 12762306a36Sopenharmony_ci } else { 12862306a36Sopenharmony_ci vdev->timeout.boot = 1000; 12962306a36Sopenharmony_ci vdev->timeout.jsm = 500; 13062306a36Sopenharmony_ci vdev->timeout.tdr = 2000; 13162306a36Sopenharmony_ci vdev->timeout.reschedule_suspend = 10; 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic int ivpu_pll_wait_for_cmd_send(struct ivpu_device *vdev) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci return REGB_POLL_FLD(VPU_37XX_BUTTRESS_WP_REQ_CMD, SEND, 0, PLL_TIMEOUT_US); 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci/* Send KMD initiated workpoint change */ 14162306a36Sopenharmony_cistatic int ivpu_pll_cmd_send(struct ivpu_device *vdev, u16 min_ratio, u16 max_ratio, 14262306a36Sopenharmony_ci u16 target_ratio, u16 config) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci int ret; 14562306a36Sopenharmony_ci u32 val; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci ret = ivpu_pll_wait_for_cmd_send(vdev); 14862306a36Sopenharmony_ci if (ret) { 14962306a36Sopenharmony_ci ivpu_err(vdev, "Failed to sync before WP request: %d\n", ret); 15062306a36Sopenharmony_ci return ret; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci val = REGB_RD32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0); 15462306a36Sopenharmony_ci val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0, MIN_RATIO, min_ratio, val); 15562306a36Sopenharmony_ci val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0, MAX_RATIO, max_ratio, val); 15662306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0, val); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci val = REGB_RD32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1); 15962306a36Sopenharmony_ci val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1, TARGET_RATIO, target_ratio, val); 16062306a36Sopenharmony_ci val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1, EPP, PLL_DEFAULT_EPP_VALUE, val); 16162306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1, val); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci val = REGB_RD32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2); 16462306a36Sopenharmony_ci val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2, CONFIG, config, val); 16562306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2, val); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci val = REGB_RD32(VPU_37XX_BUTTRESS_WP_REQ_CMD); 16862306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_BUTTRESS_WP_REQ_CMD, SEND, val); 16962306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_WP_REQ_CMD, val); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci ret = ivpu_pll_wait_for_cmd_send(vdev); 17262306a36Sopenharmony_ci if (ret) 17362306a36Sopenharmony_ci ivpu_err(vdev, "Failed to sync after WP request: %d\n", ret); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci return ret; 17662306a36Sopenharmony_ci} 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_cistatic int ivpu_pll_wait_for_lock(struct ivpu_device *vdev, bool enable) 17962306a36Sopenharmony_ci{ 18062306a36Sopenharmony_ci u32 exp_val = enable ? 0x1 : 0x0; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci if (IVPU_WA(punit_disabled)) 18362306a36Sopenharmony_ci return 0; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci return REGB_POLL_FLD(VPU_37XX_BUTTRESS_PLL_STATUS, LOCK, exp_val, PLL_TIMEOUT_US); 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic int ivpu_pll_wait_for_status_ready(struct ivpu_device *vdev) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci if (IVPU_WA(punit_disabled)) 19162306a36Sopenharmony_ci return 0; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci return REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_STATUS, READY, 1, PLL_TIMEOUT_US); 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic void ivpu_pll_init_frequency_ratios(struct ivpu_device *vdev) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci struct ivpu_hw_info *hw = vdev->hw; 19962306a36Sopenharmony_ci u8 fuse_min_ratio, fuse_max_ratio, fuse_pn_ratio; 20062306a36Sopenharmony_ci u32 fmin_fuse, fmax_fuse; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci fmin_fuse = REGB_RD32(VPU_37XX_BUTTRESS_FMIN_FUSE); 20362306a36Sopenharmony_ci fuse_min_ratio = REG_GET_FLD(VPU_37XX_BUTTRESS_FMIN_FUSE, MIN_RATIO, fmin_fuse); 20462306a36Sopenharmony_ci fuse_pn_ratio = REG_GET_FLD(VPU_37XX_BUTTRESS_FMIN_FUSE, PN_RATIO, fmin_fuse); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci fmax_fuse = REGB_RD32(VPU_37XX_BUTTRESS_FMAX_FUSE); 20762306a36Sopenharmony_ci fuse_max_ratio = REG_GET_FLD(VPU_37XX_BUTTRESS_FMAX_FUSE, MAX_RATIO, fmax_fuse); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci hw->pll.min_ratio = clamp_t(u8, ivpu_pll_min_ratio, fuse_min_ratio, fuse_max_ratio); 21062306a36Sopenharmony_ci hw->pll.max_ratio = clamp_t(u8, ivpu_pll_max_ratio, hw->pll.min_ratio, fuse_max_ratio); 21162306a36Sopenharmony_ci hw->pll.pn_ratio = clamp_t(u8, fuse_pn_ratio, hw->pll.min_ratio, hw->pll.max_ratio); 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_cistatic int ivpu_hw_37xx_wait_for_vpuip_bar(struct ivpu_device *vdev) 21562306a36Sopenharmony_ci{ 21662306a36Sopenharmony_ci return REGV_POLL_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, AON, 0, 100); 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic int ivpu_pll_drive(struct ivpu_device *vdev, bool enable) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci struct ivpu_hw_info *hw = vdev->hw; 22262306a36Sopenharmony_ci u16 target_ratio; 22362306a36Sopenharmony_ci u16 config; 22462306a36Sopenharmony_ci int ret; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci if (IVPU_WA(punit_disabled)) { 22762306a36Sopenharmony_ci ivpu_dbg(vdev, PM, "Skipping PLL request on %s\n", 22862306a36Sopenharmony_ci ivpu_platform_to_str(vdev->platform)); 22962306a36Sopenharmony_ci return 0; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci if (enable) { 23362306a36Sopenharmony_ci target_ratio = hw->pll.pn_ratio; 23462306a36Sopenharmony_ci config = hw->config; 23562306a36Sopenharmony_ci } else { 23662306a36Sopenharmony_ci target_ratio = 0; 23762306a36Sopenharmony_ci config = 0; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci ivpu_dbg(vdev, PM, "PLL workpoint request: config 0x%04x pll ratio 0x%x\n", 24162306a36Sopenharmony_ci config, target_ratio); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci ret = ivpu_pll_cmd_send(vdev, hw->pll.min_ratio, hw->pll.max_ratio, target_ratio, config); 24462306a36Sopenharmony_ci if (ret) { 24562306a36Sopenharmony_ci ivpu_err(vdev, "Failed to send PLL workpoint request: %d\n", ret); 24662306a36Sopenharmony_ci return ret; 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci ret = ivpu_pll_wait_for_lock(vdev, enable); 25062306a36Sopenharmony_ci if (ret) { 25162306a36Sopenharmony_ci ivpu_err(vdev, "Timed out waiting for PLL lock\n"); 25262306a36Sopenharmony_ci return ret; 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci if (enable) { 25662306a36Sopenharmony_ci ret = ivpu_pll_wait_for_status_ready(vdev); 25762306a36Sopenharmony_ci if (ret) { 25862306a36Sopenharmony_ci ivpu_err(vdev, "Timed out waiting for PLL ready status\n"); 25962306a36Sopenharmony_ci return ret; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci ret = ivpu_hw_37xx_wait_for_vpuip_bar(vdev); 26362306a36Sopenharmony_ci if (ret) { 26462306a36Sopenharmony_ci ivpu_err(vdev, "Timed out waiting for VPUIP bar\n"); 26562306a36Sopenharmony_ci return ret; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci return 0; 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic int ivpu_pll_enable(struct ivpu_device *vdev) 27362306a36Sopenharmony_ci{ 27462306a36Sopenharmony_ci return ivpu_pll_drive(vdev, true); 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_cistatic int ivpu_pll_disable(struct ivpu_device *vdev) 27862306a36Sopenharmony_ci{ 27962306a36Sopenharmony_ci return ivpu_pll_drive(vdev, false); 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic void ivpu_boot_host_ss_rst_clr_assert(struct ivpu_device *vdev) 28362306a36Sopenharmony_ci{ 28462306a36Sopenharmony_ci u32 val = 0; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, TOP_NOC, val); 28762306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, DSS_MAS, val); 28862306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, MSS_MAS, val); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_SS_CPR_RST_CLR, val); 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic void ivpu_boot_host_ss_rst_drive(struct ivpu_device *vdev, bool enable) 29462306a36Sopenharmony_ci{ 29562306a36Sopenharmony_ci u32 val = REGV_RD32(VPU_37XX_HOST_SS_CPR_RST_SET); 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci if (enable) { 29862306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, TOP_NOC, val); 29962306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, DSS_MAS, val); 30062306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, MSS_MAS, val); 30162306a36Sopenharmony_ci } else { 30262306a36Sopenharmony_ci val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, TOP_NOC, val); 30362306a36Sopenharmony_ci val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, DSS_MAS, val); 30462306a36Sopenharmony_ci val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, MSS_MAS, val); 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_SS_CPR_RST_SET, val); 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic void ivpu_boot_host_ss_clk_drive(struct ivpu_device *vdev, bool enable) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci u32 val = REGV_RD32(VPU_37XX_HOST_SS_CPR_CLK_SET); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci if (enable) { 31562306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, TOP_NOC, val); 31662306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, DSS_MAS, val); 31762306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, MSS_MAS, val); 31862306a36Sopenharmony_ci } else { 31962306a36Sopenharmony_ci val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, TOP_NOC, val); 32062306a36Sopenharmony_ci val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, DSS_MAS, val); 32162306a36Sopenharmony_ci val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, MSS_MAS, val); 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_SS_CPR_CLK_SET, val); 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cistatic int ivpu_boot_noc_qreqn_check(struct ivpu_device *vdev, u32 exp_val) 32862306a36Sopenharmony_ci{ 32962306a36Sopenharmony_ci u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QREQN); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, exp_val, val)) 33262306a36Sopenharmony_ci return -EIO; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci return 0; 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistatic int ivpu_boot_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val) 33862306a36Sopenharmony_ci{ 33962306a36Sopenharmony_ci u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QACCEPTN); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QACCEPTN, TOP_SOCMMIO, exp_val, val)) 34262306a36Sopenharmony_ci return -EIO; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci return 0; 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_cistatic int ivpu_boot_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) 34862306a36Sopenharmony_ci{ 34962306a36Sopenharmony_ci u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QDENY); 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QDENY, TOP_SOCMMIO, exp_val, val)) 35262306a36Sopenharmony_ci return -EIO; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci return 0; 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistatic int ivpu_boot_top_noc_qrenqn_check(struct ivpu_device *vdev, u32 exp_val) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QREQN); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) || 36262306a36Sopenharmony_ci !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val)) 36362306a36Sopenharmony_ci return -EIO; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci return 0; 36662306a36Sopenharmony_ci} 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cistatic int ivpu_boot_top_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QACCEPTN); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) || 37362306a36Sopenharmony_ci !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val)) 37462306a36Sopenharmony_ci return -EIO; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci return 0; 37762306a36Sopenharmony_ci} 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_cistatic int ivpu_boot_top_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QDENY); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) || 38462306a36Sopenharmony_ci !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val)) 38562306a36Sopenharmony_ci return -EIO; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci return 0; 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cistatic int ivpu_boot_host_ss_configure(struct ivpu_device *vdev) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci ivpu_boot_host_ss_rst_clr_assert(vdev); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci return ivpu_boot_noc_qreqn_check(vdev, 0x0); 39562306a36Sopenharmony_ci} 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_cistatic void ivpu_boot_vpu_idle_gen_disable(struct ivpu_device *vdev) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_SS_AON_VPU_IDLE_GEN, 0x0); 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cistatic int ivpu_boot_host_ss_axi_drive(struct ivpu_device *vdev, bool enable) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci int ret; 40562306a36Sopenharmony_ci u32 val; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QREQN); 40862306a36Sopenharmony_ci if (enable) 40962306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val); 41062306a36Sopenharmony_ci else 41162306a36Sopenharmony_ci val = REG_CLR_FLD(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val); 41262306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_SS_NOC_QREQN, val); 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci ret = ivpu_boot_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0); 41562306a36Sopenharmony_ci if (ret) { 41662306a36Sopenharmony_ci ivpu_err(vdev, "Failed qacceptn check: %d\n", ret); 41762306a36Sopenharmony_ci return ret; 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci ret = ivpu_boot_noc_qdeny_check(vdev, 0x0); 42162306a36Sopenharmony_ci if (ret) 42262306a36Sopenharmony_ci ivpu_err(vdev, "Failed qdeny check: %d\n", ret); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci return ret; 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_cistatic int ivpu_boot_host_ss_axi_enable(struct ivpu_device *vdev) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci return ivpu_boot_host_ss_axi_drive(vdev, true); 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_cistatic int ivpu_boot_host_ss_top_noc_drive(struct ivpu_device *vdev, bool enable) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci int ret; 43562306a36Sopenharmony_ci u32 val; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci val = REGV_RD32(MTL_VPU_TOP_NOC_QREQN); 43862306a36Sopenharmony_ci if (enable) { 43962306a36Sopenharmony_ci val = REG_SET_FLD(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, val); 44062306a36Sopenharmony_ci val = REG_SET_FLD(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); 44162306a36Sopenharmony_ci } else { 44262306a36Sopenharmony_ci val = REG_CLR_FLD(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, val); 44362306a36Sopenharmony_ci val = REG_CLR_FLD(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci REGV_WR32(MTL_VPU_TOP_NOC_QREQN, val); 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci ret = ivpu_boot_top_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0); 44862306a36Sopenharmony_ci if (ret) { 44962306a36Sopenharmony_ci ivpu_err(vdev, "Failed qacceptn check: %d\n", ret); 45062306a36Sopenharmony_ci return ret; 45162306a36Sopenharmony_ci } 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci ret = ivpu_boot_top_noc_qdeny_check(vdev, 0x0); 45462306a36Sopenharmony_ci if (ret) 45562306a36Sopenharmony_ci ivpu_err(vdev, "Failed qdeny check: %d\n", ret); 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci return ret; 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_cistatic int ivpu_boot_host_ss_top_noc_enable(struct ivpu_device *vdev) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci return ivpu_boot_host_ss_top_noc_drive(vdev, true); 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_cistatic void ivpu_boot_pwr_island_trickle_drive(struct ivpu_device *vdev, bool enable) 46662306a36Sopenharmony_ci{ 46762306a36Sopenharmony_ci u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0); 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci if (enable) 47062306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, MSS_CPU, val); 47162306a36Sopenharmony_ci else 47262306a36Sopenharmony_ci val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, MSS_CPU, val); 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, val); 47562306a36Sopenharmony_ci} 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_cistatic void ivpu_boot_pwr_island_drive(struct ivpu_device *vdev, bool enable) 47862306a36Sopenharmony_ci{ 47962306a36Sopenharmony_ci u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0); 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci if (enable) 48262306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, MSS_CPU, val); 48362306a36Sopenharmony_ci else 48462306a36Sopenharmony_ci val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, MSS_CPU, val); 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, val); 48762306a36Sopenharmony_ci} 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_cistatic int ivpu_boot_wait_for_pwr_island_status(struct ivpu_device *vdev, u32 exp_val) 49062306a36Sopenharmony_ci{ 49162306a36Sopenharmony_ci /* FPGA model (UPF) is not power aware, skipped Power Island polling */ 49262306a36Sopenharmony_ci if (ivpu_is_fpga(vdev)) 49362306a36Sopenharmony_ci return 0; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci return REGV_POLL_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_STATUS0, MSS_CPU, 49662306a36Sopenharmony_ci exp_val, PWR_ISLAND_STATUS_TIMEOUT_US); 49762306a36Sopenharmony_ci} 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_cistatic void ivpu_boot_pwr_island_isolation_drive(struct ivpu_device *vdev, bool enable) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0); 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci if (enable) 50462306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, MSS_CPU, val); 50562306a36Sopenharmony_ci else 50662306a36Sopenharmony_ci val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, MSS_CPU, val); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, val); 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cistatic void ivpu_boot_dpu_active_drive(struct ivpu_device *vdev, bool enable) 51262306a36Sopenharmony_ci{ 51362306a36Sopenharmony_ci u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_DPU_ACTIVE); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci if (enable) 51662306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, DPU_ACTIVE, val); 51762306a36Sopenharmony_ci else 51862306a36Sopenharmony_ci val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, DPU_ACTIVE, val); 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, val); 52162306a36Sopenharmony_ci} 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_cistatic int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci int ret; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci ivpu_boot_pwr_island_trickle_drive(vdev, true); 52862306a36Sopenharmony_ci ivpu_boot_pwr_island_drive(vdev, true); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci ret = ivpu_boot_wait_for_pwr_island_status(vdev, 0x1); 53162306a36Sopenharmony_ci if (ret) { 53262306a36Sopenharmony_ci ivpu_err(vdev, "Timed out waiting for power island status\n"); 53362306a36Sopenharmony_ci return ret; 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci ret = ivpu_boot_top_noc_qrenqn_check(vdev, 0x0); 53762306a36Sopenharmony_ci if (ret) { 53862306a36Sopenharmony_ci ivpu_err(vdev, "Failed qrenqn check %d\n", ret); 53962306a36Sopenharmony_ci return ret; 54062306a36Sopenharmony_ci } 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci ivpu_boot_host_ss_clk_drive(vdev, true); 54362306a36Sopenharmony_ci ivpu_boot_pwr_island_isolation_drive(vdev, false); 54462306a36Sopenharmony_ci ivpu_boot_host_ss_rst_drive(vdev, true); 54562306a36Sopenharmony_ci ivpu_boot_dpu_active_drive(vdev, true); 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci return ret; 54862306a36Sopenharmony_ci} 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_cistatic int ivpu_boot_pwr_domain_disable(struct ivpu_device *vdev) 55162306a36Sopenharmony_ci{ 55262306a36Sopenharmony_ci ivpu_boot_dpu_active_drive(vdev, false); 55362306a36Sopenharmony_ci ivpu_boot_pwr_island_isolation_drive(vdev, true); 55462306a36Sopenharmony_ci ivpu_boot_pwr_island_trickle_drive(vdev, false); 55562306a36Sopenharmony_ci ivpu_boot_pwr_island_drive(vdev, false); 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci return ivpu_boot_wait_for_pwr_island_status(vdev, 0x0); 55862306a36Sopenharmony_ci} 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_cistatic void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev) 56162306a36Sopenharmony_ci{ 56262306a36Sopenharmony_ci u32 val = REGV_RD32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES); 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, NOSNOOP_OVERRIDE_EN, val); 56562306a36Sopenharmony_ci val = REG_CLR_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AW_NOSNOOP_OVERRIDE, val); 56662306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AR_NOSNOOP_OVERRIDE, val); 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, val); 56962306a36Sopenharmony_ci} 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_cistatic void ivpu_boot_tbu_mmu_enable(struct ivpu_device *vdev) 57262306a36Sopenharmony_ci{ 57362306a36Sopenharmony_ci u32 val = REGV_RD32(VPU_37XX_HOST_IF_TBU_MMUSSIDV); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU0_AWMMUSSIDV, val); 57662306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU0_ARMMUSSIDV, val); 57762306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU2_AWMMUSSIDV, val); 57862306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU2_ARMMUSSIDV, val); 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_IF_TBU_MMUSSIDV, val); 58162306a36Sopenharmony_ci} 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_cistatic void ivpu_boot_soc_cpu_boot(struct ivpu_device *vdev) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci u32 val; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci val = REGV_RD32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC); 58862306a36Sopenharmony_ci val = REG_SET_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTRUN0, val); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci val = REG_CLR_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTVEC, val); 59162306a36Sopenharmony_ci REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci val = REG_SET_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); 59462306a36Sopenharmony_ci REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci val = REG_CLR_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); 59762306a36Sopenharmony_ci REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci val = vdev->fw->entry_point >> 9; 60062306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, val); 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, DONE, val); 60362306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, val); 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci ivpu_dbg(vdev, PM, "Booting firmware, mode: %s\n", 60662306a36Sopenharmony_ci vdev->fw->entry_point == vdev->fw->cold_boot_entry_point ? "cold boot" : "resume"); 60762306a36Sopenharmony_ci} 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_cistatic int ivpu_boot_d0i3_drive(struct ivpu_device *vdev, bool enable) 61062306a36Sopenharmony_ci{ 61162306a36Sopenharmony_ci int ret; 61262306a36Sopenharmony_ci u32 val; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US); 61562306a36Sopenharmony_ci if (ret) { 61662306a36Sopenharmony_ci ivpu_err(vdev, "Failed to sync before D0i3 transition: %d\n", ret); 61762306a36Sopenharmony_ci return ret; 61862306a36Sopenharmony_ci } 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci val = REGB_RD32(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL); 62162306a36Sopenharmony_ci if (enable) 62262306a36Sopenharmony_ci val = REG_SET_FLD(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, I3, val); 62362306a36Sopenharmony_ci else 62462306a36Sopenharmony_ci val = REG_CLR_FLD(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, I3, val); 62562306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, val); 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US); 62862306a36Sopenharmony_ci if (ret) 62962306a36Sopenharmony_ci ivpu_err(vdev, "Failed to sync after D0i3 transition: %d\n", ret); 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci return ret; 63262306a36Sopenharmony_ci} 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_cistatic int ivpu_hw_37xx_info_init(struct ivpu_device *vdev) 63562306a36Sopenharmony_ci{ 63662306a36Sopenharmony_ci struct ivpu_hw_info *hw = vdev->hw; 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci hw->tile_fuse = TILE_FUSE_ENABLE_BOTH; 63962306a36Sopenharmony_ci hw->sku = TILE_SKU_BOTH_MTL; 64062306a36Sopenharmony_ci hw->config = WP_CONFIG_2_TILE_4_3_RATIO; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci ivpu_pll_init_frequency_ratios(vdev); 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci ivpu_hw_init_range(&hw->ranges.global, 0x80000000, SZ_512M); 64562306a36Sopenharmony_ci ivpu_hw_init_range(&hw->ranges.user, 0xc0000000, 255 * SZ_1M); 64662306a36Sopenharmony_ci ivpu_hw_init_range(&hw->ranges.shave, 0x180000000, SZ_2G); 64762306a36Sopenharmony_ci ivpu_hw_init_range(&hw->ranges.dma, 0x200000000, SZ_8G); 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci ivpu_hw_read_platform(vdev); 65062306a36Sopenharmony_ci ivpu_hw_wa_init(vdev); 65162306a36Sopenharmony_ci ivpu_hw_timeouts_init(vdev); 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci return 0; 65462306a36Sopenharmony_ci} 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_cistatic int ivpu_hw_37xx_reset(struct ivpu_device *vdev) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci int ret = 0; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci if (ivpu_boot_pwr_domain_disable(vdev)) { 66162306a36Sopenharmony_ci ivpu_err(vdev, "Failed to disable power domain\n"); 66262306a36Sopenharmony_ci ret = -EIO; 66362306a36Sopenharmony_ci } 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci if (ivpu_pll_disable(vdev)) { 66662306a36Sopenharmony_ci ivpu_err(vdev, "Failed to disable PLL\n"); 66762306a36Sopenharmony_ci ret = -EIO; 66862306a36Sopenharmony_ci } 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci return ret; 67162306a36Sopenharmony_ci} 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_cistatic int ivpu_hw_37xx_d0i3_enable(struct ivpu_device *vdev) 67462306a36Sopenharmony_ci{ 67562306a36Sopenharmony_ci int ret; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci ret = ivpu_boot_d0i3_drive(vdev, true); 67862306a36Sopenharmony_ci if (ret) 67962306a36Sopenharmony_ci ivpu_err(vdev, "Failed to enable D0i3: %d\n", ret); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci udelay(5); /* VPU requires 5 us to complete the transition */ 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci return ret; 68462306a36Sopenharmony_ci} 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_cistatic int ivpu_hw_37xx_d0i3_disable(struct ivpu_device *vdev) 68762306a36Sopenharmony_ci{ 68862306a36Sopenharmony_ci int ret; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci ret = ivpu_boot_d0i3_drive(vdev, false); 69162306a36Sopenharmony_ci if (ret) 69262306a36Sopenharmony_ci ivpu_err(vdev, "Failed to disable D0i3: %d\n", ret); 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci return ret; 69562306a36Sopenharmony_ci} 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_cistatic int ivpu_hw_37xx_power_up(struct ivpu_device *vdev) 69862306a36Sopenharmony_ci{ 69962306a36Sopenharmony_ci int ret; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci ret = ivpu_hw_37xx_d0i3_disable(vdev); 70262306a36Sopenharmony_ci if (ret) 70362306a36Sopenharmony_ci ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret); 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci ret = ivpu_pll_enable(vdev); 70662306a36Sopenharmony_ci if (ret) { 70762306a36Sopenharmony_ci ivpu_err(vdev, "Failed to enable PLL: %d\n", ret); 70862306a36Sopenharmony_ci return ret; 70962306a36Sopenharmony_ci } 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci ret = ivpu_boot_host_ss_configure(vdev); 71262306a36Sopenharmony_ci if (ret) { 71362306a36Sopenharmony_ci ivpu_err(vdev, "Failed to configure host SS: %d\n", ret); 71462306a36Sopenharmony_ci return ret; 71562306a36Sopenharmony_ci } 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci /* 71862306a36Sopenharmony_ci * The control circuitry for vpu_idle indication logic powers up active. 71962306a36Sopenharmony_ci * To ensure unnecessary low power mode signal from LRT during bring up, 72062306a36Sopenharmony_ci * KMD disables the circuitry prior to bringing up the Main Power island. 72162306a36Sopenharmony_ci */ 72262306a36Sopenharmony_ci ivpu_boot_vpu_idle_gen_disable(vdev); 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci ret = ivpu_boot_pwr_domain_enable(vdev); 72562306a36Sopenharmony_ci if (ret) { 72662306a36Sopenharmony_ci ivpu_err(vdev, "Failed to enable power domain: %d\n", ret); 72762306a36Sopenharmony_ci return ret; 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci ret = ivpu_boot_host_ss_axi_enable(vdev); 73162306a36Sopenharmony_ci if (ret) { 73262306a36Sopenharmony_ci ivpu_err(vdev, "Failed to enable AXI: %d\n", ret); 73362306a36Sopenharmony_ci return ret; 73462306a36Sopenharmony_ci } 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci ret = ivpu_boot_host_ss_top_noc_enable(vdev); 73762306a36Sopenharmony_ci if (ret) 73862306a36Sopenharmony_ci ivpu_err(vdev, "Failed to enable TOP NOC: %d\n", ret); 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci return ret; 74162306a36Sopenharmony_ci} 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_cistatic int ivpu_hw_37xx_boot_fw(struct ivpu_device *vdev) 74462306a36Sopenharmony_ci{ 74562306a36Sopenharmony_ci ivpu_boot_no_snoop_enable(vdev); 74662306a36Sopenharmony_ci ivpu_boot_tbu_mmu_enable(vdev); 74762306a36Sopenharmony_ci ivpu_boot_soc_cpu_boot(vdev); 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci return 0; 75062306a36Sopenharmony_ci} 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_cistatic bool ivpu_hw_37xx_is_idle(struct ivpu_device *vdev) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci u32 val; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci if (IVPU_WA(punit_disabled)) 75762306a36Sopenharmony_ci return true; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci val = REGB_RD32(VPU_37XX_BUTTRESS_VPU_STATUS); 76062306a36Sopenharmony_ci return REG_TEST_FLD(VPU_37XX_BUTTRESS_VPU_STATUS, READY, val) && 76162306a36Sopenharmony_ci REG_TEST_FLD(VPU_37XX_BUTTRESS_VPU_STATUS, IDLE, val); 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_cistatic int ivpu_hw_37xx_power_down(struct ivpu_device *vdev) 76562306a36Sopenharmony_ci{ 76662306a36Sopenharmony_ci int ret = 0; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci if (!ivpu_hw_37xx_is_idle(vdev)) 76962306a36Sopenharmony_ci ivpu_warn(vdev, "VPU not idle during power down\n"); 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci if (ivpu_hw_37xx_reset(vdev)) { 77262306a36Sopenharmony_ci ivpu_err(vdev, "Failed to reset VPU\n"); 77362306a36Sopenharmony_ci ret = -EIO; 77462306a36Sopenharmony_ci } 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci if (ivpu_hw_37xx_d0i3_enable(vdev)) { 77762306a36Sopenharmony_ci ivpu_err(vdev, "Failed to enter D0I3\n"); 77862306a36Sopenharmony_ci ret = -EIO; 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci return ret; 78262306a36Sopenharmony_ci} 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_cistatic void ivpu_hw_37xx_wdt_disable(struct ivpu_device *vdev) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci u32 val; 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci /* Enable writing and set non-zero WDT value */ 78962306a36Sopenharmony_ci REGV_WR32(MTL_VPU_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); 79062306a36Sopenharmony_ci REGV_WR32(MTL_VPU_CPU_SS_TIM_WATCHDOG, TIM_WATCHDOG_RESET_VALUE); 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci /* Enable writing and disable watchdog timer */ 79362306a36Sopenharmony_ci REGV_WR32(MTL_VPU_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); 79462306a36Sopenharmony_ci REGV_WR32(MTL_VPU_CPU_SS_TIM_WDOG_EN, 0); 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci /* Now clear the timeout interrupt */ 79762306a36Sopenharmony_ci val = REGV_RD32(MTL_VPU_CPU_SS_TIM_GEN_CONFIG); 79862306a36Sopenharmony_ci val = REG_CLR_FLD(MTL_VPU_CPU_SS_TIM_GEN_CONFIG, WDOG_TO_INT_CLR, val); 79962306a36Sopenharmony_ci REGV_WR32(MTL_VPU_CPU_SS_TIM_GEN_CONFIG, val); 80062306a36Sopenharmony_ci} 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_cistatic u32 ivpu_hw_37xx_pll_to_freq(u32 ratio, u32 config) 80362306a36Sopenharmony_ci{ 80462306a36Sopenharmony_ci u32 pll_clock = PLL_REF_CLK_FREQ * ratio; 80562306a36Sopenharmony_ci u32 cpu_clock; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci if ((config & 0xff) == PLL_RATIO_4_3) 80862306a36Sopenharmony_ci cpu_clock = pll_clock * 2 / 4; 80962306a36Sopenharmony_ci else 81062306a36Sopenharmony_ci cpu_clock = pll_clock * 2 / 5; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci return cpu_clock; 81362306a36Sopenharmony_ci} 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci/* Register indirect accesses */ 81662306a36Sopenharmony_cistatic u32 ivpu_hw_37xx_reg_pll_freq_get(struct ivpu_device *vdev) 81762306a36Sopenharmony_ci{ 81862306a36Sopenharmony_ci u32 pll_curr_ratio; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci pll_curr_ratio = REGB_RD32(VPU_37XX_BUTTRESS_CURRENT_PLL); 82162306a36Sopenharmony_ci pll_curr_ratio &= VPU_37XX_BUTTRESS_CURRENT_PLL_RATIO_MASK; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci if (!ivpu_is_silicon(vdev)) 82462306a36Sopenharmony_ci return PLL_SIMULATION_FREQ; 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci return ivpu_hw_37xx_pll_to_freq(pll_curr_ratio, vdev->hw->config); 82762306a36Sopenharmony_ci} 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_cistatic u32 ivpu_hw_37xx_reg_telemetry_offset_get(struct ivpu_device *vdev) 83062306a36Sopenharmony_ci{ 83162306a36Sopenharmony_ci return REGB_RD32(VPU_37XX_BUTTRESS_VPU_TELEMETRY_OFFSET); 83262306a36Sopenharmony_ci} 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_cistatic u32 ivpu_hw_37xx_reg_telemetry_size_get(struct ivpu_device *vdev) 83562306a36Sopenharmony_ci{ 83662306a36Sopenharmony_ci return REGB_RD32(VPU_37XX_BUTTRESS_VPU_TELEMETRY_SIZE); 83762306a36Sopenharmony_ci} 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_cistatic u32 ivpu_hw_37xx_reg_telemetry_enable_get(struct ivpu_device *vdev) 84062306a36Sopenharmony_ci{ 84162306a36Sopenharmony_ci return REGB_RD32(VPU_37XX_BUTTRESS_VPU_TELEMETRY_ENABLE); 84262306a36Sopenharmony_ci} 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_cistatic void ivpu_hw_37xx_reg_db_set(struct ivpu_device *vdev, u32 db_id) 84562306a36Sopenharmony_ci{ 84662306a36Sopenharmony_ci u32 reg_stride = MTL_VPU_CPU_SS_DOORBELL_1 - MTL_VPU_CPU_SS_DOORBELL_0; 84762306a36Sopenharmony_ci u32 val = REG_FLD(MTL_VPU_CPU_SS_DOORBELL_0, SET); 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci REGV_WR32I(MTL_VPU_CPU_SS_DOORBELL_0, reg_stride, db_id, val); 85062306a36Sopenharmony_ci} 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_cistatic u32 ivpu_hw_37xx_reg_ipc_rx_addr_get(struct ivpu_device *vdev) 85362306a36Sopenharmony_ci{ 85462306a36Sopenharmony_ci return REGV_RD32(VPU_37XX_HOST_SS_TIM_IPC_FIFO_ATM); 85562306a36Sopenharmony_ci} 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_cistatic u32 ivpu_hw_37xx_reg_ipc_rx_count_get(struct ivpu_device *vdev) 85862306a36Sopenharmony_ci{ 85962306a36Sopenharmony_ci u32 count = REGV_RD32_SILENT(VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT); 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci return REG_GET_FLD(VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT, FILL_LEVEL, count); 86262306a36Sopenharmony_ci} 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_cistatic void ivpu_hw_37xx_reg_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr) 86562306a36Sopenharmony_ci{ 86662306a36Sopenharmony_ci REGV_WR32(MTL_VPU_CPU_SS_TIM_IPC_FIFO, vpu_addr); 86762306a36Sopenharmony_ci} 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_cistatic void ivpu_hw_37xx_irq_clear(struct ivpu_device *vdev) 87062306a36Sopenharmony_ci{ 87162306a36Sopenharmony_ci REGV_WR64(VPU_37XX_HOST_SS_ICB_CLEAR_0, ICB_0_1_IRQ_MASK); 87262306a36Sopenharmony_ci} 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_cistatic void ivpu_hw_37xx_irq_enable(struct ivpu_device *vdev) 87562306a36Sopenharmony_ci{ 87662306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, ITF_FIREWALL_VIOLATION_MASK); 87762306a36Sopenharmony_ci REGV_WR64(VPU_37XX_HOST_SS_ICB_ENABLE_0, ICB_0_1_IRQ_MASK); 87862306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_ENABLE_MASK); 87962306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x0); 88062306a36Sopenharmony_ci} 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_cistatic void ivpu_hw_37xx_irq_disable(struct ivpu_device *vdev) 88362306a36Sopenharmony_ci{ 88462306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x1); 88562306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_DISABLE_MASK); 88662306a36Sopenharmony_ci REGV_WR64(VPU_37XX_HOST_SS_ICB_ENABLE_0, 0x0ull); 88762306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, 0x0); 88862306a36Sopenharmony_ci} 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_cistatic void ivpu_hw_37xx_irq_wdt_nce_handler(struct ivpu_device *vdev) 89162306a36Sopenharmony_ci{ 89262306a36Sopenharmony_ci ivpu_err_ratelimited(vdev, "WDT NCE irq\n"); 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci ivpu_pm_schedule_recovery(vdev); 89562306a36Sopenharmony_ci} 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_cistatic void ivpu_hw_37xx_irq_wdt_mss_handler(struct ivpu_device *vdev) 89862306a36Sopenharmony_ci{ 89962306a36Sopenharmony_ci ivpu_err_ratelimited(vdev, "WDT MSS irq\n"); 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci ivpu_hw_wdt_disable(vdev); 90262306a36Sopenharmony_ci ivpu_pm_schedule_recovery(vdev); 90362306a36Sopenharmony_ci} 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_cistatic void ivpu_hw_37xx_irq_noc_firewall_handler(struct ivpu_device *vdev) 90662306a36Sopenharmony_ci{ 90762306a36Sopenharmony_ci ivpu_err_ratelimited(vdev, "NOC Firewall irq\n"); 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci ivpu_pm_schedule_recovery(vdev); 91062306a36Sopenharmony_ci} 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci/* Handler for IRQs from VPU core (irqV) */ 91362306a36Sopenharmony_cistatic u32 ivpu_hw_37xx_irqv_handler(struct ivpu_device *vdev, int irq) 91462306a36Sopenharmony_ci{ 91562306a36Sopenharmony_ci u32 status = REGV_RD32(VPU_37XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK; 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_SS_ICB_CLEAR_0, status); 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT, status)) 92062306a36Sopenharmony_ci ivpu_mmu_irq_evtq_handler(vdev); 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT, status)) 92362306a36Sopenharmony_ci ivpu_ipc_irq_handler(vdev); 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT, status)) 92662306a36Sopenharmony_ci ivpu_dbg(vdev, IRQ, "MMU sync complete\n"); 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT, status)) 92962306a36Sopenharmony_ci ivpu_mmu_irq_gerr_handler(vdev); 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, status)) 93262306a36Sopenharmony_ci ivpu_hw_37xx_irq_wdt_mss_handler(vdev); 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, status)) 93562306a36Sopenharmony_ci ivpu_hw_37xx_irq_wdt_nce_handler(vdev); 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, status)) 93862306a36Sopenharmony_ci ivpu_hw_37xx_irq_noc_firewall_handler(vdev); 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci return status; 94162306a36Sopenharmony_ci} 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci/* Handler for IRQs from Buttress core (irqB) */ 94462306a36Sopenharmony_cistatic u32 ivpu_hw_37xx_irqb_handler(struct ivpu_device *vdev, int irq) 94562306a36Sopenharmony_ci{ 94662306a36Sopenharmony_ci u32 status = REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) & BUTTRESS_IRQ_MASK; 94762306a36Sopenharmony_ci bool schedule_recovery = false; 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci if (status == 0) 95062306a36Sopenharmony_ci return 0; 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE, status)) 95362306a36Sopenharmony_ci ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x", 95462306a36Sopenharmony_ci REGB_RD32(VPU_37XX_BUTTRESS_CURRENT_PLL)); 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR, status)) { 95762306a36Sopenharmony_ci ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_37XX_BUTTRESS_ATS_ERR_LOG_0)); 95862306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_ATS_ERR_CLEAR, 0x1); 95962306a36Sopenharmony_ci schedule_recovery = true; 96062306a36Sopenharmony_ci } 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, UFI_ERR, status)) { 96362306a36Sopenharmony_ci u32 ufi_log = REGB_RD32(VPU_37XX_BUTTRESS_UFI_ERR_LOG); 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci ivpu_err(vdev, "UFI_ERR irq (0x%08x) opcode: 0x%02lx axi_id: 0x%02lx cq_id: 0x%03lx", 96662306a36Sopenharmony_ci ufi_log, REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, OPCODE, ufi_log), 96762306a36Sopenharmony_ci REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, AXI_ID, ufi_log), 96862306a36Sopenharmony_ci REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, CQ_ID, ufi_log)); 96962306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_UFI_ERR_CLEAR, 0x1); 97062306a36Sopenharmony_ci schedule_recovery = true; 97162306a36Sopenharmony_ci } 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci /* This must be done after interrupts are cleared at the source. */ 97462306a36Sopenharmony_ci if (IVPU_WA(interrupt_clear_with_0)) 97562306a36Sopenharmony_ci /* 97662306a36Sopenharmony_ci * Writing 1 triggers an interrupt, so we can't perform read update write. 97762306a36Sopenharmony_ci * Clear local interrupt status by writing 0 to all bits. 97862306a36Sopenharmony_ci */ 97962306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, 0x0); 98062306a36Sopenharmony_ci else 98162306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, status); 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci if (schedule_recovery) 98462306a36Sopenharmony_ci ivpu_pm_schedule_recovery(vdev); 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci return status; 98762306a36Sopenharmony_ci} 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_cistatic irqreturn_t ivpu_hw_37xx_irq_handler(int irq, void *ptr) 99062306a36Sopenharmony_ci{ 99162306a36Sopenharmony_ci struct ivpu_device *vdev = ptr; 99262306a36Sopenharmony_ci u32 ret_irqv, ret_irqb; 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x1); 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci ret_irqv = ivpu_hw_37xx_irqv_handler(vdev, irq); 99762306a36Sopenharmony_ci ret_irqb = ivpu_hw_37xx_irqb_handler(vdev, irq); 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci /* Re-enable global interrupts to re-trigger MSI for pending interrupts */ 100062306a36Sopenharmony_ci REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x0); 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci return IRQ_RETVAL(ret_irqb | ret_irqv); 100362306a36Sopenharmony_ci} 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_cistatic void ivpu_hw_37xx_diagnose_failure(struct ivpu_device *vdev) 100662306a36Sopenharmony_ci{ 100762306a36Sopenharmony_ci u32 irqv = REGV_RD32(VPU_37XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK; 100862306a36Sopenharmony_ci u32 irqb = REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) & BUTTRESS_IRQ_MASK; 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci if (ivpu_hw_37xx_reg_ipc_rx_count_get(vdev)) 101162306a36Sopenharmony_ci ivpu_err(vdev, "IPC FIFO queue not empty, missed IPC IRQ"); 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, irqv)) 101462306a36Sopenharmony_ci ivpu_err(vdev, "WDT MSS timeout detected\n"); 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, irqv)) 101762306a36Sopenharmony_ci ivpu_err(vdev, "WDT NCE timeout detected\n"); 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, irqv)) 102062306a36Sopenharmony_ci ivpu_err(vdev, "NOC Firewall irq detected\n"); 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR, irqb)) 102362306a36Sopenharmony_ci ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_37XX_BUTTRESS_ATS_ERR_LOG_0)); 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, UFI_ERR, irqb)) { 102662306a36Sopenharmony_ci u32 ufi_log = REGB_RD32(VPU_37XX_BUTTRESS_UFI_ERR_LOG); 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci ivpu_err(vdev, "UFI_ERR irq (0x%08x) opcode: 0x%02lx axi_id: 0x%02lx cq_id: 0x%03lx", 102962306a36Sopenharmony_ci ufi_log, REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, OPCODE, ufi_log), 103062306a36Sopenharmony_ci REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, AXI_ID, ufi_log), 103162306a36Sopenharmony_ci REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, CQ_ID, ufi_log)); 103262306a36Sopenharmony_ci } 103362306a36Sopenharmony_ci} 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ciconst struct ivpu_hw_ops ivpu_hw_37xx_ops = { 103662306a36Sopenharmony_ci .info_init = ivpu_hw_37xx_info_init, 103762306a36Sopenharmony_ci .power_up = ivpu_hw_37xx_power_up, 103862306a36Sopenharmony_ci .is_idle = ivpu_hw_37xx_is_idle, 103962306a36Sopenharmony_ci .power_down = ivpu_hw_37xx_power_down, 104062306a36Sopenharmony_ci .reset = ivpu_hw_37xx_reset, 104162306a36Sopenharmony_ci .boot_fw = ivpu_hw_37xx_boot_fw, 104262306a36Sopenharmony_ci .wdt_disable = ivpu_hw_37xx_wdt_disable, 104362306a36Sopenharmony_ci .diagnose_failure = ivpu_hw_37xx_diagnose_failure, 104462306a36Sopenharmony_ci .reg_pll_freq_get = ivpu_hw_37xx_reg_pll_freq_get, 104562306a36Sopenharmony_ci .reg_telemetry_offset_get = ivpu_hw_37xx_reg_telemetry_offset_get, 104662306a36Sopenharmony_ci .reg_telemetry_size_get = ivpu_hw_37xx_reg_telemetry_size_get, 104762306a36Sopenharmony_ci .reg_telemetry_enable_get = ivpu_hw_37xx_reg_telemetry_enable_get, 104862306a36Sopenharmony_ci .reg_db_set = ivpu_hw_37xx_reg_db_set, 104962306a36Sopenharmony_ci .reg_ipc_rx_addr_get = ivpu_hw_37xx_reg_ipc_rx_addr_get, 105062306a36Sopenharmony_ci .reg_ipc_rx_count_get = ivpu_hw_37xx_reg_ipc_rx_count_get, 105162306a36Sopenharmony_ci .reg_ipc_tx_set = ivpu_hw_37xx_reg_ipc_tx_set, 105262306a36Sopenharmony_ci .irq_clear = ivpu_hw_37xx_irq_clear, 105362306a36Sopenharmony_ci .irq_enable = ivpu_hw_37xx_irq_enable, 105462306a36Sopenharmony_ci .irq_disable = ivpu_hw_37xx_irq_disable, 105562306a36Sopenharmony_ci .irq_handler = ivpu_hw_37xx_irq_handler, 105662306a36Sopenharmony_ci}; 1057