diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2020-02-19 11:33:26 +0100 |
---|---|---|
committer | Stephen Boyd <sboyd@kernel.org> | 2020-03-20 17:55:31 -0700 |
commit | 84655b762a276f4ad033288954f698e136704178 (patch) | |
tree | 106b852cc1f31df55288937ef9604c9ea14db982 /drivers | |
parent | eb9d6428a7dbd82255b9eabf4ffab54c230b06bc (diff) |
clk: versatile: Add device tree probing for IM-PD1 clocks
As we want to move these clocks over to probe from the device
tree we add a device tree probing path.
The old platform data path will be deleted once we have the
device tree overall code in place.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lkml.kernel.org/r/20200219103326.81120-3-linus.walleij@linaro.org
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/versatile/clk-icst.h | 1 | ||||
-rw-r--r-- | drivers/clk/versatile/clk-impd1.c | 79 |
2 files changed, 80 insertions, 0 deletions
diff --git a/drivers/clk/versatile/clk-icst.h b/drivers/clk/versatile/clk-icst.h index 1206f008c11a..1a119ef11066 100644 --- a/drivers/clk/versatile/clk-icst.h +++ b/drivers/clk/versatile/clk-icst.h @@ -11,6 +11,7 @@ enum icst_control_type { ICST_INTEGRATOR_AP_PCI, /* Odd bit pattern storage */ ICST_INTEGRATOR_CP_CM_CORE, /* Only 8 bits of VDW and 3 bits of OD */ ICST_INTEGRATOR_CP_CM_MEM, /* Only 8 bits of VDW and 3 bits of OD */ + ICST_INTEGRATOR_IM_PD1, /* Like the Versatile, all control bits */ }; /** diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c index 1991f15a5db9..b05da8516d4c 100644 --- a/drivers/clk/versatile/clk-impd1.c +++ b/drivers/clk/versatile/clk-impd1.c @@ -7,7 +7,11 @@ #include <linux/clkdev.h> #include <linux/err.h> #include <linux/io.h> +#include <linux/platform_device.h> #include <linux/platform_data/clk-integrator.h> +#include <linux/module.h> +#include <linux/mfd/syscon.h> +#include <linux/regmap.h> #include "icst.h" #include "clk-icst.h" @@ -175,3 +179,78 @@ void integrator_impd1_clk_exit(unsigned int id) kfree(imc->pclkname); } EXPORT_SYMBOL_GPL(integrator_impd1_clk_exit); + +static int integrator_impd1_clk_spawn(struct device *dev, + struct device_node *parent, + struct device_node *np) +{ + struct regmap *map; + struct clk *clk = ERR_PTR(-EINVAL); + const char *name = np->name; + const char *parent_name; + const struct clk_icst_desc *desc; + int ret; + + map = syscon_node_to_regmap(parent); + if (IS_ERR(map)) { + pr_err("no regmap for syscon IM-PD1 ICST clock parent\n"); + return PTR_ERR(map); + } + + if (of_device_is_compatible(np, "arm,impd1-vco1")) { + desc = &impd1_icst1_desc; + } else if (of_device_is_compatible(np, "arm,impd1-vco2")) { + desc = &impd1_icst2_desc; + } else { + dev_err(dev, "not a clock node %s\n", name); + return -ENODEV; + } + + parent_name = of_clk_get_parent_name(np, 0); + clk = icst_clk_setup(NULL, desc, name, parent_name, map, + ICST_INTEGRATOR_IM_PD1); + if (!IS_ERR(clk)) { + of_clk_add_provider(np, of_clk_src_simple_get, clk); + ret = 0; + } else { + dev_err(dev, "error setting up IM-PD1 ICST clock\n"); + ret = PTR_ERR(clk); + } + + return ret; +} + +static int integrator_impd1_clk_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *child; + int ret = 0; + + for_each_available_child_of_node(np, child) { + ret = integrator_impd1_clk_spawn(dev, np, child); + if (ret) + break; + } + + return ret; +} + +static const struct of_device_id impd1_syscon_match[] = { + { .compatible = "arm,im-pd1-syscon", }, + {} +}; +MODULE_DEVICE_TABLE(of, impd1_syscon_match); + +static struct platform_driver impd1_clk_driver = { + .driver = { + .name = "impd1-clk", + .of_match_table = impd1_syscon_match, + }, + .probe = integrator_impd1_clk_probe, +}; +builtin_platform_driver(impd1_clk_driver); + +MODULE_AUTHOR("Linus Walleij <linusw@kernel.org>"); +MODULE_DESCRIPTION("Arm IM-PD1 module clock driver"); +MODULE_LICENSE("GPL v2"); |