clk: loongson2: Avoid hardcoding firmware name of the reference clock
Loongson-2K0300 requires a reference clock with a frequency different from previous SoCs (120MHz v.s. 100MHz), thus hardcoding the firmware name of the reference clock as ref_100m isn't a good idea. This patch retrives the clock name of the reference clock dynamically during probe, avoiding the hardcoded pdata structure and preparing for support of future SoCs. Signed-off-by: Yao Zi <ziyao@disroot.org> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
This commit is contained in:
@@ -13,10 +13,6 @@
|
||||
#include <linux/io-64-nonatomic-lo-hi.h>
|
||||
#include <dt-bindings/clock/loongson,ls2k-clk.h>
|
||||
|
||||
static const struct clk_parent_data pdata[] = {
|
||||
{ .fw_name = "ref_100m", },
|
||||
};
|
||||
|
||||
enum loongson2_clk_type {
|
||||
CLK_TYPE_PLL,
|
||||
CLK_TYPE_SCALE,
|
||||
@@ -275,7 +271,8 @@ static const struct clk_ops loongson2_freqscale_recalc_ops = {
|
||||
.recalc_rate = loongson2_freqscale_recalc_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw *loongson2_clk_register(struct loongson2_clk_provider *clp,
|
||||
static struct clk_hw *loongson2_clk_register(const char *parent,
|
||||
struct loongson2_clk_provider *clp,
|
||||
const struct loongson2_clk_board_info *cld,
|
||||
const struct clk_ops *ops)
|
||||
{
|
||||
@@ -292,11 +289,7 @@ static struct clk_hw *loongson2_clk_register(struct loongson2_clk_provider *clp,
|
||||
init.ops = ops;
|
||||
init.flags = 0;
|
||||
init.num_parents = 1;
|
||||
|
||||
if (!cld->parent_name)
|
||||
init.parent_data = pdata;
|
||||
else
|
||||
init.parent_names = &cld->parent_name;
|
||||
init.parent_names = &parent;
|
||||
|
||||
clk->reg = clp->base + cld->reg_offset;
|
||||
clk->div_shift = cld->div_shift;
|
||||
@@ -321,11 +314,17 @@ static int loongson2_clk_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct loongson2_clk_provider *clp;
|
||||
const struct loongson2_clk_board_info *p, *data;
|
||||
const char *refclk_name, *parent_name;
|
||||
|
||||
data = device_get_match_data(dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
refclk_name = of_clk_get_parent_name(dev->of_node, 0);
|
||||
if (IS_ERR(refclk_name))
|
||||
return dev_err_probe(dev, PTR_ERR(refclk_name),
|
||||
"failed to get refclk name\n");
|
||||
|
||||
for (p = data; p->name; p++)
|
||||
clks_num = max(clks_num, p->id + 1);
|
||||
|
||||
@@ -347,18 +346,20 @@ static int loongson2_clk_probe(struct platform_device *pdev)
|
||||
|
||||
for (i = 0; i < clks_num; i++) {
|
||||
p = &data[i];
|
||||
parent_name = p->parent_name ? p->parent_name : refclk_name;
|
||||
|
||||
switch (p->type) {
|
||||
case CLK_TYPE_PLL:
|
||||
hw = loongson2_clk_register(clp, p,
|
||||
hw = loongson2_clk_register(parent_name, clp, p,
|
||||
&loongson2_pll_recalc_ops);
|
||||
break;
|
||||
case CLK_TYPE_SCALE:
|
||||
hw = loongson2_clk_register(clp, p,
|
||||
hw = loongson2_clk_register(parent_name, clp, p,
|
||||
&loongson2_freqscale_recalc_ops);
|
||||
break;
|
||||
case CLK_TYPE_DIVIDER:
|
||||
hw = devm_clk_hw_register_divider(dev, p->name,
|
||||
p->parent_name, 0,
|
||||
parent_name, 0,
|
||||
clp->base + p->reg_offset,
|
||||
p->div_shift, p->div_width,
|
||||
CLK_DIVIDER_ONE_BASED |
|
||||
@@ -366,15 +367,15 @@ static int loongson2_clk_probe(struct platform_device *pdev)
|
||||
&clp->clk_lock);
|
||||
break;
|
||||
case CLK_TYPE_GATE:
|
||||
hw = devm_clk_hw_register_gate(dev, p->name, p->parent_name,
|
||||
hw = devm_clk_hw_register_gate(dev, p->name, parent_name,
|
||||
p->flags,
|
||||
clp->base + p->reg_offset,
|
||||
p->bit_idx, 0,
|
||||
&clp->clk_lock);
|
||||
break;
|
||||
case CLK_TYPE_FIXED:
|
||||
hw = devm_clk_hw_register_fixed_rate_parent_data(dev, p->name, pdata,
|
||||
0, p->fixed_rate);
|
||||
hw = devm_clk_hw_register_fixed_rate(dev, p->name, parent_name,
|
||||
0, p->fixed_rate);
|
||||
break;
|
||||
default:
|
||||
return dev_err_probe(dev, -EINVAL, "Invalid clk type\n");
|
||||
|
||||
Reference in New Issue
Block a user