summaryrefslogtreecommitdiffstats
path: root/include/linux/clk.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/clk.h')
-rw-r--r--include/linux/clk.h715
1 files changed, 539 insertions, 176 deletions
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 6565429a9b..7ba0679d03 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -13,8 +13,11 @@
#include <linux/err.h>
#include <linux/spinlock.h>
#include <linux/stringify.h>
+#include <linux/container_of.h>
+#include <deep-probe.h>
+#include <xfuncs.h>
-struct device_d;
+struct device;
/*
* The base API.
@@ -59,64 +62,7 @@ struct clk_bulk_data {
*
* clk_get should not be called from within interrupt context.
*/
-struct clk *clk_get(struct device_d *dev, const char *id);
-
-/**
- * clk_bulk_get - lookup and obtain a number of references to clock producer.
- * @dev: device for clock "consumer"
- * @num_clks: the number of clk_bulk_data
- * @clks: the clk_bulk_data table of consumer
- *
- * This helper function allows drivers to get several clk consumers in one
- * operation. If any of the clk cannot be acquired then any clks
- * that were obtained will be freed before returning to the caller.
- *
- * Returns 0 if all clocks specified in clk_bulk_data table are obtained
- * successfully, or valid IS_ERR() condition containing errno.
- * The implementation uses @dev and @clk_bulk_data.id to determine the
- * clock consumer, and thereby the clock producer.
- * The clock returned is stored in each @clk_bulk_data.clk field.
- *
- * Drivers must assume that the clock source is not enabled.
- *
- * clk_bulk_get should not be called from within interrupt context.
- */
-int __must_check clk_bulk_get(struct device_d *dev, int num_clks,
- struct clk_bulk_data *clks);
-
-/**
- * clk_bulk_get_optional - lookup and obtain a number of references to clock producer
- * @dev: device for clock "consumer"
- * @num_clks: the number of clk_bulk_data
- * @clks: the clk_bulk_data table of consumer
- *
- * Behaves the same as clk_bulk_get() except where there is no clock producer.
- * In this case, instead of returning -ENOENT, the function returns 0 and
- * NULL for a clk for which a clock producer could not be determined.
- */
-int __must_check clk_bulk_get_optional(struct device_d *dev, int num_clks,
- struct clk_bulk_data *clks);
-
-/**
- * clk_bulk_get_all - lookup and obtain all available references to clock
- * producer.
- * @dev: device for clock "consumer"
- * @clks: pointer to the clk_bulk_data table of consumer
- *
- * This helper function allows drivers to get all clk consumers in one
- * operation. If any of the clk cannot be acquired then any clks
- * that were obtained will be freed before returning to the caller.
- *
- * Returns a positive value for the number of clocks obtained while the
- * clock references are stored in the clk_bulk_data table in @clks field.
- * Returns 0 if there're none and a negative value if something failed.
- *
- * Drivers must assume that the clock source is not enabled.
- *
- * clk_bulk_get should not be called from within interrupt context.
- */
-int __must_check clk_bulk_get_all(struct device_d *dev,
- struct clk_bulk_data **clks);
+struct clk *clk_get(struct device *dev, const char *id);
/**
* clk_enable - inform the system when the clock source should be running.
@@ -129,18 +75,6 @@ int __must_check clk_bulk_get_all(struct device_d *dev,
int clk_enable(struct clk *clk);
/**
- * clk_bulk_enable - inform the system when the set of clks should be running.
- * @num_clks: the number of clk_bulk_data
- * @clks: the clk_bulk_data table of consumer
- *
- * May be called from atomic contexts.
- *
- * Returns success (0) or negative errno.
- */
-int __must_check clk_bulk_enable(int num_clks,
- const struct clk_bulk_data *clks);
-
-/**
* clk_disable - inform the system when the clock source is no longer required.
* @clk: clock source
*
@@ -155,24 +89,6 @@ int __must_check clk_bulk_enable(int num_clks,
void clk_disable(struct clk *clk);
/**
- * clk_bulk_disable - inform the system when the set of clks is no
- * longer required.
- * @num_clks: the number of clk_bulk_data
- * @clks: the clk_bulk_data table of consumer
- *
- * Inform the system that a set of clks is no longer required by
- * a driver and may be shut down.
- *
- * May be called from atomic contexts.
- *
- * Implementation detail: if the set of clks is shared between
- * multiple drivers, clk_bulk_enable() calls must be balanced by the
- * same number of clk_bulk_disable() calls for the clock source to be
- * disabled.
- */
-void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks);
-
-/**
* clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
* This is only valid once the clock source has been enabled.
* @clk: clock source
@@ -180,32 +96,6 @@ void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks);
unsigned long clk_get_rate(struct clk *clk);
unsigned long clk_hw_get_rate(struct clk_hw *hw);
-/**
- * clk_bulk_put - "free" the clock source
- * @num_clks: the number of clk_bulk_data
- * @clks: the clk_bulk_data table of consumer
- *
- * Note: drivers must ensure that all clk_bulk_enable calls made on this
- * clock source are balanced by clk_bulk_disable calls prior to calling
- * this function.
- *
- * clk_bulk_put should not be called from within interrupt context.
- */
-void clk_bulk_put(int num_clks, struct clk_bulk_data *clks);
-
-/**
- * clk_bulk_put_all - "free" all the clock source
- * @num_clks: the number of clk_bulk_data
- * @clks: the clk_bulk_data table of consumer
- *
- * Note: drivers must ensure that all clk_bulk_enable calls made on this
- * clock source are balanced by clk_bulk_disable calls prior to calling
- * this function.
- *
- * clk_bulk_put_all should not be called from within interrupt context.
- */
-void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks);
-
/*
* The remaining APIs are optional for machine class support.
*/
@@ -239,6 +129,7 @@ int clk_hw_set_rate(struct clk_hw *hw, unsigned long rate);
*/
int clk_set_parent(struct clk *clk, struct clk *parent);
int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *hwp);
+struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int idx);
/**
* clk_get_parent - get the parent clock source for this clock
@@ -249,6 +140,7 @@ int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *hwp);
*/
struct clk *clk_get_parent(struct clk *clk);
struct clk_hw *clk_hw_get_parent(struct clk_hw *hw);
+int clk_hw_get_parent_index(struct clk_hw *hw);
int clk_set_phase(struct clk *clk, int degrees);
int clk_get_phase(struct clk *clk);
@@ -281,55 +173,34 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id);
* Assumes clkdev, see clkdev.h for more info.
*/
int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
- struct device_d *dev);
+ struct device *dev);
#else
-static inline struct clk *clk_get(struct device_d *dev, const char *id)
+static inline struct clk *clk_get(struct device *dev, const char *id)
{
return NULL;
}
-static inline int __must_check clk_bulk_get(struct device_d *dev, int num_clks,
- struct clk_bulk_data *clks)
-{
- return 0;
-}
-
-static inline int __must_check clk_bulk_get_optional(struct device_d *dev,
- int num_clks,
- struct clk_bulk_data *clks)
+static inline struct clk *clk_get_parent(struct clk *clk)
{
- return 0;
+ return NULL;
}
-static inline int __must_check clk_bulk_get_all(struct device_d *dev,
- struct clk_bulk_data **clks)
+static inline int clk_hw_get_parent_index(struct clk_hw *hw)
{
- return 0;
+ return -EINVAL;
}
-static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {}
-
-static inline void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) {}
-
static inline int clk_enable(struct clk *clk)
{
return 0;
}
-static inline int __must_check clk_bulk_enable(int num_clks, struct clk_bulk_data *clks)
-{
- return 0;
-}
-
static inline void clk_disable(struct clk *clk)
{
}
-static inline void clk_bulk_disable(int num_clks,
- struct clk_bulk_data *clks) {}
-
static inline unsigned long clk_get_rate(struct clk *clk)
{
return 0;
@@ -346,6 +217,9 @@ static inline int clk_set_rate(struct clk *clk, unsigned long rate)
}
#endif
+#define clk_prepare_enable(clk) clk_enable(clk)
+#define clk_disable_unprepare(clk) clk_disable(clk)
+
static inline void clk_put(struct clk *clk)
{
}
@@ -366,6 +240,76 @@ static inline void clk_put(struct clk *clk)
#define CLK_GATE_SET_TO_DISABLE (1 << 0)
#define CLK_GATE_HIWORD_MASK (1 << 1)
+/* Ignored sanity checking flags */
+#define CLK_SET_RATE_GATE 0 /* must be gated across rate change */
+#define CLK_SET_PARENT_GATE 0 /* must be gated across re-parent */
+
+
+/**
+ * struct clk_ops - Callback operations for hardware clocks; these are to
+ * be provided by the clock implementation, and will be called by drivers
+ * through the clk_* api.
+ *
+ * @init: Perform platform-specific initialization magic.
+ * This is not used by any of the basic clock types.
+ * This callback exist for HW which needs to perform some
+ * initialisation magic for CCF to get an accurate view of the
+ * clock. It may also be used dynamic resource allocation is
+ * required. It shall not used to deal with clock parameters,
+ * such as rate or parents.
+ * Returns 0 on success, -EERROR otherwise.
+ *
+ * @enable: Prepare and enable the clock atomically. This must not return
+ * until the clock is generating a valid clock signal, usable by
+ * consumer devices.
+ *
+ * @disable: Unprepare and disable the clock atomically.
+ *
+ * @is_enabled: Queries the hardware to determine if the clock is enabled.
+ * Optional, if this op is not set then the enable count will be
+ * used.
+ *
+ * @recalc_rate Recalculate the rate of this clock, by querying hardware. The
+ * parent rate is an input parameter. If the driver cannot figure
+ * out a rate for this clock, it must return 0. Returns the
+ * calculated rate. Optional, but recommended - if this op is not
+ * set then clock rate will be initialized to 0.
+ *
+ * @round_rate: Given a target rate as input, returns the closest rate actually
+ * supported by the clock. The parent rate is an input/output
+ * parameter.
+ *
+ * @set_parent: Change the input source of this clock; for clocks with multiple
+ * possible parents specify a new parent by passing in the index
+ * as a u8 corresponding to the parent in either the .parent_names
+ * or .parents arrays. This function in affect translates an
+ * array index into the value programmed into the hardware.
+ * Returns 0 on success, -EERROR otherwise.
+ *
+ * @get_parent: Queries the hardware to determine the parent of a clock. The
+ * return value is a u8 which specifies the index corresponding to
+ * the parent clock. This index can be applied to either the
+ * .parent_names or .parents arrays. In short, this function
+ * translates the parent value read from hardware into an array
+ * index.
+ *
+ * @set_rate: Change the rate of this clock. The requested rate is specified
+ * by the second argument, which should typically be the return
+ * of .round_rate call. The third argument gives the parent rate
+ * which is likely helpful for most .set_rate implementation.
+ * Returns 0 on success, -EERROR otherwise.
+ *
+ * @set_phase: Shift the phase this clock signal in degrees specified
+ * by the second argument. Valid values for degrees are
+ * 0-359. Return 0 on success, otherwise -EERROR.
+ *
+ * @get_phase: Queries the hardware to get the current phase of a clock.
+ * Returned values are 0-359 degrees on success, negative
+ * error codes on failure.
+ *
+ * Unlike Linux, there is no differentiation between clk_prepare/clk_enable
+ * and clk_unprepare/clk_disable in barebox as all work is atomic.
+ */
struct clk_ops {
int (*init)(struct clk_hw *hw);
int (*enable)(struct clk_hw *hw);
@@ -390,6 +334,8 @@ struct clk_ops {
* @name: clock name
* @ops: operations this clock supports
* @parent_names: array of string names for all possible parents
+ * @parent_hws: array of pointers to all possible parents (when all parents
+ * are internal to the clk controller)
* @num_parents: number of possible parents
* @flags: framework-level hints and quirks
*/
@@ -397,6 +343,7 @@ struct clk_init_data {
const char *name;
const struct clk_ops *ops;
const char * const *parent_names;
+ const struct clk_hw **parent_hws;
unsigned int num_parents;
unsigned long flags;
};
@@ -430,15 +377,16 @@ struct clk_hw {
const struct clk_init_data *init;
};
-static inline struct clk *clk_hw_to_clk(struct clk_hw *hw)
+static inline struct clk *clk_hw_to_clk(const struct clk_hw *hw)
{
- return &hw->clk;
+ return IS_ERR(hw) ? ERR_CAST(hw) : (struct clk *)&hw->clk;
}
-static inline struct clk_hw *clk_to_clk_hw(struct clk *clk)
+static inline struct clk_hw *clk_to_clk_hw(const struct clk *clk)
{
- return container_of(clk, struct clk_hw, clk);
+ return container_of_safe(clk, struct clk_hw, clk);
}
+#define __clk_get_hw(clk) clk_to_clk_hw(clk)
struct clk_div_table {
unsigned int val;
@@ -449,6 +397,12 @@ struct clk *clk_register_fixed_rate(const char *name,
const char *parent_name, unsigned long flags,
unsigned long fixed_rate);
+struct clk_hw *clk_hw_register_fixed_rate(struct device *dev,
+ const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ unsigned long rate);
+
static inline struct clk *clk_fixed(const char *name, int rate)
{
return clk_register_fixed_rate(name, NULL, 0, rate);
@@ -473,6 +427,7 @@ struct clk_divider {
#define clk_div_mask(width) ((1 << (width)) - 1)
#define CLK_DIVIDER_POWER_OF_TWO (1 << 1)
+#define CLK_DIVIDER_ALLOW_ZERO (1 << 2)
#define CLK_DIVIDER_HIWORD_MASK (1 << 3)
#define CLK_DIVIDER_READ_ONLY (1 << 5)
@@ -482,6 +437,16 @@ struct clk_divider {
extern const struct clk_ops clk_divider_ops;
extern const struct clk_ops clk_divider_ro_ops;
+static inline void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent)
+{
+ /* clk_get_parent always reads from HW, so nothing to update here */
+}
+
+static inline int __clk_get_enable_count(struct clk *clk)
+{
+ return !clk ? 0 : clk->enable_count;
+}
+
unsigned long divider_recalc_rate(struct clk *clk, unsigned long parent_rate,
unsigned int val,
const struct clk_div_table *table,
@@ -502,10 +467,10 @@ void clk_divider_free(struct clk *clk_divider);
struct clk *clk_divider(const char *name, const char *parent,
unsigned clk_flags, void __iomem *reg, u8 shift,
u8 width, unsigned div_flags);
-struct clk *clk_register_divider(struct device_d *dev, const char *name,
- const char *parent_name, unsigned long flags,
- void __iomem *reg, u8 shift, u8 width,
- u8 clk_divider_flags, spinlock_t *lock);
+struct clk *clk_register_divider(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 shift, u8 width,
+ u8 clk_divider_flags, spinlock_t *lock);
struct clk *clk_divider_one_based(const char *name, const char *parent,
unsigned clk_flags, void __iomem *reg,
u8 shift, u8 width, unsigned div_flags);
@@ -513,11 +478,29 @@ struct clk *clk_divider_table(const char *name, const char *parent,
unsigned clk_flags, void __iomem *reg, u8 shift,
u8 width, const struct clk_div_table *table,
unsigned div_flags);
-struct clk *clk_register_divider_table(struct device_d *dev, const char *name,
- const char *parent_name, unsigned long flags,
- void __iomem *reg, u8 shift, u8 width,
- u8 clk_divider_flags, const struct clk_div_table *table,
- spinlock_t *lock);
+struct clk *clk_register_divider_table(struct device *dev, const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ void __iomem *reg, u8 shift, u8 width,
+ u8 clk_divider_flags,
+ const struct clk_div_table *table,
+ spinlock_t *lock);
+
+struct clk_hw *clk_hw_register_divider_table(struct device *dev,
+ const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ void __iomem *reg, u8 shift,
+ u8 width,
+ u8 clk_divider_flags,
+ const struct clk_div_table *table,
+ spinlock_t *lock);
+
+struct clk_hw *clk_hw_register_divider(struct device *dev, const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ void __iomem *reg, u8 shift, u8 width,
+ u8 clk_divider_flags, spinlock_t *lock);
struct clk_fixed_factor {
struct clk_hw hw;
@@ -536,9 +519,17 @@ extern struct clk_ops clk_fixed_factor_ops;
struct clk *clk_fixed_factor(const char *name,
const char *parent, unsigned int mult, unsigned int div,
unsigned flags);
-struct clk *clk_register_fixed_factor(struct device_d *dev, const char *name,
- const char *parent_name, unsigned long flags,
- unsigned int mult, unsigned int div);
+struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ unsigned int mult, unsigned int div);
+
+struct clk_hw *clk_hw_register_fixed_factor(struct device *dev,
+ const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ unsigned int mult,
+ unsigned int div);
/**
* struct clk_fractional_divider - adjustable fractional divider clock
@@ -600,6 +591,7 @@ struct clk_mux {
int shift;
int width;
unsigned flags;
+ u32 *table;
spinlock_t *lock;
};
@@ -616,11 +608,42 @@ void clk_mux_free(struct clk *clk_mux);
struct clk *clk_mux(const char *name, unsigned clk_flags, void __iomem *reg,
u8 shift, u8 width, const char * const *parents,
u8 num_parents, unsigned mux_flags);
-struct clk *clk_register_mux(struct device_d *dev, const char *name,
- const char * const *parent_names, u8 num_parents,
- unsigned long flags,
- void __iomem *reg, u8 shift, u8 width,
- u8 clk_mux_flags, spinlock_t *lock);
+struct clk *clk_register_mux(struct device *dev, const char *name,
+ const char * const *parent_names, u8 num_parents,
+ unsigned long flags,
+ void __iomem *reg, u8 shift, u8 width,
+ u8 clk_mux_flags, spinlock_t *lock);
+
+struct clk_hw *__clk_hw_register_mux(struct device *dev,
+ const char *name, u8 num_parents,
+ const char * const *parent_names,
+ unsigned long flags, void __iomem *reg,
+ u8 shift, u32 mask,
+ u8 clk_mux_flags, u32 *table,
+ spinlock_t *lock);
+
+#define clk_hw_register_mux(dev, name, parent_names, \
+ num_parents, flags, reg, shift, mask, \
+ clk_mux_flags, lock) \
+ __clk_hw_register_mux((dev), (name), (num_parents), \
+ (parent_names), \
+ (flags), (reg), (shift), (mask), \
+ (clk_mux_flags), NULL, (lock))
+
+#define clk_hw_register_mux_table(dev, name, parent_names, num_parents, \
+ flags, reg, shift, mask, clk_mux_flags, \
+ table, lock) \
+ __clk_hw_register_mux((dev), (name), (num_parents), \
+ (parent_names), (flags), (reg), \
+ (shift), (mask), (clk_mux_flags), (table), \
+ (lock))
+
+int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
+ unsigned int val);
+unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index);
+
+long clk_mux_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate);
struct clk_gate {
struct clk_hw hw;
@@ -647,10 +670,24 @@ struct clk *clk_gate_inverted(const char *name, const char *parent, void __iomem
u8 shift, unsigned flags);
struct clk *clk_gate_shared(const char *name, const char *parent, const char *shared,
unsigned flags);
-struct clk *clk_register_gate(struct device_d *dev, const char *name,
- const char *parent_name, unsigned long flags,
- void __iomem *reg, u8 bit_idx,
- u8 clk_gate_flags, spinlock_t *lock);
+struct clk *clk_register_gate(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 bit_idx,
+ u8 clk_gate_flags, spinlock_t *lock);
+
+static inline struct clk_hw *clk_hw_register_gate(struct device *dev,
+ const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ void __iomem *reg,
+ u8 bit_idx,
+ u8 clk_gate_flags,
+ spinlock_t *lock)
+{
+ return clk_to_clk_hw(clk_register_gate(dev, xstrdup(name), xstrdup(parent_name),
+ flags, reg, bit_idx,
+ clk_gate_flags, lock));
+}
int clk_is_enabled(struct clk *clk);
int clk_hw_is_enabled(struct clk_hw *hw);
@@ -662,7 +699,12 @@ int clk_parent_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate);
int bclk_register(struct clk *clk);
-struct clk *clk_register(struct device_d *dev, struct clk_hw *hw);
+struct clk *clk_register(struct device *dev, struct clk_hw *hw);
+
+static inline int clk_hw_register(struct device *dev, struct clk_hw *hw)
+{
+ return PTR_ERR_OR_ZERO(clk_register(dev, hw));
+}
struct clk *clk_lookup(const char *name);
@@ -676,11 +718,33 @@ struct clk *clk_register_composite(const char *name,
struct clk *gate_clk,
unsigned long flags);
+struct clk_hw *clk_hw_register_composite(struct device *dev,
+ const char *name,
+ const char * const *parent_names,
+ int num_parents,
+ struct clk_hw *mux_hw,
+ const struct clk_ops *mux_ops,
+ struct clk_hw *rate_hw,
+ const struct clk_ops *rate_ops,
+ struct clk_hw *gate_hw,
+ const struct clk_ops *gate_ops,
+ unsigned long flags);
+
static inline const char *clk_hw_get_name(struct clk_hw *hw)
{
return hw->clk.name;
}
+static inline unsigned int clk_hw_get_num_parents(const struct clk_hw *hw)
+{
+ return hw->clk.num_parents;
+}
+
+static inline unsigned long clk_hw_get_flags(const struct clk_hw *hw)
+{
+ return hw->clk.flags;
+}
+
int clk_name_set_parent(const char *clkname, const char *clkparentname);
int clk_name_set_rate(const char *clkname, unsigned long rate);
@@ -695,11 +759,16 @@ struct clk_onecell_data {
unsigned int clk_num;
};
+struct clk_hw_onecell_data {
+ unsigned int num;
+ struct clk_hw *hws[];
+};
+
#if defined(CONFIG_COMMON_CLK_OF_PROVIDER)
#define CLK_OF_DECLARE(name, compat, fn) \
const struct of_device_id __clk_of_table_##name \
-__attribute__ ((unused,section (".__clk_of_table"))) \
+ __ll_elem(.__clk_of_table) \
= { .compatible = compat, .data = fn }
void of_clk_del_provider(struct device_node *np);
@@ -708,6 +777,8 @@ typedef int (*of_clk_init_cb_t)(struct device_node *);
struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, void *data);
+struct clk_hw *of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data);
+struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data);
struct clk *of_clk_get(struct device_node *np, int index);
struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
@@ -715,16 +786,16 @@ struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec);
unsigned int of_clk_get_parent_count(struct device_node *np);
int of_clk_parent_fill(struct device_node *np, const char **parents,
unsigned int size);
-int of_clk_init(struct device_node *root, const struct of_device_id *matches);
+int of_clk_init(void);
int of_clk_add_provider(struct device_node *np,
struct clk *(*clk_src_get)(struct of_phandle_args *args,
void *data),
void *data);
-static inline unsigned int clk_get_num_parents(const struct clk *hw)
-{
- return hw->num_parents;
-}
+int of_clk_add_hw_provider(struct device_node *np,
+ struct clk_hw *(*clk_hw_src_get)(struct of_phandle_args *clkspec,
+ void *data),
+ void *data);
#else
@@ -743,11 +814,21 @@ static inline struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec
{
return ERR_PTR(-ENOENT);
}
+static inline struct clk_hw *of_clk_hw_onecell_get(struct of_phandle_args *clkspec,
+ void *data)
+{
+ return ERR_PTR(-ENOENT);
+}
static inline struct clk *
of_clk_src_simple_get(struct of_phandle_args *clkspec, void *data)
{
return ERR_PTR(-ENOENT);
}
+static inline struct clk_hw *
+of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data)
+{
+ return ERR_PTR(-ENOENT);
+}
static inline struct clk *of_clk_get(struct device_node *np, int index)
{
return ERR_PTR(-ENOENT);
@@ -761,8 +842,8 @@ static inline unsigned int of_clk_get_parent_count(struct device_node *np)
{
return 0;
}
-static inline int of_clk_init(struct device_node *root,
- const struct of_device_id *matches)
+
+static inline int of_clk_init(void)
{
return 0;
}
@@ -773,6 +854,14 @@ static inline int of_clk_add_provider(struct device_node *np,
{
return 0;
}
+
+static inline int of_clk_add_hw_provider(struct device_node *np,
+ struct clk_hw *(*clk_hw_src_get)(struct of_phandle_args *clkspec,
+ void *data),
+ void *data)
+{
+ return 0;
+}
#endif
#define CLK_OF_DECLARE_DRIVER(name, compat, fn) CLK_OF_DECLARE(name, compat, fn)
@@ -787,4 +876,278 @@ static inline void clk_unregister(struct clk *clk)
{
}
+static inline void clk_hw_unregister(struct clk_hw *hw)
+{
+}
+
+#ifdef CONFIG_COMMON_CLK
+
+/**
+ * clk_bulk_get - lookup and obtain a number of references to clock producer.
+ * @dev: device for clock "consumer"
+ * @num_clks: the number of clk_bulk_data
+ * @clks: the clk_bulk_data table of consumer
+ *
+ * This helper function allows drivers to get several clk consumers in one
+ * operation. If any of the clk cannot be acquired then any clks
+ * that were obtained will be freed before returning to the caller.
+ *
+ * Returns 0 if all clocks specified in clk_bulk_data table are obtained
+ * successfully, or valid IS_ERR() condition containing errno.
+ * The implementation uses @dev and @clk_bulk_data.id to determine the
+ * clock consumer, and thereby the clock producer.
+ * The clock returned is stored in each @clk_bulk_data.clk field.
+ *
+ * Drivers must assume that the clock source is not enabled.
+ *
+ * clk_bulk_get should not be called from within interrupt context.
+ */
+int __must_check clk_bulk_get(struct device *dev, int num_clks,
+ struct clk_bulk_data *clks);
+
+/**
+ * clk_bulk_get_optional - lookup and obtain a number of references to clock producer
+ * @dev: device for clock "consumer"
+ * @num_clks: the number of clk_bulk_data
+ * @clks: the clk_bulk_data table of consumer
+ *
+ * Behaves the same as clk_bulk_get() except where there is no clock producer.
+ * In this case, instead of returning -ENOENT, the function returns 0 and
+ * NULL for a clk for which a clock producer could not be determined.
+ */
+int __must_check clk_bulk_get_optional(struct device *dev, int num_clks,
+ struct clk_bulk_data *clks);
+
+/**
+ * clk_bulk_get_all - lookup and obtain all available references to clock
+ * producer.
+ * @dev: device for clock "consumer"
+ * @clks: pointer to the clk_bulk_data table of consumer
+ *
+ * This helper function allows drivers to get all clk consumers in one
+ * operation. If any of the clk cannot be acquired then any clks
+ * that were obtained will be freed before returning to the caller.
+ *
+ * Returns a positive value for the number of clocks obtained while the
+ * clock references are stored in the clk_bulk_data table in @clks field.
+ * Returns 0 if there're none and a negative value if something failed.
+ *
+ * Drivers must assume that the clock source is not enabled.
+ *
+ * clk_bulk_get should not be called from within interrupt context.
+ */
+int __must_check clk_bulk_get_all(struct device *dev,
+ struct clk_bulk_data **clks);
+
+/**
+ * clk_bulk_put - "free" the clock source
+ * @num_clks: the number of clk_bulk_data
+ * @clks: the clk_bulk_data table of consumer
+ *
+ * Note: drivers must ensure that all clk_bulk_enable calls made on this
+ * clock source are balanced by clk_bulk_disable calls prior to calling
+ * this function.
+ *
+ * clk_bulk_put should not be called from within interrupt context.
+ */
+void clk_bulk_put(int num_clks, struct clk_bulk_data *clks);
+
+/**
+ * clk_bulk_put_all - "free" all the clock source
+ * @num_clks: the number of clk_bulk_data
+ * @clks: the clk_bulk_data table of consumer
+ *
+ * Note: drivers must ensure that all clk_bulk_enable calls made on this
+ * clock source are balanced by clk_bulk_disable calls prior to calling
+ * this function.
+ *
+ * clk_bulk_put_all should not be called from within interrupt context.
+ */
+void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks);
+
+/**
+ * clk_bulk_enable - inform the system when the set of clks should be running.
+ * @num_clks: the number of clk_bulk_data
+ * @clks: the clk_bulk_data table of consumer
+ *
+ * May be called from atomic contexts.
+ *
+ * Returns success (0) or negative errno.
+ */
+int __must_check clk_bulk_enable(int num_clks,
+ const struct clk_bulk_data *clks);
+
+/**
+ * clk_bulk_disable - inform the system when the set of clks is no
+ * longer required.
+ * @num_clks: the number of clk_bulk_data
+ * @clks: the clk_bulk_data table of consumer
+ *
+ * Inform the system that a set of clks is no longer required by
+ * a driver and may be shut down.
+ *
+ * May be called from atomic contexts.
+ *
+ * Implementation detail: if the set of clks is shared between
+ * multiple drivers, clk_bulk_enable() calls must be balanced by the
+ * same number of clk_bulk_disable() calls for the clock source to be
+ * disabled.
+ */
+void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks);
+
+#else
+static inline int __must_check clk_bulk_get(struct device *dev, int num_clks,
+ struct clk_bulk_data *clks)
+{
+ return 0;
+}
+
+static inline int __must_check clk_bulk_get_optional(struct device *dev,
+ int num_clks,
+ struct clk_bulk_data *clks)
+{
+ return 0;
+}
+
+static inline int __must_check clk_bulk_get_all(struct device *dev,
+ struct clk_bulk_data **clks)
+{
+ return 0;
+}
+
+static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {}
+
+static inline void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) {}
+
+static inline int __must_check clk_bulk_enable(int num_clks, struct clk_bulk_data *clks)
+{
+ return 0;
+}
+
+static inline void clk_bulk_disable(int num_clks,
+ struct clk_bulk_data *clks) {}
+
+#endif
+
+/**
+ * clk_hw_register_fixed_rate_with_accuracy - register fixed-rate clock with
+ * the clock framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @fixed_rate: non-adjustable clock rate
+ * @fixed_accuracy: non-adjustable clock accuracy (ignored)
+ */
+#define clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name, \
+ flags, fixed_rate, \
+ fixed_accuracy) \
+ clk_hw_register_fixed_rate((dev), (name), (parent_name), (flags), (fixed_rate))
+
+#define clk_bulk_prepare_enable clk_bulk_enable
+#define clk_bulk_disable_unprepare clk_bulk_disable
+
+/**
+ * clk_get_optional - lookup and obtain a reference to an optional clock
+ * producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Behaves the same as clk_get() except where there is no clock producer. In
+ * this case, instead of returning -ENOENT, the function returns NULL.
+ */
+static inline struct clk *clk_get_optional(struct device *dev, const char *id)
+{
+ struct clk *clk = clk_get(dev, id);
+
+ if (clk == ERR_PTR(-ENOENT))
+ return NULL;
+
+ return clk;
+}
+
+/**
+ * clk_get_enabled - clk_get() + clk_prepare_enable()
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Return: a struct clk corresponding to the clock producer, or
+ * valid IS_ERR() condition containing errno. The implementation
+ * uses @dev and @id to determine the clock consumer, and thereby
+ * the clock producer. (IOW, @id may be identical strings, but
+ * clk_get may return different clock producers depending on @dev.)
+ *
+ * The returned clk (if valid) is enabled.
+ */
+static inline struct clk *clk_get_enabled(struct device *dev, const char *id)
+{
+ struct clk *clk;
+ int ret;
+
+ clk = clk_get(dev, id);
+ if (IS_ERR(clk))
+ return clk;
+
+ ret = clk_enable(clk);
+ if (ret) {
+ clk_put(clk);
+ return ERR_PTR(ret);
+ }
+
+ return clk;
+}
+
+/**
+ * clk_get_optional_enabled - clk_get_optional() +
+ * clk_prepare_enable()
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Return: a struct clk corresponding to the clock producer, or
+ * valid IS_ERR() condition containing errno. The implementation
+ * uses @dev and @id to determine the clock consumer, and thereby
+ * the clock producer. If no such clk is found, it returns NULL
+ * which serves as a dummy clk. That's the only difference compared
+ * to clk_get_enabled().
+ *
+ * The returned clk (if valid) is enabled.
+ */
+static inline struct clk *clk_get_optional_enabled(struct device *dev, const char *id)
+{
+ struct clk *clk;
+ int ret;
+
+ clk = clk_get_optional(dev, id);
+ if (IS_ERR_OR_NULL(clk))
+ return clk;
+
+ ret = clk_enable(clk);
+ if (ret) {
+ clk_put(clk);
+ return ERR_PTR(ret);
+ }
+
+ return clk;
+}
+
+/**
+ * clk_get_if_available - get clock, ignoring known unavailable clock controller
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Return: a struct clk corresponding to the clock producer, a
+ * valid IS_ERR() condition containing errno or NULL if it could
+ * be determined that the clock producer will never be probed in
+ * absence of modules.
+ */
+static inline struct clk *clk_get_if_available(struct device *dev, const char *id)
+{
+ struct clk *clk = clk_get(dev, id);
+
+ if (clk == ERR_PTR(-EPROBE_DEFER) && deep_probe_is_supported())
+ return NULL;
+
+ return clk;
+}
+
#endif