mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 08:38:45 +02:00 
			
		
		
		
	 a82fcb16d9
			
		
	
	
		a82fcb16d9
		
	
	
	
	
		
			
			Add a test managed version of of_clk_add_hw_provider() that automatically unregisters the clk_hw provider upon test conclusion. Cc: Brendan Higgins <brendan.higgins@linux.dev> Cc: David Gow <davidgow@google.com> Cc: Rae Moar <rmoar@google.com> Cc: Peng Fan <peng.fan@nxp.com> Signed-off-by: Stephen Boyd <sboyd@kernel.org> Link: https://lore.kernel.org/r/20240822002433.1163814-2-sboyd@kernel.org
		
			
				
	
	
		
			237 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			237 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| /*
 | |
|  * KUnit helpers for clk providers and consumers
 | |
|  */
 | |
| #include <linux/clk.h>
 | |
| #include <linux/clk-provider.h>
 | |
| #include <linux/err.h>
 | |
| #include <linux/kernel.h>
 | |
| #include <linux/slab.h>
 | |
| 
 | |
| #include <kunit/clk.h>
 | |
| #include <kunit/resource.h>
 | |
| 
 | |
| KUNIT_DEFINE_ACTION_WRAPPER(clk_disable_unprepare_wrapper,
 | |
| 			    clk_disable_unprepare, struct clk *);
 | |
| /**
 | |
|  * clk_prepare_enable_kunit() - Test managed clk_prepare_enable()
 | |
|  * @test: The test context
 | |
|  * @clk: clk to prepare and enable
 | |
|  *
 | |
|  * Return: 0 on success, or negative errno on failure.
 | |
|  */
 | |
| int clk_prepare_enable_kunit(struct kunit *test, struct clk *clk)
 | |
