if (!core)
return;
--- if (WARN_ON(core->protect_count == 0))
+++ if (WARN(core->protect_count == 0,
+++ "%s already unprotected\n", core->name))
return;
if (--core->protect_count > 0)
if (!core)
return;
--- if (WARN_ON(core->prepare_count == 0))
+++ if (WARN(core->prepare_count == 0,
+++ "%s already unprepared\n", core->name))
return;
--- if (WARN_ON(core->prepare_count == 1 && core->flags & CLK_IS_CRITICAL))
+++ if (WARN(core->prepare_count == 1 && core->flags & CLK_IS_CRITICAL,
+++ "Unpreparing critical %s\n", core->name))
return;
if (--core->prepare_count > 0)
return;
--- WARN_ON(core->enable_count > 0);
+++ WARN(core->enable_count > 0, "Unpreparing enabled %s\n", core->name);
trace_clk_unprepare(core);
if (!core)
return;
--- if (WARN_ON(core->enable_count == 0))
+++ if (WARN(core->enable_count == 0, "%s already disabled\n", core->name))
return;
--- if (WARN_ON(core->enable_count == 1 && core->flags & CLK_IS_CRITICAL))
+++ if (WARN(core->enable_count == 1 && core->flags & CLK_IS_CRITICAL,
+++ "Disabling critical %s\n", core->name))
return;
if (--core->enable_count > 0)
if (!core)
return 0;
--- if (WARN_ON(core->prepare_count == 0))
+++ if (WARN(core->prepare_count == 0,
+++ "Enabling unprepared %s\n", core->name))
return -ESHUTDOWN;
if (core->enable_count == 0) {
{
lockdep_assert_held(&prepare_lock);
- - if (!core)
+ + if (!core) {
+ + req->rate = 0;
return 0;
+ + }
clk_core_init_rate_req(core, req);
trace_clk_set_phase(core, degrees);
- - if (core->ops->set_phase)
+ + if (core->ops->set_phase) {
ret = core->ops->set_phase(core->hw, degrees);
+ + if (!ret)
+ + core->phase = degrees;
+ + }
trace_clk_set_phase_complete(core, degrees);
int ret;
clk_prepare_lock();
+ + /* Always try to update cached phase if possible */
+ + if (core->ops->get_phase)
+ + core->phase = core->ops->get_phase(core->hw);
ret = core->phase;
clk_prepare_unlock();
return 0;
}
- -
- -
- - static int clk_summary_open(struct inode *inode, struct file *file)
- - {
- - return single_open(file, clk_summary_show, inode->i_private);
- - }
- -
- - static const struct file_operations clk_summary_fops = {
- - .open = clk_summary_open,
- - .read = seq_read,
- - .llseek = seq_lseek,
- - .release = single_release,
- - };
+ + DEFINE_SHOW_ATTRIBUTE(clk_summary);
static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
{
seq_putc(s, '}');
}
- - static int clk_dump(struct seq_file *s, void *data)
+ + static int clk_dump_show(struct seq_file *s, void *data)
{
struct clk_core *c;
bool first_node = true;
seq_puts(s, "}\n");
return 0;
}
- -
- -
- - static int clk_dump_open(struct inode *inode, struct file *file)
- - {
- - return single_open(file, clk_dump, inode->i_private);
- - }
- -
- - static const struct file_operations clk_dump_fops = {
- - .open = clk_dump_open,
- - .read = seq_read,
- - .llseek = seq_lseek,
- - .release = single_release,
- - };
+ + DEFINE_SHOW_ATTRIBUTE(clk_dump);
static const struct {
unsigned long flag;
#undef ENTRY
};
- - static int clk_flags_dump(struct seq_file *s, void *data)
+ + static int clk_flags_show(struct seq_file *s, void *data)
{
struct clk_core *core = s->private;
unsigned long flags = core->flags;
return 0;
}
+ + DEFINE_SHOW_ATTRIBUTE(clk_flags);
- - static int clk_flags_open(struct inode *inode, struct file *file)
- - {
- - return single_open(file, clk_flags_dump, inode->i_private);
- - }
- -
- - static const struct file_operations clk_flags_fops = {
- - .open = clk_flags_open,
- - .read = seq_read,
- - .llseek = seq_lseek,
- - .release = single_release,
- - };
- -
- - static int possible_parents_dump(struct seq_file *s, void *data)
+ + static int possible_parents_show(struct seq_file *s, void *data)
{
struct clk_core *core = s->private;
int i;
return 0;
}
- -
- - static int possible_parents_open(struct inode *inode, struct file *file)
- - {
- - return single_open(file, possible_parents_dump, inode->i_private);
- - }
- -
- - static const struct file_operations possible_parents_fops = {
- - .open = possible_parents_open,
- - .read = seq_read,
- - .llseek = seq_lseek,
- - .release = single_release,
- - };
+ + DEFINE_SHOW_ATTRIBUTE(possible_parents);
static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
{
}
/*
+ + * optional platform-specific magic
+ + *
+ + * The .init callback is not used by any of the basic clock types, but
+ + * exists for weird hardware that must perform initialization magic.
+ + * Please consider other ways of solving initialization problems before
+ + * using this callback, as its use is discouraged.
+ + */
+ + if (core->ops->init)
+ + core->ops->init(core->hw);
+ +
+ + /*
* Set clk's accuracy. The preferred method is to use
* .recalc_accuracy. For simple clocks and lazy developers the default
* fallback is to use the parent's accuracy. If a clock doesn't have a
core->rate = core->req_rate = rate;
/*
+ + * Enable CLK_IS_CRITICAL clocks so newly added critical clocks
+ + * don't get accidentally disabled when walking the orphan tree and
+ + * reparenting clocks
+ + */
+ + if (core->flags & CLK_IS_CRITICAL) {
+ + unsigned long flags;
+ +
+ + clk_core_prepare(core);
+ +
+ + flags = clk_enable_lock();
+ + clk_core_enable(core);
+ + clk_enable_unlock(flags);
+ + }
+ +
+ + /*
* walk the list of orphan clocks and reparent any that newly finds a
* parent.
*/
hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
struct clk_core *parent = __clk_init_parent(orphan);
- - unsigned long flags;
/*
- - * we could call __clk_set_parent, but that would result in a
- - * redundant call to the .set_rate op, if it exists
+ + * We need to use __clk_set_parent_before() and _after() to
+ + * to properly migrate any prepare/enable count of the orphan
+ + * clock. This is important for CLK_IS_CRITICAL clocks, which
+ + * are enabled during init but might not have a parent yet.
*/
if (parent) {
/* update the clk tree topology */
- - flags = clk_enable_lock();
- - clk_reparent(orphan, parent);
- - clk_enable_unlock(flags);
+ + __clk_set_parent_before(orphan, parent);
+ + __clk_set_parent_after(orphan, parent, NULL);
__clk_recalc_accuracies(orphan);
__clk_recalc_rates(orphan, 0);
}
}
- - /*
- - * optional platform-specific magic
- - *
- - * The .init callback is not used by any of the basic clock types, but
- - * exists for weird hardware that must perform initialization magic.
- - * Please consider other ways of solving initialization problems before
- - * using this callback, as its use is discouraged.
- - */
- - if (core->ops->init)
- - core->ops->init(core->hw);
- -
- - if (core->flags & CLK_IS_CRITICAL) {
- - unsigned long flags;
- -
- - clk_core_prepare(core);
- -
- - flags = clk_enable_lock();
- - clk_core_enable(core);
- - clk_enable_unlock(flags);
- - }
- -
kref_init(&core->ref);
out:
clk_pm_runtime_put(core);
EXPORT_SYMBOL_GPL(of_clk_parent_fill);
struct clock_provider {
- -- of_clk_init_cb_t clk_init_cb;
+ ++ void (*clk_init_cb)(struct device_node *);
struct device_node *np;
struct list_head node;
};