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:
Stephen Boyd 2016-04-21 14:47:18 -07:00
commit 58657d189a
13 changed files with 673 additions and 88 deletions

View File

@ -236,6 +236,7 @@ certainly invest a bit more effort into libata core layer).
CLOCK CLOCK
devm_clk_get() devm_clk_get()
devm_clk_put() devm_clk_put()
devm_clk_hw_register()
DMA DMA
dmam_alloc_coherent() dmam_alloc_coherent()

View File

@ -211,17 +211,18 @@ static void clk_composite_disable(struct clk_hw *hw)
gate_ops->disable(gate_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, const char * const *parent_names, int num_parents,
struct clk_hw *mux_hw, const struct clk_ops *mux_ops, 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 *rate_hw, const struct clk_ops *rate_ops,
struct clk_hw *gate_hw, const struct clk_ops *gate_ops, struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
unsigned long flags) unsigned long flags)
{ {
struct clk *clk; struct clk_hw *hw;
struct clk_init_data init; struct clk_init_data init;
struct clk_composite *composite; struct clk_composite *composite;
struct clk_ops *clk_composite_ops; struct clk_ops *clk_composite_ops;
int ret;
composite = kzalloc(sizeof(*composite), GFP_KERNEL); composite = kzalloc(sizeof(*composite), GFP_KERNEL);
if (!composite) if (!composite)
@ -231,12 +232,13 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
init.flags = flags | CLK_IS_BASIC; init.flags = flags | CLK_IS_BASIC;
init.parent_names = parent_names; init.parent_names = parent_names;
init.num_parents = num_parents; init.num_parents = num_parents;
hw = &composite->hw;
clk_composite_ops = &composite->ops; clk_composite_ops = &composite->ops;
if (mux_hw && mux_ops) { if (mux_hw && mux_ops) {
if (!mux_ops->get_parent) { if (!mux_ops->get_parent) {
clk = ERR_PTR(-EINVAL); hw = ERR_PTR(-EINVAL);
goto err; goto err;
} }
@ -251,7 +253,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
if (rate_hw && rate_ops) { if (rate_hw && rate_ops) {
if (!rate_ops->recalc_rate) { if (!rate_ops->recalc_rate) {
clk = ERR_PTR(-EINVAL); hw = ERR_PTR(-EINVAL);
goto err; goto err;
} }
clk_composite_ops->recalc_rate = clk_composite_recalc_rate; 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_hw && gate_ops) {
if (!gate_ops->is_enabled || !gate_ops->enable || if (!gate_ops->is_enabled || !gate_ops->enable ||
!gate_ops->disable) { !gate_ops->disable) {
clk = ERR_PTR(-EINVAL); hw = ERR_PTR(-EINVAL);
goto err; goto err;
} }
@ -300,24 +302,43 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
init.ops = clk_composite_ops; init.ops = clk_composite_ops;
composite->hw.init = &init; composite->hw.init = &init;
clk = clk_register(dev, &composite->hw); ret = clk_hw_register(dev, hw);
if (IS_ERR(clk)) if (ret) {
hw = ERR_PTR(ret);
goto err; goto err;
}
if (composite->mux_hw) if (composite->mux_hw)
composite->mux_hw->clk = clk; composite->mux_hw->clk = hw->clk;
if (composite->rate_hw) if (composite->rate_hw)
composite->rate_hw->clk = clk; composite->rate_hw->clk = hw->clk;
if (composite->gate_hw) if (composite->gate_hw)
composite->gate_hw->clk = clk; composite->gate_hw->clk = hw->clk;
return clk; return hw;
err: err:
kfree(composite); 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) void clk_unregister_composite(struct clk *clk)

View File

@ -426,15 +426,16 @@ const struct clk_ops clk_divider_ro_ops = {
}; };
EXPORT_SYMBOL_GPL(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, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 shift, u8 width, void __iomem *reg, u8 shift, u8 width,
u8 clk_divider_flags, const struct clk_div_table *table, u8 clk_divider_flags, const struct clk_div_table *table,
spinlock_t *lock) spinlock_t *lock)
{ {
struct clk_divider *div; struct clk_divider *div;
struct clk *clk; struct clk_hw *hw;
struct clk_init_data init; struct clk_init_data init;
int ret;
if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) { if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
if (width + shift > 16) { if (width + shift > 16) {
@ -467,12 +468,14 @@ static struct clk *_register_divider(struct device *dev, const char *name,
div->table = table; div->table = table;
/* register the clock */ /* register the clock */
clk = clk_register(dev, &div->hw); hw = &div->hw;
ret = clk_hw_register(dev, hw);
if (IS_ERR(clk)) if (ret) {
kfree(div); 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, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 shift, u8 width, void __iomem *reg, u8 shift, u8 width,
u8 clk_divider_flags, spinlock_t *lock) 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, return _register_divider(dev, name, parent_name, flags, reg, shift,
width, clk_divider_flags, NULL, lock); 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 * 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, void __iomem *reg, u8 shift, u8 width,
u8 clk_divider_flags, const struct clk_div_table *table, u8 clk_divider_flags, const struct clk_div_table *table,
spinlock_t *lock) 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, return _register_divider(dev, name, parent_name, flags, reg, shift,
width, clk_divider_flags, table, lock); 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) void clk_unregister_divider(struct clk *clk)
{ {
@ -537,3 +597,18 @@ void clk_unregister_divider(struct clk *clk)
kfree(div); kfree(div);
} }
EXPORT_SYMBOL_GPL(clk_unregister_divider); 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);

View File

@ -68,13 +68,14 @@ const struct clk_ops clk_fixed_factor_ops = {
}; };
EXPORT_SYMBOL_GPL(clk_fixed_factor_ops); EXPORT_SYMBOL_GPL(clk_fixed_factor_ops);
struct clk *clk_register_fixed_factor(struct device *dev, const char *name, struct clk_hw *clk_hw_register_fixed_factor(struct device *dev,
const char *parent_name, unsigned long flags, const char *name, const char *parent_name, unsigned long flags,
unsigned int mult, unsigned int div) unsigned int mult, unsigned int div)
{ {
struct clk_fixed_factor *fix; struct clk_fixed_factor *fix;
struct clk_init_data init; struct clk_init_data init;
struct clk *clk; struct clk_hw *hw;
int ret;
fix = kmalloc(sizeof(*fix), GFP_KERNEL); fix = kmalloc(sizeof(*fix), GFP_KERNEL);
if (!fix) if (!fix)
@ -91,12 +92,28 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
init.parent_names = &parent_name; init.parent_names = &parent_name;
init.num_parents = 1; init.num_parents = 1;
clk = clk_register(dev, &fix->hw); hw = &fix->hw;
ret = clk_hw_register(dev, hw);
if (IS_ERR(clk)) if (ret) {
kfree(fix); 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); 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); 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 #ifdef CONFIG_OF
/** /**
* of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock

View File

@ -45,8 +45,8 @@ const struct clk_ops clk_fixed_rate_ops = {
EXPORT_SYMBOL_GPL(clk_fixed_rate_ops); EXPORT_SYMBOL_GPL(clk_fixed_rate_ops);
/** /**
* clk_register_fixed_rate_with_accuracy - register fixed-rate clock with the * clk_hw_register_fixed_rate_with_accuracy - register fixed-rate clock with
* clock framework * the clock framework
* @dev: device that is registering this clock * @dev: device that is registering this clock
* @name: name of this clock * @name: name of this clock
* @parent_name: name of clock's parent * @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_rate: non-adjustable clock rate
* @fixed_accuracy: 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, const char *name, const char *parent_name, unsigned long flags,
unsigned long fixed_rate, unsigned long fixed_accuracy) unsigned long fixed_rate, unsigned long fixed_accuracy)
{ {
struct clk_fixed_rate *fixed; struct clk_fixed_rate *fixed;
struct clk *clk; struct clk_hw *hw;
struct clk_init_data init; struct clk_init_data init;
int ret;
/* allocate fixed-rate clock */ /* allocate fixed-rate clock */
fixed = kzalloc(sizeof(*fixed), GFP_KERNEL); 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; fixed->hw.init = &init;
/* register the clock */ /* register the clock */
clk = clk_register(dev, &fixed->hw); hw = &fixed->hw;
if (IS_ERR(clk)) ret = clk_hw_register(dev, hw);
if (ret) {
kfree(fixed); 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); 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 * @dev: device that is registering this clock
* @name: name of this clock * @name: name of this clock
* @parent_name: name of clock's parent * @parent_name: name of clock's parent
* @flags: framework-specific flags * @flags: framework-specific flags
* @fixed_rate: non-adjustable clock rate * @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, struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
const char *parent_name, unsigned long flags, const char *parent_name, unsigned long flags,
unsigned long fixed_rate) unsigned long fixed_rate)

View File

@ -116,14 +116,15 @@ const struct clk_ops clk_fractional_divider_ops = {
}; };
EXPORT_SYMBOL_GPL(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, const char *name, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
u8 clk_divider_flags, spinlock_t *lock) u8 clk_divider_flags, spinlock_t *lock)
{ {
struct clk_fractional_divider *fd; struct clk_fractional_divider *fd;
struct clk_init_data init; struct clk_init_data init;
struct clk *clk; struct clk_hw *hw;
int ret;
fd = kzalloc(sizeof(*fd), GFP_KERNEL); fd = kzalloc(sizeof(*fd), GFP_KERNEL);
if (!fd) if (!fd)
@ -146,10 +147,39 @@ struct clk *clk_register_fractional_divider(struct device *dev,
fd->lock = lock; fd->lock = lock;
fd->hw.init = &init; fd->hw.init = &init;
clk = clk_register(dev, &fd->hw); hw = &fd->hw;
if (IS_ERR(clk)) ret = clk_hw_register(dev, hw);
if (ret) {
kfree(fd); 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); 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);
}

View File

@ -110,7 +110,7 @@ const struct clk_ops clk_gate_ops = {
EXPORT_SYMBOL_GPL(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 * @dev: device that is registering this clock
* @name: name of this clock * @name: name of this clock
* @parent_name: name of this clock's parent * @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 * @clk_gate_flags: gate-specific flags for this clock
* @lock: shared register lock 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, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 bit_idx, void __iomem *reg, u8 bit_idx,
u8 clk_gate_flags, spinlock_t *lock) u8 clk_gate_flags, spinlock_t *lock)
{ {
struct clk_gate *gate; struct clk_gate *gate;
struct clk *clk; struct clk_hw *hw;
struct clk_init_data init; struct clk_init_data init;
int ret;
if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { if (clk_gate_flags & CLK_GATE_HIWORD_MASK) {
if (bit_idx > 15) { if (bit_idx > 15) {
@ -154,12 +155,29 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
gate->lock = lock; gate->lock = lock;
gate->hw.init = &init; gate->hw.init = &init;
clk = clk_register(dev, &gate->hw); hw = &gate->hw;
ret = clk_hw_register(dev, hw);
if (IS_ERR(clk)) if (ret) {
kfree(gate); 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); EXPORT_SYMBOL_GPL(clk_register_gate);
@ -178,3 +196,14 @@ void clk_unregister_gate(struct clk *clk)
kfree(gate); kfree(gate);
} }
EXPORT_SYMBOL_GPL(clk_unregister_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);

View File

@ -94,13 +94,13 @@ const struct clk_ops clk_gpio_mux_ops = {
}; };
EXPORT_SYMBOL_GPL(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, const char * const *parent_names, u8 num_parents, unsigned gpio,
bool active_low, unsigned long flags, bool active_low, unsigned long flags,
const struct clk_ops *clk_gpio_ops) const struct clk_ops *clk_gpio_ops)
{ {
struct clk_gpio *clk_gpio; struct clk_gpio *clk_gpio;
struct clk *clk; struct clk_hw *hw;
struct clk_init_data init = {}; struct clk_init_data init = {};
unsigned long gpio_flags; unsigned long gpio_flags;
int err; 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->gpiod = gpio_to_desc(gpio);
clk_gpio->hw.init = &init; clk_gpio->hw.init = &init;
hw = &clk_gpio->hw;
if (dev) if (dev)
clk = devm_clk_register(dev, &clk_gpio->hw); err = devm_clk_hw_register(dev, hw);
else else
clk = clk_register(NULL, &clk_gpio->hw); err = clk_hw_register(NULL, hw);
if (!IS_ERR(clk)) if (!err)
return clk; return hw;
if (!dev) { if (!dev) {
gpiod_put(clk_gpio->gpiod); gpiod_put(clk_gpio->gpiod);
kfree(clk_gpio); 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 * @dev: device that is registering this clock
* @name: name of this clock * @name: name of this clock
* @parent_name: name of this clock's parent * @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 * @active_low: true if gpio should be set to 0 to enable clock
* @flags: clock flags * @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, const char *parent_name, unsigned gpio, bool active_low,
unsigned long flags) 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, (parent_name ? 1 : 0), gpio, active_low, flags,
&clk_gpio_gate_ops); &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); 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 * @dev: device that is registering this clock
* @name: name of this clock * @name: name of this clock
* @parent_names: names of this clock's parents * @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 * @active_low: true if gpio should be set to 0 to enable clock
* @flags: clock flags * @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, const char * const *parent_names, u8 num_parents, unsigned gpio,
bool active_low, unsigned long flags) 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, return clk_register_gpio(dev, name, parent_names, num_parents,
gpio, active_low, flags, &clk_gpio_mux_ops); 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); EXPORT_SYMBOL_GPL(clk_register_gpio_mux);
static int gpio_clk_driver_probe(struct platform_device *pdev) static int gpio_clk_driver_probe(struct platform_device *pdev)

View File

@ -113,16 +113,17 @@ const struct clk_ops clk_mux_ro_ops = {
}; };
EXPORT_SYMBOL_GPL(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, const char * const *parent_names, u8 num_parents,
unsigned long flags, unsigned long flags,
void __iomem *reg, u8 shift, u32 mask, void __iomem *reg, u8 shift, u32 mask,
u8 clk_mux_flags, u32 *table, spinlock_t *lock) u8 clk_mux_flags, u32 *table, spinlock_t *lock)
{ {
struct clk_mux *mux; struct clk_mux *mux;
struct clk *clk; struct clk_hw *hw;
struct clk_init_data init; struct clk_init_data init;
u8 width = 0; u8 width = 0;
int ret;
if (clk_mux_flags & CLK_MUX_HIWORD_MASK) { if (clk_mux_flags & CLK_MUX_HIWORD_MASK) {
width = fls(mask) - ffs(mask) + 1; 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->table = table;
mux->hw.init = &init; mux->hw.init = &init;
clk = clk_register(dev, &mux->hw); hw = &mux->hw;
ret = clk_hw_register(dev, hw);
if (IS_ERR(clk)) if (ret) {
kfree(mux); 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); 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); 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) void clk_unregister_mux(struct clk *clk)
{ {
struct clk_mux *mux; struct clk_mux *mux;
@ -195,3 +229,14 @@ void clk_unregister_mux(struct clk *clk)
kfree(mux); kfree(mux);
} }
EXPORT_SYMBOL_GPL(clk_unregister_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);

View File

@ -2547,6 +2547,22 @@ fail_out:
} }
EXPORT_SYMBOL_GPL(clk_register); 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. */ /* Free memory allocated for a clock. */
static void __clk_release(struct kref *ref) static void __clk_release(struct kref *ref)
{ {
@ -2648,11 +2664,26 @@ unlock:
} }
EXPORT_SYMBOL_GPL(clk_unregister); 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) static void devm_clk_release(struct device *dev, void *res)
{ {
clk_unregister(*(struct clk **)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() * devm_clk_register - resource managed clk_register()
* @dev: device that is registering this clock * @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); 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) static int devm_clk_match(struct device *dev, void *res, void *data)
{ {
struct clk *c = res; struct clk *c = res;
@ -2691,6 +2752,15 @@ static int devm_clk_match(struct device *dev, void *res, void *data)
return c == 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() * devm_clk_unregister - resource managed clk_unregister()
* @clk: clock to 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); 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 * clkdev helpers
*/ */
@ -2866,6 +2952,7 @@ struct of_clk_provider {
struct device_node *node; struct device_node *node;
struct clk *(*get)(struct of_phandle_args *clkspec, void *data); struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
struct clk_hw *(*get_hw)(struct of_phandle_args *clkspec, void *data);
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); 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 *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
{ {
struct clk_onecell_data *clk_data = 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); 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 * of_clk_add_provider() - Register a clock provider for a node
* @np: Device node pointer associated with clock provider * @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); 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 * of_clk_del_provider() - Remove a previously registered clock provider
* @np: Device node pointer associated with 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); 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, struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
const char *dev_id, const char *con_id) const char *dev_id, const char *con_id)
{ {
struct of_clk_provider *provider; struct of_clk_provider *provider;
struct clk *clk = ERR_PTR(-EPROBE_DEFER); struct clk *clk = ERR_PTR(-EPROBE_DEFER);
struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER);
if (!clkspec) if (!clkspec)
return ERR_PTR(-EINVAL); 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); mutex_lock(&of_clk_mutex);
list_for_each_entry(provider, &of_clk_providers, link) { list_for_each_entry(provider, &of_clk_providers, link) {
if (provider->node == clkspec->np) if (provider->node == clkspec->np)
clk = provider->get(clkspec, provider->data); hw = __of_clk_get_hw_from_provider(provider, clkspec);
if (!IS_ERR(clk)) { if (!IS_ERR(hw)) {
clk = __clk_create_clk(__clk_get_hw(clk), dev_id, clk = __clk_create_clk(hw, dev_id, con_id);
con_id);
if (!IS_ERR(clk) && !__clk_get(clk)) { if (!IS_ERR(clk) && !__clk_get(clk)) {
__clk_free_clk(clk); __clk_free_clk(clk);

View File

@ -301,6 +301,20 @@ clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
} }
EXPORT_SYMBOL(clkdev_alloc); 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 * clkdev_create - allocate and add a clkdev lookup structure
* @clk: struct clk to associate with all clk_lookups * @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); 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, int clk_add_alias(const char *alias, const char *alias_dev_name,
const char *con_id, struct device *dev) 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); EXPORT_SYMBOL(clk_register_clkdev);
/** /**
* clk_register_clkdevs - register a set of clk_lookup for a struct clk * clk_hw_register_clkdev - register one clock lookup for a struct clk_hw
* @clk: struct clk to associate with all clk_lookups * @hw: struct clk_hw to associate with all clk_lookups
* @cl: array of clk_lookup structures with con_id and dev_id pre-initialized * @con_id: connection ID string on device
* @num: number of clk_lookup structures to register * @dev_id: format string describing device name
* *
* To make things easier for mass registration, we detect error clks * con_id or dev_id may be NULL as a wildcard, just as in the rest of
* from a previous clk_register() call, and return the error code for * clkdev.
* those. This is to permit this function to be called immediately
* after clk_register().
*/ */
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++) { return cl ? 0 : -ENOMEM;
cl->clk_hw = __clk_get_hw(clk);
__clkdev_add(cl);
}
return 0;
} }
EXPORT_SYMBOL(clk_register_clkdevs); EXPORT_SYMBOL(clk_hw_register_clkdev);

