From 542b46b065dd2257e14c3057aeec092e0091d8fa Mon Sep 17 00:00:00 2001 From: Vivek Aknurwar Date: Wed, 26 Jan 2022 10:47:50 -0800 Subject: [PATCH] clk: qcom: rpmh: Add support for fixed-factor clocks Usually xo_pad and bi_tcxo frequencies are identical. However, some chips include an extra clock divider between xo_pad and bi_tcxo to provide reference clocks to chip peripherals (PHY's). Add support for fixed-factor clocks to capture this extra divide factor. Change-Id: I3d32a4b708f1dd1ee37ca4e7557094e77a6db808 Signed-off-by: Vivek Aknurwar --- drivers/clk/qcom/clk-rpmh.c | 86 +++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c index 35d91bd2318d..eac5b4a1ad2c 100644 --- a/drivers/clk/qcom/clk-rpmh.c +++ b/drivers/clk/qcom/clk-rpmh.c @@ -114,6 +114,36 @@ static DEFINE_MUTEX(rpmh_clk_lock); }, \ } +#define DEFINE_CLK_RPMH_FIXED(_platform, _name, _name_active, \ + _parent_name, _name_active_parent, \ + _div) \ + static struct clk_fixed_factor _platform##_##_name = { \ + .mult = 1, \ + .div = _div, \ + .hw.init = &(struct clk_init_data){ \ + .ops = &clk_fixed_factor_ops, \ + .name = #_name, \ + .parent_data = &(const struct clk_parent_data){ \ + .fw_name = #_parent_name, \ + .name = #_parent_name, \ + }, \ + .num_parents = 1, \ + }, \ + }; \ + static struct clk_fixed_factor _platform##_##_name_active = { \ + .mult = 1, \ + .div = _div, \ + .hw.init = &(struct clk_init_data){ \ + .ops = &clk_fixed_factor_ops, \ + .name = #_name_active, \ + .parent_data = &(const struct clk_parent_data){ \ + .fw_name = #_name_active_parent,\ + .name = #_name_active_parent, \ + }, \ + .num_parents = 1, \ + }, \ + } + #define DEFINE_CLK_RPMH_ARC(_platform, _name, _name_active, _res_name, \ _res_on, _div) \ __DEFINE_CLK_RPMH(_platform, _name, _name_active, _res_name, \ @@ -571,7 +601,6 @@ static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec, { struct clk_rpmh_desc *rpmh = data; unsigned int idx = clkspec->args[0]; - struct clk_rpmh *c; if (idx >= rpmh->num_clks) { pr_err("%s: invalid index %u\n", __func__, idx); @@ -581,10 +610,6 @@ static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec, if (!rpmh->clks[idx]) return ERR_PTR(-ENOENT); - c = to_clk_rpmh(rpmh->clks[idx]); - if (!c->res_addr) - return ERR_PTR(-ENODEV); - return rpmh->clks[idx]; } @@ -612,31 +637,36 @@ static int clk_rpmh_probe(struct platform_device *pdev) name = hw_clks[i]->init->name; - rpmh_clk = to_clk_rpmh(hw_clks[i]); - res_addr = cmd_db_read_addr(rpmh_clk->res_name); - if (!res_addr) { - if (rpmh_clk->optional) - continue; - WARN(1, "clk-rpmh: Missing RPMh resource address for %s\n", - rpmh_clk->res_name); - return -ENODEV; + if (hw_clks[i]->init->ops != &clk_fixed_factor_ops) { + rpmh_clk = to_clk_rpmh(hw_clks[i]); + res_addr = cmd_db_read_addr(rpmh_clk->res_name); + if (!res_addr) { + hw_clks[i] = NULL; + + if (rpmh_clk->optional) + continue; + + WARN(1, "clk-rpmh: Missing RPMh resource address for %s\n", + rpmh_clk->res_name); + return -ENODEV; + } + + data = cmd_db_read_aux_data(rpmh_clk->res_name, &aux_data_len); + if (IS_ERR(data)) { + ret = PTR_ERR(data); + WARN(1, "clk-rpmh: error reading RPMh aux data for %s (%d)\n", + rpmh_clk->res_name, ret); + return ret; + } + + /* Convert unit from Khz to Hz */ + if (aux_data_len == sizeof(*data)) + rpmh_clk->unit = le32_to_cpu(data->unit) * 1000ULL; + + rpmh_clk->res_addr += res_addr; + rpmh_clk->dev = &pdev->dev; } - data = cmd_db_read_aux_data(rpmh_clk->res_name, &aux_data_len); - if (IS_ERR(data)) { - ret = PTR_ERR(data); - WARN(1, "clk-rpmh: error reading RPMh aux data for %s (%d)\n", - rpmh_clk->res_name, ret); - return ret; - } - - /* Convert unit from Khz to Hz */ - if (aux_data_len == sizeof(*data)) - rpmh_clk->unit = le32_to_cpu(data->unit) * 1000ULL; - - rpmh_clk->res_addr += res_addr; - rpmh_clk->dev = &pdev->dev; - ret = devm_clk_hw_register(&pdev->dev, hw_clks[i]); if (ret) { dev_err(&pdev->dev, "failed to register %s\n", name);