forked from mirrors/linux
		
	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:
		
							parent
							
								
									4f83b5233f
								
							
						
					
					
						commit
						0b9266d295
					
				
					 2 changed files with 36 additions and 7 deletions
				
			
		|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
|  * | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Daniel Palmer
						Daniel Palmer