clk: fixed: add devm helper for clk_hw_register_fixed_factor()

Add a devm helper for clk_hw_register_fixed_factor() so that drivers that internally
register fixed factor clocks for things like dividers don't need to manually unregister
them on remove or if probe fails.

Signed-off-by: Daniel Palmer <daniel@0x0f.com>
Link: https://lore.kernel.org/r/20210211052206.2955988-4-daniel@0x0f.com
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
This commit is contained in:
Daniel Palmer 2021-02-11 14:22:02 +09:00 committed by Stephen Boyd
parent 4f83b5233f
commit 0b9266d295
2 changed files with 36 additions and 7 deletions

View File

@ -64,10 +64,16 @@ const struct clk_ops clk_fixed_factor_ops = {
};
EXPORT_SYMBOL_GPL(clk_fixed_factor_ops);
static void devm_clk_hw_register_fixed_factor_release(struct device *dev, void *res)
{
clk_hw_unregister_fixed_factor(&((struct clk_fixed_factor *)res)->hw);
}
static struct clk_hw *
__clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
const char *name, const char *parent_name, int index,
unsigned long flags, unsigned int mult, unsigned int div)
unsigned long flags, unsigned int mult, unsigned int div,
bool devm)
{
struct clk_fixed_factor *fix;
struct clk_init_data init = { };
@ -75,7 +81,15 @@ __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
struct clk_hw *hw;
int ret;
fix = kmalloc(sizeof(*fix), GFP_KERNEL);
/* You can't use devm without a dev */
if (devm && !dev)
return ERR_PTR(-EINVAL);
if (devm)
fix = devres_alloc(devm_clk_hw_register_fixed_factor_release,
sizeof(*fix), GFP_KERNEL);
else
fix = kmalloc(sizeof(*fix), GFP_KERNEL);
if (!fix)
return ERR_PTR(-ENOMEM);
@ -99,9 +113,13 @@ __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
else
ret = of_clk_hw_register(np, hw);
if (ret) {
kfree(fix);
if (devm)
devres_free(fix);
else
kfree(fix);
hw = ERR_PTR(ret);
}
} else if (devm)
devres_add(dev, fix);
return hw;
}
@ -111,7 +129,7 @@ struct clk_hw *clk_hw_register_fixed_factor(struct device *dev,
unsigned int mult, unsigned int div)
{
return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, -1,
flags, mult, div);
flags, mult, div, false);
}
EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor);
@ -153,6 +171,15 @@ void clk_hw_unregister_fixed_factor(struct clk_hw *hw)
}
EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_factor);
struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev,
const char *name, const char *parent_name, unsigned long flags,
unsigned int mult, unsigned int div)
{
return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, -1,
flags, mult, div, true);
}
EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor);
#ifdef CONFIG_OF
static const struct of_device_id set_rate_parent_matches[] = {
{ .compatible = "allwinner,sun4i-a10-pll3-2x-clk" },
@ -185,7 +212,7 @@ static struct clk_hw *_of_fixed_factor_clk_setup(struct device_node *node)
flags |= CLK_SET_RATE_PARENT;
hw = __clk_hw_register_fixed_factor(NULL, node, clk_name, NULL, 0,
flags, mult, div);
flags, mult, div, false);
if (IS_ERR(hw)) {
/*
* Clear OF_POPULATED flag so that clock registration can be

View File

@ -941,7 +941,9 @@ 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_hw *devm_clk_hw_register_fixed_factor(struct device *dev,
const char *name, const char *parent_name, unsigned long flags,
unsigned int mult, unsigned int div);
/**
* struct clk_fractional_divider - adjustable fractional divider clock
*