mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 10:29:37 +00:00
clk: qcom: common: Add API to register board clocks backwards compatibly
We want to put the XO board clocks into the dt files, but we also need to be backwards compatible with an older dtb. Add an API to the common code to do this. This also makes a place for us to handle the case when the RPM clock driver is enabled and we don't want to register the fixed factor clock. Cc: Georgi Djakov <georgi.djakov@linaro.org> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
This commit is contained in:
parent
8005c49d9a
commit
ee15faffef
2 changed files with 91 additions and 0 deletions
|
@ -17,6 +17,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "clk-rcg.h"
|
||||
|
@ -88,6 +89,92 @@ static void qcom_cc_gdsc_unregister(void *data)
|
|||
gdsc_unregister(data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Backwards compatibility with old DTs. Register a pass-through factor 1/1
|
||||
* clock to translate 'path' clk into 'name' clk and regsiter the 'path'
|
||||
* clk as a fixed rate clock if it isn't present.
|
||||
*/
|
||||
static int _qcom_cc_register_board_clk(struct device *dev, const char *path,
|
||||
const char *name, unsigned long rate,
|
||||
bool add_factor)
|
||||
{
|
||||
struct device_node *node = NULL;
|
||||
struct device_node *clocks_node;
|
||||
struct clk_fixed_factor *factor;
|
||||
struct clk_fixed_rate *fixed;
|
||||
struct clk *clk;
|
||||
struct clk_init_data init_data = { };
|
||||
|
||||
clocks_node = of_find_node_by_path("/clocks");
|
||||
if (clocks_node)
|
||||
node = of_find_node_by_name(clocks_node, path);
|
||||
of_node_put(clocks_node);
|
||||
|
||||
if (!node) {
|
||||
fixed = devm_kzalloc(dev, sizeof(*fixed), GFP_KERNEL);
|
||||
if (!fixed)
|
||||
return -EINVAL;
|
||||
|
||||
fixed->fixed_rate = rate;
|
||||
fixed->hw.init = &init_data;
|
||||
|
||||
init_data.name = path;
|
||||
init_data.flags = CLK_IS_ROOT;
|
||||
init_data.ops = &clk_fixed_rate_ops;
|
||||
|
||||
clk = devm_clk_register(dev, &fixed->hw);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
of_node_put(node);
|
||||
|
||||
if (add_factor) {
|
||||
factor = devm_kzalloc(dev, sizeof(*factor), GFP_KERNEL);
|
||||
if (!factor)
|
||||
return -EINVAL;
|
||||
|
||||
factor->mult = factor->div = 1;
|
||||
factor->hw.init = &init_data;
|
||||
|
||||
init_data.name = name;
|
||||
init_data.parent_names = &path;
|
||||
init_data.num_parents = 1;
|
||||
init_data.flags = 0;
|
||||
init_data.ops = &clk_fixed_factor_ops;
|
||||
|
||||
clk = devm_clk_register(dev, &factor->hw);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qcom_cc_register_board_clk(struct device *dev, const char *path,
|
||||
const char *name, unsigned long rate)
|
||||
{
|
||||
bool add_factor = true;
|
||||
struct device_node *node;
|
||||
|
||||
/* The RPM clock driver will add the factor clock if present */
|
||||
if (IS_ENABLED(CONFIG_QCOM_RPMCC)) {
|
||||
node = of_find_compatible_node(NULL, NULL, "qcom,rpmcc");
|
||||
if (of_device_is_available(node))
|
||||
add_factor = false;
|
||||
of_node_put(node);
|
||||
}
|
||||
|
||||
return _qcom_cc_register_board_clk(dev, path, name, rate, add_factor);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_cc_register_board_clk);
|
||||
|
||||
int qcom_cc_register_sleep_clk(struct device *dev)
|
||||
{
|
||||
return _qcom_cc_register_board_clk(dev, "sleep_clk", "sleep_clk_src",
|
||||
32768, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_cc_register_sleep_clk);
|
||||
|
||||
int qcom_cc_really_probe(struct platform_device *pdev,
|
||||
const struct qcom_cc_desc *desc, struct regmap *regmap)
|
||||
{
|
||||
|
|
|
@ -37,6 +37,10 @@ extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
|
|||
extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map,
|
||||
u8 src);
|
||||
|
||||
extern int qcom_cc_register_board_clk(struct device *dev, const char *path,
|
||||
const char *name, unsigned long rate);
|
||||
extern int qcom_cc_register_sleep_clk(struct device *dev);
|
||||
|
||||
extern struct regmap *qcom_cc_map(struct platform_device *pdev,
|
||||
const struct qcom_cc_desc *desc);
|
||||
extern int qcom_cc_really_probe(struct platform_device *pdev,
|
||||
|
|
Loading…
Reference in a new issue