diff options
Diffstat (limited to 'include/linux/clk.h')
-rw-r--r-- | include/linux/clk.h | 715 |
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 |