1 /*
2 * Copyright (c) 2022 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * Verify SMBUS Basic API, tests should work on any board
9 */
10
11 #include <zephyr/kernel.h>
12 #include <zephyr/ztest.h>
13 #include <zephyr/drivers/smbus.h>
14
15 #include <smbus_utils.h>
16
17 BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_NODELABEL(smbus0), okay),
18 "SMBus node is disabled!");
19
20 #define FAKE_ADDRESS 0x10
21
22 /**
23 * The test is run in userspace only if CONFIG_USERSPACE option is
24 * enabled, otherwise it is the same as ZTEST()
25 */
ZTEST_USER(test_smbus_general,test_smbus_basic_api)26 ZTEST_USER(test_smbus_general, test_smbus_basic_api)
27 {
28 const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(smbus0));
29 uint32_t cfg = SMBUS_MODE_CONTROLLER;
30 uint32_t cfg_tmp;
31 int ret;
32
33 zassert_true(device_is_ready(dev), "Device is not ready");
34
35 ret = smbus_configure(dev, cfg);
36 zassert_ok(ret, "SMBUS config failed");
37
38 ret = smbus_get_config(dev, &cfg_tmp);
39 zassert_ok(ret, "SMBUS get_config failed");
40
41 zassert_equal(cfg, cfg_tmp, "get_config returned invalid config");
42 }
43
44 /**
45 * The test is run in userspace only if CONFIG_USERSPACE option is
46 * enabled, otherwise it is the same as ZTEST()
47 */
ZTEST(test_smbus_general,test_smbus_smbalert_api)48 ZTEST(test_smbus_general, test_smbus_smbalert_api)
49 {
50 const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(smbus0));
51 void *dummy; /* For the dummy function pointer use this */
52 int ret;
53
54 /* Note! Only for test using stack variables to ease userspace tests */
55 struct smbus_callback callback = {
56 .handler = (void *)&dummy,
57 .addr = FAKE_ADDRESS,
58 };
59
60 zassert_true(device_is_ready(dev), "Device is not ready");
61
62 /* Smbalert callbacks */
63
64 /* Try to remove not existing callback */
65 ret = smbus_smbalert_remove_cb(dev, &callback);
66 if (IS_ENABLED(CONFIG_SMBUS_INTEL_PCH_SMBALERT)) {
67 zassert_equal(ret, -ENOENT, "Callback remove failed");
68 } else {
69 zassert_equal(ret, -ENOSYS, "Check for ENOSYS failed");
70 }
71
72 /* Set callback */
73 ret = smbus_smbalert_set_cb(dev, &callback);
74 if (IS_ENABLED(CONFIG_SMBUS_INTEL_PCH_SMBALERT)) {
75 zassert_ok(ret, "Callback set failed");
76 } else {
77 zassert_equal(ret, -ENOSYS, "Check for ENOSYS failed");
78 }
79
80 /* Remove existing callback */
81 ret = smbus_smbalert_remove_cb(dev, &callback);
82 if (IS_ENABLED(CONFIG_SMBUS_INTEL_PCH_SMBALERT)) {
83 zassert_ok(ret, "Callback remove failed");
84 } else {
85 zassert_equal(ret, -ENOSYS, "Check for ENOSYS failed");
86 }
87 }
88
89 /**
90 * The test is run in userspace only if CONFIG_USERSPACE option is
91 * enabled, otherwise it is the same as ZTEST()
92 */
ZTEST(test_smbus_general,test_smbus_host_notify_api)93 ZTEST(test_smbus_general, test_smbus_host_notify_api)
94 {
95 const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(smbus0));
96 void *dummy; /* For the dummy function pointer use this */
97 int ret;
98
99 /* Note! Only for test using stack variables to ease userspace tests */
100 struct smbus_callback callback = {
101 .handler = (void *)&dummy,
102 .addr = FAKE_ADDRESS,
103 };
104
105 zassert_true(device_is_ready(dev), "Device is not ready");
106
107 /* Host Notify callbacks */
108
109 /* Try to remove not existing callback */
110 ret = smbus_host_notify_remove_cb(dev, &callback);
111 if (IS_ENABLED(CONFIG_SMBUS_INTEL_PCH_HOST_NOTIFY)) {
112 zassert_equal(ret, -ENOENT, "Callback remove failed");
113 } else {
114 zassert_equal(ret, -ENOSYS, "Check for ENOSYS failed");
115 }
116
117 /* Set callback */
118 ret = smbus_host_notify_set_cb(dev, &callback);
119 if (IS_ENABLED(CONFIG_SMBUS_INTEL_PCH_HOST_NOTIFY)) {
120 zassert_ok(ret, "Callback set failed");
121 } else {
122 zassert_equal(ret, -ENOSYS, "Check for ENOSYS failed");
123 }
124
125 /* Remove existing callback */
126 ret = smbus_host_notify_remove_cb(dev, &callback);
127 if (IS_ENABLED(CONFIG_SMBUS_INTEL_PCH_HOST_NOTIFY)) {
128 zassert_ok(ret, "Callback remove failed");
129 } else {
130 zassert_equal(ret, -ENOSYS, "Check for ENOSYS failed");
131 }
132 }
133
134 /**
135 * The test is run in userspace only if CONFIG_USERSPACE option is
136 * enabled, otherwise it is the same as ZTEST()
137 */
ZTEST_USER(test_smbus_general,test_smbus_api_errors)138 ZTEST_USER(test_smbus_general, test_smbus_api_errors)
139 {
140 const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(smbus0));
141 uint8_t fake_addr = 0x10;
142 uint8_t buf[2];
143 int ret;
144
145 zassert_true(device_is_ready(dev), "Device is not ready");
146
147 /* Test parsing SMBus quick */
148 ret = smbus_quick(dev, fake_addr, 3);
149 zassert_equal(ret, -EINVAL, "Wrong parameter check failed");
150
151 /* Test parsing SMBus block_write */
152 ret = smbus_block_write(dev, fake_addr, 0, 0, buf);
153 zassert_equal(ret, -EINVAL, "Wrong parameter check failed");
154 ret = smbus_block_write(dev, fake_addr, 0, SMBUS_BLOCK_BYTES_MAX + 1,
155 buf);
156 zassert_equal(ret, -EINVAL, "Wrong parameter check failed");
157 }
158
159 /* Setup is needed for userspace access */
smbus_test_setup(void)160 static void *smbus_test_setup(void)
161 {
162 const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(smbus0));
163
164 zassert_true(device_is_ready(dev), "Device is not ready");
165
166 k_object_access_grant(dev, k_current_get());
167
168 return NULL;
169 }
170
171 ZTEST_SUITE(test_smbus_general, NULL, smbus_test_setup, NULL, NULL, NULL);
172