{
return clk_core_is_prepared(hw->core);
}
++++ +EXPORT_SYMBOL_GPL(clk_hw_is_prepared);
bool clk_hw_rate_is_protected(const struct clk_hw *hw)
{
return clk_core_rate_is_protected(hw->core);
}
++++ +EXPORT_SYMBOL_GPL(clk_hw_rate_is_protected);
bool clk_hw_is_enabled(const struct clk_hw *hw)
{
return clk_core_is_enabled(hw->core);
}
++++ +EXPORT_SYMBOL_GPL(clk_hw_is_enabled);
bool __clk_is_enabled(struct clk *clk)
{
if (!parent)
return -EINVAL;
----- for (i = 0; i < core->num_parents; i++)
----- if (clk_core_get_parent_by_index(core, i) == parent)
+++++ for (i = 0; i < core->num_parents; i++) {
+++++ if (core->parents[i] == parent)
return i;
+++++ if (core->parents[i])
+++++ continue;
+++++
+++++ /* Fallback to comparing globally unique names */
+++++ if (!strcmp(parent->name, core->parent_names[i])) {
+++++ core->parents[i] = parent;
+++++ return i;
+++++ }
+++++ }
+++++
return -EINVAL;
}
seq_printf(s, "\"protect_count\": %d,", c->protect_count);
seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
----- seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
+++++ seq_printf(s, "\"phase\": %d,", clk_core_get_phase(c));
seq_printf(s, "\"duty_cycle\": %u",
clk_core_get_scaled_duty_cycle(c, 100000));
}
}
EXPORT_SYMBOL(of_clk_get);
+ ++++/*
+ ++++ * 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_clk_get()
+ ++++ * is called even if of_property_match_string() returns an error.
+ ++++ */
static struct clk *__of_clk_get_by_name(struct device_node *np,
const char *dev_id,
const char *name)
return cl;
}
++ +++static int do_clk_register_clkdev(struct clk_hw *hw,
++ +++ struct clk_lookup **cl, const char *con_id, const char *dev_id)
++ +++{
++ +++ if (IS_ERR(hw))
++ +++ return PTR_ERR(hw);
++ +++ /*
++ +++ * Since dev_id can be NULL, and NULL is handled specially, we must
++ +++ * pass it as either a NULL format string, or with "%s".
++ +++ */
++ +++ if (dev_id)
++ +++ *cl = __clk_register_clkdev(hw, con_id, "%s", dev_id);
++ +++ else
++ +++ *cl = __clk_register_clkdev(hw, con_id, NULL);
++ +++
++ +++ return *cl ? 0 : -ENOMEM;
++ +++}
++ +++
/**
* clk_register_clkdev - register one clock lookup for a struct clk
* @clk: struct clk to associate with all clk_lookups
if (IS_ERR(clk))
return PTR_ERR(clk);
-- --- /*
-- --- * Since dev_id can be NULL, and NULL is handled specially, we must
-- --- * pass it as either a NULL format string, or with "%s".
-- --- */
-- --- if (dev_id)
-- --- cl = __clk_register_clkdev(__clk_get_hw(clk), con_id, "%s",
-- --- dev_id);
-- --- else
-- --- cl = __clk_register_clkdev(__clk_get_hw(clk), con_id, NULL);
-- ---
-- --- return cl ? 0 : -ENOMEM;
++ +++ return do_clk_register_clkdev(__clk_get_hw(clk), &cl, con_id,
++ +++ dev_id);
}
EXPORT_SYMBOL(clk_register_clkdev);
{
struct clk_lookup *cl;
-- --- if (IS_ERR(hw))
-- --- return PTR_ERR(hw);
++ +++ return do_clk_register_clkdev(hw, &cl, con_id, dev_id);
++ +++}
++ +++EXPORT_SYMBOL(clk_hw_register_clkdev);
-- --- /*
-- --- * Since dev_id can be NULL, and NULL is handled specially, we must
-- --- * pass it as either a NULL format string, or with "%s".
-- --- */
-- --- if (dev_id)
-- --- cl = __clk_register_clkdev(hw, con_id, "%s", dev_id);
-- --- else
-- --- cl = __clk_register_clkdev(hw, con_id, NULL);
++ +++static void devm_clkdev_release(struct device *dev, void *res)
++ +++{
++ +++ clkdev_drop(*(struct clk_lookup **)res);
++ +++}
+ +++
- return cl ? 0 : -ENOMEM;
++ +++static int devm_clk_match_clkdev(struct device *dev, void *res, void *data)
++ +++{
++ +++ struct clk_lookup **l = res;
+
- --- return cl ? 0 : -ENOMEM;
++ +++ return *l == data;
}
-- ---EXPORT_SYMBOL(clk_hw_register_clkdev);
++ +++
++ +++/**
++ +++ * devm_clk_release_clkdev - Resource managed clkdev lookup release
++ +++ * @dev: device this lookup is bound
++ +++ * @con_id: connection ID string on device
++ +++ * @dev_id: format string describing device name
++ +++ *
++ +++ * Drop the clkdev lookup created with devm_clk_hw_register_clkdev.
++ +++ * Normally this function will not need to be called and the resource
++ +++ * management code will ensure that the resource is freed.
++ +++ */
++ +++void devm_clk_release_clkdev(struct device *dev, const char *con_id,
++ +++ const char *dev_id)
++ +++{
++ +++ struct clk_lookup *cl;
++ +++ int rval;
++ +++
++ +++ cl = clk_find(dev_id, con_id);
++ +++ WARN_ON(!cl);
++ +++ rval = devres_release(dev, devm_clkdev_release,
++ +++ devm_clk_match_clkdev, cl);
++ +++ WARN_ON(rval);
++ +++}
++ +++EXPORT_SYMBOL(devm_clk_release_clkdev);
++ +++
++ +++/**
++ +++ * devm_clk_hw_register_clkdev - managed clk lookup registration for clk_hw
++ +++ * @dev: device this lookup is bound
++ +++ * @hw: struct clk_hw to associate with all clk_lookups
++ +++ * @con_id: connection ID string on device
++ +++ * @dev_id: format string describing device name
++ +++ *
++ +++ * con_id or dev_id may be NULL as a wildcard, just as in the rest of
++ +++ * clkdev.
++ +++ *
++ +++ * To make things easier for mass registration, we detect error clk_hws
++ +++ * from a previous clk_hw_register_*() call, and return the error code for
++ +++ * those. This is to permit this function to be called immediately
++ +++ * after clk_hw_register_*().
++ +++ */
++ +++int devm_clk_hw_register_clkdev(struct device *dev, struct clk_hw *hw,
++ +++ const char *con_id, const char *dev_id)
++ +++{
++ +++ int rval = -ENOMEM;
++ +++ struct clk_lookup **cl;
++ +++
++ +++ cl = devres_alloc(devm_clkdev_release, sizeof(*cl), GFP_KERNEL);
++ +++ if (cl) {
++ +++ rval = do_clk_register_clkdev(hw, cl, con_id, dev_id);
++ +++ if (!rval)
++ +++ devres_add(dev, cl);
++ +++ else
++ +++ devres_free(cl);
++ +++ }
++ +++ return rval;
++ +++}
++ +++EXPORT_SYMBOL(devm_clk_hw_register_clkdev);