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 <quic_viveka@quicinc.com>
This commit is contained in:
Vivek Aknurwar 2022-01-26 10:47:50 -08:00 committed by Mike Tipton
parent a1dca775aa
commit 542b46b065

View File

@ -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);