From a0082a4c813cbb120c85efb856d5c877e691c861 Mon Sep 17 00:00:00 2001 From: Darshana Patil Date: Wed, 4 Jan 2023 12:58:31 -0800 Subject: [PATCH] video: driver: amend xo reset clock as shared resource Use devm_reset_control_get_exclusive_released() instead of devm_reset_control_get() to get the reset control of video_xo_reset clock as it is shared reset clock between eva and video drivers. Use reset_control_acquire() before assert and reset_control_release() after de-assert video_xo_reset clock to avoid eva driver operating on it in parallel. Change-Id: I4936ed7a4556bb56d4b28546084fc877080308ef Signed-off-by: Deepa Guthyappa Madivalara Signed-off-by: Darshana Patil --- driver/platform/anorak/src/msm_vidc_anorak.c | 4 +- .../platform/common/inc/msm_vidc_platform.h | 1 + driver/platform/kalama/src/msm_vidc_kalama.c | 4 +- .../pineapple/src/msm_vidc_pineapple.c | 8 +- driver/platform/waipio/src/msm_vidc_waipio.c | 6 +- driver/variant/iris33/src/msm_vidc_iris33.c | 30 +++++++ driver/vidc/inc/resources.h | 5 ++ driver/vidc/src/resources.c | 82 ++++++++++++++++++- 8 files changed, 126 insertions(+), 14 deletions(-) diff --git a/driver/platform/anorak/src/msm_vidc_anorak.c b/driver/platform/anorak/src/msm_vidc_anorak.c index 9b9a297ba2..ed82cd2193 100644 --- a/driver/platform/anorak/src/msm_vidc_anorak.c +++ b/driver/platform/anorak/src/msm_vidc_anorak.c @@ -2314,9 +2314,9 @@ static const struct clk_table anorak_clk_table[] = { { "video_cc_mvs0_clk_src", VIDEO_CC_MVS0_CLK_SRC, 1 }, }; -/* name */ +/* name, exclusive_release */ static const struct clk_rst_table anorak_clk_reset_table[] = { - { "video_axi_reset" }, + { "video_axi_reset", 0 }, }; /* name, llcc_id */ diff --git a/driver/platform/common/inc/msm_vidc_platform.h b/driver/platform/common/inc/msm_vidc_platform.h index 40edd300fd..9bd7c677df 100644 --- a/driver/platform/common/inc/msm_vidc_platform.h +++ b/driver/platform/common/inc/msm_vidc_platform.h @@ -60,6 +60,7 @@ struct clk_table { struct clk_rst_table { const char *name; + bool exclusive_release; }; struct subcache_table { diff --git a/driver/platform/kalama/src/msm_vidc_kalama.c b/driver/platform/kalama/src/msm_vidc_kalama.c index 4a1e8828a0..9f699d6ece 100644 --- a/driver/platform/kalama/src/msm_vidc_kalama.c +++ b/driver/platform/kalama/src/msm_vidc_kalama.c @@ -2514,9 +2514,9 @@ static const struct clk_table kalama_clk_table[] = { { "video_cc_mvs0_clk_src", VIDEO_CC_MVS0_CLK_SRC, 1 }, }; -/* name */ +/* name, exclusive_release */ static const struct clk_rst_table kalama_clk_reset_table[] = { - { "video_axi_reset" }, + { "video_axi_reset", 0 }, }; /* name, llcc_id */ diff --git a/driver/platform/pineapple/src/msm_vidc_pineapple.c b/driver/platform/pineapple/src/msm_vidc_pineapple.c index 192e9679ab..2a62101100 100644 --- a/driver/platform/pineapple/src/msm_vidc_pineapple.c +++ b/driver/platform/pineapple/src/msm_vidc_pineapple.c @@ -2547,11 +2547,11 @@ static const struct clk_table pineapple_clk_table[] = { { "video_cc_mvs0_clk_src", VIDEO_CC_MVS0_CLK_SRC, 1 }, }; -/* name */ +/* name, exclusive_release */ static const struct clk_rst_table pineapple_clk_reset_table[] = { - { "video_axi_reset" }, - { "video_xo_reset" }, - { "video_mvs0c_reset" }, + { "video_axi_reset", 0 }, + { "video_xo_reset", 1 }, + { "video_mvs0c_reset", 0 }, }; /* name, llcc_id */ diff --git a/driver/platform/waipio/src/msm_vidc_waipio.c b/driver/platform/waipio/src/msm_vidc_waipio.c index d7c9cbdb00..f2aaa59cd2 100644 --- a/driver/platform/waipio/src/msm_vidc_waipio.c +++ b/driver/platform/waipio/src/msm_vidc_waipio.c @@ -2060,10 +2060,10 @@ static const struct clk_table waipio_clk_table[] = { { "video_cc_mvs0_clk_src", VIDEO_CC_MVS0_CLK_SRC, 1 }, }; -/* name */ +/* name, exclusive_release */ static const struct clk_rst_table waipio_clk_reset_table[] = { - { "video_axi_reset" }, - { "video_core_reset" }, + { "video_axi_reset", 0 }, + { "video_core_reset", 0 }, }; /* name, llcc_id */ diff --git a/driver/variant/iris33/src/msm_vidc_iris33.c b/driver/variant/iris33/src/msm_vidc_iris33.c index cc358e7065..121753af6f 100644 --- a/driver/variant/iris33/src/msm_vidc_iris33.c +++ b/driver/variant/iris33/src/msm_vidc_iris33.c @@ -4,6 +4,7 @@ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include "msm_vidc_iris33.h" #include "msm_vidc_buffer_iris33.h" #include "msm_vidc_power_iris33.h" @@ -384,6 +385,7 @@ static int __power_off_iris33_controller(struct msm_vidc_core *core) { int rc = 0; int value = 0; + u32 count = 0; /* * mask fal10_veto QLPAC error since fal10_veto can go 1 @@ -467,6 +469,28 @@ static int __power_off_iris33_controller(struct msm_vidc_core *core) if (rc) return rc; + /* + * need to acquire "video_xo_reset" before assert and release + * after de-assert "video_xo_reset" reset clock to avoid other + * drivers (eva driver) operating on this shared reset clock + * and AON_WRAPPER_SPARE register in parallel. + */ + count = 0; + do { + rc = call_res_op(core, reset_control_acquire, core, "video_xo_reset"); + if (rc) { + d_vpr_e("%s: failed to acquire video_xo_reset control\n", __func__); + } else { + count++; + usleep_range(1000, 1000); + } + } while (rc && count < 100); + + if (count >= 100) { + d_vpr_e("%s: timeout acquiring video_xo_reset\n", __func__); + goto skip_video_xo_reset; + } + /* poll AON spare register bit0 to become zero with 50ms timeout */ rc = __read_register_with_poll_timeout(core, AON_WRAPPER_SPARE, 0x1, 0x0, 1000, 50 * 1000); @@ -500,6 +524,12 @@ static int __power_off_iris33_controller(struct msm_vidc_core *core) if (rc) return rc; + /* release reset control for other consumers */ + rc = call_res_op(core, reset_control_release, core, "video_xo_reset"); + if (rc) + d_vpr_e("%s: failed to release video_xo_reset reset\n", __func__); + +skip_video_xo_reset: /* Enable MVP NoC clock */ rc = __write_register_masked(core, AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL, 0x0, BIT(0)); diff --git a/driver/vidc/inc/resources.h b/driver/vidc/inc/resources.h index 830ca2d796..463cb6cbba 100644 --- a/driver/vidc/inc/resources.h +++ b/driver/vidc/inc/resources.h @@ -136,6 +136,7 @@ struct clock_set { struct reset_info { struct reset_control *rst; const char *name; + bool exclusive_release; }; struct reset_set { @@ -208,6 +209,10 @@ struct msm_vidc_resources_ops { int (*init)(struct msm_vidc_core *core); int (*reset_bridge)(struct msm_vidc_core *core); + int (*reset_control_acquire)(struct msm_vidc_core *core, + const char *name); + int (*reset_control_release)(struct msm_vidc_core *core, + const char *name); int (*reset_control_assert)(struct msm_vidc_core *core, const char *name); int (*reset_control_deassert)(struct msm_vidc_core *core, diff --git a/driver/vidc/src/resources.c b/driver/vidc/src/resources.c index ca4ca83a1e..5bc2f7deaf 100644 --- a/driver/vidc/src/resources.c +++ b/driver/vidc/src/resources.c @@ -401,17 +401,24 @@ static int __init_reset_clocks(struct msm_vidc_core *core) rsts->count = rst_count; /* populate clock field from platform data */ - for (cnt = 0; cnt < rsts->count; cnt++) + for (cnt = 0; cnt < rsts->count; cnt++) { rsts->reset_tbl[cnt].name = rst_tbl[cnt].name; + rsts->reset_tbl[cnt].exclusive_release = rst_tbl[cnt].exclusive_release; + } /* print reset clock fields */ venus_hfi_for_each_reset_clock(core, rinfo) { - d_vpr_h("%s: reset clk %s\n", __func__, rinfo->name); + d_vpr_h("%s: reset clk %s, exclusive %d\n", + __func__, rinfo->name, rinfo->exclusive_release); } /* get reset clock handle */ venus_hfi_for_each_reset_clock(core, rinfo) { - rinfo->rst = devm_reset_control_get(&core->pdev->dev, rinfo->name); + if (rinfo->exclusive_release) + rinfo->rst = devm_reset_control_get_exclusive_released( + &core->pdev->dev, rinfo->name); + else + rinfo->rst = devm_reset_control_get(&core->pdev->dev, rinfo->name); if (IS_ERR_OR_NULL(rinfo->rst)) { d_vpr_e("%s: failed to get reset clock: %s\n", __func__, rinfo->name); rc = PTR_ERR(rinfo->rst) ? @@ -1323,6 +1330,73 @@ static int __init_resources(struct msm_vidc_core *core) return rc; } +static int __reset_control_acquire_name(struct msm_vidc_core *core, + const char *name) +{ + struct reset_info *rcinfo = NULL; + int rc = 0; + bool found = false; + + venus_hfi_for_each_reset_clock(core, rcinfo) { + if (strcmp(rcinfo->name, name)) + continue; + + /* this function is valid only for exclusive_release reset clocks*/ + if (!rcinfo->exclusive_release) { + d_vpr_e("%s: unsupported reset control (%s), exclusive %d\n", + __func__, name, rcinfo->exclusive_release); + return -EINVAL; + } + + found = true; + rc = reset_control_acquire(rcinfo->rst); + if (rc) + d_vpr_e("%s: failed to acquire reset control (%s), rc = %d\n", + __func__, rcinfo->name, rc); + else + d_vpr_h("%s: acquire reset control (%s)\n", + __func__, rcinfo->name); + break; + } + if (!found) { + d_vpr_e("%s: reset control (%s) not found\n", __func__, name); + rc = -EINVAL; + } + + return rc; +} + +static int __reset_control_release_name(struct msm_vidc_core *core, + const char *name) +{ + struct reset_info *rcinfo = NULL; + int rc = 0; + bool found = false; + + venus_hfi_for_each_reset_clock(core, rcinfo) { + if (strcmp(rcinfo->name, name)) + continue; + + /* this function is valid only for exclusive_release reset clocks*/ + if (!rcinfo->exclusive_release) { + d_vpr_e("%s: unsupported reset control (%s), exclusive %d\n", + __func__, name, rcinfo->exclusive_release); + return -EINVAL; + } + + found = true; + reset_control_release(rcinfo->rst); + d_vpr_h("%s: release reset control (%s)\n", __func__, rcinfo->name); + break; + } + if (!found) { + d_vpr_e("%s: reset control (%s) not found\n", __func__, name); + rc = -EINVAL; + } + + return rc; +} + static int __reset_control_assert_name(struct msm_vidc_core *core, const char *name) { @@ -1448,6 +1522,8 @@ static int __reset_ahb2axi_bridge(struct msm_vidc_core *core) static const struct msm_vidc_resources_ops res_ops = { .init = __init_resources, .reset_bridge = __reset_ahb2axi_bridge, + .reset_control_acquire = __reset_control_acquire_name, + .reset_control_release = __reset_control_release_name, .reset_control_assert = __reset_control_assert_name, .reset_control_deassert = __reset_control_deassert_name, .gdsc_on = __enable_regulator,