Skip to content

Commit 2790e2a

Browse files
Frank Oltmannsbebarino
authored andcommitted
clk: fractional-divider: tests: Add test suite for edge cases
In light of the recent discovery that the fractional divisor approximation does not utilize the full available range for clocks that are flagged CLK_FRAC_DIVIDER_ZERO_BASED [1], implement tests for the edge cases of this clock type. Signed-off-by: Frank Oltmanns <frank@oltmanns.dev> Link: https://lore.kernel.org/lkml/20230529133433.56215-1-frank@oltmanns.dev [1] Link: https://lore.kernel.org/r/20230617131041.18313-3-frank@oltmanns.dev [sboyd@kernel.org: Rename suite and tests slightly, drop unused includes, store parent rate to compare instead of repeating equation] Signed-off-by: Stephen Boyd <sboyd@kernel.org>
1 parent 2e9abc6 commit 2790e2a

File tree

4 files changed

+156
-0
lines changed

4 files changed

+156
-0
lines changed

drivers/clk/.kunitconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ CONFIG_KUNIT=y
22
CONFIG_COMMON_CLK=y
33
CONFIG_CLK_KUNIT_TEST=y
44
CONFIG_CLK_GATE_KUNIT_TEST=y
5+
CONFIG_CLK_FD_KUNIT_TEST=y
56
CONFIG_UML_PCI_OVER_VIRTIO=n

drivers/clk/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,4 +517,11 @@ config CLK_GATE_KUNIT_TEST
517517
help
518518
Kunit test for the basic clk gate type.
519519

520+
config CLK_FD_KUNIT_TEST
521+
tristate "Basic fractional divider type Kunit test" if !KUNIT_ALL_TESTS
522+
depends on KUNIT
523+
default KUNIT_ALL_TESTS
524+
help
525+
Kunit test for the clk-fractional-divider type.
526+
520527
endif

