blob: 70de20a95d213f7c13097f3234d7c016dd3e3f9a [file] [log] [blame]
Eric Holmberg6275b602012-11-19 13:05:04 -07001/* arch/arm/mach-msm/smp2p_gpio_test.c
2 *
3 * Copyright (c) 2013, 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/irq.h>
22#include <linux/bitmap.h>
23#include "smp2p_private.h"
24#include "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 INIT_COMPLETION(info->cb_completion);
67}
68
69static int __devinit 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_4_in", node->name) == 0) {
91 gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].in;
92 } else if (strcmp("qcom,smp2pgpio_test_smp2p_4_out", node->name) == 0) {
93 gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].out;
94 } else if (strcmp("qcom,smp2pgpio_test_smp2p_7_in", node->name) == 0) {
95 gpio_info_ptr = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in;
96 } else if (strcmp("qcom,smp2pgpio_test_smp2p_7_out", node->name) == 0) {
97 gpio_info_ptr = &gpio_info[SMP2P_REMOTE_MOCK_PROC].out;
98 } else {
99 pr_err("%s: unable to match device type '%s'\n",
100 __func__, node->name);
101 return -ENODEV;
102 }
103
104 /* retrieve the GPIO and interrupt ID's */
105 cnt = of_gpio_count(node);
106 if (cnt && gpio_info_ptr) {
107 /*
108 * Instead of looping through all 32-bits, we can just get the
109 * first pin to get the base IDs. This saves on the verbosity
110 * of the device tree nodes as well.
111 */
112 id = of_get_gpio(node, 0);
113 gpio_info_ptr->gpio_base_id = id;
114 gpio_info_ptr->irq_base_id = gpio_to_irq(id);
115 }
116 return 0;
117}
118
119/*
120 * NOTE: Instead of match table and device driver, you may be able to just
121 * call of_find_compatible_node() in your init function.
122 */
123static struct of_device_id msm_smp2p_match_table[] __devinitdata = {
124 /* modem */
125 {.compatible = "qcom,smp2pgpio_test_smp2p_1_out", },
126 {.compatible = "qcom,smp2pgpio_test_smp2p_1_in", },
127
128 /* audio (adsp) */
129 {.compatible = "qcom,smp2pgpio_test_smp2p_2_out", },
130 {.compatible = "qcom,smp2pgpio_test_smp2p_2_in", },
131
132 /* wcnss */
133 {.compatible = "qcom,smp2pgpio_test_smp2p_4_out", },
134 {.compatible = "qcom,smp2pgpio_test_smp2p_4_in", },
135
136 /* mock loopback */
137 {.compatible = "qcom,smp2pgpio_test_smp2p_7_out", },
138 {.compatible = "qcom,smp2pgpio_test_smp2p_7_in", },
139 {},
140};
141
142static struct platform_driver smp2p_gpio_driver = {
143 .probe = smp2p_gpio_test_probe,
144 .driver = {
145 .name = "smp2pgpio_test",
146 .owner = THIS_MODULE,
147 .of_match_table = msm_smp2p_match_table,
148 },
149};
150
151/**
152 * smp2p_ut_local_gpio_out - Verify outbound functionality.
153 *
154 * @s: pointer to output file
155 */
156static void smp2p_ut_local_gpio_out(struct seq_file *s)
157{
158 int failed = 0;
159 struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].out;
160 int ret;
161 int id;
162 struct msm_smp2p_remote_mock *mock;
163
164 seq_printf(s, "Running %s\n", __func__);
165 do {
166 /* initialize mock edge */
167 ret = smp2p_reset_mock_edge();
168 UT_ASSERT_INT(ret, ==, 0);
169
170 mock = msm_smp2p_get_remote_mock();
171 UT_ASSERT_PTR(mock, !=, NULL);
172
173 mock->rx_interrupt_count = 0;
174 memset(&mock->remote_item, 0,
175 sizeof(struct smp2p_smem_item));
176 smp2p_init_header((struct smp2p_smem *)&mock->remote_item,
177 SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC,
178 0, 1);
179 strlcpy(mock->remote_item.entries[0].name, "smp2p",
180 SMP2P_MAX_ENTRY_NAME);
181 SMP2P_SET_ENT_VALID(
182 mock->remote_item.header.valid_total_ent, 1);
183 msm_smp2p_set_remote_mock_exists(true);
184 mock->tx_interrupt();
185
186 /* open GPIO entry */
187 smp2p_gpio_open_test_entry("smp2p",
188 SMP2P_REMOTE_MOCK_PROC, true);
189
190 /* verify set/get functions */
191 UT_ASSERT_INT(0, <, cb_info->gpio_base_id);
192 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
193 int pin = cb_info->gpio_base_id + id;
194
195 mock->rx_interrupt_count = 0;
196 gpio_set_value(pin, 1);
197 UT_ASSERT_INT(1, ==, mock->rx_interrupt_count);
198 UT_ASSERT_INT(1, ==, gpio_get_value(pin));
199
200 gpio_set_value(pin, 0);
201 UT_ASSERT_INT(2, ==, mock->rx_interrupt_count);
202 UT_ASSERT_INT(0, ==, gpio_get_value(pin));
203 }
204 if (failed)
205 break;
206
207 seq_printf(s, "\tOK\n");
208 } while (0);
209
210 if (failed) {
211 pr_err("%s: Failed\n", __func__);
212 seq_printf(s, "\tFailed\n");
213 }
214
215 smp2p_gpio_open_test_entry("smp2p",
216 SMP2P_REMOTE_MOCK_PROC, false);
217}
218
219/**
220 * smp2p_gpio_irq - Interrupt handler for inbound entries.
221 *
222 * @irq: Virtual IRQ being triggered
223 * @data: Cookie data (struct gpio_info * in this case)
224 * @returns: Number of bytes written
225 */
226static irqreturn_t smp2p_gpio_irq(int irq, void *data)
227{
228 struct gpio_info *gpio_ptr = (struct gpio_info *)data;
229 int offset;
230
231 if (!gpio_ptr) {
232 pr_err("%s: gpio_ptr is NULL for irq %d\n", __func__, irq);
233 return IRQ_HANDLED;
234 }
235
236 offset = irq - gpio_ptr->irq_base_id;
237 if (offset >= 0 && offset < SMP2P_BITS_PER_ENTRY)
238 set_bit(offset, gpio_ptr->triggered_irqs);
239 else
240 pr_err("%s: invalid irq offset base %d; irq %d\n",
241 __func__, gpio_ptr->irq_base_id, irq);
242
243 ++gpio_ptr->cb_count;
244 complete(&gpio_ptr->cb_completion);
245 return IRQ_HANDLED;
246}
247
248/**
249 * smp2p_ut_local_gpio_in - Verify inbound functionality.
250 *
251 * @s: pointer to output file
252 */
253static void smp2p_ut_local_gpio_in(struct seq_file *s)
254{
255 int failed = 0;
256 struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in;
257 int id;
258 int ret;
259 int virq;
260 struct msm_smp2p_remote_mock *mock;
261
262 seq_printf(s, "Running %s\n", __func__);
263
264 cb_data_reset(cb_info);
265 do {
266 /* initialize mock edge */
267 ret = smp2p_reset_mock_edge();
268 UT_ASSERT_INT(ret, ==, 0);
269
270 mock = msm_smp2p_get_remote_mock();
271 UT_ASSERT_PTR(mock, !=, NULL);
272
273 mock->rx_interrupt_count = 0;
274 memset(&mock->remote_item, 0,
275 sizeof(struct smp2p_smem_item));
276 smp2p_init_header((struct smp2p_smem *)&mock->remote_item,
277 SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC,
278 0, 1);
279 strlcpy(mock->remote_item.entries[0].name, "smp2p",
280 SMP2P_MAX_ENTRY_NAME);
281 SMP2P_SET_ENT_VALID(
282 mock->remote_item.header.valid_total_ent, 1);
283 msm_smp2p_set_remote_mock_exists(true);
284 mock->tx_interrupt();
285
286 smp2p_gpio_open_test_entry("smp2p",
287 SMP2P_REMOTE_MOCK_PROC, true);
288
289 /* verify set/get functions locally */
290 UT_ASSERT_INT(0, <, cb_info->gpio_base_id);
291 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
292 int pin;
293 int current_value;
294
295 /* verify pin value cannot be set */
296 pin = cb_info->gpio_base_id + id;
297 current_value = gpio_get_value(pin);
298
299 gpio_set_value(pin, 0);
300 UT_ASSERT_INT(current_value, ==, gpio_get_value(pin));
301 gpio_set_value(pin, 1);
302 UT_ASSERT_INT(current_value, ==, gpio_get_value(pin));
303
304 /* verify no interrupts */
305 UT_ASSERT_INT(0, ==, cb_info->cb_count);
306 }
307 if (failed)
308 break;
309
310 /* register for interrupts */
311 UT_ASSERT_INT(0, <, cb_info->irq_base_id);
312 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
313 virq = cb_info->irq_base_id + id;
314 UT_ASSERT_INT(0, >, (unsigned int)irq_to_desc(virq));
315 ret = request_irq(virq,
316 smp2p_gpio_irq, IRQF_TRIGGER_RISING,
317 "smp2p_test", cb_info);
318 UT_ASSERT_INT(0, ==, ret);
319 }
320 if (failed)
321 break;
322
323 /* verify both rising and falling edge interrupts */
324 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
325 virq = cb_info->irq_base_id + id;
326 irq_set_irq_type(virq, IRQ_TYPE_EDGE_BOTH);
327 cb_data_reset(cb_info);
328
329 /* verify rising-edge interrupt */
330 mock->remote_item.entries[0].entry = 1 << id;
331 mock->tx_interrupt();
332 UT_ASSERT_INT(cb_info->cb_count, ==, 1);
333 UT_ASSERT_INT(0, <,
334 test_bit(id, cb_info->triggered_irqs));
335 test_bit(id, cb_info->triggered_irqs);
336
337 /* verify falling-edge interrupt */
338 mock->remote_item.entries[0].entry = 0;
339 mock->tx_interrupt();
340 UT_ASSERT_INT(cb_info->cb_count, ==, 2);
341 UT_ASSERT_INT(0, <,
342 test_bit(id, cb_info->triggered_irqs));
343 }
344 if (failed)
345 break;
346
347 /* verify rising-edge interrupts */
348 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
349 virq = cb_info->irq_base_id + id;
350 irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
351 cb_data_reset(cb_info);
352
353 /* verify only rising-edge interrupt is triggered */
354 mock->remote_item.entries[0].entry = 1 << id;
355 mock->tx_interrupt();
356 UT_ASSERT_INT(cb_info->cb_count, ==, 1);
357 UT_ASSERT_INT(0, <,
358 test_bit(id, cb_info->triggered_irqs));
359 test_bit(id, cb_info->triggered_irqs);
360
361 mock->remote_item.entries[0].entry = 0;
362 mock->tx_interrupt();
363 UT_ASSERT_INT(cb_info->cb_count, ==, 1);
364 UT_ASSERT_INT(0, <,
365 test_bit(id, cb_info->triggered_irqs));
366 }
367 if (failed)
368 break;
369
370 /* verify falling-edge interrupts */
371 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
372 virq = cb_info->irq_base_id + id;
373 irq_set_irq_type(virq, IRQ_TYPE_EDGE_FALLING);
374 cb_data_reset(cb_info);
375
376 /* verify only rising-edge interrupt is triggered */
377 mock->remote_item.entries[0].entry = 1 << id;
378 mock->tx_interrupt();
379 UT_ASSERT_INT(cb_info->cb_count, ==, 0);
380 UT_ASSERT_INT(0, ==,
381 test_bit(id, cb_info->triggered_irqs));
382
383 mock->remote_item.entries[0].entry = 0;
384 mock->tx_interrupt();
385 UT_ASSERT_INT(cb_info->cb_count, ==, 1);
386 UT_ASSERT_INT(0, <,
387 test_bit(id, cb_info->triggered_irqs));
388 }
389 if (failed)
390 break;
391
392 seq_printf(s, "\tOK\n");
393 } while (0);
394
395 if (failed) {
396 pr_err("%s: Failed\n", __func__);
397 seq_printf(s, "\tFailed\n");
398 }
399
400 /* unregister for interrupts */
401 if (cb_info->irq_base_id) {
402 for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id)
403 free_irq(cb_info->irq_base_id + id, cb_info);
404 }
405
406 smp2p_gpio_open_test_entry("smp2p",
407 SMP2P_REMOTE_MOCK_PROC, false);
408}
409
410/**
411 * smp2p_gpio_write_bits - writes value to each GPIO pin specified in mask.
412 *
413 * @gpio: gpio test structure
414 * @mask: 1 = write gpio_value to this GPIO pin
415 * @gpio_value: value to write to GPIO pin
416 */
417static void smp2p_gpio_write_bits(struct gpio_info *gpio, uint32_t mask,
418 int gpio_value)
419{
420 int n;
421
422 for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) {
423 if (mask & 0x1)
424 gpio_set_value(gpio->gpio_base_id + n, gpio_value);
425 mask >>= 1;
426 }
427}
428
429static void smp2p_gpio_set_bits(struct gpio_info *gpio, uint32_t mask)
430{
431 smp2p_gpio_write_bits(gpio, mask, 1);
432}
433
434static void smp2p_gpio_clr_bits(struct gpio_info *gpio, uint32_t mask)
435{
436 smp2p_gpio_write_bits(gpio, mask, 0);
437}
438
439/**
440 * smp2p_gpio_get_value - reads entire 32-bits of GPIO
441 *
442 * @gpio: gpio structure
443 * @returns: 32 bit value of GPIO pins
444 */
445static uint32_t smp2p_gpio_get_value(struct gpio_info *gpio)
446{
447 int n;
448 uint32_t value = 0;
449
450 for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) {
451 if (gpio_get_value(gpio->gpio_base_id + n))
452 value |= 1 << n;
453 }
454 return value;
455}
456
457/**
458 * smp2p_ut_remote_inout_core - Verify inbound/outbound functionality.
459 *
460 * @s: pointer to output file
461 * @remote_pid: Remote processor to test
462 * @name: Name of the test for reporting
463 *
464 * This test verifies inbound/outbound functionality for the remote processor.
465 */
466static void smp2p_ut_remote_inout_core(struct seq_file *s, int remote_pid,
467 const char *name)
468{
469 int failed = 0;
470 uint32_t request;
471 uint32_t response;
472 struct gpio_info *cb_in;
473 struct gpio_info *cb_out;
474 int id;
475 int ret;
476
477 seq_printf(s, "Running %s for '%s' remote pid %d\n",
478 __func__, smp2p_pid_to_name(remote_pid), remote_pid);
479
480 cb_in = &gpio_info[remote_pid].in;
481 cb_out = &gpio_info[remote_pid].out;
482 cb_data_reset(cb_in);
483 cb_data_reset(cb_out);
484 do {
485 /* open test entries */
486 msm_smp2p_deinit_rmt_lpb_proc(remote_pid);
487 smp2p_gpio_open_test_entry("smp2p", remote_pid, true);
488
489 /* register for interrupts */
490 UT_ASSERT_INT(0, <, cb_in->gpio_base_id);
491 UT_ASSERT_INT(0, <, cb_in->irq_base_id);
492 for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
493 int virq = cb_in->irq_base_id + id;
494 UT_ASSERT_INT(0, >, (unsigned int)irq_to_desc(virq));
495 ret = request_irq(virq,
496 smp2p_gpio_irq,
497 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
498 "smp2p_test", cb_in);
499 UT_ASSERT_INT(0, ==, ret);
500 }
501 if (failed)
502 break;
503
504 /* write echo of data value 0 */
505 UT_ASSERT_INT(0, <, cb_out->gpio_base_id);
506 request = 0x0;
507 SMP2P_SET_RMT_CMD_TYPE(request, 1);
508 SMP2P_SET_RMT_CMD(request, SMP2P_LB_CMD_ECHO);
509 SMP2P_SET_RMT_DATA(request, 0x0);
510
511 smp2p_gpio_set_bits(cb_out, SMP2P_RMT_IGNORE_MASK);
512 smp2p_gpio_clr_bits(cb_out, ~SMP2P_RMT_IGNORE_MASK);
513 smp2p_gpio_set_bits(cb_out, request);
514
515 UT_ASSERT_INT(cb_in->cb_count, ==, 0);
516 smp2p_gpio_clr_bits(cb_out, SMP2P_RMT_IGNORE_MASK);
517
518 /* verify response */
519 do {
520 /* wait for up to 32 changes */
521 if (wait_for_completion_timeout(
522 &cb_in->cb_completion, HZ / 2) == 0)
523 break;
524 INIT_COMPLETION(cb_in->cb_completion);
525 } while (cb_in->cb_count < 32);
526 UT_ASSERT_INT(cb_in->cb_count, >, 0);
527 response = smp2p_gpio_get_value(cb_in);
528 SMP2P_SET_RMT_CMD_TYPE(request, 0);
529 UT_ASSERT_HEX(request, ==, response);
530
531 /* write echo of data value of all 1's */
532 request = 0x0;
533 SMP2P_SET_RMT_CMD_TYPE(request, 1);
534 SMP2P_SET_RMT_CMD(request, SMP2P_LB_CMD_ECHO);
535 SMP2P_SET_RMT_DATA(request, ~0);
536
537 smp2p_gpio_set_bits(cb_out, SMP2P_RMT_IGNORE_MASK);
538 cb_data_reset(cb_in);
539 smp2p_gpio_clr_bits(cb_out, ~SMP2P_RMT_IGNORE_MASK);
540 smp2p_gpio_set_bits(cb_out, request);
541
542 UT_ASSERT_INT(cb_in->cb_count, ==, 0);
543 smp2p_gpio_clr_bits(cb_out, SMP2P_RMT_IGNORE_MASK);
544
545 /* verify response including 24 interrupts */
546 do {
547 UT_ASSERT_INT(
548 (int)wait_for_completion_timeout(
549 &cb_in->cb_completion, HZ / 2),
550 >, 0);
551 INIT_COMPLETION(cb_in->cb_completion);
552 } while (cb_in->cb_count < 24);
553 response = smp2p_gpio_get_value(cb_in);
554 SMP2P_SET_RMT_CMD_TYPE(request, 0);
555 UT_ASSERT_HEX(request, ==, response);
556 UT_ASSERT_INT(24, ==, cb_in->cb_count);
557
558 seq_printf(s, "\tOK\n");
559 } while (0);
560
561 if (failed) {
562 pr_err("%s: Failed\n", name);
563 seq_printf(s, "\tFailed\n");
564 }
565
566 /* unregister for interrupts */
567 if (cb_in->irq_base_id) {
568 for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id)
569 free_irq(cb_in->irq_base_id + id, cb_in);
570 }
571
572 smp2p_gpio_open_test_entry("smp2p", remote_pid, false);
573 msm_smp2p_init_rmt_lpb_proc(remote_pid);
574}
575
576/**
577 * smp2p_ut_remote_inout - Verify inbound/outbound functionality for all.
578 *
579 * @s: pointer to output file
580 *
581 * This test verifies inbound and outbound functionality for all
582 * configured remote processor.
583 */
584static void smp2p_ut_remote_inout(struct seq_file *s)
585{
586 struct smp2p_interrupt_config *int_cfg;
587 int pid;
588
589 int_cfg = smp2p_get_interrupt_config();
590 if (!int_cfg) {
591 seq_printf(s, "Remote processor config unavailable\n");
592 return;
593 }
594
595 for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) {
596 if (!int_cfg[pid].is_configured)
597 continue;
598
599 smp2p_ut_remote_inout_core(s, pid, __func__);
600 }
601}
602
603static int __init smp2p_debugfs_init(void)
604{
605 /* register GPIO pins */
606 (void)platform_driver_register(&smp2p_gpio_driver);
607
608 /*
609 * Add Unit Test entries.
610 *
611 * The idea with unit tests is that you can run all of them
612 * from ADB shell by doing:
613 * adb shell
614 * cat ut*
615 *
616 * And if particular tests fail, you can then repeatedly run the
617 * failing tests as you debug and resolve the failing test.
618 */
619 smp2p_debug_create("ut_local_gpio_out", smp2p_ut_local_gpio_out);
620 smp2p_debug_create("ut_local_gpio_in", smp2p_ut_local_gpio_in);
621 smp2p_debug_create("ut_remote_gpio_inout", smp2p_ut_remote_inout);
622 return 0;
623}
624late_initcall(smp2p_debugfs_init);