Commit 7d2f353b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

Pull clk fixes from Stephen Boyd:
 "One clk driver fix and two clk framework fixes:

   - Fix an OOB access when devm_get_clk_from_child() is used and
     devm_clk_release() casts the void pointer to the wrong type

   - Move clk_rate_exclusive_{get,put}() within the correct ifdefs in
     clk.h so that the stubs are used when CONFIG_COMMON_CLK=n

   - Register the proper clk provider function depending on the value of
     #clock-cells in the TI keystone driver"

* tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux:
  clk: Fix slab-out-of-bounds error in devm_clk_release()
  clk: Fix undefined reference to `clk_rate_exclusive_{get,put}'
  clk: keystone: syscon-clk: Fix audio refclk
parents 382d4cd1 66fbfb35
...@@ -205,18 +205,19 @@ EXPORT_SYMBOL(devm_clk_put); ...@@ -205,18 +205,19 @@ EXPORT_SYMBOL(devm_clk_put);
struct clk *devm_get_clk_from_child(struct device *dev, struct clk *devm_get_clk_from_child(struct device *dev,
struct device_node *np, const char *con_id) struct device_node *np, const char *con_id)
{ {
struct clk **ptr, *clk; struct devm_clk_state *state;
struct clk *clk;
ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
if (!ptr) if (!state)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
clk = of_clk_get_by_name(np, con_id); clk = of_clk_get_by_name(np, con_id);
if (!IS_ERR(clk)) { if (!IS_ERR(clk)) {
*ptr = clk; state->clk = clk;
devres_add(dev, ptr); devres_add(dev, state);
} else { } else {
devres_free(ptr); devres_free(state);
} }
return clk; return clk;
......
...@@ -151,8 +151,10 @@ static int ti_syscon_gate_clk_probe(struct platform_device *pdev) ...@@ -151,8 +151,10 @@ static int ti_syscon_gate_clk_probe(struct platform_device *pdev)
data[i].name); data[i].name);
} }
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, if (num_clks == 1)
hw_data); return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
hw_data->hws[0]);
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data);
} }
#define TI_SYSCON_CLK_GATE(_name, _offset, _bit_idx) \ #define TI_SYSCON_CLK_GATE(_name, _offset, _bit_idx) \
......
...@@ -183,6 +183,39 @@ int clk_get_scaled_duty_cycle(struct clk *clk, unsigned int scale); ...@@ -183,6 +183,39 @@ int clk_get_scaled_duty_cycle(struct clk *clk, unsigned int scale);
*/ */
bool clk_is_match(const struct clk *p, const struct clk *q); bool clk_is_match(const struct clk *p, const struct clk *q);
/**
* clk_rate_exclusive_get - get exclusivity over the rate control of a
* producer
* @clk: clock source
*
* This function allows drivers to get exclusive control over the rate of a
* provider. It prevents any other consumer to execute, even indirectly,
* opereation which could alter the rate of the provider or cause glitches
*
* If exlusivity is claimed more than once on clock, even by the same driver,
* the rate effectively gets locked as exclusivity can't be preempted.
*
* Must not be called from within atomic context.
*
* Returns success (0) or negative errno.
*/
int clk_rate_exclusive_get(struct clk *clk);
/**
* clk_rate_exclusive_put - release exclusivity over the rate control of a
* producer
* @clk: clock source
*
* This function allows drivers to release the exclusivity it previously got
* from clk_rate_exclusive_get()
*
* The caller must balance the number of clk_rate_exclusive_get() and
* clk_rate_exclusive_put() calls.
*
* Must not be called from within atomic context.
*/
void clk_rate_exclusive_put(struct clk *clk);
#else #else
static inline int clk_notifier_register(struct clk *clk, static inline int clk_notifier_register(struct clk *clk,
...@@ -236,6 +269,13 @@ static inline bool clk_is_match(const struct clk *p, const struct clk *q) ...@@ -236,6 +269,13 @@ static inline bool clk_is_match(const struct clk *p, const struct clk *q)
return p == q; return p == q;
} }
static inline int clk_rate_exclusive_get(struct clk *clk)
{
return 0;
}
static inline void clk_rate_exclusive_put(struct clk *clk) {}
#endif #endif
#ifdef CONFIG_HAVE_CLK_PREPARE #ifdef CONFIG_HAVE_CLK_PREPARE
...@@ -583,38 +623,6 @@ struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id); ...@@ -583,38 +623,6 @@ struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id);
*/ */
struct clk *devm_get_clk_from_child(struct device *dev, struct clk *devm_get_clk_from_child(struct device *dev,
struct device_node *np, const char *con_id); struct device_node *np, const char *con_id);
/**
* clk_rate_exclusive_get - get exclusivity over the rate control of a
* producer
* @clk: clock source
*
* This function allows drivers to get exclusive control over the rate of a
* provider. It prevents any other consumer to execute, even indirectly,
* opereation which could alter the rate of the provider or cause glitches
*
* If exlusivity is claimed more than once on clock, even by the same driver,
* the rate effectively gets locked as exclusivity can't be preempted.
*
* Must not be called from within atomic context.
*
* Returns success (0) or negative errno.
*/
int clk_rate_exclusive_get(struct clk *clk);
/**
* clk_rate_exclusive_put - release exclusivity over the rate control of a
* producer
* @clk: clock source
*
* This function allows drivers to release the exclusivity it previously got
* from clk_rate_exclusive_get()
*
* The caller must balance the number of clk_rate_exclusive_get() and
* clk_rate_exclusive_put() calls.
*
* Must not be called from within atomic context.
*/
void clk_rate_exclusive_put(struct clk *clk);
/** /**
* clk_enable - inform the system when the clock source should be running. * clk_enable - inform the system when the clock source should be running.
...@@ -974,14 +982,6 @@ static inline void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) {} ...@@ -974,14 +982,6 @@ static inline void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) {}
static inline void devm_clk_put(struct device *dev, struct clk *clk) {} static inline void devm_clk_put(struct device *dev, struct clk *clk) {}
static inline int clk_rate_exclusive_get(struct clk *clk)
{
return 0;
}
static inline void clk_rate_exclusive_put(struct clk *clk) {}
static inline int clk_enable(struct clk *clk) static inline int clk_enable(struct clk *clk)
{ {
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment