diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c index 31e588a6054f..8777eab86b01 100644 --- a/drivers/clk/qcom/clk-branch.c +++ b/drivers/clk/qcom/clk-branch.c @@ -206,8 +206,48 @@ static void clk_branch2_list_registers(struct seq_file *f, struct clk_hw *hw) } } +static int clk_branch2_set_flags(struct clk_hw *hw, unsigned long flags) +{ + struct clk_branch *br = to_clk_branch(hw); + u32 cbcr_val = 0, cbcr_mask; + int ret; + + 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; + } + + ret = regmap_update_bits(br->clkr.regmap, br->halt_reg, cbcr_mask, + cbcr_val); + /* Make sure power is enabled/disabled before returning. */ + mb(); + + udelay(1); + + return ret; +} + static struct clk_regmap_ops clk_branch2_regmap_ops = { .list_registers = clk_branch2_list_registers, + .set_flags = clk_branch2_set_flags, }; static int clk_branch2_init(struct clk_hw *hw) @@ -311,55 +351,3 @@ const struct clk_ops clk_branch_simple_ops = { .debug_init = clk_branch_debug_init, }; 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/drivers/clk/qcom/clk-regmap.h b/drivers/clk/qcom/clk-regmap.h index 8ad7f5486b49..cdf4a4e7547f 100644 --- a/drivers/clk/qcom/clk-regmap.h +++ b/drivers/clk/qcom/clk-regmap.h @@ -19,12 +19,16 @@ struct regmap; * @list_rate: On success, return the nth supported frequency for a given * clock that is below rate_max. Return -ENXIO in case there is * no frequency table. + * + * @set_flags: Set custom flags which deal with hardware specifics. Returns 0 + * on success, error otherwise. */ struct clk_regmap_ops { void (*list_registers)(struct seq_file *f, struct clk_hw *hw); long (*list_rate)(struct clk_hw *hw, unsigned int n, unsigned long rate_max); + int (*set_flags)(struct clk_hw *clk, unsigned long flags); }; /** diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index 4ef70ac293df..9e377dfaf05b 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -445,6 +445,29 @@ int qcom_clk_get_voltage(struct clk *clk, unsigned long rate) } EXPORT_SYMBOL(qcom_clk_get_voltage); +int qcom_clk_set_flags(struct clk *clk, unsigned long flags) +{ + struct clk_regmap *rclk; + struct clk_hw *hw; + + if (IS_ERR_OR_NULL(clk)) + return 0; + + hw = __clk_get_hw(clk); + if (IS_ERR_OR_NULL(hw)) + return -EINVAL; + + if (!clk_is_regmap_clk(hw)) + return -EINVAL; + + rclk = to_clk_regmap(hw); + if (rclk->ops && rclk->ops->set_flags) + return rclk->ops->set_flags(hw, flags); + + return 0; +} +EXPORT_SYMBOL(qcom_clk_set_flags); + int qcom_cc_runtime_init(struct platform_device *pdev, struct qcom_cc_desc *desc) {