Merge branch 'clk-hw-register' (early part) into clk-next
* 'clk-hw-register' (early part): clk: fixed-rate: Add hw based registration APIs clk: gpio: Add hw based registration APIs clk: composite: Add hw based registration APIs clk: fractional-divider: Add hw based registration APIs clk: fixed-factor: Add hw based registration APIs clk: mux: Add hw based registration APIs clk: gate: Add hw based registration APIs clk: divider: Add hw based registration APIs clkdev: Add clk_hw based registration APIs clk: Add clk_hw OF clk providers clk: Add {devm_}clk_hw_{register,unregister}() APIs clkdev: Remove clk_register_clkdevs()
This commit is contained in:
commit
58657d189a
@ -236,6 +236,7 @@ certainly invest a bit more effort into libata core layer).
|
||||
CLOCK
|
||||
devm_clk_get()
|
||||
devm_clk_put()
|
||||
devm_clk_hw_register()
|
||||
|
||||
DMA
|
||||
dmam_alloc_coherent()
|
||||
|
@ -211,17 +211,18 @@ static void clk_composite_disable(struct clk_hw *hw)
|
||||
gate_ops->disable(gate_hw);
|
||||
}
|
||||
|
||||
struct clk *clk_register_composite(struct device *dev, const char *name,
|
||||
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)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk_hw *hw;
|
||||
struct clk_init_data init;
|
||||
struct clk_composite *composite;
|
||||
struct clk_ops *clk_composite_ops;
|
||||
int ret;
|
||||
|
||||
composite = kzalloc(sizeof(*composite), GFP_KERNEL);
|
||||
if (!composite)
|
||||
@ -231,12 +232,13 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
|
||||
init.flags = flags | CLK_IS_BASIC;
|
||||
init.parent_names = parent_names;
|
||||
init.num_parents = num_parents;
|
||||
hw = &composite->hw;
|
||||
|
||||
clk_composite_ops = &composite->ops;
|
||||
|
||||
if (mux_hw && mux_ops) {
|
||||
if (!mux_ops->get_parent) {
|
||||
clk = ERR_PTR(-EINVAL);
|
||||
hw = ERR_PTR(-EINVAL);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -251,7 +253,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
|
||||
|
||||
if (rate_hw && rate_ops) {
|
||||
if (!rate_ops->recalc_rate) {
|
||||
clk = ERR_PTR(-EINVAL);
|
||||
hw = ERR_PTR(-EINVAL);
|
||||
goto err;
|
||||
}
|
||||
clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
|
||||
@ -286,7 +288,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
|
||||
if (gate_hw && gate_ops) {
|
||||
if (!gate_ops->is_enabled || !gate_ops->enable ||
|
||||
!gate_ops->disable) {
|
||||
clk = ERR_PTR(-EINVAL);
|
||||
hw = ERR_PTR(-EINVAL);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -300,24 +302,43 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
|
||||
init.ops = clk_composite_ops;
|
||||
composite->hw.init = &init;
|
||||
|
||||
clk = clk_register(dev, &composite->hw);
|
||||
if (IS_ERR(clk))
|
||||
ret = clk_hw_register(dev, hw);
|
||||
if (ret) {
|
||||
hw = ERR_PTR(ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (composite->mux_hw)
|
||||
composite->mux_hw->clk = clk;
|
||||
composite->mux_hw->clk = hw->clk;
|
||||
|
||||
if (composite->rate_hw)
|
||||
composite->rate_hw->clk = clk;
|
||||
composite->rate_hw->clk = hw->clk;
|
||||
|
||||
if (composite->gate_hw)
|
||||
composite->gate_hw->clk = clk;
|
||||
composite->gate_hw->clk = hw->clk;
|
||||
|
||||
return clk;
|
||||
return hw;
|
||||
|
||||
err:
|
||||
kfree(composite);
|
||||
return clk;
|
||||
return hw;
|
||||
}
|
||||
|
||||
struct clk *clk_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)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
|
||||
hw = clk_hw_register_composite(dev, name, parent_names, num_parents,
|
||||
mux_hw, mux_ops, rate_hw, rate_ops, gate_hw, gate_ops,
|
||||
flags);
|
||||
if (IS_ERR(hw))
|
||||
return ERR_CAST(hw);
|
||||
return hw->clk;
|
||||
}
|
||||
|
||||
void clk_unregister_composite(struct clk *clk)
|
||||
|
@ -426,15 +426,16 @@ const struct clk_ops clk_divider_ro_ops = {
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_divider_ro_ops);
|
||||
|
||||
static struct clk *_register_divider(struct device *dev, const char *name,
|
||||
static struct 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, const struct clk_div_table *table,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
struct clk_divider *div;
|
||||
struct clk *clk;
|
||||
struct clk_hw *hw;
|
||||
struct clk_init_data init;
|
||||
int ret;
|
||||
|
||||
if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
|
||||
if (width + shift > 16) {
|
||||
@ -467,12 +468,14 @@ static struct clk *_register_divider(struct device *dev, const char *name,
|
||||
div->table = table;
|
||||
|
||||
/* register the clock */
|
||||
clk = clk_register(dev, &div->hw);
|
||||
|
||||
if (IS_ERR(clk))
|
||||
hw = &div->hw;
|
||||
ret = clk_hw_register(dev, hw);
|
||||
if (ret) {
|
||||
kfree(div);
|
||||
hw = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return clk;
|
||||
return hw;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -491,11 +494,38 @@ 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_hw *hw;
|
||||
|
||||
hw = _register_divider(dev, name, parent_name, flags, reg, shift,
|
||||
width, clk_divider_flags, NULL, lock);
|
||||
if (IS_ERR(hw))
|
||||
return ERR_CAST(hw);
|
||||
return hw->clk;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register_divider);
|
||||
|
||||
/**
|
||||
* clk_hw_register_divider - register a divider clock with the clock framework
|
||||
* @dev: device registering this clock
|
||||
* @name: name of this clock
|
||||
* @parent_name: name of clock's parent
|
||||
* @flags: framework-specific flags
|
||||
* @reg: register address to adjust divider
|
||||
* @shift: number of bits to shift the bitfield
|
||||
* @width: width of the bitfield
|
||||
* @clk_divider_flags: divider-specific flags for this clock
|
||||
* @lock: shared register lock for this clock
|
||||
*/
|
||||
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)
|
||||
{
|
||||
return _register_divider(dev, name, parent_name, flags, reg, shift,
|
||||
width, clk_divider_flags, NULL, lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register_divider);
|
||||
EXPORT_SYMBOL_GPL(clk_hw_register_divider);
|
||||
|
||||
/**
|
||||
* clk_register_divider_table - register a table based divider clock with
|
||||
@ -516,11 +546,41 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
|
||||
void __iomem *reg, u8 shift, u8 width,
|
||||
u8 clk_divider_flags, const struct clk_div_table *table,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
|
||||
hw = _register_divider(dev, name, parent_name, flags, reg, shift,
|
||||
width, clk_divider_flags, table, lock);
|
||||
if (IS_ERR(hw))
|
||||
return ERR_CAST(hw);
|
||||
return hw->clk;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register_divider_table);
|
||||
|
||||
/**
|
||||
* clk_hw_register_divider_table - register a table based divider clock with
|
||||
* the clock framework
|
||||
* @dev: device registering this clock
|
||||
* @name: name of this clock
|
||||
* @parent_name: name of clock's parent
|
||||
* @flags: framework-specific flags
|
||||
* @reg: register address to adjust divider
|
||||
* @shift: number of bits to shift the bitfield
|
||||
* @width: width of the bitfield
|
||||
* @clk_divider_flags: divider-specific flags for this clock
|
||||
* @table: array of divider/value pairs ending with a div set to 0
|
||||
* @lock: shared register lock for this clock
|
||||
*/
|
||||
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)
|
||||
{
|
||||
return _register_divider(dev, name, parent_name, flags, reg, shift,
|
||||
width, clk_divider_flags, table, lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register_divider_table);
|
||||
EXPORT_SYMBOL_GPL(clk_hw_register_divider_table);
|
||||
|
||||
void clk_unregister_divider(struct clk *clk)
|
||||
{
|
||||
@ -537,3 +597,18 @@ void clk_unregister_divider(struct clk *clk)
|
||||
kfree(div);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_unregister_divider);
|
||||
|
||||
/**
|
||||
* clk_hw_unregister_divider - unregister a clk divider
|
||||
* @hw: hardware-specific clock data to unregister
|
||||
*/
|
||||
void clk_hw_unregister_divider(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_divider *div;
|
||||
|
||||
div = to_clk_divider(hw);
|
||||
|
||||
clk_hw_unregister(hw);
|
||||
kfree(div);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_unregister_divider);
|
||||
|
@ -68,13 +68,14 @@ const struct clk_ops clk_fixed_factor_ops = {
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_fixed_factor_ops);
|
||||
|
||||
struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned long flags,
|
||||
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_fixed_factor *fix;
|
||||
struct clk_init_data init;
|
||||
struct clk *clk;
|
||||
struct clk_hw *hw;
|
||||
int ret;
|
||||
|
||||
fix = kmalloc(sizeof(*fix), GFP_KERNEL);
|
||||
if (!fix)
|
||||
@ -91,12 +92,28 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
clk = clk_register(dev, &fix->hw);
|
||||
|
||||
if (IS_ERR(clk))
|
||||
hw = &fix->hw;
|
||||
ret = clk_hw_register(dev, hw);
|
||||
if (ret) {
|
||||
kfree(fix);
|
||||
hw = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return clk;
|
||||
return hw;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor);
|
||||
|
||||
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 *hw;
|
||||
|
||||
hw = clk_hw_register_fixed_factor(dev, name, parent_name, flags, mult,
|
||||
div);
|
||||
if (IS_ERR(hw))
|
||||
return ERR_CAST(hw);
|
||||
return hw->clk;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register_fixed_factor);
|
||||
|
||||
@ -113,6 +130,17 @@ void clk_unregister_fixed_factor(struct clk *clk)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_unregister_fixed_factor);
|
||||
|
||||
void clk_hw_unregister_fixed_factor(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_fixed_factor *fix;
|
||||
|
||||
fix = to_clk_fixed_factor(hw);
|
||||
|
||||
clk_hw_unregister(hw);
|
||||
kfree(fix);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_factor);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
/**
|
||||
* of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock
|
||||
|
@ -45,8 +45,8 @@ const struct clk_ops clk_fixed_rate_ops = {
|
||||
EXPORT_SYMBOL_GPL(clk_fixed_rate_ops);
|
||||
|
||||
/**
|
||||
* clk_register_fixed_rate_with_accuracy - register fixed-rate clock with the
|
||||
* clock framework
|
||||
* 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
|
||||
@ -54,13 +54,14 @@ EXPORT_SYMBOL_GPL(clk_fixed_rate_ops);
|
||||
* @fixed_rate: non-adjustable clock rate
|
||||
* @fixed_accuracy: non-adjustable clock rate
|
||||
*/
|
||||
struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev,
|
||||
struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev,
|
||||
const char *name, const char *parent_name, unsigned long flags,
|
||||
unsigned long fixed_rate, unsigned long fixed_accuracy)
|
||||
{
|
||||
struct clk_fixed_rate *fixed;
|
||||
struct clk *clk;
|
||||
struct clk_hw *hw;
|
||||
struct clk_init_data init;
|
||||
int ret;
|
||||
|
||||
/* allocate fixed-rate clock */
|
||||
fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
|
||||
@ -79,22 +80,49 @@ struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev,
|
||||
fixed->hw.init = &init;
|
||||
|
||||
/* register the clock */
|
||||
clk = clk_register(dev, &fixed->hw);
|
||||
if (IS_ERR(clk))
|
||||
hw = &fixed->hw;
|
||||
ret = clk_hw_register(dev, hw);
|
||||
if (ret) {
|
||||
kfree(fixed);
|
||||
hw = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return clk;
|
||||
return hw;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_register_fixed_rate_with_accuracy);
|
||||
|
||||
struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev,
|
||||
const char *name, const char *parent_name, unsigned long flags,
|
||||
unsigned long fixed_rate, unsigned long fixed_accuracy)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
|
||||
hw = clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name,
|
||||
flags, fixed_rate, fixed_accuracy);
|
||||
if (IS_ERR(hw))
|
||||
return ERR_CAST(hw);
|
||||
return hw->clk;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register_fixed_rate_with_accuracy);
|
||||
|
||||
/**
|
||||
* clk_register_fixed_rate - register fixed-rate clock with the clock framework
|
||||
* clk_hw_register_fixed_rate - 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
|
||||
*/
|
||||
struct clk_hw *clk_hw_register_fixed_rate(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned long flags,
|
||||
unsigned long fixed_rate)
|
||||
{
|
||||
return clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name,
|
||||
flags, fixed_rate, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_register_fixed_rate);
|
||||
|
||||
struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned long flags,
|
||||
unsigned long fixed_rate)
|
||||
|
@ -116,14 +116,15 @@ const struct clk_ops clk_fractional_divider_ops = {
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_fractional_divider_ops);
|
||||
|
||||
struct clk *clk_register_fractional_divider(struct device *dev,
|
||||
struct clk_hw *clk_hw_register_fractional_divider(struct device *dev,
|
||||
const char *name, const char *parent_name, unsigned long flags,
|
||||
void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
|
||||
u8 clk_divider_flags, spinlock_t *lock)
|
||||
{
|
||||
struct clk_fractional_divider *fd;
|
||||
struct clk_init_data init;
|
||||
struct clk *clk;
|
||||
struct clk_hw *hw;
|
||||
int ret;
|
||||
|
||||
fd = kzalloc(sizeof(*fd), GFP_KERNEL);
|
||||
if (!fd)
|
||||
@ -146,10 +147,39 @@ struct clk *clk_register_fractional_divider(struct device *dev,
|
||||
fd->lock = lock;
|
||||
fd->hw.init = &init;
|
||||
|
||||
clk = clk_register(dev, &fd->hw);
|
||||
if (IS_ERR(clk))
|
||||
hw = &fd->hw;
|
||||
ret = clk_hw_register(dev, hw);
|
||||
if (ret) {
|
||||
kfree(fd);
|
||||
hw = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return clk;
|
||||
return hw;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_register_fractional_divider);
|
||||
|
||||
struct clk *clk_register_fractional_divider(struct device *dev,
|
||||
const char *name, const char *parent_name, unsigned long flags,
|
||||
void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
|
||||
u8 clk_divider_flags, spinlock_t *lock)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
|
||||
hw = clk_hw_register_fractional_divider(dev, name, parent_name, flags,
|
||||
reg, mshift, mwidth, nshift, nwidth, clk_divider_flags,
|
||||
lock);
|
||||
if (IS_ERR(hw))
|
||||
return ERR_CAST(hw);
|
||||
return hw->clk;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register_fractional_divider);
|
||||
|
||||
void clk_hw_unregister_fractional_divider(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_fractional_divider *fd;
|
||||
|
||||
fd = to_clk_fd(hw);
|
||||
|
||||
clk_hw_unregister(hw);
|
||||
kfree(fd);
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ const struct clk_ops clk_gate_ops = {
|
||||
EXPORT_SYMBOL_GPL(clk_gate_ops);
|
||||
|
||||
/**
|
||||
* clk_register_gate - register a gate clock with the clock framework
|
||||
* clk_hw_register_gate - register a gate clock with the clock framework
|
||||
* @dev: device that is registering this clock
|
||||
* @name: name of this clock
|
||||
* @parent_name: name of this clock's parent
|
||||
@ -120,14 +120,15 @@ EXPORT_SYMBOL_GPL(clk_gate_ops);
|
||||
* @clk_gate_flags: gate-specific flags for this clock
|
||||
* @lock: shared register lock for this clock
|
||||
*/
|
||||
struct clk *clk_register_gate(struct device *dev, const char *name,
|
||||
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)
|
||||
{
|
||||
struct clk_gate *gate;
|
||||
struct clk *clk;
|
||||
struct clk_hw *hw;
|
||||
struct clk_init_data init;
|
||||
int ret;
|
||||
|
||||
if (clk_gate_flags & CLK_GATE_HIWORD_MASK) {
|
||||
if (bit_idx > 15) {
|
||||
@ -154,12 +155,29 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
|
||||
gate->lock = lock;
|
||||
gate->hw.init = &init;
|
||||
|
||||
clk = clk_register(dev, &gate->hw);
|
||||
|
||||
if (IS_ERR(clk))
|
||||
hw = &gate->hw;
|
||||
ret = clk_hw_register(dev, hw);
|
||||
if (ret) {
|
||||
kfree(gate);
|
||||
hw = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return clk;
|
||||
return hw;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_register_gate);
|
||||
|
||||
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)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
|
||||
hw = clk_hw_register_gate(dev, name, parent_name, flags, reg,
|
||||
bit_idx, clk_gate_flags, lock);
|
||||
if (IS_ERR(hw))
|
||||
return ERR_CAST(hw);
|
||||
return hw->clk;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register_gate);
|
||||
|
||||
@ -178,3 +196,14 @@ void clk_unregister_gate(struct clk *clk)
|
||||
kfree(gate);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_unregister_gate);
|
||||
|
||||
void clk_hw_unregister_gate(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_gate *gate;
|
||||
|
||||
gate = to_clk_gate(hw);
|
||||
|
||||
clk_hw_unregister(hw);
|
||||
kfree(gate);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_unregister_gate);
|
||||
|
@ -94,13 +94,13 @@ const struct clk_ops clk_gpio_mux_ops = {
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_gpio_mux_ops);
|
||||
|
||||
static struct clk *clk_register_gpio(struct device *dev, const char *name,
|
||||
static struct clk_hw *clk_register_gpio(struct device *dev, const char *name,
|
||||
const char * const *parent_names, u8 num_parents, unsigned gpio,
|
||||
bool active_low, unsigned long flags,
|
||||
const struct clk_ops *clk_gpio_ops)
|
||||
{
|
||||
struct clk_gpio *clk_gpio;
|
||||
struct clk *clk;
|
||||
struct clk_hw *hw;
|
||||
struct clk_init_data init = {};
|
||||
unsigned long gpio_flags;
|
||||
int err;
|
||||
@ -141,24 +141,26 @@ static struct clk *clk_register_gpio(struct device *dev, const char *name,
|
||||
clk_gpio->gpiod = gpio_to_desc(gpio);
|
||||
clk_gpio->hw.init = &init;
|
||||
|
||||
hw = &clk_gpio->hw;
|
||||
if (dev)
|
||||
clk = devm_clk_register(dev, &clk_gpio->hw);
|
||||
err = devm_clk_hw_register(dev, hw);
|
||||
else
|
||||
clk = clk_register(NULL, &clk_gpio->hw);
|
||||
err = clk_hw_register(NULL, hw);
|
||||
|
||||
if (!IS_ERR(clk))
|
||||
return clk;
|
||||
if (!err)
|
||||
return hw;
|
||||
|
||||
if (!dev) {
|
||||
gpiod_put(clk_gpio->gpiod);
|
||||
kfree(clk_gpio);
|
||||
}
|
||||
|
||||
return clk;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
/**
|
||||
* clk_register_gpio_gate - register a gpio clock gate with the clock framework
|
||||
* clk_hw_register_gpio_gate - register a gpio clock gate with the clock
|
||||
* framework
|
||||
* @dev: device that is registering this clock
|
||||
* @name: name of this clock
|
||||
* @parent_name: name of this clock's parent
|
||||
@ -166,7 +168,7 @@ static struct clk *clk_register_gpio(struct device *dev, const char *name,
|
||||
* @active_low: true if gpio should be set to 0 to enable clock
|
||||
* @flags: clock flags
|
||||
*/
|
||||
struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
|
||||
struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned gpio, bool active_low,
|
||||
unsigned long flags)
|
||||
{
|
||||
@ -175,10 +177,24 @@ struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
|
||||
(parent_name ? 1 : 0), gpio, active_low, flags,
|
||||
&clk_gpio_gate_ops);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_register_gpio_gate);
|
||||
|
||||
struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned gpio, bool active_low,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
|
||||
hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpio, active_low,
|
||||
flags);
|
||||
if (IS_ERR(hw))
|
||||
return ERR_CAST(hw);
|
||||
return hw->clk;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register_gpio_gate);
|
||||
|
||||
/**
|
||||
* clk_register_gpio_mux - register a gpio clock mux with the clock framework
|
||||
* clk_hw_register_gpio_mux - register a gpio clock mux with the clock framework
|
||||
* @dev: device that is registering this clock
|
||||
* @name: name of this clock
|
||||
* @parent_names: names of this clock's parents
|
||||
@ -187,7 +203,7 @@ EXPORT_SYMBOL_GPL(clk_register_gpio_gate);
|
||||
* @active_low: true if gpio should be set to 0 to enable clock
|
||||
* @flags: clock flags
|
||||
*/
|
||||
struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
|
||||
struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name,
|
||||
const char * const *parent_names, u8 num_parents, unsigned gpio,
|
||||
bool active_low, unsigned long flags)
|
||||
{
|
||||
@ -199,6 +215,20 @@ struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
|
||||
return clk_register_gpio(dev, name, parent_names, num_parents,
|
||||
gpio, active_low, flags, &clk_gpio_mux_ops);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_register_gpio_mux);
|
||||
|
||||
struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
|
||||
const char * const *parent_names, u8 num_parents, unsigned gpio,
|
||||
bool active_low, unsigned long flags)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
|
||||
hw = clk_hw_register_gpio_mux(dev, name, parent_names, num_parents,
|
||||
gpio, active_low, flags);
|
||||
if (IS_ERR(hw))
|
||||
return ERR_CAST(hw);
|
||||
return hw->clk;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register_gpio_mux);
|
||||
|
||||
static int gpio_clk_driver_probe(struct platform_device *pdev)
|
||||
|
@ -113,16 +113,17 @@ const struct clk_ops clk_mux_ro_ops = {
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
|
||||
|
||||
struct clk *clk_register_mux_table(struct device *dev, const char *name,
|
||||
struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
|
||||
const char * const *parent_names, u8 num_parents,
|
||||
unsigned long flags,
|
||||
void __iomem *reg, u8 shift, u32 mask,
|
||||
u8 clk_mux_flags, u32 *table, spinlock_t *lock)
|
||||
{
|
||||
struct clk_mux *mux;
|
||||
struct clk *clk;
|
||||
struct clk_hw *hw;
|
||||
struct clk_init_data init;
|
||||
u8 width = 0;
|
||||
int ret;
|
||||
|
||||
if (clk_mux_flags & CLK_MUX_HIWORD_MASK) {
|
||||
width = fls(mask) - ffs(mask) + 1;
|
||||
@ -157,12 +158,31 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
|
||||
mux->table = table;
|
||||
mux->hw.init = &init;
|
||||
|
||||
clk = clk_register(dev, &mux->hw);
|
||||
|
||||
if (IS_ERR(clk))
|
||||
hw = &mux->hw;
|
||||
ret = clk_hw_register(dev, hw);
|
||||
if (ret) {
|
||||
kfree(mux);
|
||||
hw = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return clk;
|
||||
return hw;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_register_mux_table);
|
||||
|
||||
struct clk *clk_register_mux_table(struct device *dev, const char *name,
|
||||
const char * const *parent_names, u8 num_parents,
|
||||
unsigned long flags,
|
||||
void __iomem *reg, u8 shift, u32 mask,
|
||||
u8 clk_mux_flags, u32 *table, spinlock_t *lock)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
|
||||
hw = clk_hw_register_mux_table(dev, name, parent_names, num_parents,
|
||||
flags, reg, shift, mask, clk_mux_flags,
|
||||
table, lock);
|
||||
if (IS_ERR(hw))
|
||||
return ERR_CAST(hw);
|
||||
return hw->clk;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register_mux_table);
|
||||
|
||||
@ -180,6 +200,20 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register_mux);
|
||||
|
||||
struct clk_hw *clk_hw_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)
|
||||
{
|
||||
u32 mask = BIT(width) - 1;
|
||||
|
||||
return clk_hw_register_mux_table(dev, name, parent_names, num_parents,
|
||||
flags, reg, shift, mask, clk_mux_flags,
|
||||
NULL, lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_register_mux);
|
||||
|
||||
void clk_unregister_mux(struct clk *clk)
|
||||
{
|
||||
struct clk_mux *mux;
|
||||
@ -195,3 +229,14 @@ void clk_unregister_mux(struct clk *clk)
|
||||
kfree(mux);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_unregister_mux);
|
||||
|
||||
void clk_hw_unregister_mux(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_mux *mux;
|
||||
|
||||
mux = to_clk_mux(hw);
|
||||
|
||||
clk_hw_unregister(hw);
|
||||
kfree(mux);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_unregister_mux);
|
||||
|
@ -2547,6 +2547,22 @@ fail_out:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register);
|
||||
|
||||
/**
|
||||
* clk_hw_register - register a clk_hw and return an error code
|
||||
* @dev: device that is registering this clock
|
||||
* @hw: link to hardware-specific clock data
|
||||
*
|
||||
* clk_hw_register is the primary interface for populating the clock tree with
|
||||
* new clock nodes. It returns an integer equal to zero indicating success or
|
||||
* less than zero indicating failure. Drivers must test for an error code after
|
||||
* calling clk_hw_register().
|
||||
*/
|
||||
int clk_hw_register(struct device *dev, struct clk_hw *hw)
|
||||
{
|
||||
return PTR_ERR_OR_ZERO(clk_register(dev, hw));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_register);
|
||||
|
||||
/* Free memory allocated for a clock. */
|
||||
static void __clk_release(struct kref *ref)
|
||||
{
|
||||
@ -2648,11 +2664,26 @@ unlock:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_unregister);
|
||||
|
||||
/**
|
||||
* clk_hw_unregister - unregister a currently registered clk_hw
|
||||
* @hw: hardware-specific clock data to unregister
|
||||
*/
|
||||
void clk_hw_unregister(struct clk_hw *hw)
|
||||
{
|
||||
clk_unregister(hw->clk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_unregister);
|
||||
|
||||
static void devm_clk_release(struct device *dev, void *res)
|
||||
{
|
||||
clk_unregister(*(struct clk **)res);
|
||||
}
|
||||
|
||||
static void devm_clk_hw_release(struct device *dev, void *res)
|
||||
{
|
||||
clk_hw_unregister(*(struct clk_hw **)res);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_clk_register - resource managed clk_register()
|
||||
* @dev: device that is registering this clock
|
||||
@ -2683,6 +2714,36 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_clk_register);
|
||||
|
||||
/**
|
||||
* devm_clk_hw_register - resource managed clk_hw_register()
|
||||
* @dev: device that is registering this clock
|
||||
* @hw: link to hardware-specific clock data
|
||||
*
|
||||
* Managed clk_hw_register(). Clocks returned from this function are
|
||||
* automatically clk_hw_unregister()ed on driver detach. See clk_hw_register()
|
||||
* for more information.
|
||||
*/
|
||||
int devm_clk_hw_register(struct device *dev, struct clk_hw *hw)
|
||||
{
|
||||
struct clk_hw **hwp;
|
||||
int ret;
|
||||
|
||||
hwp = devres_alloc(devm_clk_hw_release, sizeof(*hwp), GFP_KERNEL);
|
||||
if (!hwp)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = clk_hw_register(dev, hw);
|
||||
if (!ret) {
|
||||
*hwp = hw;
|
||||
devres_add(dev, hwp);
|
||||
} else {
|
||||
devres_free(hwp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_clk_hw_register);
|
||||
|
||||
static int devm_clk_match(struct device *dev, void *res, void *data)
|
||||
{
|
||||
struct clk *c = res;
|
||||
@ -2691,6 +2752,15 @@ static int devm_clk_match(struct device *dev, void *res, void *data)
|
||||
return c == data;
|
||||
}
|
||||
|
||||
static int devm_clk_hw_match(struct device *dev, void *res, void *data)
|
||||
{
|
||||
struct clk_hw *hw = res;
|
||||
|
||||
if (WARN_ON(!hw))
|
||||
return 0;
|
||||
return hw == data;
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_clk_unregister - resource managed clk_unregister()
|
||||
* @clk: clock to unregister
|
||||
@ -2705,6 +2775,22 @@ void devm_clk_unregister(struct device *dev, struct clk *clk)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_clk_unregister);
|
||||
|
||||
/**
|
||||
* devm_clk_hw_unregister - resource managed clk_hw_unregister()
|
||||
* @dev: device that is unregistering the hardware-specific clock data
|
||||
* @hw: link to hardware-specific clock data
|
||||
*
|
||||
* Unregister a clk_hw registered with devm_clk_hw_register(). Normally
|
||||
* this function will not need to be called and the resource management
|
||||
* code will ensure that the resource is freed.
|
||||
*/
|
||||
void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw)
|
||||
{
|
||||
WARN_ON(devres_release(dev, devm_clk_hw_release, devm_clk_hw_match,
|
||||
hw));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_clk_hw_unregister);
|
||||
|
||||
/*
|
||||
* clkdev helpers
|
||||
*/
|
||||
@ -2866,6 +2952,7 @@ struct of_clk_provider {
|
||||
|
||||
struct device_node *node;
|
||||
struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
|
||||
struct clk_hw *(*get_hw)(struct of_phandle_args *clkspec, void *data);
|
||||
void *data;
|
||||
};
|
||||
|
||||
@ -2882,6 +2969,12 @@ struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_clk_src_simple_get);
|
||||
|
||||
struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_clk_hw_simple_get);
|
||||
|
||||
struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
|
||||
{
|
||||
struct clk_onecell_data *clk_data = data;
|
||||
@ -2896,6 +2989,21 @@ struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_clk_src_onecell_get);
|
||||
|
||||
struct clk_hw *
|
||||
of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data)
|
||||
{
|
||||
struct clk_hw_onecell_data *hw_data = data;
|
||||
unsigned int idx = clkspec->args[0];
|
||||
|
||||
if (idx >= hw_data->num) {
|
||||
pr_err("%s: invalid index %u\n", __func__, idx);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return hw_data->hws[idx];
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_clk_hw_onecell_get);
|
||||
|
||||
/**
|
||||
* of_clk_add_provider() - Register a clock provider for a node
|
||||
* @np: Device node pointer associated with clock provider
|
||||
@ -2931,6 +3039,41 @@ int of_clk_add_provider(struct device_node *np,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_clk_add_provider);
|
||||
|
||||
/**
|
||||
* of_clk_add_hw_provider() - Register a clock provider for a node
|
||||
* @np: Device node pointer associated with clock provider
|
||||
* @get: callback for decoding clk_hw
|
||||
* @data: context pointer for @get callback.
|
||||
*/
|
||||
int of_clk_add_hw_provider(struct device_node *np,
|
||||
struct clk_hw *(*get)(struct of_phandle_args *clkspec,
|
||||
void *data),
|
||||
void *data)
|
||||
{
|
||||
struct of_clk_provider *cp;
|
||||
int ret;
|
||||
|
||||
cp = kzalloc(sizeof(*cp), GFP_KERNEL);
|
||||
if (!cp)
|
||||
return -ENOMEM;
|
||||
|
||||
cp->node = of_node_get(np);
|
||||
cp->data = data;
|
||||
cp->get_hw = get;
|
||||
|
||||
mutex_lock(&of_clk_mutex);
|
||||
list_add(&cp->link, &of_clk_providers);
|
||||
mutex_unlock(&of_clk_mutex);
|
||||
pr_debug("Added clk_hw provider from %s\n", np->full_name);
|
||||
|
||||
ret = of_clk_set_defaults(np, true);
|
||||
if (ret < 0)
|
||||
of_clk_del_provider(np);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_clk_add_hw_provider);
|
||||
|
||||
/**
|
||||
* of_clk_del_provider() - Remove a previously registered clock provider
|
||||
* @np: Device node pointer associated with clock provider
|
||||
@ -2952,11 +3095,32 @@ void of_clk_del_provider(struct device_node *np)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_clk_del_provider);
|
||||
|
||||
static struct clk_hw *
|
||||
__of_clk_get_hw_from_provider(struct of_clk_provider *provider,
|
||||
struct of_phandle_args *clkspec)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
if (provider->get_hw) {
|
||||
hw = provider->get_hw(clkspec, provider->data);
|
||||
} else if (provider->get) {
|
||||
clk = provider->get(clkspec, provider->data);
|
||||
if (!IS_ERR(clk))
|
||||
hw = __clk_get_hw(clk);
|
||||
else
|
||||
hw = ERR_CAST(clk);
|
||||
}
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
|
||||
const char *dev_id, const char *con_id)
|
||||
{
|
||||
struct of_clk_provider *provider;
|
||||
struct clk *clk = ERR_PTR(-EPROBE_DEFER);
|
||||
struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
if (!clkspec)
|
||||
return ERR_PTR(-EINVAL);
|
||||
@ -2965,10 +3129,9 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
|
||||
mutex_lock(&of_clk_mutex);
|
||||
list_for_each_entry(provider, &of_clk_providers, link) {
|
||||
if (provider->node == clkspec->np)
|
||||
clk = provider->get(clkspec, provider->data);
|
||||
if (!IS_ERR(clk)) {
|
||||
clk = __clk_create_clk(__clk_get_hw(clk), dev_id,
|
||||
con_id);
|
||||
hw = __of_clk_get_hw_from_provider(provider, clkspec);
|
||||
if (!IS_ERR(hw)) {
|
||||
clk = __clk_create_clk(hw, dev_id, con_id);
|
||||
|
||||
if (!IS_ERR(clk) && !__clk_get(clk)) {
|
||||
__clk_free_clk(clk);
|
||||
|
@ -301,6 +301,20 @@ clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
|
||||
}
|
||||
EXPORT_SYMBOL(clkdev_alloc);
|
||||
|
||||
struct clk_lookup *
|
||||
clkdev_hw_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt, ...)
|
||||
{
|
||||
struct clk_lookup *cl;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, dev_fmt);
|
||||
cl = vclkdev_alloc(hw, con_id, dev_fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return cl;
|
||||
}
|
||||
EXPORT_SYMBOL(clkdev_hw_alloc);
|
||||
|
||||
/**
|
||||
* clkdev_create - allocate and add a clkdev lookup structure
|
||||
* @clk: struct clk to associate with all clk_lookups
|
||||
@ -324,6 +338,29 @@ struct clk_lookup *clkdev_create(struct clk *clk, const char *con_id,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clkdev_create);
|
||||
|
||||
/**
|
||||
* clkdev_hw_create - allocate and add a clkdev lookup structure
|
||||
* @hw: struct clk_hw to associate with all clk_lookups
|
||||
* @con_id: connection ID string on device
|
||||
* @dev_fmt: format string describing device name
|
||||
*
|
||||
* Returns a clk_lookup structure, which can be later unregistered and
|
||||
* freed.
|
||||
*/
|
||||
struct clk_lookup *clkdev_hw_create(struct clk_hw *hw, const char *con_id,
|
||||
const char *dev_fmt, ...)
|
||||
{
|
||||
struct clk_lookup *cl;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, dev_fmt);
|
||||
cl = vclkdev_create(hw, con_id, dev_fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return cl;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clkdev_hw_create);
|
||||
|
||||
int clk_add_alias(const char *alias, const char *alias_dev_name,
|
||||
const char *con_id, struct device *dev)
|
||||
{
|
||||
@ -404,28 +441,28 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
|
||||
EXPORT_SYMBOL(clk_register_clkdev);
|
||||
|
||||
/**
|
||||
* clk_register_clkdevs - register a set of clk_lookup for a struct clk
|
||||
* @clk: struct clk to associate with all clk_lookups
|
||||
* @cl: array of clk_lookup structures with con_id and dev_id pre-initialized
|
||||
* @num: number of clk_lookup structures to register
|
||||
* clk_hw_register_clkdev - register one clock lookup for a struct clk_hw
|
||||
* @hw: struct clk_hw to associate with all clk_lookups
|
||||
* @con_id: connection ID string on device
|
||||
* @dev_id: format string describing device name
|
||||
*
|
||||
* To make things easier for mass registration, we detect error clks
|
||||
* from a previous clk_register() call, and return the error code for
|
||||
* those. This is to permit this function to be called immediately
|
||||
* after clk_register().
|
||||
* con_id or dev_id may be NULL as a wildcard, just as in the rest of
|
||||
* clkdev.
|
||||
*/
|
||||
int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num)
|
||||
int clk_hw_register_clkdev(struct clk_hw *hw, const char *con_id,
|
||||
const char *dev_id)
|
||||
{
|
||||
unsigned i;
|
||||
struct clk_lookup *cl;
|
||||
|
||||
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(hw, con_id, "%s", dev_id);
|
||||
else
|
||||
cl = __clk_register_clkdev(hw, con_id, NULL);
|
||||
|
||||
for (i = 0; i < num; i++, cl++) {
|
||||
cl->clk_hw = __clk_get_hw(clk);
|
||||
__clkdev_add(cl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return cl ? 0 : -ENOMEM;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_register_clkdevs);
|
||||
EXPORT_SYMBOL(clk_hw_register_clkdev);
|
||||
|
@ -283,10 +283,17 @@ extern const struct clk_ops clk_fixed_rate_ops;
|
||||
struct clk *clk_register_fixed_rate(struct device *dev, 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 fixed_rate);
|
||||
struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev,
|
||||
const char *name, const char *parent_name, unsigned long flags,
|
||||
unsigned long fixed_rate, unsigned long fixed_accuracy);
|
||||
void clk_unregister_fixed_rate(struct clk *clk);
|
||||
struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev,
|
||||
const char *name, const char *parent_name, unsigned long flags,
|
||||
unsigned long fixed_rate, unsigned long fixed_accuracy);
|
||||
|
||||
void of_fixed_clk_setup(struct device_node *np);
|
||||
|
||||
/**
|
||||
@ -327,7 +334,12 @@ 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);
|
||||
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);
|
||||
void clk_unregister_gate(struct clk *clk);
|
||||
void clk_hw_unregister_gate(struct clk_hw *hw);
|
||||
|
||||
struct clk_div_table {
|
||||
unsigned int val;
|
||||
@ -408,12 +420,22 @@ 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_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 *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);
|
||||
void clk_unregister_divider(struct clk *clk);
|
||||
void clk_hw_unregister_divider(struct clk_hw *hw);
|
||||
|
||||
/**
|
||||
* struct clk_mux - multiplexer clock
|
||||
@ -464,14 +486,25 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
|
||||
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,
|
||||
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_table(struct device *dev, const char *name,
|
||||
const char * const *parent_names, u8 num_parents,
|
||||
unsigned long flags,
|
||||
void __iomem *reg, u8 shift, u32 mask,
|
||||
u8 clk_mux_flags, u32 *table, spinlock_t *lock);
|
||||
struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
|
||||
const char * const *parent_names, u8 num_parents,
|
||||
unsigned long flags,
|
||||
void __iomem *reg, u8 shift, u32 mask,
|
||||
u8 clk_mux_flags, u32 *table, spinlock_t *lock);
|
||||
|
||||
void clk_unregister_mux(struct clk *clk);
|
||||
void clk_hw_unregister_mux(struct clk_hw *hw);
|
||||
|
||||
void of_fixed_factor_clk_setup(struct device_node *node);
|
||||
|
||||
@ -500,6 +533,10 @@ 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);
|
||||
void clk_unregister_fixed_factor(struct clk *clk);
|
||||
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);
|
||||
void clk_hw_unregister_fixed_factor(struct clk_hw *hw);
|
||||
|
||||
/**
|
||||
* struct clk_fractional_divider - adjustable fractional divider clock
|
||||
@ -534,6 +571,11 @@ struct clk *clk_register_fractional_divider(struct device *dev,
|
||||
const char *name, const char *parent_name, unsigned long flags,
|
||||
void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
|
||||
u8 clk_divider_flags, spinlock_t *lock);
|
||||
struct clk_hw *clk_hw_register_fractional_divider(struct device *dev,
|
||||
const char *name, const char *parent_name, unsigned long flags,
|
||||
void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
|
||||
u8 clk_divider_flags, spinlock_t *lock);
|
||||
void clk_hw_unregister_fractional_divider(struct clk_hw *hw);
|
||||
|
||||
/**
|
||||
* struct clk_multiplier - adjustable multiplier clock
|
||||
@ -605,6 +647,13 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
|
||||
struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
|
||||
unsigned long flags);
|
||||
void clk_unregister_composite(struct clk *clk);
|
||||
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);
|
||||
void clk_hw_unregister_composite(struct clk_hw *hw);
|
||||
|
||||
/***
|
||||
* struct clk_gpio_gate - gpio gated clock
|
||||
@ -627,6 +676,10 @@ extern const struct clk_ops clk_gpio_gate_ops;
|
||||
struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned gpio, bool active_low,
|
||||
unsigned long flags);
|
||||
struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned gpio, bool active_low,
|
||||
unsigned long flags);
|
||||
void clk_hw_unregister_gpio_gate(struct clk_hw *hw);
|
||||
|
||||
/**
|
||||
* struct clk_gpio_mux - gpio controlled clock multiplexer
|
||||
@ -642,6 +695,10 @@ extern const struct clk_ops clk_gpio_mux_ops;
|
||||
struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
|
||||
const char * const *parent_names, u8 num_parents, unsigned gpio,
|
||||
bool active_low, unsigned long flags);
|
||||
struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name,
|
||||
const char * const *parent_names, u8 num_parents, unsigned gpio,
|
||||
bool active_low, unsigned long flags);
|
||||
void clk_hw_unregister_gpio_mux(struct clk_hw *hw);
|
||||
|
||||
/**
|
||||
* clk_register - allocate a new clock, register it and return an opaque cookie
|
||||
@ -657,9 +714,15 @@ struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
|
||||
struct clk *clk_register(struct device *dev, struct clk_hw *hw);
|
||||
struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
|
||||
|
||||
int __must_check clk_hw_register(struct device *dev, struct clk_hw *hw);
|
||||
int __must_check devm_clk_hw_register(struct device *dev, struct clk_hw *hw);
|
||||
|
||||
void clk_unregister(struct clk *clk);
|
||||
void devm_clk_unregister(struct device *dev, struct clk *clk);
|
||||
|
||||
void clk_hw_unregister(struct clk_hw *hw);
|
||||
void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw);
|
||||
|
||||
/* helper functions */
|
||||
const char *__clk_get_name(const struct clk *clk);
|
||||
const char *clk_hw_get_name(const struct clk_hw *hw);
|
||||
@ -705,6 +768,11 @@ struct clk_onecell_data {
|
||||
unsigned int clk_num;
|
||||
};
|
||||
|
||||
struct clk_hw_onecell_data {
|
||||
size_t num;
|
||||
struct clk_hw *hws[];
|
||||
};
|
||||
|
||||
extern struct of_device_id __clk_of_table;
|
||||
|
||||
#define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn)
|
||||
@ -714,10 +782,18 @@ int of_clk_add_provider(struct device_node *np,
|
||||
struct clk *(*clk_src_get)(struct of_phandle_args *args,
|
||||
void *data),
|
||||
void *data);
|
||||
int of_clk_add_hw_provider(struct device_node *np,
|
||||
struct clk_hw *(*get)(struct of_phandle_args *clkspec,
|
||||
void *data),
|
||||
void *data);
|
||||
void of_clk_del_provider(struct device_node *np);
|
||||
struct clk *of_clk_src_simple_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_src_onecell_get(struct of_phandle_args *clkspec, void *data);
|
||||
struct clk_hw *of_clk_hw_onecell_get(struct of_phandle_args *clkspec,
|
||||
void *data);
|
||||
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);
|
||||
@ -735,17 +811,34 @@ 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 *(*get)(struct of_phandle_args *clkspec,
|
||||
void *data),
|
||||
void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void of_clk_del_provider(struct device_node *np) {}
|
||||
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_src_onecell_get(
|
||||
struct of_phandle_args *clkspec, void *data)
|
||||
{
|
||||
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 int of_clk_get_parent_count(struct device_node *np)
|
||||
{
|
||||
return 0;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <asm/clkdev.h>
|
||||
|
||||
struct clk;
|
||||
struct clk_hw;
|
||||
struct device;
|
||||
|
||||
struct clk_lookup {
|
||||
@ -34,18 +35,22 @@ struct clk_lookup {
|
||||
|
||||
struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
|
||||
const char *dev_fmt, ...) __printf(3, 4);
|
||||
struct clk_lookup *clkdev_hw_alloc(struct clk_hw *hw, const char *con_id,
|
||||
const char *dev_fmt, ...) __printf(3, 4);
|
||||
|
||||
void clkdev_add(struct clk_lookup *cl);
|
||||
void clkdev_drop(struct clk_lookup *cl);
|
||||
|
||||
struct clk_lookup *clkdev_create(struct clk *clk, const char *con_id,
|
||||
const char *dev_fmt, ...) __printf(3, 4);
|
||||
struct clk_lookup *clkdev_hw_create(struct clk_hw *hw, const char *con_id,
|
||||
const char *dev_fmt, ...) __printf(3, 4);
|
||||
|
||||
void clkdev_add_table(struct clk_lookup *, size_t);
|
||||
int clk_add_alias(const char *, const char *, const char *, struct device *);
|
||||
|
||||
int clk_register_clkdev(struct clk *, const char *, const char *);
|
||||
int clk_register_clkdevs(struct clk *, struct clk_lookup *, size_t);
|
||||
int clk_hw_register_clkdev(struct clk_hw *, const char *, const char *);
|
||||
|
||||
#ifdef CONFIG_COMMON_CLK
|
||||
int __clk_get(struct clk *clk);
|
||||
|
Loading…
Reference in New Issue
Block a user