drivers/clk/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-multiplier.o
1212
obj-$(CONFIG_COMMON_CLK) += clk-mux.o
1313
obj-$(CONFIG_COMMON_CLK) += clk-composite.o
1414
obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o
15+
obj-$(CONFIG_CLK_FD_KUNIT_TEST) += clk-fractional-divider_test.o
1516
obj-$(CONFIG_COMMON_CLK) += clk-gpio.o
1617
ifeq ($(CONFIG_OF), y)
1718
obj-$(CONFIG_COMMON_CLK) += clk-conf.o
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Kunit test for clock fractional divider
4+
*/
5+
#include <linux/clk-provider.h>
6+
#include <kunit/test.h>
7+
8+
#include "clk-fractional-divider.h"
9+
10+
/*
11+
* Test the maximum denominator case for fd clock without flags.
12+
*
13+
* Expect the highest possible denominator to be used in order to get as close as possible to the
14+
* requested rate.
15+
*/
16+
static void clk_fd_test_approximation_max_denominator(struct kunit *test)
17+
{
18+
struct clk_fractional_divider *fd;
19+
unsigned long rate, parent_rate, parent_rate_before, m, n, max_n;
20+
21+
fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL);
22+
KUNIT_ASSERT_NOT_NULL(test, fd);
23+
24+
fd->mwidth = 3;
25+
fd->nwidth = 3;
26+
max_n = 7;
27+
28+
rate = 240000000;
29+
parent_rate = (max_n + 1) * rate; /* so that it exceeds the maximum divisor */
30+
parent_rate_before = parent_rate;
31+
32+
clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n);
33+
KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before);
34+
35+
KUNIT_EXPECT_EQ(test, m, 1);
36+
KUNIT_EXPECT_EQ(test, n, max_n);
37+
}
38+
39+
/*
40+
* Test the maximum numerator case for fd clock without flags.
41+
*
42+
* Expect the highest possible numerator to be used in order to get as close as possible to the
43+
* requested rate.
44+
*/
45+
static void clk_fd_test_approximation_max_numerator(struct kunit *test)
46+
{
47+
struct clk_fractional_divider *fd;
48+
unsigned long rate, parent_rate, parent_rate_before, m, n, max_m;
49+
50+
fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL);
51+
KUNIT_ASSERT_NOT_NULL(test, fd);
52+
53+
fd->mwidth = 3;
54+
max_m = 7;
55+
fd->nwidth = 3;
56+
57+
rate = 240000000;
58+
parent_rate = rate / (max_m + 1); /* so that it exceeds the maximum numerator */
59+
parent_rate_before = parent_rate;
60+
61+
clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n);
62+
KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before);
63+
64+
KUNIT_EXPECT_EQ(test, m, max_m);
65+
KUNIT_EXPECT_EQ(test, n, 1);
66+
}
67+
68+
/*
69+
* Test the maximum denominator case for zero based fd clock.
70+
*
71+
* Expect the highest possible denominator to be used in order to get as close as possible to the
72+
* requested rate.
73+
*/
74+
static void clk_fd_test_approximation_max_denominator_zero_based(struct kunit *test)
75+
{
76+
struct clk_fractional_divider *fd;
77+
unsigned long rate, parent_rate, parent_rate_before, m, n, max_n;
78+
79+
fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL);
80+
KUNIT_ASSERT_NOT_NULL(test, fd);
81+
82+
fd->flags = CLK_FRAC_DIVIDER_ZERO_BASED;
83+
fd->mwidth = 3;
84+
fd->nwidth = 3;
85+
max_n = 8;
86+
87+
rate = 240000000;
88+
parent_rate = (max_n + 1) * rate; /* so that it exceeds the maximum divisor */
89+
parent_rate_before = parent_rate;
90+
91+
clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n);
92+
KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before);
93+
94+
KUNIT_EXPECT_EQ(test, m, 1);
95+
KUNIT_EXPECT_EQ(test, n, max_n);
96+
}
97+
98+
/*
99+
* Test the maximum numerator case for zero based fd clock.
100+
*
101+
* Expect the highest possible numerator to be used in order to get as close as possible to the
102+
* requested rate.
103+
*/
104+
static void clk_fd_test_approximation_max_numerator_zero_based(struct kunit *test)
105+
{
106+
struct clk_fractional_divider *fd;
107+
unsigned long rate, parent_rate, parent_rate_before, m, n, max_m;
108+
109+
fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL);
110+
KUNIT_ASSERT_NOT_NULL(test, fd);
111+
112+
fd->flags = CLK_FRAC_DIVIDER_ZERO_BASED;
113+
fd->mwidth = 3;
114+
max_m = 8;
115+
fd->nwidth = 3;
116+
117+
rate = 240000000;
118+
parent_rate = rate / (max_m + 1); /* so that it exceeds the maximum numerator */
119+
parent_rate_before = parent_rate;
120+
121+
clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n);
122+
KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before);
123+
124+
KUNIT_EXPECT_EQ(test, m, max_m);
125+
KUNIT_EXPECT_EQ(test, n, 1);
126+
}
127+
128+
static struct kunit_case clk_fd_approximation_test_cases[] = {
129+
KUNIT_CASE(clk_fd_test_approximation_max_denominator),
130+
KUNIT_CASE(clk_fd_test_approximation_max_numerator),
131+
KUNIT_CASE(clk_fd_test_approximation_max_denominator_zero_based),
132+
KUNIT_CASE(clk_fd_test_approximation_max_numerator_zero_based),
133+
{}
134+
};
135+
136+
/*
137+
* Test suite for clk_fractional_divider_general_approximation().
138+
*/
139+
static struct kunit_suite clk_fd_approximation_suite = {
140+
.name = "clk-fd-approximation",
141+
.test_cases = clk_fd_approximation_test_cases,
142+
};
143+
144+
kunit_test_suites(
145+
&clk_fd_approximation_suite
146+
);
147+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)