public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Frank Oltmanns <frank@oltmanns.dev>
To: Michael Turquette <mturquette@baylibre.com>,
	Stephen Boyd <sboyd@kernel.org>
Cc: Frank Oltmanns <frank@oltmanns.dev>,
	"A.s. Dong" <aisheng.dong@nxp.com>,
	Abel Vesa <abelvesa@kernel.org>,
	Fabio Estevam <festevam@gmail.com>,
	linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org,
	linux-kernel@vger.kernel.org, NXP Linux Team <linux-imx@nxp.com>,
	Peng Fan <peng.fan@nxp.com>,
	Pengutronix Kernel Team <kernel@pengutronix.de>,
	Sascha Hauer <s.hauer@pengutronix.de>,
	Shawn Guo <shawnguo@kernel.org>,
	Elaine Zhang <zhangqing@rock-chips.com>
Subject: [PATCH v5 2/2] clk: fractional-divider: tests: Add test suite for edge cases
Date: Sat, 17 Jun 2023 15:10:41 +0200	[thread overview]
Message-ID: <20230617131041.18313-3-frank@oltmanns.dev> (raw)
In-Reply-To: <20230617131041.18313-1-frank@oltmanns.dev>

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]
---
Please note: I get two checkpatch warnings for this patch:
 - Concerning the help text in Kconfig.
 - Regarding the file being added, asking if MAINTAINERS needs updating.

Both the help text as well as the MAINTAINERS file seem fine to me.

As expected, when the tests are run *without* PATCH 1, the two "zero
based" test cases fail:

================= clk-fd-test (4 subtests) =================
[PASSED] clk_fd_test_approximation_max_denominator
[PASSED] clk_fd_test_approximation_max_numerator
# clk_fd_test_approximation_max_denominator_zero_based: EXPECTATION FAILED at drivers/clk/clk-fractional-divider_test.c:104
Expected n == max_n, but
    n == 7 (0x7)
    max_n == 8 (0x8)
[FAILED] clk_fd_test_approximation_max_denominator_zero_based
# clk_fd_test_approximation_max_numerator_zero_based: EXPECTATION FAILED at drivers/clk/clk-fractional-divider_test.c:134
Expected m == max_m, but
    m == 7 (0x7)
    max_m == 8 (0x8)
[FAILED] clk_fd_test_approximation_max_numerator_zero_based
# clk-fd-test: pass:2 fail:2 skip:0 total:4
# Totals: pass:2 fail:2 skip:0 total:4
=================== [FAILED] clk-fd-test ===================

Best regards,
  Frank

 drivers/clk/.kunitconfig                  |   1 +
 drivers/clk/Kconfig                       |   7 +
 drivers/clk/Makefile                      |   1 +
 drivers/clk/clk-fractional-divider_test.c | 157 ++++++++++++++++++++++
 4 files changed, 166 insertions(+)
 create mode 100644 drivers/clk/clk-fractional-divider_test.c

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 016814e15536..3fbb40cb5551 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -513,4 +513,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 0aebef17edc6..9d2337c12dd1 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..7b8105496cbb
--- /dev/null
+++ b/drivers/clk/clk-fractional-divider_test.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Kunit test for clock fractional divider
+ */
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+/* Needed for clk_hw_get_clk() */
+#include "clk.h"
+
+/* Needed for clk_fractional_divider_general_approximation */
+#include "clk-fractional-divider.h"
+
+#include <kunit/test.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;
+	struct clk_hw *hw;
+	unsigned long rate, parent_rate, 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;
+
+	hw = &fd->hw;
+
+	rate = 240000000;
+	parent_rate = (max_n + 1) * rate; /* so that it exceeds the maximum divisor */
+
+	clk_fractional_divider_general_approximation(hw, rate, &parent_rate, &m, &n);
+	KUNIT_EXPECT_EQ(test, parent_rate, (max_n + 1) * rate); /* parent remains unchanged */
+	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;
+	struct clk_hw *hw;
+	unsigned long rate, parent_rate, 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;
+
+	hw = &fd->hw;
+
+	rate = 240000000;
+	parent_rate = rate / (max_m + 1); /* so that it exceeds the maximum numerator */
+
+	clk_fractional_divider_general_approximation(hw, rate, &parent_rate, &m, &n);
+	KUNIT_EXPECT_EQ(test, parent_rate, rate / (max_m + 1)); /* parent remains unchanged */
+	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;
+	struct clk_hw *hw;
+	unsigned long rate, parent_rate, 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;
+
+	hw = &fd->hw;
+
+	rate = 240000000;
+	parent_rate = (max_n + 1) * rate; /* so that it exceeds the maximum divisor */
+
+	clk_fractional_divider_general_approximation(hw, rate, &parent_rate, &m, &n);
+	KUNIT_EXPECT_EQ(test, parent_rate, (max_n + 1) * rate); /* parent remains unchanged */
+	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;
+	struct clk_hw *hw;
+	unsigned long rate, parent_rate, 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;
+
+	hw = &fd->hw;
+
+	rate = 240000000;
+	parent_rate = rate / (max_m + 1); /* so that it exceeds the maximum numerator */
+
+	clk_fractional_divider_general_approximation(hw, rate, &parent_rate, &m, &n);
+	KUNIT_EXPECT_EQ(test, parent_rate, rate / (max_m + 1)); /* parent remains unchanged */
+	KUNIT_EXPECT_EQ(test, m, max_m);
+	KUNIT_EXPECT_EQ(test, n, 1);
+}
+
+static struct kunit_case clk_fd_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 a fractional divider clock.
+ */
+static struct kunit_suite clk_fd_test_suite = {
+	.name = "clk-fd-test",
+	.test_cases = clk_fd_test_cases,
+};
+
+kunit_test_suites(
+	&clk_fd_test_suite
+);
+MODULE_LICENSE("GPL");
-- 
2.41.0


  parent reply	other threads:[~2023-06-17 13:11 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-17 13:10 [PATCH v5 0/2] clk: fractional-divider: Improve approximation when zero based and export Frank Oltmanns
2023-06-17 13:10 ` [PATCH v5 1/2] " Frank Oltmanns
2023-06-17 13:10 ` Frank Oltmanns [this message]
2023-07-17  8:24 ` [PATCH v5 0/2] " Frank Oltmanns

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230617131041.18313-3-frank@oltmanns.dev \
    --to=frank@oltmanns.dev \
    --cc=abelvesa@kernel.org \
    --cc=aisheng.dong@nxp.com \
    --cc=festevam@gmail.com \
    --cc=kernel@pengutronix.de \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-imx@nxp.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mturquette@baylibre.com \
    --cc=peng.fan@nxp.com \
    --cc=s.hauer@pengutronix.de \
    --cc=sboyd@kernel.org \
    --cc=shawnguo@kernel.org \
    --cc=zhangqing@rock-chips.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox