static HLIST_HEAD(clk_orphan_list);
static LIST_HEAD(clk_notifier_list);
+++ +static struct hlist_head *all_lists[] = {
+++ + &clk_root_list,
+++ + &clk_orphan_list,
+++ + NULL,
+++ +};
+++ +
/*** private data structures ***/
struct clk_parent_map {
{
struct clk *clk_user;
++++ lockdep_assert_held(&prepare_lock);
++++
*min_rate = core->min_rate;
*max_rate = core->max_rate;
if (core->parent == parent)
return 0;
---- /* verify ops for for multi-parent clks */
++++ /* verify ops for multi-parent clks */
if (core->num_parents > 1 && !core->ops->set_parent)
return -EPERM;
return ret;
}
++++int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *parent)
++++{
++++ return clk_core_set_parent_nolock(hw->core, parent->core);
++++}
++++EXPORT_SYMBOL_GPL(clk_hw_set_parent);
++++
/**
* clk_set_parent - switch the parent of a mux clk
* @clk: the mux clk whose input we are switching
static DEFINE_MUTEX(clk_debug_lock);
static HLIST_HEAD(clk_debug_list);
--- -static struct hlist_head *all_lists[] = {
--- - &clk_root_list,
--- - &clk_orphan_list,
--- - NULL,
--- -};
--- -
static struct hlist_head *orphan_list[] = {
&clk_orphan_list,
NULL,
static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
int level)
{
---- if (!c)
---- return;
----
seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu %5d %6d\n",
level * 3 + 1, "",
30 - level * 3, c->name,
{
struct clk_core *child;
---- if (!c)
---- return;
----
clk_summary_show_one(s, c, level);
hlist_for_each_entry(child, &c->children, child_node)
static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
{
---- if (!c)
---- return;
++++ unsigned long min_rate, max_rate;
++++
++++ clk_core_get_boundaries(c, &min_rate, &max_rate);
/* This should be JSON format, i.e. elements separated with a comma */
seq_printf(s, "\"%s\": { ", c->name);
seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
seq_printf(s, "\"protect_count\": %d,", c->protect_count);
seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
++++ seq_printf(s, "\"min_rate\": %lu,", min_rate);
++++ seq_printf(s, "\"max_rate\": %lu,", max_rate);
seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
seq_printf(s, "\"phase\": %d,", clk_core_get_phase(c));
seq_printf(s, "\"duty_cycle\": %u",
{
struct clk_core *child;
---- if (!c)
---- return;
----
clk_dump_one(s, c, level);
hlist_for_each_entry(child, &c->children, child_node) {
*/
parent = clk_core_get_parent_by_index(core, i);
if (parent)
---- seq_printf(s, "%s", parent->name);
++++ seq_puts(s, parent->name);
else if (core->parents[i].name)
---- seq_printf(s, "%s", core->parents[i].name);
++++ seq_puts(s, core->parents[i].name);
else if (core->parents[i].fw_name)
seq_printf(s, "<%s>(fw)", core->parents[i].fw_name);
else if (core->parents[i].index >= 0)
---- seq_printf(s, "%s",
---- of_clk_get_parent_name(core->of_node,
---- core->parents[i].index));
++++ seq_puts(s,
++++ of_clk_get_parent_name(core->of_node,
++++ core->parents[i].index));
else
seq_puts(s, "(missing)");
}
DEFINE_SHOW_ATTRIBUTE(clk_duty_cycle);
++++static int clk_min_rate_show(struct seq_file *s, void *data)
++++{
++++ struct clk_core *core = s->private;
++++ unsigned long min_rate, max_rate;
++++
++++ clk_prepare_lock();
++++ clk_core_get_boundaries(core, &min_rate, &max_rate);
++++ clk_prepare_unlock();
++++ seq_printf(s, "%lu\n", min_rate);
++++
++++ return 0;
++++}
++++DEFINE_SHOW_ATTRIBUTE(clk_min_rate);
++++
++++static int clk_max_rate_show(struct seq_file *s, void *data)
++++{
++++ struct clk_core *core = s->private;
++++ unsigned long min_rate, max_rate;
++++
++++ clk_prepare_lock();
++++ clk_core_get_boundaries(core, &min_rate, &max_rate);
++++ clk_prepare_unlock();
++++ seq_printf(s, "%lu\n", max_rate);
++++
++++ return 0;
++++}
++++DEFINE_SHOW_ATTRIBUTE(clk_max_rate);
++++
static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
{
struct dentry *root;
core->dentry = root;
debugfs_create_ulong("clk_rate", 0444, root, &core->rate);
++++ debugfs_create_file("clk_min_rate", 0444, root, core, &clk_min_rate_fops);
++++ debugfs_create_file("clk_max_rate", 0444, root, core, &clk_max_rate_fops);
debugfs_create_ulong("clk_accuracy", 0444, root, &core->accuracy);
debugfs_create_u32("clk_phase", 0444, root, &core->phase);
debugfs_create_file("clk_flags", 0444, root, core, &clk_flags_fops);
return 0;
}
----static int clk_core_populate_parent_map(struct clk_core *core)
++++static int clk_core_populate_parent_map(struct clk_core *core,
++++ const struct clk_init_data *init)
{
---- const struct clk_init_data *init = core->hw->init;
u8 num_parents = init->num_parents;
const char * const *parent_names = init->parent_names;
const struct clk_hw **parent_hws = init->parent_hws;
{
int ret;
struct clk_core *core;
++++ const struct clk_init_data *init = hw->init;
++++
++++ /*
++++ * The init data is not supposed to be used outside of registration path.
++++ * Set it to NULL so that provider drivers can't use it either and so that
++++ * we catch use of hw->init early on in the core.
++++ */
++++ hw->init = NULL;
core = kzalloc(sizeof(*core), GFP_KERNEL);
if (!core) {
goto fail_out;
}
---- core->name = kstrdup_const(hw->init->name, GFP_KERNEL);
++++ core->name = kstrdup_const(init->name, GFP_KERNEL);
if (!core->name) {
ret = -ENOMEM;
goto fail_name;
}
---- if (WARN_ON(!hw->init->ops)) {
++++ if (WARN_ON(!init->ops)) {
ret = -EINVAL;
goto fail_ops;
}
---- core->ops = hw->init->ops;
++++ core->ops = init->ops;
if (dev && pm_runtime_enabled(dev))
core->rpm_enabled = true;
if (dev && dev->driver)
core->owner = dev->driver->owner;
core->hw = hw;
---- core->flags = hw->init->flags;
---- core->num_parents = hw->init->num_parents;
++++ core->flags = init->flags;
++++ core->num_parents = init->num_parents;
core->min_rate = 0;
core->max_rate = ULONG_MAX;
hw->core = core;
---- ret = clk_core_populate_parent_map(core);
++++ ret = clk_core_populate_parent_map(core, init);
if (ret)
goto fail_parents;
.set_parent = clk_nodrv_set_parent,
};
+++ +static void clk_core_evict_parent_cache_subtree(struct clk_core *root,
+++ + struct clk_core *target)
+++ +{
+++ + int i;
+++ + struct clk_core *child;
+++ +
+++ + for (i = 0; i < root->num_parents; i++)
+++ + if (root->parents[i].core == target)
+++ + root->parents[i].core = NULL;
+++ +
+++ + hlist_for_each_entry(child, &root->children, child_node)
+++ + clk_core_evict_parent_cache_subtree(child, target);
+++ +}
+++ +
+++ +/* Remove this clk from all parent caches */
+++ +static void clk_core_evict_parent_cache(struct clk_core *core)
+++ +{
+++ + struct hlist_head **lists;
+++ + struct clk_core *root;
+++ +
+++ + lockdep_assert_held(&prepare_lock);
+++ +
+++ + for (lists = all_lists; *lists; lists++)
+++ + hlist_for_each_entry(root, *lists, child_node)
+++ + clk_core_evict_parent_cache_subtree(root, core);
+++ +
+++ +}
+++ +
/**
* clk_unregister - unregister a currently registered clock
* @clk: clock to unregister
clk_core_set_parent_nolock(child, NULL);
}
+++ + clk_core_evict_parent_cache(clk->core);
+++ +
hlist_del_init(&clk->core->child_node);
if (clk->core->prepare_count)
}
EXPORT_SYMBOL(devm_of_clk_del_provider);
----/*
---- * Beware the return values when np is valid, but no clock provider is found.
---- * If name == NULL, the function returns -ENOENT.
---- * If name != NULL, the function returns -EINVAL. This is because
---- * of_parse_phandle_with_args() is called even if of_property_match_string()
---- * returns an error.
++++/**
++++ * of_parse_clkspec() - Parse a DT clock specifier for a given device node
++++ * @np: device node to parse clock specifier from
++++ * @index: index of phandle to parse clock out of. If index < 0, @name is used
++++ * @name: clock name to find and parse. If name is NULL, the index is used
++++ * @out_args: Result of parsing the clock specifier
++++ *
++++ * Parses a device node's "clocks" and "clock-names" properties to find the
++++ * phandle and cells for the index or name that is desired. The resulting clock
++++ * specifier is placed into @out_args, or an errno is returned when there's a
++++ * parsing error. The @index argument is ignored if @name is non-NULL.
++++ *
++++ * Example:
++++ *
++++ * phandle1: clock-controller@1 {
++++ * #clock-cells = <2>;
++++ * }
++++ *
++++ * phandle2: clock-controller@2 {
++++ * #clock-cells = <1>;
++++ * }
++++ *
++++ * clock-consumer@3 {
++++ * clocks = <&phandle1 1 2 &phandle2 3>;
++++ * clock-names = "name1", "name2";
++++ * }
++++ *
++++ * To get a device_node for `clock-controller@2' node you may call this
++++ * function a few different ways:
++++ *
++++ * of_parse_clkspec(clock-consumer@3, -1, "name2", &args);
++++ * of_parse_clkspec(clock-consumer@3, 1, NULL, &args);
++++ * of_parse_clkspec(clock-consumer@3, 1, "name2", &args);
++++ *
++++ * Return: 0 upon successfully parsing the clock specifier. Otherwise, -ENOENT
++++ * if @name is NULL or -EINVAL if @name is non-NULL and it can't be found in
++++ * the "clock-names" property of @np.
*/
static int of_parse_clkspec(const struct device_node *np, int index,
const char *name, struct of_phandle_args *out_args)