Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * KUnit test for clk fixed rate basic type
  4 */
  5#include <linux/clk.h>
  6#include <linux/clk-provider.h>
  7#include <linux/completion.h>
  8#include <linux/of.h>
  9#include <linux/platform_device.h>
 10
 11#include <kunit/clk.h>
 12#include <kunit/of.h>
 13#include <kunit/platform_device.h>
 14#include <kunit/resource.h>
 15#include <kunit/test.h>
 16
 17#include "clk-fixed-rate_test.h"
 18
 19/**
 20 * struct clk_hw_fixed_rate_kunit_params - Parameters to pass to __clk_hw_register_fixed_rate()
 21 * @dev: device registering clk
 22 * @np: device_node of device registering clk
 23 * @name: name of clk
 24 * @parent_name: parent name of clk
 25 * @parent_hw: clk_hw pointer to parent of clk
 26 * @parent_data: parent_data describing parent of clk
 27 * @flags: clk framework flags
 28 * @fixed_rate: frequency of clk
 29 * @fixed_accuracy: accuracy of clk
 30 * @clk_fixed_flags: fixed rate specific clk flags
 31 */
 32struct clk_hw_fixed_rate_kunit_params {
 33	struct device *dev;
 34	struct device_node *np;
 35	const char *name;
 36	const char *parent_name;
 37	const struct clk_hw *parent_hw;
 38	const struct clk_parent_data *parent_data;
 39	unsigned long flags;
 40	unsigned long fixed_rate;
 41	unsigned long fixed_accuracy;
 42	unsigned long clk_fixed_flags;
 43};
 44
 45static int
 46clk_hw_register_fixed_rate_kunit_init(struct kunit_resource *res, void *context)
 47{
 48	struct clk_hw_fixed_rate_kunit_params *params = context;
 49	struct clk_hw *hw;
 50
 51	hw = __clk_hw_register_fixed_rate(params->dev, params->np,
 52					  params->name,
 53					  params->parent_name,
 54					  params->parent_hw,
 55					  params->parent_data,
 56					  params->flags,
 57					  params->fixed_rate,
 58					  params->fixed_accuracy,
 59					  params->clk_fixed_flags,
 60					  false);
 61	if (IS_ERR(hw))
 62		return PTR_ERR(hw);
 63
 64	res->data = hw;
 65
 66	return 0;
 67}
 68
 69static void clk_hw_register_fixed_rate_kunit_exit(struct kunit_resource *res)
 70{
 71	struct clk_hw *hw = res->data;
 72
 73	clk_hw_unregister_fixed_rate(hw);
 74}
 75
 76/**
 77 * clk_hw_register_fixed_rate_kunit() - Test managed __clk_hw_register_fixed_rate()
 78 * @test: The test context
 79 * @params: Arguments to __clk_hw_register_fixed_rate()
 80 *
 81 * Return: Registered fixed rate clk_hw or ERR_PTR on failure
 82 */
 83static struct clk_hw *
 84clk_hw_register_fixed_rate_kunit(struct kunit *test,
 85				 struct clk_hw_fixed_rate_kunit_params *params)
 86{
 87	struct clk_hw *hw;
 88
 89	hw = kunit_alloc_resource(test,
 90				  clk_hw_register_fixed_rate_kunit_init,
 91				  clk_hw_register_fixed_rate_kunit_exit,
 92				  GFP_KERNEL, params);
 93	if (!hw)
 94		return ERR_PTR(-EINVAL);
 95
 96	return hw;
 97}
 98
 99/**
100 * clk_hw_unregister_fixed_rate_kunit() - Test managed clk_hw_unregister_fixed_rate()
101 * @test: The test context
102 * @hw: fixed rate clk to unregister upon test completion
103 *
104 * Automatically unregister @hw when @test is complete via
105 * clk_hw_unregister_fixed_rate().
106 *
107 * Return: 0 on success or negative errno on failure
108 */
109static int clk_hw_unregister_fixed_rate_kunit(struct kunit *test, struct clk_hw *hw)
110{
111	if (!kunit_alloc_resource(test, NULL,
112				  clk_hw_register_fixed_rate_kunit_exit,
113				  GFP_KERNEL, hw))
114		return -ENOMEM;
115
116	return 0;
117}
118
119/*
120 * Test that clk_get_rate() on a fixed rate clk registered with
121 * clk_hw_register_fixed_rate() gets the proper frequency.
122 */
123static void clk_fixed_rate_rate_test(struct kunit *test)
124{
125	struct clk_hw *hw;
126	struct clk *clk;
127	const unsigned long fixed_rate = 230000;
128
129	hw = clk_hw_register_fixed_rate(NULL, "test-fixed-rate", NULL, 0, fixed_rate);
130	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
131	KUNIT_ASSERT_EQ(test, 0, clk_hw_unregister_fixed_rate_kunit(test, hw));
132
133	clk = clk_hw_get_clk_prepared_enabled_kunit(test, hw, __func__);
134	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, clk);
135
136	KUNIT_EXPECT_EQ(test, fixed_rate, clk_get_rate(clk));
137}
138
139/*
140 * Test that clk_get_accuracy() on a fixed rate clk registered via
141 * clk_hw_register_fixed_rate_with_accuracy() gets the proper accuracy.
142 */
143static void clk_fixed_rate_accuracy_test(struct kunit *test)
144{
145	struct clk_hw *hw;
146	struct clk *clk;
147	const unsigned long fixed_accuracy = 5000;
148
149	hw = clk_hw_register_fixed_rate_with_accuracy(NULL, "test-fixed-rate",
150						      NULL, 0, 0,
151						      fixed_accuracy);
152	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
153	KUNIT_ASSERT_EQ(test, 0, clk_hw_unregister_fixed_rate_kunit(test, hw));
154
155	clk = clk_hw_get_clk_kunit(test, hw, __func__);
156	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, clk);
157
158	KUNIT_EXPECT_EQ(test, fixed_accuracy, clk_get_accuracy(clk));
159}
160
161/* Test suite for a fixed rate clk without any parent */
162static struct kunit_case clk_fixed_rate_test_cases[] = {
163	KUNIT_CASE(clk_fixed_rate_rate_test),
164	KUNIT_CASE(clk_fixed_rate_accuracy_test),
165	{}
166};
167
168static struct kunit_suite clk_fixed_rate_suite = {
169	.name = "clk_fixed_rate",
170	.test_cases = clk_fixed_rate_test_cases,
171};
172
173/*
174 * Test that clk_get_parent() on a fixed rate clk gets the proper parent.
175 */
176static void clk_fixed_rate_parent_test(struct kunit *test)
177{
178	struct clk_hw *hw, *parent_hw;
179	struct clk *expected_parent, *actual_parent;
180	struct clk *clk;
181	const char *parent_name = "test-fixed-rate-parent";
182	struct clk_hw_fixed_rate_kunit_params parent_params = {
183		.name = parent_name,
184	};
185
186	parent_hw = clk_hw_register_fixed_rate_kunit(test, &parent_params);
187	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent_hw);
188	KUNIT_ASSERT_STREQ(test, parent_name, clk_hw_get_name(parent_hw));
189
190	expected_parent = clk_hw_get_clk_kunit(test, parent_hw, __func__);
191	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, expected_parent);
192
193	hw = clk_hw_register_fixed_rate(NULL, "test-fixed-rate", parent_name, 0, 0);
194	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
195	KUNIT_ASSERT_EQ(test, 0, clk_hw_unregister_fixed_rate_kunit(test, hw));
196
197	clk = clk_hw_get_clk_kunit(test, hw, __func__);
198	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, clk);
199
200	actual_parent = clk_get_parent(clk);
201	KUNIT_EXPECT_TRUE(test, clk_is_match(expected_parent, actual_parent));
202}
203
204/*
205 * Test that clk_get_rate() on a fixed rate clk ignores the parent rate.
206 */
207static void clk_fixed_rate_parent_rate_test(struct kunit *test)
208{
209	struct clk_hw *hw, *parent_hw;
210	struct clk *clk;
211	const unsigned long expected_rate = 1405;
212	const unsigned long parent_rate = 90402;
213	const char *parent_name = "test-fixed-rate-parent";
214	struct clk_hw_fixed_rate_kunit_params parent_params = {
215		.name = parent_name,
216		.fixed_rate = parent_rate,
217	};
218
219	parent_hw = clk_hw_register_fixed_rate_kunit(test, &parent_params);
220	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent_hw);
221	KUNIT_ASSERT_STREQ(test, parent_name, clk_hw_get_name(parent_hw));
222
223	hw = clk_hw_register_fixed_rate(NULL, "test-fixed-rate", parent_name, 0,
224					expected_rate);
225	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
226	KUNIT_ASSERT_EQ(test, 0, clk_hw_unregister_fixed_rate_kunit(test, hw));
227
228	clk = clk_hw_get_clk_prepared_enabled_kunit(test, hw, __func__);
229	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, clk);
230
231	KUNIT_EXPECT_EQ(test, expected_rate, clk_get_rate(clk));
232}
233
234/*
235 * Test that clk_get_accuracy() on a fixed rate clk ignores the parent accuracy.
236 */
237static void clk_fixed_rate_parent_accuracy_test(struct kunit *test)
238{
239	struct clk_hw *hw, *parent_hw;
240	struct clk *clk;
241	const unsigned long expected_accuracy = 900;
242	const unsigned long parent_accuracy = 24000;
243	const char *parent_name = "test-fixed-rate-parent";
244	struct clk_hw_fixed_rate_kunit_params parent_params = {
245		.name = parent_name,
246		.fixed_accuracy = parent_accuracy,
247	};
248
249	parent_hw = clk_hw_register_fixed_rate_kunit(test, &parent_params);
250	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent_hw);
251	KUNIT_ASSERT_STREQ(test, parent_name, clk_hw_get_name(parent_hw));
252
253	hw = clk_hw_register_fixed_rate_with_accuracy(NULL, "test-fixed-rate",
254						      parent_name, 0, 0,
255						      expected_accuracy);
256	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
257	KUNIT_ASSERT_EQ(test, 0, clk_hw_unregister_fixed_rate_kunit(test, hw));
258
259	clk = clk_hw_get_clk_kunit(test, hw, __func__);
260	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, clk);
261
262	KUNIT_EXPECT_EQ(test, expected_accuracy, clk_get_accuracy(clk));
263}
264
265/* Test suite for a fixed rate clk with a parent */
266static struct kunit_case clk_fixed_rate_parent_test_cases[] = {
267	KUNIT_CASE(clk_fixed_rate_parent_test),
268	KUNIT_CASE(clk_fixed_rate_parent_rate_test),
269	KUNIT_CASE(clk_fixed_rate_parent_accuracy_test),
270	{}
271};
272
273static struct kunit_suite clk_fixed_rate_parent_suite = {
274	.name = "clk_fixed_rate_parent",
275	.test_cases = clk_fixed_rate_parent_test_cases,
276};
277
278struct clk_fixed_rate_of_test_context {
279	struct device *dev;
280	struct platform_driver pdrv;
281	struct completion probed;
282};
283
284static inline struct clk_fixed_rate_of_test_context *
285pdev_to_clk_fixed_rate_of_test_context(struct platform_device *pdev)
286{
287	return container_of(to_platform_driver(pdev->dev.driver),
288			    struct clk_fixed_rate_of_test_context,
289			    pdrv);
290}
291
292/*
293 * Test that of_fixed_clk_setup() registers a fixed rate clk with the proper
294 * rate.
295 */
296static void clk_fixed_rate_of_probe_test(struct kunit *test)
297{
298	struct clk_fixed_rate_of_test_context *ctx = test->priv;
299	struct device *dev = ctx->dev;
300	struct clk *clk;
301
302	clk = clk_get_kunit(test, dev, NULL);
303	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, clk);
304
305	KUNIT_ASSERT_EQ(test, 0, clk_prepare_enable_kunit(test, clk));
306	KUNIT_EXPECT_EQ(test, TEST_FIXED_FREQUENCY, clk_get_rate(clk));
307}
308
309/*
310 * Test that of_fixed_clk_setup() registers a fixed rate clk with the proper
311 * accuracy.
312 */
313static void clk_fixed_rate_of_accuracy_test(struct kunit *test)
314{
315	struct clk_fixed_rate_of_test_context *ctx = test->priv;
316	struct device *dev = ctx->dev;
317	struct clk *clk;
318
319	clk = clk_get_kunit(test, dev, NULL);
320	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, clk);
321
322	KUNIT_EXPECT_EQ(test, TEST_FIXED_ACCURACY, clk_get_accuracy(clk));
323}
324
325static struct kunit_case clk_fixed_rate_of_cases[] = {
326	KUNIT_CASE(clk_fixed_rate_of_probe_test),
327	KUNIT_CASE(clk_fixed_rate_of_accuracy_test),
328	{}
329};
330
331static int clk_fixed_rate_of_test_probe(struct platform_device *pdev)
332{
333	struct clk_fixed_rate_of_test_context *ctx;
334
335	ctx = pdev_to_clk_fixed_rate_of_test_context(pdev);
336	ctx->dev = &pdev->dev;
337	complete(&ctx->probed);
338
339	return 0;
340}
341
342static int clk_fixed_rate_of_init(struct kunit *test)
343{
344	struct clk_fixed_rate_of_test_context *ctx;
345	static const struct of_device_id match_table[] = {
346		{ .compatible = "test,single-clk-consumer" },
347		{ }
348	};
349
350	KUNIT_ASSERT_EQ(test, 0, of_overlay_apply_kunit(test, kunit_clk_fixed_rate_test));
351
352	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
353	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
354	test->priv = ctx;
355
356	ctx->pdrv.probe = clk_fixed_rate_of_test_probe;
357	ctx->pdrv.driver.of_match_table = match_table;
358	ctx->pdrv.driver.name = __func__;
359	ctx->pdrv.driver.owner = THIS_MODULE;
360	init_completion(&ctx->probed);
361
362	KUNIT_ASSERT_EQ(test, 0, kunit_platform_driver_register(test, &ctx->pdrv));
363	KUNIT_ASSERT_NE(test, 0, wait_for_completion_timeout(&ctx->probed, HZ));
364
365	return 0;
366}
367
368static struct kunit_suite clk_fixed_rate_of_suite = {
369	.name = "clk_fixed_rate_of",
370	.init = clk_fixed_rate_of_init,
371	.test_cases = clk_fixed_rate_of_cases,
372};
373
374kunit_test_suites(
375	&clk_fixed_rate_suite,
376	&clk_fixed_rate_of_suite,
377	&clk_fixed_rate_parent_suite,
378);
379MODULE_LICENSE("GPL");
380MODULE_DESCRIPTION("KUnit test for clk fixed rate basic type");