struct kref ref;
};
+#define CREATE_TRACE_POINTS
+#include <trace/events/clk.h>
+
struct clk {
struct clk_core *core;
const char *dev_id;
{
struct clk_core *child;
+ lockdep_assert_held(&prepare_lock);
+
hlist_for_each_entry(child, &clk->children, child_node)
clk_unprepare_unused_subtree(child);
return;
if (clk_core_is_prepared(clk)) {
+ trace_clk_unprepare(clk);
if (clk->ops->unprepare_unused)
clk->ops->unprepare_unused(clk->hw);
else if (clk->ops->unprepare)
clk->ops->unprepare(clk->hw);
+ trace_clk_unprepare_complete(clk);
}
}
struct clk_core *child;
unsigned long flags;
+ lockdep_assert_held(&prepare_lock);
+
hlist_for_each_entry(child, &clk->children, child_node)
clk_disable_unused_subtree(child);
* back to .disable
*/
if (clk_core_is_enabled(clk)) {
+ trace_clk_disable(clk);
if (clk->ops->disable_unused)
clk->ops->disable_unused(clk->hw);
else if (clk->ops->disable)
clk->ops->disable(clk->hw);
+ trace_clk_disable_complete(clk);
}
unlock_out:
WARN_ON(clk->enable_count > 0);
+ trace_clk_unprepare(clk);
+
if (clk->ops->unprepare)
clk->ops->unprepare(clk->hw);
+ trace_clk_unprepare_complete(clk);
clk_core_unprepare(clk->parent);
}
if (ret)
return ret;
- if (clk->ops->prepare) {
+ trace_clk_prepare(clk);
+
+ if (clk->ops->prepare)
ret = clk->ops->prepare(clk->hw);
- if (ret) {
- clk_core_unprepare(clk->parent);
- return ret;
- }
+
+ trace_clk_prepare_complete(clk);
+
+ if (ret) {
+ clk_core_unprepare(clk->parent);
+ return ret;
}
}
if (--clk->enable_count > 0)
return;
+ trace_clk_disable(clk);
+
if (clk->ops->disable)
clk->ops->disable(clk->hw);
+ trace_clk_disable_complete(clk);
+
clk_core_disable(clk->parent);
}
if (ret)
return ret;
- if (clk->ops->enable) {
+ trace_clk_enable(clk);
+
+ if (clk->ops->enable)
ret = clk->ops->enable(clk->hw);
- if (ret) {
- clk_core_disable(clk->parent);
- return ret;
- }
+
+ trace_clk_enable_complete(clk);
+
+ if (ret) {
+ clk_core_disable(clk->parent);
+ return ret;
}
}
struct clk_core *parent;
struct clk_hw *parent_hw;
+ lockdep_assert_held(&prepare_lock);
+
if (!clk)
return 0;
unsigned long parent_accuracy = 0;
struct clk_core *child;
+ lockdep_assert_held(&prepare_lock);
+
if (clk->parent)
parent_accuracy = clk->parent->accuracy;
unsigned long parent_rate = 0;
struct clk_core *child;
+ lockdep_assert_held(&prepare_lock);
+
old_rate = clk->rate;
if (clk->parent)
old_parent = __clk_set_parent_before(clk, parent);
+ trace_clk_set_parent(clk, parent);
+
/* change clock input source */
if (parent && clk->ops->set_parent)
ret = clk->ops->set_parent(clk->hw, p_index);
+ trace_clk_set_parent_complete(clk, parent);
+
if (ret) {
flags = clk_enable_lock();
clk_reparent(clk, old_parent);
unsigned long new_rate;
int ret = NOTIFY_DONE;
+ lockdep_assert_held(&prepare_lock);
+
new_rate = clk_recalc(clk, parent_rate);
/* abort rate change if a driver returns NOTIFY_BAD or NOTIFY_STOP */
if (clk->new_parent && clk->new_parent != clk->parent) {
old_parent = __clk_set_parent_before(clk, clk->new_parent);
+ trace_clk_set_parent(clk, clk->new_parent);
if (clk->ops->set_rate_and_parent) {
skip_set_rate = true;
clk->ops->set_parent(clk->hw, clk->new_parent_index);
}
+ trace_clk_set_parent_complete(clk, clk->new_parent);
__clk_set_parent_after(clk, clk->new_parent, old_parent);
}
+ trace_clk_set_rate(clk, clk->new_rate);
+
if (!skip_set_rate && clk->ops->set_rate)
clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate);
+ trace_clk_set_rate_complete(clk, clk->new_rate);
+
clk->rate = clk_recalc(clk, best_parent_rate);
if (clk->notifier_count && old_rate != clk->rate)
if (!clk)
return 0;
- /* verify ops for for multi-parent clks */
- if ((clk->num_parents > 1) && (!clk->ops->set_parent))
- return -ENOSYS;
-
/* prevent racing with updates to the clock topology */
clk_prepare_lock();
if (clk->parent == parent)
goto out;
+ /* verify ops for for multi-parent clks */
+ if ((clk->num_parents > 1) && (!clk->ops->set_parent)) {
+ ret = -ENOSYS;
+ goto out;
+ }
+
/* check that we are allowed to re-parent if the clock is in use */
if ((clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) {
ret = -EBUSY;
*/
int clk_set_phase(struct clk *clk, int degrees)
{
- int ret = 0;
+ int ret = -EINVAL;
if (!clk)
- goto out;
+ return 0;
/* sanity check degrees */
degrees %= 360;
clk_prepare_lock();
- if (!clk->core->ops->set_phase)
- goto out_unlock;
+ trace_clk_set_phase(clk->core, degrees);
+
+ if (clk->core->ops->set_phase)
+ ret = clk->core->ops->set_phase(clk->core->hw, degrees);
- ret = clk->core->ops->set_phase(clk->core->hw, degrees);
+ trace_clk_set_phase_complete(clk->core, degrees);
if (!ret)
clk->core->phase = degrees;
-out_unlock:
clk_prepare_unlock();
-out:
return ret;
}
EXPORT_SYMBOL_GPL(clk_set_phase);
struct clk_core *clk = container_of(ref, struct clk_core, ref);
int i = clk->num_parents;
+ lockdep_assert_held(&prepare_lock);
+
kfree(clk->parents);
while (--i >= 0)
kfree_const(clk->parent_names[i]);