diff --git a/Documentation/dev-tools/kunit/api/clk.rst b/Documentation/dev-tools/kunit/api/clk.rst new file mode 100644 index 0000000000000000000000000000000000000000..eeaa500894536fdc3cfc0660dc1eaec7118f7561 --- /dev/null +++ b/Documentation/dev-tools/kunit/api/clk.rst @@ -0,0 +1,10 @@ +.. SPDX-License-Identifier: GPL-2.0 + +======== +Clk API +======== + +The KUnit clk API is used to test clk providers and clk consumers. + +.. kernel-doc:: drivers/clk/clk_kunit_helpers.c + :export: diff --git a/Documentation/dev-tools/kunit/api/index.rst b/Documentation/dev-tools/kunit/api/index.rst index 02b26f5e8750801338ee2458b35be30cff70b7f9..5cdb552a0808f25baeff5e47a9227b7b62c69e40 100644 --- a/Documentation/dev-tools/kunit/api/index.rst +++ b/Documentation/dev-tools/kunit/api/index.rst @@ -9,6 +9,7 @@ API Reference test resource functionredirection + clk of platformdevice @@ -34,6 +35,10 @@ Documentation/dev-tools/kunit/api/functionredirection.rst Driver KUnit API ================ +Documentation/dev-tools/kunit/api/clk.rst + + - Documents the KUnit clk API + Documentation/dev-tools/kunit/api/of.rst - Documents the KUnit device tree (OF) API diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index f793a16cad40bfff0d06989179e5401d7f3e69cc..b0675c2ab471ce9cf5b8d760647447e7662d462d 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -18,6 +18,11 @@ ifeq ($(CONFIG_OF), y) obj-$(CONFIG_COMMON_CLK) += clk-conf.o endif +# KUnit specific helpers +ifeq ($(CONFIG_COMMON_CLK), y) +obj-$(CONFIG_KUNIT) += clk_kunit_helpers.o +endif + # hardware specific clock types # please keep this section sorted lexicographically by file path name obj-$(CONFIG_COMMON_CLK_APPLE_NCO) += clk-apple-nco.o diff --git a/drivers/clk/clk_kunit_helpers.c b/drivers/clk/clk_kunit_helpers.c new file mode 100644 index 0000000000000000000000000000000000000000..52fd25594c9607dd595fac8a6639d7cc88dccf8d --- /dev/null +++ b/drivers/clk/clk_kunit_helpers.c @@ -0,0 +1,207 @@ +// 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); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("KUnit helpers for clk providers and consumers"); diff --git a/include/kunit/clk.h b/include/kunit/clk.h new file mode 100644 index 0000000000000000000000000000000000000000..73bc99cefe7b534c1dff85b0c2b2d51673a3c524 --- /dev/null +++ b/include/kunit/clk.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _CLK_KUNIT_H +#define _CLK_KUNIT_H + +struct clk; +struct clk_hw; +struct device; +struct device_node; +struct kunit; + +struct clk * +clk_get_kunit(struct kunit *test, struct device *dev, const char *con_id); +struct clk * +of_clk_get_kunit(struct kunit *test, struct device_node *np, int index); + +struct clk * +clk_hw_get_clk_kunit(struct kunit *test, struct clk_hw *hw, const char *con_id); +struct clk * +clk_hw_get_clk_prepared_enabled_kunit(struct kunit *test, struct clk_hw *hw, + const char *con_id); + +int clk_prepare_enable_kunit(struct kunit *test, struct clk *clk); + +int clk_hw_register_kunit(struct kunit *test, struct device *dev, struct clk_hw *hw); +int of_clk_hw_register_kunit(struct kunit *test, struct device_node *node, + struct clk_hw *hw); + +#endif