From 45055bdb07ba5ad99c8baf399c9412a120aad42b Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Thu, 23 Apr 2020 23:45:59 +0530 Subject: [PATCH] clk: qcom: Add qcom implementation of qcom_clk_set_flags The qcom_clk_set_flags API would be used to set/clear the memory flags for the desired branches. Change-Id: I58b2347f63d382168b61dd04ead57ad114559eb2 Signed-off-by: Taniya Das --- drivers/clk/qcom/clk-branch.c | 55 ++++++++++++++++++++++++++++++++++- include/linux/clk/qcom.h | 12 +++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c index 43ad05b584d7..b6dd1862517e 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, The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016, 2020, The Linux Foundation. All rights reserved. */ #include @@ -11,6 +11,7 @@ #include #include #include +#include #include "clk-branch.h" @@ -210,3 +211,55 @@ const struct clk_ops clk_branch_simple_ops = { .is_enabled = clk_is_enabled_regmap, }; EXPORT_SYMBOL_GPL(clk_branch_simple_ops); + +int qcom_clk_set_flags(struct clk *clk, unsigned long flags) +{ + struct clk_hw *hw; + struct clk_branch *br; + u32 cbcr_val = 0, cbcr_mask; + int ret; + + if (IS_ERR_OR_NULL(clk)) + return 0; + + hw = __clk_get_hw(clk); + if (IS_ERR_OR_NULL(hw)) + return -EINVAL; + + switch (flags) { + case CLKFLAG_PERIPH_OFF_SET: + cbcr_val = cbcr_mask = BIT(12); + break; + case CLKFLAG_PERIPH_OFF_CLEAR: + cbcr_mask = BIT(12); + break; + case CLKFLAG_RETAIN_PERIPH: + cbcr_val = cbcr_mask = BIT(13); + break; + case CLKFLAG_NORETAIN_PERIPH: + cbcr_mask = BIT(13); + break; + case CLKFLAG_RETAIN_MEM: + cbcr_val = cbcr_mask = BIT(14); + break; + case CLKFLAG_NORETAIN_MEM: + cbcr_mask = BIT(14); + break; + default: + return -EINVAL; + } + + br = to_clk_branch(hw); + ret = regmap_update_bits(br->clkr.regmap, br->halt_reg, cbcr_mask, + cbcr_val); + if (ret) + return ret; + + /* Make sure power is enabled/disabled before returning. */ + mb(); + + udelay(1); + + return 0; +} +EXPORT_SYMBOL(qcom_clk_set_flags); diff --git a/include/linux/clk/qcom.h b/include/linux/clk/qcom.h index 8e510b10b987..1ae1f16cca7a 100644 --- a/include/linux/clk/qcom.h +++ b/include/linux/clk/qcom.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ #ifndef __LINUX_CLK_QCOM_H_ @@ -8,6 +8,16 @@ #include +enum branch_mem_flags { + CLKFLAG_RETAIN_PERIPH, + CLKFLAG_NORETAIN_PERIPH, + CLKFLAG_RETAIN_MEM, + CLKFLAG_NORETAIN_MEM, + CLKFLAG_PERIPH_OFF_SET, + CLKFLAG_PERIPH_OFF_CLEAR, +}; + int qcom_clk_get_voltage(struct clk *clk, unsigned long rate); +int qcom_clk_set_flags(struct clk *clk, unsigned long flags); #endif /* __LINUX_CLK_QCOM_H_ */