mmc: sdhci-of-aspeed: Add KUnit tests for phase calculations
authorAndrew Jeffery <andrew@aj.id.au>
Thu, 14 Jan 2021 03:14:31 +0000 (13:44 +1030)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 1 Feb 2021 10:54:47 +0000 (11:54 +0100)
Converting degrees of phase to logic delays is irritating to test on
hardware, so lets exercise the function using KUnit.

Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Link: https://lore.kernel.org/r/20210114031433.2388532-5-andrew@aj.id.au
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/Kconfig
drivers/mmc/host/sdhci-of-aspeed-test.c [new file with mode: 0644]
drivers/mmc/host/sdhci-of-aspeed.c

index 596f326..d6f00d1 100644 (file)
@@ -168,6 +168,20 @@ config MMC_SDHCI_OF_ASPEED
 
          If unsure, say N.
 
+config MMC_SDHCI_OF_ASPEED_TEST
+       bool "Tests for the ASPEED SDHCI driver"
+       depends on MMC_SDHCI_OF_ASPEED && KUNIT=y
+       help
+         Enable KUnit tests for the ASPEED SDHCI driver. Select this
+         option only if you will boot the kernel for the purpose of running
+         unit tests (e.g. under UML or qemu).
+
+         The KUnit tests generally exercise parts of the driver that do not
+         directly touch the hardware, for example, the phase correction
+         calculations.
+
+         If unsure, say N.
+
 config MMC_SDHCI_OF_AT91
        tristate "SDHCI OF support for the Atmel SDMMC controller"
        depends on MMC_SDHCI_PLTFM
diff --git a/drivers/mmc/host/sdhci-of-aspeed-test.c b/drivers/mmc/host/sdhci-of-aspeed-test.c
new file mode 100644 (file)
index 0000000..3407060
--- /dev/null
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (C) 2020 IBM Corp. */
+
+#include <kunit/test.h>
+
+static void aspeed_sdhci_phase_ddr52(struct kunit *test)
+{
+       int rate = 52000000;
+
+       KUNIT_EXPECT_EQ(test, 0,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 0));
+       KUNIT_EXPECT_EQ(test, 0,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 1));
+       KUNIT_EXPECT_EQ(test, 1,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 2));
+       KUNIT_EXPECT_EQ(test, 1,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 3));
+       KUNIT_EXPECT_EQ(test, 2,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 4));
+       KUNIT_EXPECT_EQ(test, 3,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 5));
+       KUNIT_EXPECT_EQ(test, 14,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 23));
+       KUNIT_EXPECT_EQ(test, 15,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 24));
+       KUNIT_EXPECT_EQ(test, 15,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 25));
+
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 0,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 180));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 0,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 181));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 1,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 182));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 1,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 183));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 2,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 184));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 3,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 185));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 14,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 203));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 204));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 205));
+}
+
+static void aspeed_sdhci_phase_hs200(struct kunit *test)
+{
+       int rate = 200000000;
+
+       KUNIT_EXPECT_EQ(test, 0,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 0));
+       KUNIT_EXPECT_EQ(test, 0,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 5));
+       KUNIT_EXPECT_EQ(test, 1,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 6));
+       KUNIT_EXPECT_EQ(test, 1,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 7));
+       KUNIT_EXPECT_EQ(test, 14,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 89));
+       KUNIT_EXPECT_EQ(test, 15,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 90));
+       KUNIT_EXPECT_EQ(test, 15,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 91));
+       KUNIT_EXPECT_EQ(test, 15,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 96));
+
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 180));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 185));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 1,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 186));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 1,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 187));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 14,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 269));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 270));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 271));
+       KUNIT_EXPECT_EQ(test, (int)ASPEED_SDHCI_TAP_PARAM_INVERT_CLK | 15,
+                       aspeed_sdhci_phase_to_tap(NULL, rate, 276));
+}
+
+static struct kunit_case aspeed_sdhci_test_cases[] = {
+       KUNIT_CASE(aspeed_sdhci_phase_ddr52),
+       KUNIT_CASE(aspeed_sdhci_phase_hs200),
+       {}
+};
+
+static struct kunit_suite aspeed_sdhci_test_suite = {
+       .name = "sdhci-of-aspeed",
+       .test_cases = aspeed_sdhci_test_cases,
+};
+kunit_test_suite(aspeed_sdhci_test_suite);
index 4b30f6a..3b0d381 100644 (file)
@@ -579,6 +579,10 @@ static void __exit aspeed_sdc_exit(void)
 }
 module_exit(aspeed_sdc_exit);
 
+#if defined(CONFIG_MMC_SDHCI_OF_ASPEED_TEST)
+#include "sdhci-of-aspeed-test.c"
+#endif
+
 MODULE_DESCRIPTION("Driver for the ASPEED SD/SDIO/SDHCI Controllers");
 MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
 MODULE_AUTHOR("Andrew Jeffery <andrew@aj.id.au>");