summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorqctecmdr <qctecmdr@localhost>2023-04-09 23:52:36 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2023-04-09 23:52:36 -0700
commit8c168cdcbf7eedc8142537bc7eaec34ab2cc51e3 (patch)
tree70df8b40769ecc01b3062c337e3286d100c671b4
parentec1f1800efa2c4f93f648a185b8d7860f8014dde (diff)
parent0e3cc983e8bf95a01c47ac00307a9808d5329297 (diff)
downloadvideo-driver-8c168cdcbf7eedc8142537bc7eaec34ab2cc51e3.tar.gz
Merge "video: driver: Modify AR50LT Reset sequence"
-rw-r--r--driver/variant/ar50lt/src/msm_vidc_ar50lt.c167
1 files changed, 141 insertions, 26 deletions
diff --git a/driver/variant/ar50lt/src/msm_vidc_ar50lt.c b/driver/variant/ar50lt/src/msm_vidc_ar50lt.c
index f183763..204acfe 100644
--- a/driver/variant/ar50lt/src/msm_vidc_ar50lt.c
+++ b/driver/variant/ar50lt/src/msm_vidc_ar50lt.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "msm_vidc_ar50lt.h"
@@ -65,6 +65,8 @@
/* VIDC_UC_REGION_ADDR */
#define VIDC_CPU_CS_SCIBARG2_AR50_LT (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x68)
+#define VIDC_CPU_CS_AHB_BRIDGE_SYNC_RESET (VIDC_CPU_CS_BASE_OFFS_AR50_LT + 0x160)
+
#define VIDC_CPU_IC_SOFTINT_EN_AR50_LT (VIDC_CPU_IC_BASE_OFFS_AR50_LT + 0x148)
#define VIDC_CPU_IC_SOFTINT_AR50_LT (VIDC_CPU_IC_BASE_OFFS_AR50_LT + 0x150)
#define VIDC_CPU_IC_SOFTINT_H2A_BMSK_AR50_LT 0x8000
@@ -104,6 +106,14 @@
#define VIDC_WRAPPER_INTR_CLEAR_A2H_BMSK_AR50_LT 0x4
#define VIDC_WRAPPER_INTR_CLEAR_A2H_SHFT_AR50_LT 0x2
+#define WRAPPER_CORE_POWER_STATUS (VIDC_WRAPPER_BASE_OFFS_AR50_LT + 0x90)
+
+#define VENUS_WRAPPER_VCODEC0_SW_RESET (VIDC_WRAPPER_BASE_OFFS_AR50_LT + 0x98)
+#define VENUS_WRAPPER_VCODEC0_SW_RESET___M 0x09FFFF7F
+#define DMA_NOC_SW_RESET 0x00000004
+#define DMA_RIF_SW_RESET 0x00000008
+#define NOC_PARTIAL_RESET_SW_RESET 0x8000000
+
/*
* --------------------------------------------------------------------------
* MODULE: tz_wrapper
@@ -132,6 +142,11 @@
#define VIDC_UC_REGION_ADDR_AR50_LT VIDC_CPU_CS_SCIBARG1_AR50_LT
#define VIDC_UC_REGION_SIZE_AR50_LT VIDC_CPU_CS_SCIBARG2_AR50_LT
+#define VENUS_SS_VIDEO_NOC_PARTIAL_RESET_REQ 0x60
+#define VENUS_SS_VIDEO_NOC_PARTIAL_RESET_ACK 0x64
+
+#define VENUS_DMA_SPARE_3 0x3BDC
+
static int __boot_firmware_ar50lt(struct msm_vidc_core *vidc_core)
{
int rc = 0;
@@ -545,31 +560,122 @@ fail_regulator:
return rc;
}
+static bool is_ar50lt_hw_power_collapsed(struct msm_vidc_core *core)
+{
+ int rc = 0;
+ u32 value = 0, pwr_status = 0;
+
+ rc = __read_register(core, WRAPPER_CORE_POWER_STATUS, &value);
+ if (rc)
+ return false;
+
+ // if (1), CORE_SS(0) power is on and if (0), CORE_ss(0) power is off
+ pwr_status = value & BIT(1);
+
+ return pwr_status ? false : true;
+
+}
+
static int __power_off_ar50lt_hardware(struct msm_vidc_core *core)
{
int rc = 0;
+ if (core->hw_power_control && is_ar50lt_hw_power_collapsed(core)) {
+ d_vpr_h("%s: hardware power control enabled and power collapsed\n", __func__);
+ goto disable_power;
+ }
+
+ d_vpr_e("%s: hardware is not power collapsed, doing now\n", __func__);
+
+ rc = __write_register(core, VENUS_DMA_SPARE_3, 0x1);
+ if (rc)
+ return rc;
+
+ rc = __write_register(core, VENUS_SS_VIDEO_NOC_PARTIAL_RESET_REQ, 0x1);
+ if (rc)
+ return rc;
+
+ rc = __read_register_with_poll_timeout(core, VENUS_SS_VIDEO_NOC_PARTIAL_RESET_ACK,
+ BIT(0), 0x1, 2000, 50000);
+ if (rc)
+ d_vpr_h("%s: VENUS_SS_VIDEO_NOC_PARTIAL_RESET_ACK assert failed with %d\n",
+ __func__, rc);
+
+ rc = __write_register_masked(core, VENUS_WRAPPER_VCODEC0_SW_RESET,
+ NOC_PARTIAL_RESET_SW_RESET, BIT(27));
+ if (rc)
+ return rc;
+
+ rc = __write_register_masked(core, VENUS_WRAPPER_VCODEC0_SW_RESET,
+ 0x0, BIT(27));
+ if (rc)
+ return rc;
+
+ rc = __write_register(core, VENUS_SS_VIDEO_NOC_PARTIAL_RESET_REQ, 0);
+ if (rc)
+ return rc;
+
+ rc = __read_register_with_poll_timeout(core, VENUS_SS_VIDEO_NOC_PARTIAL_RESET_ACK,
+ BIT(0), 0x0, 2000, 50000);
+ if (rc)
+ d_vpr_h("%s: VENUS_SS_VIDEO_NOC_PARTIAL_RESET_ACK deassert failed with %d\n",
+ __func__, rc);
+
+ rc = __write_register(core, VENUS_WRAPPER_VCODEC0_SW_RESET,
+ VENUS_WRAPPER_VCODEC0_SW_RESET___M &
+ (~(DMA_NOC_SW_RESET | DMA_RIF_SW_RESET | NOC_PARTIAL_RESET_SW_RESET)));
+ if (rc)
+ return rc;
+
+ rc = __write_register(core, VENUS_WRAPPER_VCODEC0_SW_RESET, 0);
+ if (rc)
+ return rc;
+
+ rc = __write_register(core, VENUS_WRAPPER_VCODEC0_SW_RESET,
+ VENUS_WRAPPER_VCODEC0_SW_RESET___M &
+ (~(DMA_NOC_SW_RESET | NOC_PARTIAL_RESET_SW_RESET)));
+ if (rc)
+ return rc;
+
+ rc = __write_register(core, VENUS_WRAPPER_VCODEC0_SW_RESET, 0);
+ if (rc)
+ return rc;
+
+ /*
+ * Reset both sides of 2 ahb2ahb_bridges (TZ and non-TZ)
+ */
+ rc = __write_register(core, VIDC_CPU_CS_AHB_BRIDGE_SYNC_RESET, 0x3);
+ if (rc)
+ return rc;
+ rc = __write_register(core, VIDC_CPU_CS_AHB_BRIDGE_SYNC_RESET, 0x2);
+ if (rc)
+ return rc;
+ rc = __write_register(core, VIDC_CPU_CS_AHB_BRIDGE_SYNC_RESET, 0x0);
+ if (rc)
+ return rc;
+
+disable_power:
/* power down process */
rc = __disable_regulator_ar50lt(core, "venus-core0");
if (rc) {
- d_vpr_e("%s: disable regulator vcodec failed\n", __func__);
+ d_vpr_e("%s: disable regulator vcodec failed with %d\n", __func__, rc);
rc = 0;
}
rc = __disable_unprepare_clock_ar50lt(core, "core0_clk");
if (rc) {
- d_vpr_e("%s: disable unprepare core0_clk failed\n", __func__);
+ d_vpr_e("%s: disable unprepare core0_clk failed with %d\n", __func__, rc);
rc = 0;
}
rc = __disable_unprepare_clock_ar50lt(core, "core0_bus_clk");
if (rc) {
- d_vpr_e("%s: disable unprepare core0_bus_clk failed\n", __func__);
+ d_vpr_e("%s: disable unprepare core0_bus_clk failed with %d\n", __func__, rc);
rc = 0;
}
rc = __disable_unprepare_clock_ar50lt(core, "throttle_clk");
if (rc) {
- d_vpr_e("%s: disable unprepare throttle_clk failed\n", __func__);
+ d_vpr_e("%s: disable unprepare throttle_clk failed with %d\n", __func__, rc);
rc = 0;
}
@@ -580,30 +686,36 @@ static int __power_off_ar50lt_controller(struct msm_vidc_core *core)
{
int rc = 0;
+ /* power down process */
+ rc = __disable_regulator_ar50lt(core, "venus");
+ if (rc) {
+ d_vpr_e("%s: disable regulator venus failed with %d\n", __func__, rc);
+ rc = 0;
+ }
+
+ rc = __disable_unprepare_clock_ar50lt(core, "bus_clk");
+ if (rc) {
+ d_vpr_e("%s: disable unprepare bus_clk failed with %d\n", __func__, rc);
+ rc = 0;
+ }
+
rc = __disable_unprepare_clock_ar50lt(core, "core_clk");
if (rc) {
- d_vpr_e("%s: disable unprepare core_clk failed\n", __func__);
+ d_vpr_e("%s: disable unprepare core_clk failed with %d\n", __func__, rc);
rc = 0;
}
if (core->platform->data.vpu_ver != VENUS_VERSION_AR50LT_V2) {
rc = __disable_unprepare_clock_ar50lt(core, "iface_clk");
if (rc) {
- d_vpr_e("%s: disable unprepare iface_clk failed\n", __func__);
+ d_vpr_e("%s: disable unprepare iface_clk failed with %d\n", __func__, rc);
rc = 0;
}
}
- rc = __disable_unprepare_clock_ar50lt(core, "bus_clk");
+ rc = call_venus_op(core, reset_ahb2axi_bridge, core);
if (rc) {
- d_vpr_e("%s: disable unprepare bus_clk failed\n", __func__);
- rc = 0;
- }
-
- /* power down process */
- rc = __disable_regulator_ar50lt(core, "venus");
- if (rc) {
- d_vpr_e("%s: disable regulator venus failed\n", __func__);
+ d_vpr_e("%s: reset ahb2axi bridge failed with %d\n", __func__, rc);
rc = 0;
}
@@ -625,13 +737,13 @@ static int __power_on_ar50lt(struct msm_vidc_core *core)
}
rc = __power_on_ar50lt_controller(core);
if (rc) {
- d_vpr_e("%s: failed to power on ar50 controller\n", __func__);
+ d_vpr_e("%s: failed to power on ar50 controller, rc %d\n", __func__, rc);
goto fail_power_on_controller;
}
rc = __power_on_ar50lt_hardware(core);
if (rc) {
- d_vpr_e("%s: failed to power on ar50 hardware\n", __func__);
+ d_vpr_e("%s: failed to power on ar50 hardware, rc %d\n", __func__, rc);
goto fail_power_on_hardware;
}
/* video controller and hardware powered on successfully */
@@ -640,7 +752,7 @@ static int __power_on_ar50lt(struct msm_vidc_core *core)
// add check in main __set_clk_rate
rc = __scale_clocks(core);
if (rc) {
- d_vpr_e("%s: failed to scale clocks\n", __func__);
+ d_vpr_e("%s: failed to scale clocks, rc %d\n", __func__, rc);
rc = 0;
}
/*
@@ -676,14 +788,17 @@ static int __power_off_ar50lt(struct msm_vidc_core *core)
if (!core->power_enabled)
return 0;
- if (__power_off_ar50lt_hardware(core))
- d_vpr_e("%s: failed to power off hardware\n", __func__);
+ rc = __power_off_ar50lt_hardware(core);
+ if (rc)
+ d_vpr_e("%s: failed to power off hardware, rc = %d\n", __func__, rc);
- if (__power_off_ar50lt_controller(core))
- d_vpr_e("%s: failed to power off controller\n", __func__);
+ rc = __power_off_ar50lt_controller(core);
+ if (rc)
+ d_vpr_e("%s: failed to power off controller, rc = %d\n", __func__, rc);
- if (__unvote_buses(core))
- d_vpr_e("%s: failed to unvote buses\n", __func__);
+ rc = __unvote_buses(core);
+ if (rc)
+ d_vpr_e("%s: failed to unvote buses, rc = %d\n", __func__, rc);
if (!(core->intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK_AR50_LT))
disable_irq_nosync(core->dt->irq);
@@ -787,7 +902,7 @@ static struct msm_vidc_venus_ops ar50lt_ops = {
.clear_interrupt = __clear_interrupt_ar50lt,
.setup_ucregion_memmap = __setup_ucregion_memory_map_ar50lt,
.clock_config_on_enable = NULL,
- .reset_ahb2axi_bridge = NULL,
+ .reset_ahb2axi_bridge = __reset_ahb2axi_bridge,
.power_on = __power_on_ar50lt,
.power_off = __power_off_ar50lt,
.prepare_pc = __prepare_pc_ar50lt,