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