blob: 1067c4aade39d2809f3f790456064770b605ad06 [file] [log] [blame]
Karthikeyan Ramasubramanian97a10282016-09-16 12:01:18 -06001/* drivers/gpio/gpio-msm-smp2p-test.c
2 *
3 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 and
7 * only version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/of_gpio.h>
17#include <linux/of_irq.h>
18#include <linux/gpio.h>
19#include <linux/debugfs.h>
20#include <linux/completion.h>
21#include <linux/interrupt.h>
22#include <linux/bitmap.h>
23#include "../soc/qcom/smp2p_private.h"
24#include "../soc/qcom/smp2p_test_common.h"
25
26/* Interrupt callback data */
27struct gpio_info {
28 int gpio_base_id;
29 int irq_base_id;
30
31 bool initialized;
32 struct completion cb_completion;
33 int cb_count;
34 DECLARE_BITMAP(triggered_irqs, SMP2P_BITS_PER_ENTRY);
35};
36
37/* GPIO Inbound/Outbound callback info */
38struct gpio_inout {
39 struct gpio_info in;
40 struct gpio_info out;
41};
42
43static struct gpio_inout gpio_info[SMP2P_NUM_PROCS];
44
45/**
46 * Init/reset the callback data.
47 *
48 * @info: Pointer to callback data
49 */
50static void cb_data_reset(struct gpio_info *info)
51{
52 int n;
53
54 if (!info)
55 return;
56
57 if (!info->initialized) {
58 init_completion(&info->cb_completion);
59 info->initialized = true;
60 }
61 info->cb_count = 0;
62
63 for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n)
64 clear_bit(n, info->triggered_irqs);
65
66 reinit_completion(&info->cb_completion);
67}
68
69static int smp2p_gpio_test_probe(struct platform_device *pdev)
70{
71 int id;
72 int cnt;
73 struct device_node *node = pdev->dev.of_node;
74 struct gpio_info *gpio_info_ptr = NULL;
75
76 /*
77 * NOTE: This does a string-lookup of the GPIO pin name and doesn't
78 * actually directly link to the SMP2P GPIO driver since all
79 * GPIO/Interrupt access must be through standard
80 * Linux GPIO / Interrupt APIs.
81 */
82 if (strcmp("qcom,smp2pgpio_test_smp2p_1_in", node->name) == 0) {
83 gpio_info_ptr = &gpio_info[SMP2P_MODEM_PROC].in;
84 } else if (strcmp("qcom,smp2pgpio_test_smp2p_1_out", node->name) == 0) {
85 gpio_info_ptr = &gpio_info[SMP2P_MODEM_PROC].out;
86 } else if (strcmp("qcom,smp2pgpio_test_smp2p_2_in", node->name) == 0) {
87 gpio_info_ptr = &gpio_info[SMP2P_AUDIO_PROC].in;
88 } else if (strcmp("qcom,smp2pgpio_test_smp2p_2_out", node->name) == 0) {
89 gpio_info_ptr = &gpio_info[SMP2P_AUDIO_PROC].out;
90 } else if (strcmp("qcom,smp2pgpio_test_smp2p_3_in", node->name) == 0) {
91 gpio_info_ptr = &gpio_info[SMP2P_SENSOR_PROC].in;
92 } else if (strcmp("qcom,smp2pgpio_test_smp2p_3_out", node->name) == 0) {
93 gpio_info_ptr = &gpio_info[SMP2P_SENSOR_PROC].out;
94 } else if (strcmp("qcom,smp2pgpio_test_smp2p_4_in", node->name) == 0) {
95 gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].in;
96 } else if (strcmp("qcom,smp2pgpio_test_smp2p_4_out", node->name) == 0) {
97 gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].out;
98 } else if (strcmp("qcom,smp2pgpio_test_smp2p_5_in", node->name) == 0) {
99 gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].in;
100 } else if (strcmp("qcom,smp2pgpio_test_smp2p_5_out", node->name) == 0) {
101 gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].out;
102 } else if (strcmp("qcom,smp2pgpio_test_smp2p_7_in", node->name) == 0) {
103 gpio_info_ptr = &gpio_info[SMP2P_TZ_PROC].in;
104 } else if (strcmp("qcom,smp2pgpio_test_smp2p_7_out", node->name) == 0) {
105 gpio_info_ptr = &gpio_info[SMP2P_TZ_PROC].out;
106 } else if (strcmp("qcom,smp2pgpio_test_smp2p_15_in", node->name) == 0) {
107 gpio_info_ptr = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in;
108 } else if (
109 strcmp("qcom,smp2pgpio_test_smp2p_15_out", node->name) == 0) {
110 gpio_info_ptr = &gpio_info[SMP2P_REMOTE_MOCK_PROC].out;
111 } else {
112 pr_err("%s: unable to match device type '%s'\n",
113 __func__, node->name);
114 return -ENODEV;
115 }
116
117 /* retrieve the GPIO and interrupt ID's */
118 cnt = of_gpio_count(node);
119 if (cnt && gpio_info_ptr) {
120 /*
121 * Instead of looping through all 32-bits, we can just get the
122 * first pin to get the base IDs. This saves on the verbosity
123 * of the device tree nodes as well.
124 */
125 id = of_get_gpio(node, 0);
126 if (id == -EPROBE_DEFER)
127 return id;
128 gpio_info_ptr->gpio_base_id = id;
129 gpio_info_ptr->irq_base_id = gpio_to_irq(id);
130 }
131 return 0;
132}
133
134/*
135 * NOTE: Instead of match table and device driver, you may be able to just
136 * call of_find_compatible_node() in your init function.
137 */
138static const struct of_device_id msm_smp2p_match_table[] = {
139 /* modem */
140 {.compatible = "qcom,smp2pgpio_test_smp2p_1_out", },
141 {.compatible = "qcom,smp2pgpio_test_smp2p_1_in", },
142
143 /* audio (adsp) */
144 {.compatible = "qcom,smp2pgpio_test_smp2p_2_out", },
145 {.compatible = "qcom,smp2pgpio_test_smp2p_2_in", },
146
147 /* sensor */
148 {.compatible = "qcom,smp2pgpio_test_smp2p_3_out", },
149 {.compatible = "qcom,smp2pgpio_test_smp2p_3_in", },
150
151 /* wcnss */
152 {.compatible = "qcom,smp2pgpio_test_smp2p_4_out", },
153 {.compatible = "qcom,smp2pgpio_test_smp2p_4_in", },
154
155 /* CDSP */
156 {.compatible = "qcom,smp2pgpio_test_smp2p_5_out", },
157 {.compatible = "qcom,smp2pgpio_test_smp2p_5_in", },
158
159 /* TZ */
160 {.compatible = "qcom,smp2pgpio_test_smp2p_7_out", },
161 {.compatible = "qcom,smp2pgpio_test_smp2p_7_in", },
162
163 /* mock loopback */
164 {.compatible = "qcom,smp2pgpio_test_smp2p_15_out", },
165 {.compatible = "qcom,smp2pgpio_test_smp2p_15_in", },
166 {},
167};
168
169static struct platform_driver smp2p_gpio_driver = {
170 .probe = smp2p_gpio_test_probe,
171 .driver = {
172 .name = "smp2pgpio_test",
173 .owner = THIS_MODULE,
174 .of_match_table = msm_smp2p_match_table,
175 },
176};
177
178/**
179 * smp2p_ut_local_gpio_out - Verify outbound functionality.
180 *
181 * @s: pointer to output file
182 */
183static void smp2p_ut_local_gpio_out(struct seq_file *s)
184{
185 int failed = 0;
186 struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].out;
187 int ret;
188 int id;
189 struct msm_smp2p_remote_mock *mock;
190
191 seq_printf(s, "Running %s\n", __func__);
192 do {
193 /* initialize mock edge */
194 ret = smp2p_reset_mock_edge();
195 UT_ASSERT_INT(ret, ==, 0);
196
197 mock = msm_smp2p_get_remote_mock();
198 UT_ASSERT_PTR(mock, !=, NULL);
199
200 mock->rx_interrupt_count = 0;
201 memset(&mock->remote_item, 0,
202 sizeof(struct smp2p_smem_item));
203 smp2p_init_header((struct smp2p_smem *)&mock->remote_item,
204 SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC,
205 0, 1);
206 strlcpy(mock->remote_item.entries[0].name, "smp2p",
207 SMP2P_MAX_ENTRY_NAME);
208 SMP2P_SET_ENT_VALID(
209 mock->remote_item.header.valid_total_ent, 1);
210 msm_smp2p_set_remote_mock_exists(true);
211 mock->tx_interrupt();
212
213 /* open GPIO entry */
214 smp2p_gpio_open_test_entry("smp2p",
215 SMP2P_REMOTE_MOCK_PROC, true);
216
217 /* verify set/get functions */
218 UT_ASSERT_INT(0, <, cb_info->gpio_base_id);
219 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
220 int pin = cb_info->gpio_base_id + id;
221
222 mock->rx_interrupt_count = 0;
223 gpio_set_value(pin, 1);
224 UT_ASSERT_INT(1, ==, mock->rx_interrupt_count);
225 UT_ASSERT_INT(1, ==, gpio_get_value(pin));
226
227 gpio_set_value(pin, 0);
228 UT_ASSERT_INT(2, ==, mock->rx_interrupt_count);
229 UT_ASSERT_INT(0, ==, gpio_get_value(pin));
230 }
231 if (failed)
232 break;
233
234 seq_puts(s, "\tOK\n");
235 } while (0);
236
237 if (failed) {
238 pr_err("%s: Failed\n", __func__);
239 seq_puts(s, "\tFailed\n");
240 }
241
242 smp2p_gpio_open_test_entry("smp2p",
243 SMP2P_REMOTE_MOCK_PROC, false);
244}
245
246/**
247 * smp2p_gpio_irq - Interrupt handler for inbound entries.
248 *
249 * @irq: Virtual IRQ being triggered
250 * @data: Cookie data (struct gpio_info * in this case)
251 * @returns: Number of bytes written
252 */
253static irqreturn_t smp2p_gpio_irq(int irq, void *data)
254{
255 struct gpio_info *gpio_ptr = (struct gpio_info *)data;
256 int offset;
257
258 if (!gpio_ptr) {
259 pr_err("%s: gpio_ptr is NULL for irq %d\n", __func__, irq);
260 return IRQ_HANDLED;
261 }
262
263 offset = irq - gpio_ptr->irq_base_id;
264 if (offset >= 0 && offset < SMP2P_BITS_PER_ENTRY)
265 set_bit(offset, gpio_ptr->triggered_irqs);
266 else
267 pr_err("%s: invalid irq offset base %d; irq %d\n",
268 __func__, gpio_ptr->irq_base_id, irq);
269
270 ++gpio_ptr->cb_count;
271 complete(&gpio_ptr->cb_completion);
272 return IRQ_HANDLED;
273}
274
275/**
276 * smp2p_ut_local_gpio_in - Verify inbound functionality.
277 *
278 * @s: pointer to output file
279 */
280static void smp2p_ut_local_gpio_in(struct seq_file *s)
281{
282 int failed = 0;
283 struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in;
284 int id;
285 int ret;
286 int virq;
287 struct msm_smp2p_remote_mock *mock;
288
289 seq_printf(s, "Running %s\n", __func__);
290
291 cb_data_reset(cb_info);
292 do {
293 /* initialize mock edge */
294 ret = smp2p_reset_mock_edge();
295 UT_ASSERT_INT(ret, ==, 0);
296
297 mock = msm_smp2p_get_remote_mock();
298 UT_ASSERT_PTR(mock, !=, NULL);
299
300 mock->rx_interrupt_count = 0;
301 memset(&mock->remote_item, 0,
302 sizeof(struct smp2p_smem_item));
303 smp2p_init_header((struct smp2p_smem *)&mock->remote_item,
304 SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC,
305 0, 1);
306 strlcpy(mock->remote_item.entries[0].name, "smp2p",
307 SMP2P_MAX_ENTRY_NAME);
308 SMP2P_SET_ENT_VALID(
309 mock->remote_item.header.valid_total_ent, 1);
310 msm_smp2p_set_remote_mock_exists(true);
311 mock->tx_interrupt();
312
313 smp2p_gpio_open_test_entry("smp2p",
314 SMP2P_REMOTE_MOCK_PROC, true);
315
316 /* verify set/get functions locally */
317 UT_ASSERT_INT(0, <, cb_info->gpio_base_id);
318 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
319 int pin;
320 int current_value;
321
322 /* verify pin value cannot be set */
323 pin = cb_info->gpio_base_id + id;
324 current_value = gpio_get_value(pin);
325
326 gpio_set_value(pin, 0);
327 UT_ASSERT_INT(current_value, ==, gpio_get_value(pin));
328 gpio_set_value(pin, 1);
329 UT_ASSERT_INT(current_value, ==, gpio_get_value(pin));
330
331 /* verify no interrupts */
332 UT_ASSERT_INT(0, ==, cb_info->cb_count);
333 }
334 if (failed)
335 break;
336
337 /* register for interrupts */
338 UT_ASSERT_INT(0, <, cb_info->irq_base_id);
339 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
340 virq = cb_info->irq_base_id + id;
341 UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq));
342 ret = request_irq(virq,
343 smp2p_gpio_irq, IRQF_TRIGGER_RISING,
344 "smp2p_test", cb_info);
345 UT_ASSERT_INT(0, ==, ret);
346 }
347 if (failed)
348 break;
349
350 /* verify both rising and falling edge interrupts */
351 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
352 virq = cb_info->irq_base_id + id;
353 irq_set_irq_type(virq, IRQ_TYPE_EDGE_BOTH);
354 cb_data_reset(cb_info);
355
356 /* verify rising-edge interrupt */
357 mock->remote_item.entries[0].entry = 1 << id;
358 mock->tx_interrupt();
359 UT_ASSERT_INT(cb_info->cb_count, ==, 1);
360 UT_ASSERT_INT(0, <,
361 test_bit(id, cb_info->triggered_irqs));
362 test_bit(id, cb_info->triggered_irqs);
363
364 /* verify falling-edge interrupt */
365 mock->remote_item.entries[0].entry = 0;
366 mock->tx_interrupt();
367 UT_ASSERT_INT(cb_info->cb_count, ==, 2);
368 UT_ASSERT_INT(0, <,
369 test_bit(id, cb_info->triggered_irqs));
370 }
371 if (failed)
372 break;
373
374 /* verify rising-edge interrupts */
375 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
376 virq = cb_info->irq_base_id + id;
377 irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
378 cb_data_reset(cb_info);
379
380 /* verify only rising-edge interrupt is triggered */
381 mock->remote_item.entries[0].entry = 1 << id;
382 mock->tx_interrupt();
383 UT_ASSERT_INT(cb_info->cb_count, ==, 1);
384 UT_ASSERT_INT(0, <,
385 test_bit(id, cb_info->triggered_irqs));
386 test_bit(id, cb_info->triggered_irqs);
387
388 mock->remote_item.entries[0].entry = 0;
389 mock->tx_interrupt();
390 UT_ASSERT_INT(cb_info->cb_count, ==, 1);
391 UT_ASSERT_INT(0, <,
392 test_bit(id, cb_info->triggered_irqs));
393 }
394 if (failed)
395 break;
396
397 /* verify falling-edge interrupts */
398 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
399 virq = cb_info->irq_base_id + id;
400 irq_set_irq_type(virq, IRQ_TYPE_EDGE_FALLING);
401 cb_data_reset(cb_info);
402
403 /* verify only rising-edge interrupt is triggered */
404 mock->remote_item.entries[0].entry = 1 << id;
405 mock->tx_interrupt();
406 UT_ASSERT_INT(cb_info->cb_count, ==, 0);
407 UT_ASSERT_INT(0, ==,
408 test_bit(id, cb_info->triggered_irqs));
409
410 mock->remote_item.entries[0].entry = 0;
411 mock->tx_interrupt();
412 UT_ASSERT_INT(cb_info->cb_count, ==, 1);
413 UT_ASSERT_INT(0, <,
414 test_bit(id, cb_info->triggered_irqs));
415 }
416 if (failed)
417 break;
418
419 seq_puts(s, "\tOK\n");
420 } while (0);
421
422 if (failed) {
423 pr_err("%s: Failed\n", __func__);
424 seq_puts(s, "\tFailed\n");
425 }
426
427 /* unregister for interrupts */
428 if (cb_info->irq_base_id) {
429 for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id)
430 free_irq(cb_info->irq_base_id + id, cb_info);
431 }
432
433 smp2p_gpio_open_test_entry("smp2p",
434 SMP2P_REMOTE_MOCK_PROC, false);
435}
436
437/**
438 * smp2p_ut_local_gpio_in_update_open - Verify combined open/update.
439 *
440 * @s: pointer to output file
441 *
442 * If the remote side updates the SMP2P bits and sends before negotiation is
443 * complete, then the UPDATE event will have to be delayed until negotiation is
444 * complete. This should result in both the OPEN and UPDATE events coming in
445 * right after each other and the behavior should be transparent to the clients
446 * of SMP2P GPIO.
447 */
448static void smp2p_ut_local_gpio_in_update_open(struct seq_file *s)
449{
450 int failed = 0;
451 struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in;
452 int id;
453 int ret;
454 int virq;
455 struct msm_smp2p_remote_mock *mock;
456
457 seq_printf(s, "Running %s\n", __func__);
458
459 cb_data_reset(cb_info);
460 do {
461 /* initialize mock edge */
462 ret = smp2p_reset_mock_edge();
463 UT_ASSERT_INT(ret, ==, 0);
464
465 mock = msm_smp2p_get_remote_mock();
466 UT_ASSERT_PTR(mock, !=, NULL);
467
468 mock->rx_interrupt_count = 0;
469 memset(&mock->remote_item, 0,
470 sizeof(struct smp2p_smem_item));
471 smp2p_init_header((struct smp2p_smem *)&mock->remote_item,
472 SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC,
473 0, 1);
474 strlcpy(mock->remote_item.entries[0].name, "smp2p",
475 SMP2P_MAX_ENTRY_NAME);
476 SMP2P_SET_ENT_VALID(
477 mock->remote_item.header.valid_total_ent, 1);
478
479 /* register for interrupts */
480 smp2p_gpio_open_test_entry("smp2p",
481 SMP2P_REMOTE_MOCK_PROC, true);
482
483 UT_ASSERT_INT(0, <, cb_info->irq_base_id);
484 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
485 virq = cb_info->irq_base_id + id;
486 UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq));
487 ret = request_irq(virq,
488 smp2p_gpio_irq, IRQ_TYPE_EDGE_BOTH,
489 "smp2p_test", cb_info);
490 UT_ASSERT_INT(0, ==, ret);
491 }
492 if (failed)
493 break;
494
495 /* update the state value and complete negotiation */
496 mock->remote_item.entries[0].entry = 0xDEADDEAD;
497 msm_smp2p_set_remote_mock_exists(true);
498 mock->tx_interrupt();
499
500 /* verify delayed state updates were processed */
501 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
502 virq = cb_info->irq_base_id + id;
503
504 UT_ASSERT_INT(cb_info->cb_count, >, 0);
505 if (0x1 & (0xDEADDEAD >> id)) {
506 /* rising edge should have been triggered */
507 if (!test_bit(id, cb_info->triggered_irqs)) {
508 seq_printf(s, "%s:%d bit %d clear, ",
509 __func__, __LINE__, id);
510 seq_puts(s, "expected set\n");
511 failed = 1;
512 break;
513 }
514 } else {
515 /* edge should not have been triggered */
516 if (test_bit(id, cb_info->triggered_irqs)) {
517 seq_printf(s, "%s:%d bit %d set, ",
518 __func__, __LINE__, id);
519 seq_puts(s, "expected clear\n");
520 failed = 1;
521 break;
522 }
523 }
524 }
525 if (failed)
526 break;
527
528 seq_puts(s, "\tOK\n");
529 } while (0);
530
531 if (failed) {
532 pr_err("%s: Failed\n", __func__);
533 seq_puts(s, "\tFailed\n");
534 }
535
536 /* unregister for interrupts */
537 if (cb_info->irq_base_id) {
538 for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id)
539 free_irq(cb_info->irq_base_id + id, cb_info);
540 }
541
542 smp2p_gpio_open_test_entry("smp2p",
543 SMP2P_REMOTE_MOCK_PROC, false);
544}
545
546/**
547 * smp2p_gpio_write_bits - writes value to each GPIO pin specified in mask.
548 *
549 * @gpio: gpio test structure
550 * @mask: 1 = write gpio_value to this GPIO pin
551 * @gpio_value: value to write to GPIO pin
552 */
553static void smp2p_gpio_write_bits(struct gpio_info *gpio, uint32_t mask,
554 int gpio_value)
555{
556 int n;
557
558 for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) {
559 if (mask & 0x1)
560 gpio_set_value(gpio->gpio_base_id + n, gpio_value);
561 mask >>= 1;
562 }
563}
564
565static void smp2p_gpio_set_bits(struct gpio_info *gpio, uint32_t mask)
566{
567 smp2p_gpio_write_bits(gpio, mask, 1);
568}
569
570static void smp2p_gpio_clr_bits(struct gpio_info *gpio, uint32_t mask)
571{
572 smp2p_gpio_write_bits(gpio, mask, 0);
573}
574
575/**
576 * smp2p_gpio_get_value - reads entire 32-bits of GPIO
577 *
578 * @gpio: gpio structure
579 * @returns: 32 bit value of GPIO pins
580 */
581static uint32_t smp2p_gpio_get_value(struct gpio_info *gpio)
582{
583 int n;
584 uint32_t value = 0;
585
586 for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) {
587 if (gpio_get_value(gpio->gpio_base_id + n))
588 value |= 1 << n;
589 }
590 return value;
591}
592
593/**
594 * smp2p_ut_remote_inout_core - Verify inbound/outbound functionality.
595 *
596 * @s: pointer to output file
597 * @remote_pid: Remote processor to test
598 * @name: Name of the test for reporting
599 *
600 * This test verifies inbound/outbound functionality for the remote processor.
601 */
602static void smp2p_ut_remote_inout_core(struct seq_file *s, int remote_pid,
603 const char *name)
604{
605 int failed = 0;
606 uint32_t request;
607 uint32_t response;
608 struct gpio_info *cb_in;
609 struct gpio_info *cb_out;
610 int id;
611 int ret;
612
613 seq_printf(s, "Running %s for '%s' remote pid %d\n",
614 __func__, smp2p_pid_to_name(remote_pid), remote_pid);
615
616 cb_in = &gpio_info[remote_pid].in;
617 cb_out = &gpio_info[remote_pid].out;
618 cb_data_reset(cb_in);
619 cb_data_reset(cb_out);
620 do {
621 /* open test entries */
622 msm_smp2p_deinit_rmt_lpb_proc(remote_pid);
623 smp2p_gpio_open_test_entry("smp2p", remote_pid, true);
624
625 /* register for interrupts */
626 UT_ASSERT_INT(0, <, cb_in->gpio_base_id);
627 UT_ASSERT_INT(0, <, cb_in->irq_base_id);
628 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
629 int virq = cb_in->irq_base_id + id;
630
631 UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq));
632 ret = request_irq(virq,
633 smp2p_gpio_irq,
634 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
635 "smp2p_test", cb_in);
636 UT_ASSERT_INT(0, ==, ret);
637 }
638 if (failed)
639 break;
640
641 /* write echo of data value 0 */
642 UT_ASSERT_INT(0, <, cb_out->gpio_base_id);
643 request = 0x0;
644 SMP2P_SET_RMT_CMD_TYPE(request, 1);
645 SMP2P_SET_RMT_CMD(request, SMP2P_LB_CMD_ECHO);
646 SMP2P_SET_RMT_DATA(request, 0x0);
647
648 smp2p_gpio_set_bits(cb_out, SMP2P_RMT_IGNORE_MASK);
649 smp2p_gpio_clr_bits(cb_out, ~SMP2P_RMT_IGNORE_MASK);
650 smp2p_gpio_set_bits(cb_out, request);
651
652 UT_ASSERT_INT(cb_in->cb_count, ==, 0);
653 smp2p_gpio_clr_bits(cb_out, SMP2P_RMT_IGNORE_MASK);
654
655 /* verify response */
656 do {
657 /* wait for up to 32 changes */
658 if (wait_for_completion_timeout(
659 &cb_in->cb_completion, HZ / 2) == 0)
660 break;
661 reinit_completion(&cb_in->cb_completion);
662 } while (cb_in->cb_count < 32);
663 UT_ASSERT_INT(cb_in->cb_count, >, 0);
664 response = smp2p_gpio_get_value(cb_in);
665 SMP2P_SET_RMT_CMD_TYPE(request, 0);
666 UT_ASSERT_HEX(request, ==, response);
667
668 /* write echo of data value of all 1's */
669 request = 0x0;
670 SMP2P_SET_RMT_CMD_TYPE(request, 1);
671 SMP2P_SET_RMT_CMD(request, SMP2P_LB_CMD_ECHO);
672 SMP2P_SET_RMT_DATA(request, ~0);
673
674 smp2p_gpio_set_bits(cb_out, SMP2P_RMT_IGNORE_MASK);
675 cb_data_reset(cb_in);
676 smp2p_gpio_clr_bits(cb_out, ~SMP2P_RMT_IGNORE_MASK);
677 smp2p_gpio_set_bits(cb_out, request);
678
679 UT_ASSERT_INT(cb_in->cb_count, ==, 0);
680 smp2p_gpio_clr_bits(cb_out, SMP2P_RMT_IGNORE_MASK);
681
682 /* verify response including 24 interrupts */
683 do {
684 UT_ASSERT_INT(
685 (int)wait_for_completion_timeout(
686 &cb_in->cb_completion, HZ / 2),
687 >, 0);
688 reinit_completion(&cb_in->cb_completion);
689 } while (cb_in->cb_count < 24);
690 response = smp2p_gpio_get_value(cb_in);
691 SMP2P_SET_RMT_CMD_TYPE(request, 0);
692 UT_ASSERT_HEX(request, ==, response);
693 UT_ASSERT_INT(24, ==, cb_in->cb_count);
694
695 seq_puts(s, "\tOK\n");
696 } while (0);
697
698 if (failed) {
699 pr_err("%s: Failed\n", name);
700 seq_puts(s, "\tFailed\n");
701 }
702
703 /* unregister for interrupts */
704 if (cb_in->irq_base_id) {
705 for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id)
706 free_irq(cb_in->irq_base_id + id, cb_in);
707 }
708
709 smp2p_gpio_open_test_entry("smp2p", remote_pid, false);
710 msm_smp2p_init_rmt_lpb_proc(remote_pid);
711}
712
713/**
714 * smp2p_ut_remote_inout - Verify inbound/outbound functionality for all.
715 *
716 * @s: pointer to output file
717 *
718 * This test verifies inbound and outbound functionality for all
719 * configured remote processor.
720 */
721static void smp2p_ut_remote_inout(struct seq_file *s)
722{
723 struct smp2p_interrupt_config *int_cfg;
724 int pid;
725
726 int_cfg = smp2p_get_interrupt_config();
727 if (!int_cfg) {
728 seq_puts(s, "Remote processor config unavailable\n");
729 return;
730 }
731
732 for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) {
733 if (!int_cfg[pid].is_configured)
734 continue;
735
736 smp2p_ut_remote_inout_core(s, pid, __func__);
737 }
738}
739
740static int __init smp2p_debugfs_init(void)
741{
742 /* register GPIO pins */
743 (void)platform_driver_register(&smp2p_gpio_driver);
744
745 /*
746 * Add Unit Test entries.
747 *
748 * The idea with unit tests is that you can run all of them
749 * from ADB shell by doing:
750 * adb shell
751 * cat ut*
752 *
753 * And if particular tests fail, you can then repeatedly run the
754 * failing tests as you debug and resolve the failing test.
755 */
756 smp2p_debug_create("ut_local_gpio_out", smp2p_ut_local_gpio_out);
757 smp2p_debug_create("ut_local_gpio_in", smp2p_ut_local_gpio_in);
758 smp2p_debug_create("ut_local_gpio_in_update_open",
759 smp2p_ut_local_gpio_in_update_open);
760 smp2p_debug_create("ut_remote_gpio_inout", smp2p_ut_remote_inout);
761 return 0;
762}
763late_initcall(smp2p_debugfs_init);