Commit 035a61c3 authored by Tomeu Vizoso's avatar Tomeu Vizoso Committed by Michael Turquette

clk: Make clk API return per-user struct clk instances

Moves clock state to struct clk_core, but takes care to change as little API as
possible.

struct clk_hw still has a pointer to a struct clk, which is the
implementation's per-user clk instance, for backwards compatibility.

The struct clk that clk_get_parent() returns isn't owned by the caller, but by
the clock implementation, so the former shouldn't call clk_put() on it.

Because some boards in mach-omap2 still register clocks statically, their clock
registration had to be updated to take into account that the clock information
is stored in struct clk_core now.
Signed-off-by: default avatarTomeu Vizoso <tomeu.vizoso@collabora.com>
Reviewed-by: default avatarStephen Boyd <sboyd@codeaurora.org>
Tested-by: default avatarTony Lindgren <tony@atomide.com>
Signed-off-by: default avatarMichael Turquette <mturquette@linaro.org>
[mturquette@linaro.org: adapted clk_has_parent to struct clk_core
                        applied OMAP3+ DPLL fix from Tero & Tony]
parent af0f349b
This diff is collapsed.
...@@ -40,23 +40,29 @@ struct omap_clk { ...@@ -40,23 +40,29 @@ struct omap_clk {
struct clockdomain; struct clockdomain;
#define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name) \ #define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name) \
static struct clk _name = { \ static struct clk_core _name##_core = { \
.name = #_name, \ .name = #_name, \
.hw = &_name##_hw.hw, \ .hw = &_name##_hw.hw, \
.parent_names = _parent_array_name, \ .parent_names = _parent_array_name, \
.num_parents = ARRAY_SIZE(_parent_array_name), \ .num_parents = ARRAY_SIZE(_parent_array_name), \
.ops = &_clkops_name, \ .ops = &_clkops_name, \
}; \
static struct clk _name = { \
.core = &_name##_core, \
}; };
#define DEFINE_STRUCT_CLK_FLAGS(_name, _parent_array_name, \ #define DEFINE_STRUCT_CLK_FLAGS(_name, _parent_array_name, \
_clkops_name, _flags) \ _clkops_name, _flags) \
static struct clk _name = { \ static struct clk_core _name##_core = { \
.name = #_name, \ .name = #_name, \
.hw = &_name##_hw.hw, \ .hw = &_name##_hw.hw, \
.parent_names = _parent_array_name, \ .parent_names = _parent_array_name, \
.num_parents = ARRAY_SIZE(_parent_array_name), \ .num_parents = ARRAY_SIZE(_parent_array_name), \
.ops = &_clkops_name, \ .ops = &_clkops_name, \
.flags = _flags, \ .flags = _flags, \
}; \
static struct clk _name = { \
.core = &_name##_core, \
}; };
#define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name) \ #define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name) \
...@@ -248,6 +254,7 @@ extern const struct clksel_rate gpt_32k_rates[]; ...@@ -248,6 +254,7 @@ extern const struct clksel_rate gpt_32k_rates[];
extern const struct clksel_rate gpt_sys_rates[]; extern const struct clksel_rate gpt_sys_rates[];
extern const struct clksel_rate gfx_l3_rates[]; extern const struct clksel_rate gfx_l3_rates[];
extern const struct clksel_rate dsp_ick_rates[]; extern const struct clksel_rate dsp_ick_rates[];
extern struct clk_core dummy_ck_core;
extern struct clk dummy_ck; extern struct clk dummy_ck;
extern const struct clk_hw_omap_ops clkhwops_iclk_wait; extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
......
...@@ -119,8 +119,11 @@ const struct clksel_rate div31_1to31_rates[] = { ...@@ -119,8 +119,11 @@ const struct clksel_rate div31_1to31_rates[] = {
static struct clk_ops dummy_ck_ops = {}; static struct clk_ops dummy_ck_ops = {};
struct clk dummy_ck = { struct clk_core dummy_ck_core = {
.name = "dummy_clk", .name = "dummy_clk",
.ops = &dummy_ck_ops, .ops = &dummy_ck_ops,
.flags = CLK_IS_BASIC, .flags = CLK_IS_BASIC,
}; };
struct clk dummy_ck = {
.core = &dummy_ck_core,
};
...@@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw) ...@@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
struct clk_hw_omap *clk = to_clk_hw_omap(hw); struct clk_hw_omap *clk = to_clk_hw_omap(hw);
int r; int r;
struct dpll_data *dd; struct dpll_data *dd;
struct clk *parent; struct clk_hw *parent;
dd = clk->dpll_data; dd = clk->dpll_data;
if (!dd) if (!dd)
...@@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw) ...@@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
} }
} }
parent = __clk_get_parent(hw->clk); parent = __clk_get_hw(__clk_get_parent(hw->clk));
if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) { if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
WARN_ON(parent != dd->clk_bypass); WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
r = _omap3_noncore_dpll_bypass(clk); r = _omap3_noncore_dpll_bypass(clk);
} else { } else {
WARN_ON(parent != dd->clk_ref); WARN_ON(parent != __clk_get_hw(dd->clk_ref));
r = _omap3_noncore_dpll_lock(clk); r = _omap3_noncore_dpll_lock(clk);
} }
...@@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
if (!dd) if (!dd)
return -EINVAL; return -EINVAL;
if (__clk_get_parent(hw->clk) != dd->clk_ref) if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
__clk_get_hw(dd->clk_ref))
return -EINVAL; return -EINVAL;
if (dd->last_rounded_rate == 0) if (dd->last_rounded_rate == 0)
......
This diff is collapsed.
...@@ -9,9 +9,14 @@ ...@@ -9,9 +9,14 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
struct clk_hw;
#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec); struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec);
struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec); struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec);
void of_clk_lock(void); void of_clk_lock(void);
void of_clk_unlock(void); void of_clk_unlock(void);
#endif #endif
struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
const char *con_id);
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clkdev.h> #include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h> #include <linux/of.h>
#include "clk.h" #include "clk.h"
...@@ -53,7 +54,7 @@ struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec) ...@@ -53,7 +54,7 @@ struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
return clk; return clk;
} }
struct clk *of_clk_get(struct device_node *np, int index) static struct clk *__of_clk_get(struct device_node *np, int index)
{ {
struct of_phandle_args clkspec; struct of_phandle_args clkspec;
struct clk *clk; struct clk *clk;
...@@ -69,20 +70,24 @@ struct clk *of_clk_get(struct device_node *np, int index) ...@@ -69,20 +70,24 @@ struct clk *of_clk_get(struct device_node *np, int index)
clk = of_clk_get_by_clkspec(&clkspec); clk = of_clk_get_by_clkspec(&clkspec);
of_node_put(clkspec.np); of_node_put(clkspec.np);
return clk;
}
struct clk *of_clk_get(struct device_node *np, int index)
{
struct clk *clk = __of_clk_get(np, index);
if (!IS_ERR(clk))
clk = __clk_create_clk(__clk_get_hw(clk), np->full_name, NULL);
return clk; return clk;
} }
EXPORT_SYMBOL(of_clk_get); EXPORT_SYMBOL(of_clk_get);
/** static struct clk *__of_clk_get_by_name(struct device_node *np,
* of_clk_get_by_name() - Parse and lookup a clock referenced by a device node const char *dev_id,
* @np: pointer to clock consumer node const char *name)
* @name: name of consumer's clock input, or NULL for the first clock reference
*
* This function parses the clocks and clock-names properties,
* and uses them to look up the struct clk from the registered list of clock
* providers.
*/
struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
{ {
struct clk *clk = ERR_PTR(-ENOENT); struct clk *clk = ERR_PTR(-ENOENT);
...@@ -97,9 +102,11 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name) ...@@ -97,9 +102,11 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
*/ */
if (name) if (name)
index = of_property_match_string(np, "clock-names", name); index = of_property_match_string(np, "clock-names", name);
clk = of_clk_get(np, index); clk = __of_clk_get(np, index);
if (!IS_ERR(clk)) if (!IS_ERR(clk)) {
clk = __clk_create_clk(__clk_get_hw(clk), dev_id, name);
break; break;
}
else if (name && index >= 0) { else if (name && index >= 0) {
if (PTR_ERR(clk) != -EPROBE_DEFER) if (PTR_ERR(clk) != -EPROBE_DEFER)
pr_err("ERROR: could not get clock %s:%s(%i)\n", pr_err("ERROR: could not get clock %s:%s(%i)\n",
...@@ -119,7 +126,33 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name) ...@@ -119,7 +126,33 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
return clk; return clk;
} }
/**
* of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
* @np: pointer to clock consumer node
* @name: name of consumer's clock input, or NULL for the first clock reference
*
* This function parses the clocks and clock-names properties,
* and uses them to look up the struct clk from the registered list of clock
* providers.
*/
struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
{
if (!np)
return ERR_PTR(-ENOENT);
return __of_clk_get_by_name(np, np->full_name, name);
}
EXPORT_SYMBOL(of_clk_get_by_name); EXPORT_SYMBOL(of_clk_get_by_name);
#else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */
static struct clk *__of_clk_get_by_name(struct device_node *np,
const char *dev_id,
const char *name)
{
return ERR_PTR(-ENOENT);
}
#endif #endif
/* /*
...@@ -168,14 +201,29 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id) ...@@ -168,14 +201,29 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
struct clk *clk_get_sys(const char *dev_id, const char *con_id) struct clk *clk_get_sys(const char *dev_id, const char *con_id)
{ {
struct clk_lookup *cl; struct clk_lookup *cl;
struct clk *clk = NULL;
mutex_lock(&clocks_mutex); mutex_lock(&clocks_mutex);
cl = clk_find(dev_id, con_id); cl = clk_find(dev_id, con_id);
if (cl && !__clk_get(cl->clk)) if (!cl)
goto out;
if (!__clk_get(cl->clk)) {
cl = NULL; cl = NULL;
goto out;
}
#if defined(CONFIG_COMMON_CLK)
clk = __clk_create_clk(__clk_get_hw(cl->clk), dev_id, con_id);
#else
clk = cl->clk;
#endif
out:
mutex_unlock(&clocks_mutex); mutex_unlock(&clocks_mutex);
return cl ? cl->clk : ERR_PTR(-ENOENT); return cl ? clk : ERR_PTR(-ENOENT);
} }
EXPORT_SYMBOL(clk_get_sys); EXPORT_SYMBOL(clk_get_sys);
...@@ -185,10 +233,8 @@ struct clk *clk_get(struct device *dev, const char *con_id) ...@@ -185,10 +233,8 @@ struct clk *clk_get(struct device *dev, const char *con_id)
struct clk *clk; struct clk *clk;
if (dev) { if (dev) {
clk = of_clk_get_by_name(dev->of_node, con_id); clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id);
if (!IS_ERR(clk)) if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
return clk;
if (PTR_ERR(clk) == -EPROBE_DEFER)
return clk; return clk;
} }
......
...@@ -28,20 +28,20 @@ ...@@ -28,20 +28,20 @@
struct module; struct module;
struct clk { struct clk_core {
const char *name; const char *name;
const struct clk_ops *ops; const struct clk_ops *ops;
struct clk_hw *hw; struct clk_hw *hw;
struct module *owner; struct module *owner;
struct clk *parent; struct clk_core *parent;
const char **parent_names; const char **parent_names;
struct clk **parents; struct clk_core **parents;
u8 num_parents; u8 num_parents;
u8 new_parent_index; u8 new_parent_index;
unsigned long rate; unsigned long rate;
unsigned long new_rate; unsigned long new_rate;
struct clk *new_parent; struct clk_core *new_parent;
struct clk *new_child; struct clk_core *new_child;
unsigned long flags; unsigned long flags;
unsigned int enable_count; unsigned int enable_count;
unsigned int prepare_count; unsigned int prepare_count;
...@@ -57,6 +57,12 @@ struct clk { ...@@ -57,6 +57,12 @@ struct clk {
struct kref ref; struct kref ref;
}; };
struct clk {
struct clk_core *core;
const char *dev_id;
const char *con_id;
};
/* /*
* DOC: Basic clock implementations common to many platforms * DOC: Basic clock implementations common to many platforms
* *
...@@ -69,6 +75,9 @@ struct clk { ...@@ -69,6 +75,9 @@ struct clk {
#define DEFINE_CLK(_name, _ops, _flags, _parent_names, \ #define DEFINE_CLK(_name, _ops, _flags, _parent_names, \
_parents) \ _parents) \
static struct clk _name = { \ static struct clk _name = { \
.core = &_name##_core \
}; \
static struct clk_core _name##_core = { \
.name = #_name, \ .name = #_name, \
.ops = &_ops, \ .ops = &_ops, \
.hw = &_name##_hw.hw, \ .hw = &_name##_hw.hw, \
...@@ -81,9 +90,11 @@ struct clk { ...@@ -81,9 +90,11 @@ struct clk {
#define DEFINE_CLK_FIXED_RATE(_name, _flags, _rate, \ #define DEFINE_CLK_FIXED_RATE(_name, _flags, _rate, \
_fixed_rate_flags) \ _fixed_rate_flags) \
static struct clk _name; \ static struct clk _name; \
static struct clk_core _name##_core; \
static const char *_name##_parent_names[] = {}; \ static const char *_name##_parent_names[] = {}; \
static struct clk_fixed_rate _name##_hw = { \ static struct clk_fixed_rate _name##_hw = { \
.hw = { \ .hw = { \
.core = &_name##_core, \
.clk = &_name, \ .clk = &_name, \
}, \ }, \
.fixed_rate = _rate, \ .fixed_rate = _rate, \
...@@ -96,14 +107,16 @@ struct clk { ...@@ -96,14 +107,16 @@ struct clk {
_flags, _reg, _bit_idx, \ _flags, _reg, _bit_idx, \
_gate_flags, _lock) \ _gate_flags, _lock) \
static struct clk _name; \ static struct clk _name; \
static struct clk_core _name##_core; \
static const char *_name##_parent_names[] = { \ static const char *_name##_parent_names[] = { \
_parent_name, \ _parent_name, \
}; \ }; \
static struct clk *_name##_parents[] = { \ static struct clk_core *_name##_parents[] = { \
_parent_ptr, \ _parent_ptr, \
}; \ }; \
static struct clk_gate _name##_hw = { \ static struct clk_gate _name##_hw = { \
.hw = { \ .hw = { \
.core = &_name##_core, \
.clk = &_name, \ .clk = &_name, \
}, \ }, \
.reg = _reg, \ .reg = _reg, \
...@@ -118,14 +131,16 @@ struct clk { ...@@ -118,14 +131,16 @@ struct clk {
_flags, _reg, _shift, _width, \ _flags, _reg, _shift, _width, \
_divider_flags, _table, _lock) \ _divider_flags, _table, _lock) \
static struct clk _name; \ static struct clk _name; \
static struct clk_core _name##_core; \
static const char *_name##_parent_names[] = { \ static const char *_name##_parent_names[] = { \
_parent_name, \ _parent_name, \
}; \ }; \
static struct clk *_name##_parents[] = { \ static struct clk_core *_name##_parents[] = { \
_parent_ptr, \ _parent_ptr, \
}; \ }; \
static struct clk_divider _name##_hw = { \ static struct clk_divider _name##_hw = { \
.hw = { \ .hw = { \
.core = &_name##_core, \
.clk = &_name, \ .clk = &_name, \
}, \ }, \
.reg = _reg, \ .reg = _reg, \
...@@ -157,8 +172,10 @@ struct clk { ...@@ -157,8 +172,10 @@ struct clk {
_reg, _shift, _width, \ _reg, _shift, _width, \
_mux_flags, _lock) \ _mux_flags, _lock) \
static struct clk _name; \ static struct clk _name; \
static struct clk_core _name##_core; \
static struct clk_mux _name##_hw = { \ static struct clk_mux _name##_hw = { \
.hw = { \ .hw = { \
.core = &_name##_core, \
.clk = &_name, \ .clk = &_name, \
}, \ }, \
.reg = _reg, \ .reg = _reg, \
...@@ -174,14 +191,16 @@ struct clk { ...@@ -174,14 +191,16 @@ struct clk {
_parent_ptr, _flags, \ _parent_ptr, _flags, \
_mult, _div) \ _mult, _div) \
static struct clk _name; \ static struct clk _name; \
static struct clk_core _name##_core; \
static const char *_name##_parent_names[] = { \ static const char *_name##_parent_names[] = { \
_parent_name, \ _parent_name, \
}; \ }; \
static struct clk *_name##_parents[] = { \ static struct clk_core *_name##_parents[] = { \
_parent_ptr, \ _parent_ptr, \
}; \ }; \
static struct clk_fixed_factor _name##_hw = { \ static struct clk_fixed_factor _name##_hw = { \
.hw = { \ .hw = { \
.core = &_name##_core, \
.clk = &_name, \ .clk = &_name, \
}, \ }, \
.mult = _mult, \ .mult = _mult, \
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */ #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
struct clk_hw; struct clk_hw;
struct clk_core;
struct dentry; struct dentry;
/** /**
...@@ -216,13 +217,17 @@ struct clk_init_data { ...@@ -216,13 +217,17 @@ struct clk_init_data {
* clk_foo and then referenced by the struct clk instance that uses struct * clk_foo and then referenced by the struct clk instance that uses struct
* clk_foo's clk_ops * clk_foo's clk_ops
* *
* @clk: pointer to the struct clk instance that points back to this struct * @core: pointer to the struct clk_core instance that points back to this
* clk_hw instance * struct clk_hw instance
*
* @clk: pointer to the per-user struct clk instance that can be used to call
* into the clk API
* *
* @init: pointer to struct clk_init_data that contains the init data shared * @init: pointer to struct clk_init_data that contains the init data shared
* with the common clock framework. * with the common clock framework.
*/ */
struct clk_hw { struct clk_hw {
struct clk_core *core;
struct clk *clk; struct clk *clk;
const struct clk_init_data *init; const struct clk_init_data *init;
}; };
...@@ -577,9 +582,6 @@ long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate, ...@@ -577,9 +582,6 @@ long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
/* /*
* FIXME clock api without lock protection * FIXME clock api without lock protection
*/ */
int __clk_prepare(struct clk *clk);
void __clk_unprepare(struct clk *clk);
void __clk_reparent(struct clk *clk, struct clk *new_parent);
unsigned long __clk_round_rate(struct clk *clk, unsigned long rate); unsigned long __clk_round_rate(struct clk *clk, unsigned long rate);
struct of_device_id; struct of_device_id;
......
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