1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022-2024 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 WRAPPER_TZ_BASE_OFFS 0x000C0000 14 #define AON_BASE_OFFS 0x000E0000 15 #define AON_MVP_NOC_RESET 0x0001F000 16 17 #define WRAPPER_DEBUG_BRIDGE_LPI_CONTROL (WRAPPER_BASE_OFFS + 0x54) 18 #define WRAPPER_DEBUG_BRIDGE_LPI_STATUS (WRAPPER_BASE_OFFS + 0x58) 19 #define WRAPPER_IRIS_CPU_NOC_LPI_CONTROL (WRAPPER_BASE_OFFS + 0x5C) 20 #define REQ_POWER_DOWN_PREP BIT(0) 21 #define WRAPPER_IRIS_CPU_NOC_LPI_STATUS (WRAPPER_BASE_OFFS + 0x60) 22 #define WRAPPER_CORE_CLOCK_CONFIG (WRAPPER_BASE_OFFS + 0x88) 23 #define CORE_CLK_RUN 0x0 24 25 #define WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG (WRAPPER_TZ_BASE_OFFS + 0x14) 26 #define CTL_AXI_CLK_HALT BIT(0) 27 #define CTL_CLK_HALT BIT(1) 28 29 #define WRAPPER_TZ_QNS4PDXFIFO_RESET (WRAPPER_TZ_BASE_OFFS + 0x18) 30 #define RESET_HIGH BIT(0) 31 32 #define CPU_CS_AHB_BRIDGE_SYNC_RESET (CPU_CS_BASE_OFFS + 0x160) 33 #define CORE_BRIDGE_SW_RESET BIT(0) 34 #define CORE_BRIDGE_HW_RESET_DISABLE BIT(1) 35 36 #define CPU_CS_X2RPMH (CPU_CS_BASE_OFFS + 0x168) 37 #define MSK_SIGNAL_FROM_TENSILICA BIT(0) 38 #define MSK_CORE_POWER_ON BIT(1) 39 40 #define AON_WRAPPER_MVP_NOC_RESET_REQ (AON_MVP_NOC_RESET + 0x000) 41 #define VIDEO_NOC_RESET_REQ (BIT(0) | BIT(1)) 42 43 #define AON_WRAPPER_MVP_NOC_RESET_ACK (AON_MVP_NOC_RESET + 0x004) 44 45 #define VCODEC_SS_IDLE_STATUSN (VCODEC_BASE_OFFS + 0x70) 46 47 #define AON_WRAPPER_MVP_NOC_LPI_CONTROL (AON_BASE_OFFS) 48 #define AON_WRAPPER_MVP_NOC_LPI_STATUS (AON_BASE_OFFS + 0x4) 49 50 #define AON_WRAPPER_MVP_NOC_CORE_SW_RESET (AON_BASE_OFFS + 0x18) 51 #define SW_RESET BIT(0) 52 #define AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL (AON_BASE_OFFS + 0x20) 53 #define NOC_HALT BIT(0) 54 #define AON_WRAPPER_SPARE (AON_BASE_OFFS + 0x28) 55 56 static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core) 57 { 58 u32 value, pwr_status; 59 60 value = readl(core->reg_base + WRAPPER_CORE_POWER_STATUS); 61 pwr_status = value & BIT(1); 62 63 return pwr_status ? false : true; 64 } 65 66 static void iris_vpu3_power_off_hardware(struct iris_core *core) 67 { 68 u32 reg_val = 0, value, i; 69 int ret; 70 71 if (iris_vpu3x_hw_power_collapsed(core)) 72 goto disable_power; 73 74 dev_err(core->dev, "video hw is power on\n"); 75 76 value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); 77 if (value) 78 writel(CORE_CLK_RUN, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); 79 80 for (i = 0; i < core->iris_platform_data->num_vpp_pipe; i++) { 81 ret = readl_poll_timeout(core->reg_base + VCODEC_SS_IDLE_STATUSN + 4 * i, 82 reg_val, reg_val & 0x400000, 2000, 20000); 83 if (ret) 84 goto disable_power; 85 } 86 87 writel(VIDEO_NOC_RESET_REQ, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); 88 89 ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, 90 reg_val, reg_val & 0x3, 200, 2000); 91 if (ret) 92 goto disable_power; 93 94 writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); 95 96 ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, 97 reg_val, !(reg_val & 0x3), 200, 2000); 98 if (ret) 99 goto disable_power; 100 101 writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, 102 core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); 103 writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); 104 writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); 105 106 disable_power: 107 iris_vpu_power_off_hw(core); 108 } 109 110 static void iris_vpu33_power_off_hardware(struct iris_core *core) 111 { 112 u32 reg_val = 0, value, i; 113 int ret; 114 115 if (iris_vpu3x_hw_power_collapsed(core)) 116 goto disable_power; 117 118 dev_err(core->dev, "video hw is power on\n"); 119 120 value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); 121 if (value) 122 writel(CORE_CLK_RUN, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); 123 124 for (i = 0; i < core->iris_platform_data->num_vpp_pipe; i++) { 125 ret = readl_poll_timeout(core->reg_base + VCODEC_SS_IDLE_STATUSN + 4 * i, 126 reg_val, reg_val & 0x400000, 2000, 20000); 127 if (ret) 128 goto disable_power; 129 } 130 131 ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS, 132 reg_val, reg_val & BIT(0), 200, 2000); 133 if (ret) 134 goto disable_power; 135 136 /* set MNoC to low power, set PD_NOC_QREQ (bit 0) */ 137 writel(BIT(0), core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); 138 139 writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, 140 core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); 141 writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); 142 writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); 143 144 disable_power: 145 iris_vpu_power_off_hw(core); 146 } 147 148 static int iris_vpu33_power_off_controller(struct iris_core *core) 149 { 150 u32 xo_rst_tbl_size = core->iris_platform_data->controller_rst_tbl_size; 151 u32 clk_rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; 152 u32 val = 0; 153 int ret; 154 155 writel(MSK_SIGNAL_FROM_TENSILICA | MSK_CORE_POWER_ON, core->reg_base + CPU_CS_X2RPMH); 156 157 writel(REQ_POWER_DOWN_PREP, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL); 158 159 ret = readl_poll_timeout(core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_STATUS, 160 val, val & BIT(0), 200, 2000); 161 if (ret) 162 goto disable_power; 163 164 writel(0x0, core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL); 165 166 ret = readl_poll_timeout(core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_STATUS, 167 val, val == 0, 200, 2000); 168 if (ret) 169 goto disable_power; 170 171 writel(CTL_AXI_CLK_HALT | CTL_CLK_HALT, 172 core->reg_base + WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG); 173 writel(RESET_HIGH, core->reg_base + WRAPPER_TZ_QNS4PDXFIFO_RESET); 174 writel(0x0, core->reg_base + WRAPPER_TZ_QNS4PDXFIFO_RESET); 175 writel(0x0, core->reg_base + WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG); 176 177 reset_control_bulk_reset(clk_rst_tbl_size, core->resets); 178 179 /* Disable MVP NoC clock */ 180 val = readl(core->reg_base + AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL); 181 val |= NOC_HALT; 182 writel(val, core->reg_base + AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL); 183 184 /* enable MVP NoC reset */ 185 val = readl(core->reg_base + AON_WRAPPER_MVP_NOC_CORE_SW_RESET); 186 val |= SW_RESET; 187 writel(val, core->reg_base + AON_WRAPPER_MVP_NOC_CORE_SW_RESET); 188 189 /* poll AON spare register bit0 to become zero with 50ms timeout */ 190 ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_SPARE, 191 val, (val & BIT(0)) == 0, 1000, 50000); 192 if (ret) 193 goto disable_power; 194 195 /* enable bit(1) to avoid cvp noc xo reset */ 196 val = readl(core->reg_base + AON_WRAPPER_SPARE); 197 val |= BIT(1); 198 writel(val, core->reg_base + AON_WRAPPER_SPARE); 199 200 reset_control_bulk_assert(xo_rst_tbl_size, core->controller_resets); 201 202 /* De-assert MVP NoC reset */ 203 val = readl(core->reg_base + AON_WRAPPER_MVP_NOC_CORE_SW_RESET); 204 val &= ~SW_RESET; 205 writel(val, core->reg_base + AON_WRAPPER_MVP_NOC_CORE_SW_RESET); 206 207 usleep_range(80, 100); 208 209 reset_control_bulk_deassert(xo_rst_tbl_size, core->controller_resets); 210 211 /* reset AON spare register */ 212 writel(0, core->reg_base + AON_WRAPPER_SPARE); 213 214 /* Enable MVP NoC clock */ 215 val = readl(core->reg_base + AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL); 216 val &= ~NOC_HALT; 217 writel(val, core->reg_base + AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL); 218 219 iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); 220 221 disable_power: 222 iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); 223 iris_disable_unprepare_clock(core, IRIS_AXI_CLK); 224 225 return 0; 226 } 227 228 static u64 iris_vpu3x_calculate_frequency(struct iris_inst *inst, size_t data_size) 229 { 230 struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; 231 struct v4l2_format *inp_f = inst->fmt_src; 232 u32 height, width, mbs_per_second, mbpf; 233 u64 fw_cycles, fw_vpp_cycles; 234 u64 vsp_cycles, vpp_cycles; 235 u32 fps = DEFAULT_FPS; 236 237 width = max(inp_f->fmt.pix_mp.width, inst->crop.width); 238 height = max(inp_f->fmt.pix_mp.height, inst->crop.height); 239 240 mbpf = NUM_MBS_PER_FRAME(height, width); 241 mbs_per_second = mbpf * fps; 242 243 fw_cycles = fps * caps->mb_cycles_fw; 244 fw_vpp_cycles = fps * caps->mb_cycles_fw_vpp; 245 246 vpp_cycles = mult_frac(mbs_per_second, caps->mb_cycles_vpp, (u32)inst->fw_caps[PIPE].value); 247 /* 21 / 20 is minimum overhead factor */ 248 vpp_cycles += max(div_u64(vpp_cycles, 20), fw_vpp_cycles); 249 250 /* 1.059 is multi-pipe overhead */ 251 if (inst->fw_caps[PIPE].value > 1) 252 vpp_cycles += div_u64(vpp_cycles * 59, 1000); 253 254 vsp_cycles = fps * data_size * 8; 255 vsp_cycles = div_u64(vsp_cycles, 2); 256 /* VSP FW overhead 1.05 */ 257 vsp_cycles = div_u64(vsp_cycles * 21, 20); 258 259 if (inst->fw_caps[STAGE].value == STAGE_1) 260 vsp_cycles = vsp_cycles * 3; 261 262 return max3(vpp_cycles, vsp_cycles, fw_cycles); 263 } 264 265 const struct vpu_ops iris_vpu3_ops = { 266 .power_off_hw = iris_vpu3_power_off_hardware, 267 .power_off_controller = iris_vpu_power_off_controller, 268 .calc_freq = iris_vpu3x_calculate_frequency, 269 }; 270 271 const struct vpu_ops iris_vpu33_ops = { 272 .power_off_hw = iris_vpu33_power_off_hardware, 273 .power_off_controller = iris_vpu33_power_off_controller, 274 .calc_freq = iris_vpu3x_calculate_frequency, 275 }; 276