View File

@ -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, struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
const char *parent_name, unsigned long flags, const char *parent_name, unsigned long flags,
unsigned long fixed_rate); 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, struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev,
const char *name, const char *parent_name, unsigned long flags, const char *name, const char *parent_name, unsigned long flags,
unsigned long fixed_rate, unsigned long fixed_accuracy); unsigned long fixed_rate, unsigned long fixed_accuracy);
void clk_unregister_fixed_rate(struct clk *clk); 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); 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, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 bit_idx, void __iomem *reg, u8 bit_idx,
u8 clk_gate_flags, spinlock_t *lock); 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_unregister_gate(struct clk *clk);
void clk_hw_unregister_gate(struct clk_hw *hw);
struct clk_div_table { struct clk_div_table {
unsigned int val; 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, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 shift, u8 width, void __iomem *reg, u8 shift, u8 width,
u8 clk_divider_flags, spinlock_t *lock); 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, struct clk *clk_register_divider_table(struct device *dev, const char *name,
const char *parent_name, unsigned long flags, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 shift, u8 width, void __iomem *reg, u8 shift, u8 width,
u8 clk_divider_flags, const struct clk_div_table *table, u8 clk_divider_flags, const struct clk_div_table *table,
spinlock_t *lock); 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_unregister_divider(struct clk *clk);
void clk_hw_unregister_divider(struct clk_hw *hw);
/** /**
* struct clk_mux - multiplexer clock * struct clk_mux - multiplexer clock
@ -464,14 +486,25 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
unsigned long flags, unsigned long flags,
void __iomem *reg, u8 shift, u8 width, void __iomem *reg, u8 shift, u8 width,
u8 clk_mux_flags, spinlock_t *lock); 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, struct clk *clk_register_mux_table(struct device *dev, const char *name,
const char * const *parent_names, u8 num_parents, const char * const *parent_names, u8 num_parents,
unsigned long flags, unsigned long flags,
void __iomem *reg, u8 shift, u32 mask, void __iomem *reg, u8 shift, u32 mask,
u8 clk_mux_flags, u32 *table, spinlock_t *lock); 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_unregister_mux(struct clk *clk);
void clk_hw_unregister_mux(struct clk_hw *hw);
void of_fixed_factor_clk_setup(struct device_node *node); 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, const char *parent_name, unsigned long flags,
unsigned int mult, unsigned int div); unsigned int mult, unsigned int div);
void clk_unregister_fixed_factor(struct clk *clk); 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 * 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, const char *name, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
u8 clk_divider_flags, spinlock_t *lock); 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 * 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, struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
unsigned long flags); unsigned long flags);
void clk_unregister_composite(struct clk *clk); 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 * 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, struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
const char *parent_name, unsigned gpio, bool active_low, const char *parent_name, unsigned gpio, bool active_low,
unsigned long flags); 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 * 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, struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
const char * const *parent_names, u8 num_parents, unsigned gpio, const char * const *parent_names, u8 num_parents, unsigned gpio,
bool active_low, unsigned long flags); 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 * 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 *clk_register(struct device *dev, struct clk_hw *hw);
struct clk *devm_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 clk_unregister(struct clk *clk);
void devm_clk_unregister(struct device *dev, 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 */ /* helper functions */
const char *__clk_get_name(const struct clk *clk); const char *__clk_get_name(const struct clk *clk);
const char *clk_hw_get_name(const struct clk_hw *hw); const char *clk_hw_get_name(const struct clk_hw *hw);
@ -705,6 +768,11 @@ struct clk_onecell_data {
unsigned int clk_num; unsigned int clk_num;
}; };
struct clk_hw_onecell_data {
size_t num;
struct clk_hw *hws[];
};
extern struct of_device_id __clk_of_table; extern struct of_device_id __clk_of_table;
#define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn) #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, struct clk *(*clk_src_get)(struct of_phandle_args *args,
void *data), void *data),
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); void of_clk_del_provider(struct device_node *np);
struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
void *data); 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 *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); unsigned int of_clk_get_parent_count(struct device_node *np);
int of_clk_parent_fill(struct device_node *np, const char **parents, int of_clk_parent_fill(struct device_node *np, const char **parents,
unsigned int size); unsigned int size);
@ -735,17 +811,34 @@ static inline int of_clk_add_provider(struct device_node *np,
{ {
return 0; 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 void of_clk_del_provider(struct device_node *np) {}
static inline struct clk *of_clk_src_simple_get( static inline struct clk *of_clk_src_simple_get(
struct of_phandle_args *clkspec, void *data) struct of_phandle_args *clkspec, void *data)
{ {
return ERR_PTR(-ENOENT); 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( static inline struct clk *of_clk_src_onecell_get(
struct of_phandle_args *clkspec, void *data) struct of_phandle_args *clkspec, void *data)
{ {
return ERR_PTR(-ENOENT); 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) static inline int of_clk_get_parent_count(struct device_node *np)
{ {
return 0; return 0;

View File

@ -15,6 +15,7 @@
#include <asm/clkdev.h> #include <asm/clkdev.h>
struct clk; struct clk;
struct clk_hw;
struct device; struct device;
struct clk_lookup { struct clk_lookup {
@ -34,18 +35,22 @@ struct clk_lookup {
struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
const char *dev_fmt, ...) __printf(3, 4); 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_add(struct clk_lookup *cl);
void clkdev_drop(struct clk_lookup *cl); void clkdev_drop(struct clk_lookup *cl);
struct clk_lookup *clkdev_create(struct clk *clk, const char *con_id, struct clk_lookup *clkdev_create(struct clk *clk, const char *con_id,
const char *dev_fmt, ...) __printf(3, 4); 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); void clkdev_add_table(struct clk_lookup *, size_t);
int clk_add_alias(const char *, const char *, const char *, struct device *); 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_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 #ifdef CONFIG_COMMON_CLK
int __clk_get(struct clk *clk); int __clk_get(struct clk *clk);