From 754774b32b9c334557a4bbc3bb60b1239a5a2f90 Mon Sep 17 00:00:00 2001 From: Vivek Aknurwar Date: Tue, 23 Jun 2020 18:43:26 -0700 Subject: [PATCH 1/2] clk: qcom: clk-branch: Add clk_branch2_force_off_ops to force off a clock This ops is used to force off a clock when clk_disable() is called. CLK_DIS bit can be used to force off respective clock. Change-Id: Iec4204fe3bf24965d1603d0f86e74cc2818e3d1c Signed-off-by: Vivek Aknurwar --- drivers/clk/qcom/clk-branch.c | 32 +++++++++++++++++++++++++++++++- drivers/clk/qcom/clk-branch.h | 3 ++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c index 5a29357997cc..1babd87a102c 100644 --- a/drivers/clk/qcom/clk-branch.c +++ b/drivers/clk/qcom/clk-branch.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2013, 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016-2020, The Linux Foundation. All rights reserved. */ #include @@ -46,6 +46,7 @@ static bool clk_branch_check_halt(const struct clk_branch *br, bool enabling) #define BRANCH_NOC_FSM_STATUS_SHIFT 28 #define BRANCH_NOC_FSM_STATUS_MASK 0x7 #define BRANCH_NOC_FSM_STATUS_ON (0x2 << BRANCH_NOC_FSM_STATUS_SHIFT) +#define BRANCH_CLK_DIS_MASK BIT(22) static bool clk_branch2_check_halt(const struct clk_branch *br, bool enabling) { @@ -149,6 +150,26 @@ static void clk_branch2_disable(struct clk_hw *hw) clk_branch_toggle(hw, false, clk_branch2_check_halt); } +static int clk_branch2_force_off_enable(struct clk_hw *hw) +{ + struct clk_regmap *rclk = to_clk_regmap(hw); + + regmap_update_bits(rclk->regmap, rclk->enable_reg, + BRANCH_CLK_DIS_MASK, + 0x0); + return clk_branch2_enable(hw); +} + +static void clk_branch2_force_off_disable(struct clk_hw *hw) +{ + struct clk_regmap *rclk = to_clk_regmap(hw); + + regmap_update_bits(rclk->regmap, rclk->enable_reg, + BRANCH_CLK_DIS_MASK, + BRANCH_CLK_DIS_MASK); + clk_branch2_disable(hw); +} + static void clk_branch2_list_registers(struct seq_file *f, struct clk_hw *hw) { struct clk_branch *br = to_clk_branch(hw); @@ -215,6 +236,15 @@ const struct clk_ops clk_branch2_aon_ops = { }; EXPORT_SYMBOL_GPL(clk_branch2_aon_ops); +const struct clk_ops clk_branch2_force_off_ops = { + .enable = clk_branch2_force_off_enable, + .disable = clk_branch2_force_off_disable, + .is_enabled = clk_is_enabled_regmap, + .init = clk_branch2_init, + .debug_init = clk_branch_debug_init, +}; +EXPORT_SYMBOL(clk_branch2_force_off_ops); + static unsigned long clk_branch2_hw_ctl_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { diff --git a/drivers/clk/qcom/clk-branch.h b/drivers/clk/qcom/clk-branch.h index 8f71551b2aea..eeabc1573bec 100644 --- a/drivers/clk/qcom/clk-branch.h +++ b/drivers/clk/qcom/clk-branch.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2013, 2016, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2013, 2016, 2020 The Linux Foundation. All rights reserved. */ #ifndef __QCOM_CLK_BRANCH_H__ #define __QCOM_CLK_BRANCH_H__ @@ -42,6 +42,7 @@ extern const struct clk_ops clk_branch2_ops; extern const struct clk_ops clk_branch2_hw_ctl_ops; extern const struct clk_ops clk_branch_simple_ops; extern const struct clk_ops clk_branch2_aon_ops; +extern const struct clk_ops clk_branch2_force_off_ops; #define to_clk_branch(_hw) \ container_of(to_clk_regmap(_hw), struct clk_branch, clkr) From 85247000b1164aaa9bc4a70a41b2c50a0da657a8 Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Wed, 15 Jul 2020 12:01:28 +0530 Subject: [PATCH 2/2] clk: qcom: gcc-shima: Update video_axi clks to clk_branch2_force_off_ops SMMU fault is observed due to spurious AXI transaction even after gcc video_axi clocks are disabled. HW underlying may not actually turn off clocks since HW enable signals can still be asserted/waiting on certain scenarios like when CVP and MVP both are power collapsed. Use clk_branch2_force_off_ops to guarantee that clocks are actually turned off when SW disables them. Change-Id: Iaa9250a5962f3e74e971b4fc859d246960f792b0 Signed-off-by: Jagadeesh Kona --- drivers/clk/qcom/gcc-shima.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/gcc-shima.c b/drivers/clk/qcom/gcc-shima.c index c174036a88b7..768eb1662ef7 100644 --- a/drivers/clk/qcom/gcc-shima.c +++ b/drivers/clk/qcom/gcc-shima.c @@ -3184,7 +3184,7 @@ static struct clk_branch gcc_video_axi0_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_video_axi0_clk", - .ops = &clk_branch2_ops, + .ops = &clk_branch2_force_off_ops, }, }, }; @@ -3199,7 +3199,7 @@ static struct clk_branch gcc_video_axi1_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_video_axi1_clk", - .ops = &clk_branch2_ops, + .ops = &clk_branch2_force_off_ops, }, }, };