xref: /linux/drivers/pinctrl/qcom/tlmm-test.c (revision cf9610f9116d55c5a66ef9f1faecacabd93a9322)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
4  */
5 
6 #define pr_fmt(fmt) "tlmm-test: " fmt
7 
8 #include <kunit/test.h>
9 #include <linux/delay.h>
10 #include <linux/gpio/consumer.h>
11 #include <linux/interrupt.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/of.h>
15 #include <linux/of_address.h>
16 #include <linux/of_irq.h>
17 #include <linux/pinctrl/consumer.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
20 
21 /*
22  * This TLMM test module serves the purpose of validating that the TLMM driver
23  * (pinctrl-msm) delivers expected number of interrupts in response to changing
24  * GPIO state.
25  *
26  * To achieve this without external equipment the test takes a module parameter
27  * "gpio", which the tester is expected to specify an unused and non-connected
28  * pin. The GPIO state is then driven by adjusting the bias of the pin, at
29  * suitable times through the different test cases.
30  *
31  * Upon execution, the test initialization will find the TLMM node (subject to
32  * tlmm_of_match[] allow listing) and create the necessary references
33  * dynamically, rather then relying on e.g. Devicetree and phandles.
34  */
35 
36 #define MSM_PULL_MASK		GENMASK(1, 0)
37 #define MSM_PULL_DOWN		1
38 #define MSM_PULL_UP		3
39 #define TLMM_REG_SIZE		0x1000
40 
41 static int tlmm_test_gpio = -1;
42 static char *tlmm_reg_name = "default_region";
43 
44 module_param_named(gpio, tlmm_test_gpio, int, 0600);
45 module_param_named(name, tlmm_reg_name, charp, 0600);
46 
47 static struct {
48 	void __iomem *base;
49 	void __iomem *reg;
50 	int irq;
51 
52 	u32 low_val;
53 	u32 high_val;
54 } tlmm_suite;
55 
56 /**
57  * struct tlmm_test_priv - Per-test context
58  * @intr_count:		number of times hard handler was hit with TLMM_TEST_COUNT op set
59  * @thread_count:	number of times thread handler was hit with TLMM_TEST_COUNT op set
60  * @intr_op:		operations to be performed by the hard IRQ handler
61  * @intr_op_remain:	number of times the TLMM_TEST_THEN_* operations should be
62  *			performed by the hard IRQ handler
63  * @thread_op:		operations to be performed by the threaded IRQ handler
64  * @thread_op_remain:	number of times the TLMM_TEST_THEN_* operations should
65  *			be performed by the threaded IRQ handler
66  */
67 struct tlmm_test_priv {
68 	atomic_t intr_count;
69 	atomic_t thread_count;
70 
71 	unsigned int intr_op;
72 	atomic_t intr_op_remain;
73 
74 	unsigned int thread_op;
75 	atomic_t thread_op_remain;
76 };
77 
78 /* Operation masks for @intr_op and @thread_op */
79 #define TLMM_TEST_COUNT		BIT(0)
80 #define TLMM_TEST_OUTPUT_LOW	BIT(1)
81 #define TLMM_TEST_OUTPUT_HIGH	BIT(2)
82 #define TLMM_TEST_THEN_HIGH	BIT(3)
83 #define TLMM_TEST_THEN_LOW	BIT(4)
84 #define TLMM_TEST_WAKE_THREAD	BIT(5)
85 
tlmm_output_low(void)86 static void tlmm_output_low(void)
87 {
88 	writel(tlmm_suite.low_val, tlmm_suite.reg);
89 	readl(tlmm_suite.reg);
90 }
91 
tlmm_output_high(void)92 static void tlmm_output_high(void)
93 {
94 	writel(tlmm_suite.high_val, tlmm_suite.reg);
95 	readl(tlmm_suite.reg);
96 }
97 
tlmm_test_intr_fn(int irq,void * dev_id)98 static irqreturn_t tlmm_test_intr_fn(int irq, void *dev_id)
99 {
100 	struct tlmm_test_priv *priv = dev_id;
101 
102 	if (priv->intr_op & TLMM_TEST_COUNT)
103 		atomic_inc(&priv->intr_count);
104 
105 	if (priv->intr_op & TLMM_TEST_OUTPUT_LOW)
106 		tlmm_output_low();
107 	if (priv->intr_op & TLMM_TEST_OUTPUT_HIGH)
108 		tlmm_output_high();
109 
110 	if (atomic_dec_if_positive(&priv->intr_op_remain) > 0) {
111 		udelay(1);
112 
113 		if (priv->intr_op & TLMM_TEST_THEN_LOW)
114 			tlmm_output_low();
115 		if (priv->intr_op & TLMM_TEST_THEN_HIGH)
116 			tlmm_output_high();
117 	}
118 
119 	return priv->intr_op & TLMM_TEST_WAKE_THREAD ? IRQ_WAKE_THREAD : IRQ_HANDLED;
120 }
121 
tlmm_test_intr_thread_fn(int irq,void * dev_id)122 static irqreturn_t tlmm_test_intr_thread_fn(int irq, void *dev_id)
123 {
124 	struct tlmm_test_priv *priv = dev_id;
125 
126 	if (priv->thread_op & TLMM_TEST_COUNT)
127 		atomic_inc(&priv->thread_count);
128 
129 	if (priv->thread_op & TLMM_TEST_OUTPUT_LOW)
130 		tlmm_output_low();
131 	if (priv->thread_op & TLMM_TEST_OUTPUT_HIGH)
132 		tlmm_output_high();
133 
134 	if (atomic_dec_if_positive(&priv->thread_op_remain) > 0) {
135 		udelay(1);
136 		if (priv->thread_op & TLMM_TEST_THEN_LOW)
137 			tlmm_output_low();
138 		if (priv->thread_op & TLMM_TEST_THEN_HIGH)
139 			tlmm_output_high();
140 	}
141 
142 	return IRQ_HANDLED;
143 }
144 
tlmm_test_request_hard_irq(struct kunit * test,unsigned long irqflags)145 static void tlmm_test_request_hard_irq(struct kunit *test, unsigned long irqflags)
146 {
147 	struct tlmm_test_priv *priv = test->priv;
148 	int ret;
149 
150 	ret = request_irq(tlmm_suite.irq, tlmm_test_intr_fn, irqflags, test->name, priv);
151 	KUNIT_EXPECT_EQ(test, ret, 0);
152 }
153 
tlmm_test_request_threaded_irq(struct kunit * test,unsigned long irqflags)154 static void tlmm_test_request_threaded_irq(struct kunit *test, unsigned long irqflags)
155 {
156 	struct tlmm_test_priv *priv = test->priv;
157 	int ret;
158 
159 	ret = request_threaded_irq(tlmm_suite.irq,
160 				   tlmm_test_intr_fn, tlmm_test_intr_thread_fn,
161 				   irqflags, test->name, priv);
162 
163 	KUNIT_EXPECT_EQ(test, ret, 0);
164 }
165 
tlmm_test_silent(struct kunit * test,unsigned long irqflags)166 static void tlmm_test_silent(struct kunit *test, unsigned long irqflags)
167 {
168 	struct tlmm_test_priv *priv = test->priv;
169 
170 	priv->intr_op = TLMM_TEST_COUNT;
171 
172 	/* GPIO line at non-triggering level */
173 	if (irqflags == IRQF_TRIGGER_LOW || irqflags == IRQF_TRIGGER_FALLING)
174 		tlmm_output_high();
175 	else
176 		tlmm_output_low();
177 
178 	tlmm_test_request_hard_irq(test, irqflags);
179 	msleep(100);
180 	free_irq(tlmm_suite.irq, priv);
181 
182 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 0);
183 }
184 
185 /*
186  * Test that no RISING interrupts are triggered on a silent pin
187  */
tlmm_test_silent_rising(struct kunit * test)188 static void tlmm_test_silent_rising(struct kunit *test)
189 {
190 	tlmm_test_silent(test, IRQF_TRIGGER_RISING);
191 }
192 
193 /*
194  * Test that no FALLING interrupts are triggered on a silent pin
195  */
tlmm_test_silent_falling(struct kunit * test)196 static void tlmm_test_silent_falling(struct kunit *test)
197 {
198 	tlmm_test_silent(test, IRQF_TRIGGER_FALLING);
199 }
200 
201 /*
202  * Test that no LOW interrupts are triggered on a silent pin
203  */
tlmm_test_silent_low(struct kunit * test)204 static void tlmm_test_silent_low(struct kunit *test)
205 {
206 	tlmm_test_silent(test, IRQF_TRIGGER_LOW);
207 }
208 
209 /*
210  * Test that no HIGH interrupts are triggered on a silent pin
211  */
tlmm_test_silent_high(struct kunit * test)212 static void tlmm_test_silent_high(struct kunit *test)
213 {
214 	tlmm_test_silent(test, IRQF_TRIGGER_HIGH);
215 }
216 
217 /*
218  * Square wave with 10 high pulses, assert that we get 10 rising interrupts
219  */
tlmm_test_rising(struct kunit * test)220 static void tlmm_test_rising(struct kunit *test)
221 {
222 	struct tlmm_test_priv *priv = test->priv;
223 	int i;
224 
225 	priv->intr_op = TLMM_TEST_COUNT;
226 
227 	tlmm_output_low();
228 
229 	tlmm_test_request_hard_irq(test, IRQF_TRIGGER_RISING);
230 	for (i = 0; i < 10; i++) {
231 		tlmm_output_low();
232 		msleep(20);
233 		tlmm_output_high();
234 		msleep(20);
235 	}
236 
237 	free_irq(tlmm_suite.irq, priv);
238 
239 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
240 }
241 
242 /*
243  * Square wave with 10 low pulses, assert that we get 10 falling interrupts
244  */
tlmm_test_falling(struct kunit * test)245 static void tlmm_test_falling(struct kunit *test)
246 {
247 	struct tlmm_test_priv *priv = test->priv;
248 	int i;
249 
250 	priv->intr_op = TLMM_TEST_COUNT;
251 
252 	tlmm_output_high();
253 
254 	tlmm_test_request_hard_irq(test, IRQF_TRIGGER_FALLING);
255 	for (i = 0; i < 10; i++) {
256 		tlmm_output_high();
257 		msleep(20);
258 		tlmm_output_low();
259 		msleep(20);
260 	}
261 	free_irq(tlmm_suite.irq, priv);
262 
263 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
264 }
265 
266 /*
267  * Drive line low 10 times, handler drives it high to "clear the interrupt
268  * source", assert we get 10 interrupts
269  */
tlmm_test_low(struct kunit * test)270 static void tlmm_test_low(struct kunit *test)
271 {
272 	struct tlmm_test_priv *priv = test->priv;
273 	int i;
274 
275 	priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_HIGH;
276 
277 	tlmm_output_high();
278 
279 	tlmm_test_request_hard_irq(test, IRQF_TRIGGER_LOW);
280 	for (i = 0; i < 10; i++) {
281 		msleep(20);
282 		tlmm_output_low();
283 	}
284 	msleep(100);
285 	free_irq(tlmm_suite.irq, priv);
286 
287 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
288 }
289 
290 /*
291  * Drive line high 10 times, handler drives it low to "clear the interrupt
292  * source", assert we get 10 interrupts
293  */
tlmm_test_high(struct kunit * test)294 static void tlmm_test_high(struct kunit *test)
295 {
296 	struct tlmm_test_priv *priv = test->priv;
297 	int i;
298 
299 	priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_LOW;
300 
301 	tlmm_output_low();
302 
303 	tlmm_test_request_hard_irq(test, IRQF_TRIGGER_HIGH);
304 	for (i = 0; i < 10; i++) {
305 		msleep(20);
306 		tlmm_output_high();
307 	}
308 	msleep(100);
309 	free_irq(tlmm_suite.irq, priv);
310 
311 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
312 }
313 
314 /*
315  * Handler drives GPIO high to "clear the interrupt source", then low to
316  * simulate a new interrupt, repeated 10 times, assert we get 10 interrupts
317  */
tlmm_test_falling_in_handler(struct kunit * test)318 static void tlmm_test_falling_in_handler(struct kunit *test)
319 {
320 	struct tlmm_test_priv *priv = test->priv;
321 
322 	priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_HIGH | TLMM_TEST_THEN_LOW;
323 	atomic_set(&priv->intr_op_remain, 10);
324 
325 	tlmm_output_high();
326 
327 	tlmm_test_request_hard_irq(test, IRQF_TRIGGER_FALLING);
328 	msleep(20);
329 	tlmm_output_low();
330 	msleep(100);
331 	free_irq(tlmm_suite.irq, priv);
332 
333 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
334 }
335 
336 /*
337  * Handler drives GPIO low to "clear the interrupt source", then high to
338  * simulate a new interrupt, repeated 10 times, assert we get 10 interrupts
339  */
tlmm_test_rising_in_handler(struct kunit * test)340 static void tlmm_test_rising_in_handler(struct kunit *test)
341 {
342 	struct tlmm_test_priv *priv = test->priv;
343 
344 	priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_LOW | TLMM_TEST_THEN_HIGH;
345 	atomic_set(&priv->intr_op_remain, 10);
346 
347 	tlmm_output_low();
348 
349 	tlmm_test_request_hard_irq(test, IRQF_TRIGGER_RISING);
350 	msleep(20);
351 	tlmm_output_high();
352 	msleep(100);
353 	free_irq(tlmm_suite.irq, priv);
354 
355 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
356 }
357 
358 /*
359  * Square wave with 10 high pulses, assert that we get 10 rising hard and
360  * 10 threaded interrupts
361  */
tlmm_test_thread_rising(struct kunit * test)362 static void tlmm_test_thread_rising(struct kunit *test)
363 {
364 	struct tlmm_test_priv *priv = test->priv;
365 	int i;
366 
367 	priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_WAKE_THREAD;
368 	priv->thread_op = TLMM_TEST_COUNT;
369 
370 	tlmm_output_low();
371 
372 	tlmm_test_request_threaded_irq(test, IRQF_TRIGGER_RISING);
373 	for (i = 0; i < 10; i++) {
374 		tlmm_output_low();
375 		msleep(20);
376 		tlmm_output_high();
377 		msleep(20);
378 	}
379 	free_irq(tlmm_suite.irq, priv);
380 
381 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
382 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->thread_count), 10);
383 }
384 
385 /*
386  * Square wave with 10 low pulses, assert that we get 10 falling interrupts
387  */
tlmm_test_thread_falling(struct kunit * test)388 static void tlmm_test_thread_falling(struct kunit *test)
389 {
390 	struct tlmm_test_priv *priv = test->priv;
391 	int i;
392 
393 	priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_WAKE_THREAD;
394 	priv->thread_op = TLMM_TEST_COUNT;
395 
396 	tlmm_output_high();
397 
398 	tlmm_test_request_threaded_irq(test, IRQF_TRIGGER_FALLING);
399 	for (i = 0; i < 10; i++) {
400 		tlmm_output_high();
401 		msleep(20);
402 		tlmm_output_low();
403 		msleep(20);
404 	}
405 	free_irq(tlmm_suite.irq, priv);
406 
407 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
408 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->thread_count), 10);
409 }
410 
411 /*
412  * Drive line high 10 times, threaded handler drives it low to "clear the
413  * interrupt source", assert we get 10 interrupts
414  */
tlmm_test_thread_high(struct kunit * test)415 static void tlmm_test_thread_high(struct kunit *test)
416 {
417 	struct tlmm_test_priv *priv = test->priv;
418 	int i;
419 
420 	priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_WAKE_THREAD;
421 	priv->thread_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_LOW;
422 
423 	tlmm_output_low();
424 
425 	tlmm_test_request_threaded_irq(test, IRQF_TRIGGER_HIGH | IRQF_ONESHOT);
426 	for (i = 0; i < 10; i++) {
427 		tlmm_output_high();
428 		msleep(20);
429 	}
430 	free_irq(tlmm_suite.irq, priv);
431 
432 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
433 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->thread_count), 10);
434 }
435 
436 /*
437  * Drive line low 10 times, threaded handler drives it high to "clear the
438  * interrupt source", assert we get 10 interrupts
439  */
tlmm_test_thread_low(struct kunit * test)440 static void tlmm_test_thread_low(struct kunit *test)
441 {
442 	struct tlmm_test_priv *priv = test->priv;
443 	int i;
444 
445 	priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_WAKE_THREAD;
446 	priv->thread_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_HIGH;
447 
448 	tlmm_output_high();
449 
450 	tlmm_test_request_threaded_irq(test, IRQF_TRIGGER_LOW | IRQF_ONESHOT);
451 	for (i = 0; i < 10; i++) {
452 		tlmm_output_low();
453 		msleep(20);
454 	}
455 	free_irq(tlmm_suite.irq, priv);
456 
457 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
458 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->thread_count), 10);
459 }
460 
461 /*
462  * Handler drives GPIO low to "clear the interrupt source", then high in the
463  * threaded handler to simulate a new interrupt, repeated 10 times, assert we
464  * get 10 interrupts
465  */
tlmm_test_thread_rising_in_handler(struct kunit * test)466 static void tlmm_test_thread_rising_in_handler(struct kunit *test)
467 {
468 	struct tlmm_test_priv *priv = test->priv;
469 
470 	priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_LOW | TLMM_TEST_WAKE_THREAD;
471 	priv->thread_op = TLMM_TEST_COUNT | TLMM_TEST_THEN_HIGH;
472 	atomic_set(&priv->thread_op_remain, 10);
473 
474 	tlmm_output_low();
475 
476 	tlmm_test_request_threaded_irq(test, IRQF_TRIGGER_RISING);
477 	msleep(20);
478 	tlmm_output_high();
479 	msleep(100);
480 	free_irq(tlmm_suite.irq, priv);
481 
482 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
483 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->thread_count), 10);
484 }
485 
486 /*
487  * Handler drives GPIO high to "clear the interrupt source", then low in the
488  * threaded handler to simulate a new interrupt, repeated 10 times, assert we
489  * get 10 interrupts
490  */
tlmm_test_thread_falling_in_handler(struct kunit * test)491 static void tlmm_test_thread_falling_in_handler(struct kunit *test)
492 {
493 	struct tlmm_test_priv *priv = test->priv;
494 
495 	priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_HIGH | TLMM_TEST_WAKE_THREAD;
496 	priv->thread_op = TLMM_TEST_COUNT | TLMM_TEST_THEN_LOW;
497 	atomic_set(&priv->thread_op_remain, 10);
498 
499 	tlmm_output_high();
500 
501 	tlmm_test_request_threaded_irq(test, IRQF_TRIGGER_FALLING);
502 	msleep(20);
503 	tlmm_output_low();
504 	msleep(100);
505 	free_irq(tlmm_suite.irq, priv);
506 
507 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
508 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->thread_count), 10);
509 }
510 
511 /*
512  * Validate that edge interrupts occurring while irq is disabled is delivered
513  * once the interrupt is reenabled.
514  */
tlmm_test_rising_while_disabled(struct kunit * test)515 static void tlmm_test_rising_while_disabled(struct kunit *test)
516 {
517 	struct tlmm_test_priv *priv = test->priv;
518 	unsigned int after_edge;
519 	unsigned int before_edge;
520 
521 	priv->intr_op = TLMM_TEST_COUNT;
522 
523 	tlmm_output_low();
524 
525 	tlmm_test_request_hard_irq(test, IRQF_TRIGGER_RISING);
526 	msleep(20);
527 
528 	disable_irq(tlmm_suite.irq);
529 	before_edge = atomic_read(&priv->intr_count);
530 
531 	tlmm_output_high();
532 	msleep(20);
533 	after_edge = atomic_read(&priv->intr_count);
534 
535 	msleep(20);
536 	enable_irq(tlmm_suite.irq);
537 	msleep(20);
538 
539 	free_irq(tlmm_suite.irq, priv);
540 
541 	KUNIT_ASSERT_EQ(test, before_edge, 0);
542 	KUNIT_ASSERT_EQ(test, after_edge, 0);
543 	KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 1);
544 }
545 
tlmm_test_init(struct kunit * test)546 static int tlmm_test_init(struct kunit *test)
547 {
548 	struct tlmm_test_priv *priv;
549 
550 	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
551 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
552 
553 	atomic_set(&priv->intr_count, 0);
554 	atomic_set(&priv->thread_count, 0);
555 
556 	atomic_set(&priv->intr_op_remain, 0);
557 	atomic_set(&priv->thread_op_remain, 0);
558 
559 	test->priv = priv;
560 
561 	return 0;
562 }
563 
564 /*
565  * NOTE: When adding compatibles to this list, ensure that TLMM_REG_SIZE and
566  * pull configuration values are supported and correct.
567  */
568 static const struct of_device_id tlmm_of_match[] = {
569 	{ .compatible = "qcom,sc8280xp-tlmm" },
570 	{ .compatible = "qcom,x1e80100-tlmm" },
571 	{}
572 };
573 
tlmm_reg_base(struct device_node * tlmm,struct resource * res)574 static int tlmm_reg_base(struct device_node *tlmm, struct resource *res)
575 {
576 	const char **reg_names;
577 	int count;
578 	int ret;
579 	int i;
580 
581 	if (!strcmp(tlmm_reg_name, "default_region"))
582 		return of_address_to_resource(tlmm, 0, res);
583 
584 	count = of_property_count_strings(tlmm, "reg-names");
585 	if (count <= 0) {
586 		pr_err("failed to find tlmm reg name\n");
587 		return count;
588 	}
589 
590 	reg_names = kcalloc(count, sizeof(char *), GFP_KERNEL);
591 	if (!reg_names)
592 		return -ENOMEM;
593 
594 	ret = of_property_read_string_array(tlmm, "reg-names", reg_names, count);
595 	if (ret != count) {
596 		kfree(reg_names);
597 		return -EINVAL;
598 	}
599 
600 	for (i = 0; i < count; i++) {
601 		if (!strcmp(reg_names[i], tlmm_reg_name)) {
602 			ret = of_address_to_resource(tlmm, i, res);
603 			break;
604 		}
605 	}
606 	if (i == count)
607 		ret = -EINVAL;
608 
609 	kfree(reg_names);
610 
611 	return ret;
612 }
613 
tlmm_test_init_suite(struct kunit_suite * suite)614 static int tlmm_test_init_suite(struct kunit_suite *suite)
615 {
616 	struct of_phandle_args args = {};
617 	struct resource res;
618 	int ret;
619 	u32 val;
620 
621 	if (tlmm_test_gpio < 0) {
622 		pr_err("use the tlmm-test.gpio module parameter to specify which GPIO to use\n");
623 		return -EINVAL;
624 	}
625 
626 	struct device_node *tlmm __free(device_node) = of_find_matching_node(NULL, tlmm_of_match);
627 	if (!tlmm) {
628 		pr_err("failed to find tlmm node\n");
629 		return -EINVAL;
630 	}
631 
632 	ret = tlmm_reg_base(tlmm, &res);
633 	if (ret < 0)
634 		return ret;
635 
636 	tlmm_suite.base = ioremap(res.start, resource_size(&res));
637 	if (!tlmm_suite.base)
638 		return -ENOMEM;
639 
640 	args.np = tlmm;
641 	args.args_count = 2;
642 	args.args[0] = tlmm_test_gpio;
643 	args.args[1] = 0;
644 
645 	tlmm_suite.irq = irq_create_of_mapping(&args);
646 	if (!tlmm_suite.irq) {
647 		pr_err("failed to map TLMM irq %d\n", args.args[0]);
648 		goto err_unmap;
649 	}
650 
651 	tlmm_suite.reg = tlmm_suite.base + tlmm_test_gpio * TLMM_REG_SIZE;
652 	val = readl(tlmm_suite.reg) & ~MSM_PULL_MASK;
653 	tlmm_suite.low_val = val | MSM_PULL_DOWN;
654 	tlmm_suite.high_val = val | MSM_PULL_UP;
655 
656 	return 0;
657 
658 err_unmap:
659 	iounmap(tlmm_suite.base);
660 	tlmm_suite.base = NULL;
661 	return -EINVAL;
662 }
663 
tlmm_test_exit_suite(struct kunit_suite * suite)664 static void tlmm_test_exit_suite(struct kunit_suite *suite)
665 {
666 	irq_dispose_mapping(tlmm_suite.irq);
667 	iounmap(tlmm_suite.base);
668 
669 	tlmm_suite.base = NULL;
670 	tlmm_suite.irq = -1;
671 }
672 
673 static struct kunit_case tlmm_test_cases[] = {
674 	KUNIT_CASE(tlmm_test_silent_rising),
675 	KUNIT_CASE(tlmm_test_silent_falling),
676 	KUNIT_CASE(tlmm_test_silent_low),
677 	KUNIT_CASE(tlmm_test_silent_high),
678 	KUNIT_CASE(tlmm_test_rising),
679 	KUNIT_CASE(tlmm_test_falling),
680 	KUNIT_CASE(tlmm_test_high),
681 	KUNIT_CASE(tlmm_test_low),
682 	KUNIT_CASE(tlmm_test_rising_in_handler),
683 	KUNIT_CASE(tlmm_test_falling_in_handler),
684 	KUNIT_CASE(tlmm_test_thread_rising),
685 	KUNIT_CASE(tlmm_test_thread_falling),
686 	KUNIT_CASE(tlmm_test_thread_high),
687 	KUNIT_CASE(tlmm_test_thread_low),
688 	KUNIT_CASE(tlmm_test_thread_rising_in_handler),
689 	KUNIT_CASE(tlmm_test_thread_falling_in_handler),
690 	KUNIT_CASE(tlmm_test_rising_while_disabled),
691 	{}
692 };
693 
694 static struct kunit_suite tlmm_test_suite = {
695 	.name = "tlmm-test",
696 	.init = tlmm_test_init,
697 	.suite_init = tlmm_test_init_suite,
698 	.suite_exit = tlmm_test_exit_suite,
699 	.test_cases = tlmm_test_cases,
700 };
701 
702 kunit_test_suites(&tlmm_test_suite);
703 
704 MODULE_DESCRIPTION("Qualcomm TLMM test");
705 MODULE_LICENSE("GPL");
706