gpio-msm-smp2p-test.c 21 KB

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