|
5 | 5 | */ |
6 | 6 |
|
7 | 7 | #include <zephyr/drivers/uart.h> |
| 8 | +#include <zephyr/pm/device.h> |
| 9 | +#include <zephyr/pm/device_runtime.h> |
8 | 10 | #include <zephyr/random/random.h> |
9 | 11 | #include <zephyr/sys/ring_buffer.h> |
10 | 12 | #include <zephyr/ztest.h> |
@@ -57,6 +59,40 @@ ZTEST_DMEM struct dut_data duts[] = { |
57 | 59 | #endif |
58 | 60 | }; |
59 | 61 |
|
| 62 | +static void pm_check(const struct device *dev, const struct device *second_dev, bool exp_on, |
| 63 | + int line) |
| 64 | +{ |
| 65 | + if (!IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { |
| 66 | + return; |
| 67 | + } |
| 68 | + |
| 69 | + if (dev == second_dev) { |
| 70 | + return; |
| 71 | + } |
| 72 | + |
| 73 | + enum pm_device_state state; |
| 74 | + int err; |
| 75 | + int cnt; |
| 76 | + |
| 77 | + cnt = pm_device_runtime_usage(dev); |
| 78 | + err = pm_device_state_get(dev, &state); |
| 79 | + zassert_equal(err, 0); |
| 80 | + |
| 81 | + if (exp_on) { |
| 82 | + zassert_not_equal(cnt, 0, "Wrong PM cnt:%d, line:%d", cnt, line); |
| 83 | + zassert_equal(state, PM_DEVICE_STATE_ACTIVE, |
| 84 | + "Wrong PM state %s, line:%d", pm_device_state_str(state), line); |
| 85 | + return; |
| 86 | + } |
| 87 | + |
| 88 | + /* Expect device to be off. */ |
| 89 | + zassert_equal(cnt, 0, "Wrong PM count:%d, line:%d", cnt, line); |
| 90 | + zassert_equal(state, PM_DEVICE_STATE_SUSPENDED, |
| 91 | + "Wrong PM state %s, line:%d", pm_device_state_str(state), line); |
| 92 | +} |
| 93 | + |
| 94 | +#define PM_CHECK(dev, second_dev, exp_on) pm_check(dev, second_dev, exp_on, __LINE__) |
| 95 | + |
60 | 96 | static const struct device *rx_dev; |
61 | 97 | static const struct device *tx_dev; |
62 | 98 |
|
@@ -452,11 +488,20 @@ static void hci_like_callback(const struct device *dev, struct uart_event *evt, |
452 | 488 | { |
453 | 489 | switch (evt->type) { |
454 | 490 | case UART_TX_DONE: |
| 491 | + |
455 | 492 | zassert_true(dev == tx_dev); |
| 493 | + if (IS_ENABLED(CONFIG_PM_RUNTIME_IN_TEST)) { |
| 494 | + PM_CHECK(tx_dev, rx_dev, true); |
| 495 | + pm_device_runtime_put(tx_dev); |
| 496 | + } |
| 497 | + PM_CHECK(tx_dev, rx_dev, false); |
456 | 498 | k_sem_give(&tx_data.sem); |
457 | 499 | break; |
458 | 500 | case UART_TX_ABORTED: |
459 | 501 | zassert_true(dev == tx_dev); |
| 502 | + if (IS_ENABLED(CONFIG_PM_RUNTIME_IN_TEST)) { |
| 503 | + pm_device_runtime_put(tx_dev); |
| 504 | + } |
460 | 505 | zassert_false(tx_data.cont, |
461 | 506 | "Unexpected TX abort, receiver not reading data on time"); |
462 | 507 | break; |
@@ -568,6 +613,10 @@ static void hci_like_tx(struct test_tx_data *tx_data) |
568 | 613 | uint8_t len = buf[4] + 5; |
569 | 614 | int err; |
570 | 615 |
|
| 616 | + if (IS_ENABLED(CONFIG_PM_RUNTIME_IN_TEST)) { |
| 617 | + pm_device_runtime_get(tx_dev); |
| 618 | + } |
| 619 | + |
571 | 620 | err = uart_tx(tx_dev, buf, len, TX_TIMEOUT); |
572 | 621 | zassert_equal(err, 0, "Unexpected err:%d", err); |
573 | 622 | } |
@@ -595,25 +644,57 @@ static void hci_like_rx(void) |
595 | 644 | uint8_t last_hdr = 0xff; |
596 | 645 | uint8_t len; |
597 | 646 | bool cont; |
| 647 | + bool explicit_pm = IS_ENABLED(CONFIG_PM_RUNTIME_IN_TEST); |
598 | 648 |
|
599 | 649 | while (1) { |
| 650 | + if (explicit_pm) { |
| 651 | + pm_device_runtime_get(rx_dev); |
| 652 | + } |
| 653 | + |
600 | 654 | cont = rx(rx_data.buf, 1); |
601 | 655 | if (!cont) { |
| 656 | + if (explicit_pm) { |
| 657 | + pm_device_runtime_put(rx_dev); |
| 658 | + } |
602 | 659 | break; |
603 | 660 | } |
604 | 661 | check_pre_hdr(rx_data.buf, last_hdr); |
605 | 662 | last_hdr = rx_data.buf[0]; |
606 | 663 |
|
| 664 | + /* If explicitly requested device to stay on in should be on. |
| 665 | + * If application did not touch PM, device should be off. |
| 666 | + */ |
| 667 | + PM_CHECK(rx_dev, tx_dev, explicit_pm); |
| 668 | + |
607 | 669 | cont = rx(rx_data.buf, 4); |
608 | 670 | if (!cont) { |
| 671 | + if (explicit_pm) { |
| 672 | + pm_device_runtime_put(rx_dev); |
| 673 | + } |
609 | 674 | break; |
610 | 675 | } |
611 | 676 | len = get_len(rx_data.buf); |
612 | 677 |
|
| 678 | + /* If explicitly requested device to stay on in should be on. |
| 679 | + * If application did not touch PM, device should be off. |
| 680 | + */ |
| 681 | + PM_CHECK(rx_dev, tx_dev, explicit_pm); |
| 682 | + |
613 | 683 | cont = rx(rx_data.buf, len); |
614 | 684 | if (!cont) { |
| 685 | + if (explicit_pm) { |
| 686 | + pm_device_runtime_put(rx_dev); |
| 687 | + } |
615 | 688 | break; |
616 | 689 | } |
| 690 | + |
| 691 | + if (explicit_pm) { |
| 692 | + pm_device_runtime_put(rx_dev); |
| 693 | + } |
| 694 | + |
| 695 | + /* Device shall be released and off. */ |
| 696 | + PM_CHECK(rx_dev, tx_dev, false); |
| 697 | + |
617 | 698 | check_payload(rx_data.buf, len); |
618 | 699 | } |
619 | 700 | } |
@@ -677,6 +758,8 @@ static void hci_like_test(uint32_t baudrate) |
677 | 758 | /* Flush data. */ |
678 | 759 | (void)uart_tx_abort(tx_dev); |
679 | 760 | k_msleep(10); |
| 761 | + PM_CHECK(tx_dev, rx_dev, false); |
| 762 | + |
680 | 763 | (void)uart_rx_enable(rx_dev, rx_data.buf, sizeof(rx_data.buf), RX_TIMEOUT); |
681 | 764 | k_msleep(1); |
682 | 765 | (void)uart_rx_disable(rx_dev); |
|
0 commit comments