diff --git a/drivers/clk/.kunitconfig b/drivers/clk/.kunitconfig index 2fbeb71316f8..efa12ac2b3f2 100644 --- a/drivers/clk/.kunitconfig +++ b/drivers/clk/.kunitconfig @@ -2,4 +2,5 @@ CONFIG_KUNIT=y CONFIG_COMMON_CLK=y CONFIG_CLK_KUNIT_TEST=y CONFIG_CLK_GATE_KUNIT_TEST=y +CONFIG_CLK_FD_KUNIT_TEST=y CONFIG_UML_PCI_OVER_VIRTIO=n diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index c30099866174..5ac8f0692d75 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -517,4 +517,11 @@ config CLK_GATE_KUNIT_TEST help Kunit test for the basic clk gate type. +config CLK_FD_KUNIT_TEST + tristate "Basic fractional divider type Kunit test" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + help + Kunit test for the clk-fractional-divider type. + endif diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 18969cbd4bb1..fde9ceb53ce4 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-multiplier.o obj-$(CONFIG_COMMON_CLK) += clk-mux.o obj-$(CONFIG_COMMON_CLK) += clk-composite.o obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o +obj-$(CONFIG_CLK_FD_KUNIT_TEST) += clk-fractional-divider_test.o obj-$(CONFIG_COMMON_CLK) += clk-gpio.o ifeq ($(CONFIG_OF), y) obj-$(CONFIG_COMMON_CLK) += clk-conf.o diff --git a/drivers/clk/clk-fractional-divider_test.c b/drivers/clk/clk-fractional-divider_test.c new file mode 100644 index 000000000000..929eec927548 --- /dev/null +++ b/drivers/clk/clk-fractional-divider_test.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Kunit test for clock fractional divider + */ +#include +#include + +#include "clk-fractional-divider.h" + +/* + * Test the maximum denominator case for fd clock without flags. + * + * Expect the highest possible denominator to be used in order to get as close as possible to the + * requested rate. + */ +static void clk_fd_test_approximation_max_denominator(struct kunit *test) +{ + struct clk_fractional_divider *fd; + unsigned long rate, parent_rate, parent_rate_before, m, n, max_n; + + fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fd); + + fd->mwidth = 3; + fd->nwidth = 3; + max_n = 7; + + rate = 240000000; + parent_rate = (max_n + 1) * rate; /* so that it exceeds the maximum divisor */ + parent_rate_before = parent_rate; + + clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n); + KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before); + + KUNIT_EXPECT_EQ(test, m, 1); + KUNIT_EXPECT_EQ(test, n, max_n); +} + +/* + * Test the maximum numerator case for fd clock without flags. + * + * Expect the highest possible numerator to be used in order to get as close as possible to the + * requested rate. + */ +static void clk_fd_test_approximation_max_numerator(struct kunit *test) +{ + struct clk_fractional_divider *fd; + unsigned long rate, parent_rate, parent_rate_before, m, n, max_m; + + fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fd); + + fd->mwidth = 3; + max_m = 7; + fd->nwidth = 3; + + rate = 240000000; + parent_rate = rate / (max_m + 1); /* so that it exceeds the maximum numerator */ + parent_rate_before = parent_rate; + + clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n); + KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before); + + KUNIT_EXPECT_EQ(test, m, max_m); + KUNIT_EXPECT_EQ(test, n, 1); +} + +/* + * Test the maximum denominator case for zero based fd clock. + * + * Expect the highest possible denominator to be used in order to get as close as possible to the + * requested rate. + */ +static void clk_fd_test_approximation_max_denominator_zero_based(struct kunit *test) +{ + struct clk_fractional_divider *fd; + unsigned long rate, parent_rate, parent_rate_before, m, n, max_n; + + fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fd); + + fd->flags = CLK_FRAC_DIVIDER_ZERO_BASED; + fd->mwidth = 3; + fd->nwidth = 3; + max_n = 8; + + rate = 240000000; + parent_rate = (max_n + 1) * rate; /* so that it exceeds the maximum divisor */ + parent_rate_before = parent_rate; + + clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n); + KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before); + + KUNIT_EXPECT_EQ(test, m, 1); + KUNIT_EXPECT_EQ(test, n, max_n); +} + +/* + * Test the maximum numerator case for zero based fd clock. + * + * Expect the highest possible numerator to be used in order to get as close as possible to the + * requested rate. + */ +static void clk_fd_test_approximation_max_numerator_zero_based(struct kunit *test) +{ + struct clk_fractional_divider *fd; + unsigned long rate, parent_rate, parent_rate_before, m, n, max_m; + + fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fd); + + fd->flags = CLK_FRAC_DIVIDER_ZERO_BASED; + fd->mwidth = 3; + max_m = 8; + fd->nwidth = 3; + + rate = 240000000; + parent_rate = rate / (max_m + 1); /* so that it exceeds the maximum numerator */ + parent_rate_before = parent_rate; + + clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n); + KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before); + + KUNIT_EXPECT_EQ(test, m, max_m); + KUNIT_EXPECT_EQ(test, n, 1); +} + +static struct kunit_case clk_fd_approximation_test_cases[] = { + KUNIT_CASE(clk_fd_test_approximation_max_denominator), + KUNIT_CASE(clk_fd_test_approximation_max_numerator), + KUNIT_CASE(clk_fd_test_approximation_max_denominator_zero_based), + KUNIT_CASE(clk_fd_test_approximation_max_numerator_zero_based), + {} +}; + +/* + * Test suite for clk_fractional_divider_general_approximation(). + */ +static struct kunit_suite clk_fd_approximation_suite = { + .name = "clk-fd-approximation", + .test_cases = clk_fd_approximation_test_cases, +}; + +kunit_test_suites( + &clk_fd_approximation_suite +); +MODULE_LICENSE("GPL");