| {
 | |
| 	int ret;
 | |
| 
 | |
| 	ret = clk_prepare_enable(clk);
 | |
| 	if (ret)
 | |
| 		return ret;
 | |
| 
 | |
| 	return kunit_add_action_or_reset(test, clk_disable_unprepare_wrapper,
 | |
| 					 clk);
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(clk_prepare_enable_kunit);
 | |
| 
 | |
| KUNIT_DEFINE_ACTION_WRAPPER(clk_put_wrapper, clk_put, struct clk *);
 | |
| 
 | |
| static struct clk *__clk_get_kunit(struct kunit *test, struct clk *clk)
 | |
| {
 | |
| 	int ret;
 | |
| 
 | |
| 	if (IS_ERR(clk))
 | |
| 		return clk;
 | |
| 
 | |
| 	ret = kunit_add_action_or_reset(test, clk_put_wrapper, clk);
 | |
| 	if (ret)
 | |
| 		return ERR_PTR(ret);
 | |
| 
 | |
| 	return clk;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * clk_get_kunit() - Test managed clk_get()
 | |
|  * @test: The test context
 | |
|  * @dev: device for clock "consumer"
 | |
|  * @con_id: clock consumer ID
 | |
|  *
 | |
|  * Just like clk_get(), except the clk is managed by the test case and is
 | |
|  * automatically put with clk_put() after the test case concludes.
 | |
|  *
 | |
|  * Return: new clk consumer or ERR_PTR on failure.
 | |
|  */
 | |
| struct clk *
 | |
| clk_get_kunit(struct kunit *test, struct device *dev, const char *con_id)
 | |
| {
 | |
| 	struct clk *clk;
 | |
| 
 | |
| 	clk = clk_get(dev, con_id);
 | |
| 
 | |
| 	return __clk_get_kunit(test, clk);
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(clk_get_kunit);
 | |
| 
 | |
| /**
 | |
|  * of_clk_get_kunit() - Test managed of_clk_get()
 | |
|  * @test: The test context
 | |
|  * @np: device_node for clock "consumer"
 | |
|  * @index: index in 'clocks' property of @np
 | |
|  *
 | |
|  * Just like of_clk_get(), except the clk is managed by the test case and is
 | |
|  * automatically put with clk_put() after the test case concludes.
 | |
|  *
 | |
|  * Return: new clk consumer or ERR_PTR on failure.
 | |
|  */
 | |
| struct clk *
 | |
| of_clk_get_kunit(struct kunit *test, struct device_node *np, int index)
 | |
| {
 | |
| 	struct clk *clk;
 | |
| 
 | |
| 	clk = of_clk_get(np, index);
 | |
| 
 | |
| 	return __clk_get_kunit(test, clk);
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(of_clk_get_kunit);
 | |
| 
 | |
| /**
 | |
|  * clk_hw_get_clk_kunit() - Test managed clk_hw_get_clk()
 | |
|  * @test: The test context
 | |
|  * @hw: clk_hw associated with the clk being consumed
 | |
|  * @con_id: connection ID string on device
 | |
|  *
 | |
|  * Just like clk_hw_get_clk(), except the clk is managed by the test case and
 | |
|  * is automatically put with clk_put() after the test case concludes.
 | |
|  *
 | |
|  * Return: new clk consumer or ERR_PTR on failure.
 | |
|  */
 | |
| struct clk *
 | |
| clk_hw_get_clk_kunit(struct kunit *test, struct clk_hw *hw, const char *con_id)
 | |
| {
 | |
| 	struct clk *clk;
 | |
| 
 | |
| 	clk = clk_hw_get_clk(hw, con_id);
 | |
| 
 | |
| 	return __clk_get_kunit(test, clk);
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(clk_hw_get_clk_kunit);
 | |
| 
 | |
| /**
 | |
|  * clk_hw_get_clk_prepared_enabled_kunit() - Test managed clk_hw_get_clk() + clk_prepare_enable()
 | |
|  * @test: The test context
 | |
|  * @hw: clk_hw associated with the clk being consumed
 | |
|  * @con_id: connection ID string on device
 | |
|  *
 | |
|  * Just like
 | |
|  *
 | |
|  * .. code-block:: c
 | |
|  *
 | |
|  *	struct clk *clk = clk_hw_get_clk(...);
 | |
|  *	clk_prepare_enable(clk);
 | |
|  *
 | |
|  * except the clk is managed by the test case and is automatically disabled and
 | |
|  * unprepared with clk_disable_unprepare() and put with clk_put() after the
 | |
|  * test case concludes.
 | |
|  *
 | |
|  * Return: new clk consumer that is prepared and enabled or ERR_PTR on failure.
 | |
|  */
 | |
| struct clk *
 | |
| clk_hw_get_clk_prepared_enabled_kunit(struct kunit *test, struct clk_hw *hw,
 | |
| 				      const char *con_id)
 | |
| {
 | |
| 	int ret;
 | |
| 	struct clk *clk;
 | |
| 
 | |
| 	clk = clk_hw_get_clk_kunit(test, hw, con_id);
 | |
| 	if (IS_ERR(clk))
 | |
| 		return clk;
 | |
| 
 | |
| 	ret = clk_prepare_enable_kunit(test, clk);
 | |
| 	if (ret)
 | |
| 		return ERR_PTR(ret);
 | |
| 
 | |
| 	return clk;
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(clk_hw_get_clk_prepared_enabled_kunit);
 | |
| 
 | |
| KUNIT_DEFINE_ACTION_WRAPPER(clk_hw_unregister_wrapper,
 | |
| 			    clk_hw_unregister, struct clk_hw *);
 | |
| 
 | |
| /**
 | |
|  * clk_hw_register_kunit() - Test managed clk_hw_register()
 | |
|  * @test: The test context
 | |
|  * @dev: device that is registering this clock
 | |
|  * @hw: link to hardware-specific clock data
 | |
|  *
 | |
|  * Just like clk_hw_register(), except the clk registration is managed by the
 | |
|  * test case and is automatically unregistered after the test case concludes.
 | |
|  *
 | |
|  * Return: 0 on success or a negative errno value on failure.
 | |
|  */
 | |
| int clk_hw_register_kunit(struct kunit *test, struct device *dev, struct clk_hw *hw)
 | |
| {
 | |
| 	int ret;
 | |
| 
 | |
| 	ret = clk_hw_register(dev, hw);
 | |
| 	if (ret)
 | |
| 		return ret;
 | |
| 
 | |
| 	return kunit_add_action_or_reset(test, clk_hw_unregister_wrapper, hw);
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(clk_hw_register_kunit);
 | |
| 
 | |
| /**
 | |
|  * of_clk_hw_register_kunit() - Test managed of_clk_hw_register()
 | |
|  * @test: The test context
 | |
|  * @node: device_node of device that is registering this clock
 | |
|  * @hw: link to hardware-specific clock data
 | |
|  *
 | |
|  * Just like of_clk_hw_register(), except the clk registration is managed by
 | |
|  * the test case and is automatically unregistered after the test case
 | |
|  * concludes.
 | |
|  *
 | |
|  * Return: 0 on success or a negative errno value on failure.
 | |
|  */
 | |
| int of_clk_hw_register_kunit(struct kunit *test, struct device_node *node, struct clk_hw *hw)
 | |
| {
 | |
| 	int ret;
 | |
| 
 | |
| 	ret = of_clk_hw_register(node, hw);
 | |
| 	if (ret)
 | |
| 		return ret;
 | |
| 
 | |
| 	return kunit_add_action_or_reset(test, clk_hw_unregister_wrapper, hw);
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(of_clk_hw_register_kunit);
 | |
| 
 | |
| KUNIT_DEFINE_ACTION_WRAPPER(of_clk_del_provider_wrapper,
 | |
| 			    of_clk_del_provider, struct device_node *);
 | |
| 
 | |
| /**
 | |
|  * of_clk_add_hw_provider_kunit() - Test managed of_clk_add_hw_provider()
 | |
|  * @test: The test context
 | |
|  * @np: Device node pointer associated with clock provider
 | |
|  * @get: Callback for decoding clk_hw
 | |
|  * @data: Context pointer for @get callback.
 | |
|  *
 | |
|  * Just like of_clk_add_hw_provider(), except the clk_hw provider is managed by
 | |
|  * the test case and is automatically unregistered after the test case
 | |
|  * concludes.
 | |
|  *
 | |
|  * Return: 0 on success or a negative errno value on failure.
 | |
|  */
 | |
| int of_clk_add_hw_provider_kunit(struct kunit *test, struct device_node *np,
 | |
| 				 struct clk_hw *(*get)(struct of_phandle_args *clkspec, void *data),
 | |
| 				 void *data)
 | |
| {
 | |
| 	int ret;
 | |
| 
 | |
| 	ret = of_clk_add_hw_provider(np, get, data);
 | |
| 	if (ret)
 | |
| 		return ret;
 | |
| 
 | |
| 	return kunit_add_action_or_reset(test, of_clk_del_provider_wrapper, np);
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(of_clk_add_hw_provider_kunit);
 | |
| 
 | |
| MODULE_LICENSE("GPL");
 | |
| MODULE_DESCRIPTION("KUnit helpers for clk providers and consumers");
 |