clk: versatile-icst: add device tree support
This adds support for the ARM syscon ICST clocks to initialized directly from the device tree syscon node on ARM Integrator, Versatile and RealView reference designs. Cc: Michael Turquette <mturquette@baylibre.com> Cc: Stephen Boyd <sboyd@codeaurora.org> Cc: linux-clk@vger.kernel.org Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Родитель
384d977d74
Коммит
d430819d69
|
@ -3,7 +3,7 @@
|
|||
* We wrap the custom interface from <asm/hardware/icst.h> into the generic
|
||||
* clock framework.
|
||||
*
|
||||
* Copyright (C) 2012 Linus Walleij
|
||||
* Copyright (C) 2012-2015 Linus Walleij
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -206,3 +206,90 @@ struct clk *icst_clk_register(struct device *dev,
|
|||
return icst_clk_setup(dev, desc, name, parent_name, map);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(icst_clk_register);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
/*
|
||||
* In a device tree, an memory-mapped ICST clock appear as a child
|
||||
* of a syscon node. Assume this and probe it only as a child of a
|
||||
* syscon.
|
||||
*/
|
||||
|
||||
static const struct icst_params icst525_params = {
|
||||
.vco_max = ICST525_VCO_MAX_5V,
|
||||
.vco_min = ICST525_VCO_MIN,
|
||||
.vd_min = 8,
|
||||
.vd_max = 263,
|
||||
.rd_min = 3,
|
||||
.rd_max = 65,
|
||||
.s2div = icst525_s2div,
|
||||
.idx2s = icst525_idx2s,
|
||||
};
|
||||
|
||||
static const struct icst_params icst307_params = {
|
||||
.vco_max = ICST307_VCO_MAX,
|
||||
.vco_min = ICST307_VCO_MIN,
|
||||
.vd_min = 4 + 8,
|
||||
.vd_max = 511 + 8,
|
||||
.rd_min = 1 + 2,
|
||||
.rd_max = 127 + 2,
|
||||
.s2div = icst307_s2div,
|
||||
.idx2s = icst307_idx2s,
|
||||
};
|
||||
|
||||
static void __init of_syscon_icst_setup(struct device_node *np)
|
||||
{
|
||||
struct device_node *parent;
|
||||
struct regmap *map;
|
||||
struct clk_icst_desc icst_desc;
|
||||
const char *name = np->name;
|
||||
const char *parent_name;
|
||||
struct clk *regclk;
|
||||
|
||||
/* We do not release this reference, we are using it perpetually */
|
||||
parent = of_get_parent(np);
|
||||
if (!parent) {
|
||||
pr_err("no parent node for syscon ICST clock\n");
|
||||
return;
|
||||
}
|
||||
map = syscon_node_to_regmap(parent);
|
||||
if (IS_ERR(map)) {
|
||||
pr_err("no regmap for syscon ICST clock parent\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(np, "vco-offset", &icst_desc.vco_offset)) {
|
||||
pr_err("no VCO register offset for ICST clock\n");
|
||||
return;
|
||||
}
|
||||
if (of_property_read_u32(np, "lock-offset", &icst_desc.lock_offset)) {
|
||||
pr_err("no lock register offset for ICST clock\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(np, "arm,syscon-icst525"))
|
||||
icst_desc.params = &icst525_params;
|
||||
else if (of_device_is_compatible(np, "arm,syscon-icst307"))
|
||||
icst_desc.params = &icst307_params;
|
||||
else {
|
||||
pr_err("unknown ICST clock %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parent clock name is not the same as node parent */
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
regclk = icst_clk_setup(NULL, &icst_desc, name, parent_name, map);
|
||||
if (IS_ERR(regclk)) {
|
||||
pr_err("error setting up syscon ICST clock %s\n", name);
|
||||
return;
|
||||
}
|
||||
of_clk_add_provider(np, of_clk_src_simple_get, regclk);
|
||||
pr_debug("registered syscon ICST clock %s\n", name);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(arm_syscon_icst525_clk,
|
||||
"arm,syscon-icst525", of_syscon_icst_setup);
|
||||
CLK_OF_DECLARE(arm_syscon_icst307_clk,
|
||||
"arm,syscon-icst307", of_syscon_icst_setup);
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче