Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 40d18910 authored by Manikanta Kanamarlapudi's avatar Manikanta Kanamarlapudi Committed by Gerrit - the friendly Code Review server
Browse files

msm: vidc: Reset AXI CBCR register during hardware hung



During video hardware CPUSS hung, it is recommended
to reset the V-NOC module. Ensure that the V-NOC
module is reset for all types of system errors from
firmware by calling reset on AXI registers using
clock reset api's.

AXI registers needs to be reset only for specific soc architecture
which powers video noc module from different rails.
Adding the check based on hardware version to limit the register
programming.

Change-Id: I586b989cb356543c440fcaf1ef34483ac92fc53d
Signed-off-by: default avatarManikanta Kanamarlapudi <kmanikan@codeaurora.org>
parent c2795af5
Loading
Loading
Loading
Loading
+52 −5
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@
#define REG_ADDR_OFFSET_BITMASK	0x000FFFFF
#define QDSS_IOVA_START 0x80001000

#define VERSION_HANA (0x5 << 28 | 0x10 << 16)

static struct hal_device_data hal_ctxt;

#define TZBSP_MEM_PROTECT_VIDEO_VAR 0x8
@@ -3976,6 +3978,42 @@ static inline int __prepare_ahb2axi_bridge(struct venus_hfi_device *device)
	return 0;
}

static inline int __unprepare_ahb2axi_bridge(struct venus_hfi_device *device,
		u32 version)
{
	int rc;

	if (!device) {
		dprintk(VIDC_ERR, "NULL device\n");
		return -EINVAL;
	}

	/* reset axi0 and axi1 as needed only for specific video hardware */
	version &= ~GENMASK(15, 0);
	if (version != VERSION_HANA)
		return -EINVAL;

	dprintk(VIDC_ERR,
			"reset axi cbcr to recover\n");

	rc = __handle_reset_clk(device->res, ASSERT);
	if (rc) {
		dprintk(VIDC_ERR, "failed to assert reset clocks\n");
		return rc;
	}

	/* wait for deassert */
	usleep_range(150, 250);

	rc = __handle_reset_clk(device->res, DEASSERT);
	if (rc) {
		dprintk(VIDC_ERR, "failed to deassert reset clocks\n");
		return rc;
	}

	return 0;
}

static inline int __prepare_enable_clks(struct venus_hfi_device *device)
{
	struct clock_info *cl = NULL, *cl_fail = NULL;
@@ -4715,8 +4753,10 @@ static int __venus_power_on(struct venus_hfi_device *device)
	return rc;
}

static void __venus_power_off(struct venus_hfi_device *device)
static void __venus_power_off(struct venus_hfi_device *device, bool axi_reset)
{
	u32 version;

	if (!device->power_enabled)
		return;

@@ -4724,7 +4764,14 @@ static void __venus_power_off(struct venus_hfi_device *device)
		disable_irq_nosync(device->hal_data->irq);
	device->intr_status = 0;

	if (axi_reset)
		version = __read_register(device, VIDC_WRAPPER_HW_VERSION);

	__disable_unprepare_clks(device);

	if (axi_reset)
		__unprepare_ahb2axi_bridge(device, version);

	if (__disable_regulators(device))
		dprintk(VIDC_WARN, "Failed to disable regulators\n");

@@ -4759,7 +4806,7 @@ static inline int __suspend(struct venus_hfi_device *device)

	__disable_subcaches(device);

	__venus_power_off(device);
	__venus_power_off(device, false);
	dprintk(VIDC_PROF, "Venus power off\n");
	return rc;

@@ -4834,7 +4881,7 @@ static inline int __resume(struct venus_hfi_device *device)
err_reset_core:
	__tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND);
err_set_video_state:
	__venus_power_off(device);
	__venus_power_off(device, false);
err_venus_power_on:
	dprintk(VIDC_ERR, "Failed to resume from power collapse\n");
	return rc;
@@ -4893,7 +4940,7 @@ static int __load_fw(struct venus_hfi_device *device)
		subsystem_put(device->resources.fw.cookie);
	device->resources.fw.cookie = NULL;
fail_load_fw:
	__venus_power_off(device);
	__venus_power_off(device, true);
fail_venus_power_on:
fail_init_pkt:
	__deinit_resources(device);
@@ -4914,7 +4961,7 @@ static void __unload_fw(struct venus_hfi_device *device)
	__vote_buses(device, NULL, 0);
	subsystem_put(device->resources.fw.cookie);
	__interface_queues_release(device);
	__venus_power_off(device);
	__venus_power_off(device, true);
	device->resources.fw.cookie = NULL;
	__deinit_resources(device);