Loading drivers/clk/qcom/clk-rcg.h +2 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2013, 2018-2019, The Linux Foundation. All rights reserved. */ /* Copyright (c) 2013, 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef __QCOM_CLK_RCG_H__ #define __QCOM_CLK_RCG_H__ Loading Loading @@ -173,6 +173,7 @@ extern const struct clk_ops clk_gfx3d_ops; extern const struct clk_ops clk_rcg2_shared_ops; extern const struct clk_ops clk_dp_ops; extern const struct clk_ops clk_rcg2_dependent_ops; extern const struct clk_ops clk_gfx3d_src_ops; struct clk_rcg_dfs_data { struct clk_rcg2 *rcg; Loading drivers/clk/qcom/clk-rcg2.c +85 −0 Original line number Diff line number Diff line Loading @@ -1299,6 +1299,91 @@ const struct clk_ops clk_gfx3d_ops = { }; EXPORT_SYMBOL_GPL(clk_gfx3d_ops); static int clk_gfx3d_src_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate, u8 index) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); const struct freq_tbl *f; u32 cfg, old_cfg; int ret; /* Read back the old configuration */ regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &old_cfg); cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT; f = qcom_find_freq(rcg->freq_tbl, rate); if (!f) return -EINVAL; /* Update the RCG-DIV */ cfg |= f->pre_div << CFG_SRC_DIV_SHIFT; ret = regmap_write(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, cfg); if (ret) return ret; return update_config(rcg, old_cfg); } static int clk_gfx3d_src_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); struct clk_rate_request parent_req = { }; struct clk_hw *p1, *p3, *xo, *curr_p; const struct freq_tbl *f; int ret; xo = clk_hw_get_parent_by_index(hw, 0); if (req->rate == clk_hw_get_rate(xo)) { req->best_parent_hw = xo; req->best_parent_rate = req->rate; return 0; } f = qcom_find_freq(rcg->freq_tbl, req->rate); if (!f || (req->rate != f->freq)) req->rate = f->freq; /* Indexes of source from the parent map */ p1 = clk_hw_get_parent_by_index(hw, 1); p3 = clk_hw_get_parent_by_index(hw, 2); curr_p = clk_hw_get_parent(hw); parent_req.rate = f->src_freq; if (curr_p == xo || curr_p == p3) req->best_parent_hw = p1; else if (curr_p == p1) req->best_parent_hw = p3; parent_req.best_parent_hw = req->best_parent_hw; ret = __clk_determine_rate(req->best_parent_hw, &parent_req); if (ret) return ret; req->best_parent_rate = parent_req.rate; return 0; } const struct clk_ops clk_gfx3d_src_ops = { .enable = clk_rcg2_enable, .disable = clk_rcg2_disable, .is_enabled = clk_rcg2_is_enabled, .get_parent = clk_rcg2_get_parent, .set_parent = clk_rcg2_set_parent, .recalc_rate = clk_rcg2_recalc_rate, .set_rate = clk_gfx3d_set_rate, .set_rate_and_parent = clk_gfx3d_src_set_rate_and_parent, .determine_rate = clk_gfx3d_src_determine_rate, .list_rate = clk_rcg2_list_rate, .list_registers = clk_rcg2_list_registers, }; EXPORT_SYMBOL(clk_gfx3d_src_ops); static int clk_rcg2_shared_force_enable_clear(struct clk_hw *hw, const struct freq_tbl *f) { Loading Loading
drivers/clk/qcom/clk-rcg.h +2 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2013, 2018-2019, The Linux Foundation. All rights reserved. */ /* Copyright (c) 2013, 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef __QCOM_CLK_RCG_H__ #define __QCOM_CLK_RCG_H__ Loading Loading @@ -173,6 +173,7 @@ extern const struct clk_ops clk_gfx3d_ops; extern const struct clk_ops clk_rcg2_shared_ops; extern const struct clk_ops clk_dp_ops; extern const struct clk_ops clk_rcg2_dependent_ops; extern const struct clk_ops clk_gfx3d_src_ops; struct clk_rcg_dfs_data { struct clk_rcg2 *rcg; Loading
drivers/clk/qcom/clk-rcg2.c +85 −0 Original line number Diff line number Diff line Loading @@ -1299,6 +1299,91 @@ const struct clk_ops clk_gfx3d_ops = { }; EXPORT_SYMBOL_GPL(clk_gfx3d_ops); static int clk_gfx3d_src_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate, u8 index) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); const struct freq_tbl *f; u32 cfg, old_cfg; int ret; /* Read back the old configuration */ regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &old_cfg); cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT; f = qcom_find_freq(rcg->freq_tbl, rate); if (!f) return -EINVAL; /* Update the RCG-DIV */ cfg |= f->pre_div << CFG_SRC_DIV_SHIFT; ret = regmap_write(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, cfg); if (ret) return ret; return update_config(rcg, old_cfg); } static int clk_gfx3d_src_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); struct clk_rate_request parent_req = { }; struct clk_hw *p1, *p3, *xo, *curr_p; const struct freq_tbl *f; int ret; xo = clk_hw_get_parent_by_index(hw, 0); if (req->rate == clk_hw_get_rate(xo)) { req->best_parent_hw = xo; req->best_parent_rate = req->rate; return 0; } f = qcom_find_freq(rcg->freq_tbl, req->rate); if (!f || (req->rate != f->freq)) req->rate = f->freq; /* Indexes of source from the parent map */ p1 = clk_hw_get_parent_by_index(hw, 1); p3 = clk_hw_get_parent_by_index(hw, 2); curr_p = clk_hw_get_parent(hw); parent_req.rate = f->src_freq; if (curr_p == xo || curr_p == p3) req->best_parent_hw = p1; else if (curr_p == p1) req->best_parent_hw = p3; parent_req.best_parent_hw = req->best_parent_hw; ret = __clk_determine_rate(req->best_parent_hw, &parent_req); if (ret) return ret; req->best_parent_rate = parent_req.rate; return 0; } const struct clk_ops clk_gfx3d_src_ops = { .enable = clk_rcg2_enable, .disable = clk_rcg2_disable, .is_enabled = clk_rcg2_is_enabled, .get_parent = clk_rcg2_get_parent, .set_parent = clk_rcg2_set_parent, .recalc_rate = clk_rcg2_recalc_rate, .set_rate = clk_gfx3d_set_rate, .set_rate_and_parent = clk_gfx3d_src_set_rate_and_parent, .determine_rate = clk_gfx3d_src_determine_rate, .list_rate = clk_rcg2_list_rate, .list_registers = clk_rcg2_list_registers, }; EXPORT_SYMBOL(clk_gfx3d_src_ops); static int clk_rcg2_shared_force_enable_clear(struct clk_hw *hw, const struct freq_tbl *f) { Loading