| // 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"); |