1 /*
2 * Copyright (c) 2022 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*
8 * @addtogroup t_smbus_basic
9 * @{
10 * @defgroup t_smbus
11 * @brief TestPurpose: verify SMBUS can read and write
12 * @}
13 */
14
15 #include <zephyr/kernel.h>
16 #include <zephyr/ztest.h>
17 #include <zephyr/drivers/smbus.h>
18
19 BUILD_ASSERT(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(smbus0)),
20 "SMBus node is disabled!");
21
22 /* Qemu q35 has default emulated EEPROM-like devices */
23 #define QEMU_SMBUS_EEPROM_ADDR 0x50
24 #define QEMU_SMBUS_EEPROM_SIZE 256
25
26 /**
27 * The test is run in userspace only if CONFIG_USERSPACE option is
28 * enabled, otherwise it is the same as ZTEST()
29 */
ZTEST_USER(test_smbus_qemu,test_smbus_api_read_write)30 ZTEST_USER(test_smbus_qemu, test_smbus_api_read_write)
31 {
32 int ret;
33
34 const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(smbus0));
35
36 zassert_true(device_is_ready(dev), "Device is not ready");
37
38 /* Test SMBus quick */
39 ret = smbus_quick(dev, QEMU_SMBUS_EEPROM_ADDR, SMBUS_MSG_WRITE);
40 zassert_ok(ret, "SMBUS Quick W failed, ret %d", ret);
41
42 ret = smbus_quick(dev, QEMU_SMBUS_EEPROM_ADDR, SMBUS_MSG_READ);
43 zassert_ok(ret, "SMBUS Quick R failed, ret %d", ret);
44
45 /* Test SMBus Read / Write Byte Data */
46 for (uint16_t addr = 0; addr < QEMU_SMBUS_EEPROM_SIZE; addr++) {
47 /* Randomize buffer */
48 uint8_t send_byte = (uint8_t)addr;
49 uint8_t recv_byte;
50
51 ret = smbus_byte_data_write(dev, QEMU_SMBUS_EEPROM_ADDR, addr,
52 send_byte);
53 zassert_ok(ret, "SMBUS write byte data failed, ret %d", ret);
54
55 ret = smbus_byte_data_read(dev, QEMU_SMBUS_EEPROM_ADDR, addr,
56 &recv_byte);
57 zassert_ok(ret, "SMBUS read byte data failed, ret %d", ret);
58
59 zassert_equal(send_byte, recv_byte, "SMBUS data compare fail");
60 }
61
62 /* Test SMBus Read / Write Word Data */
63 for (uint16_t addr = 0; addr < QEMU_SMBUS_EEPROM_SIZE; addr += 2) {
64 uint16_t send_word = addr;
65 uint16_t recv_word;
66
67 ret = smbus_word_data_write(dev, QEMU_SMBUS_EEPROM_ADDR, addr,
68 send_word);
69 zassert_ok(ret, "SMBUS write word data failed, ret %d", ret);
70
71 ret = smbus_word_data_read(dev, QEMU_SMBUS_EEPROM_ADDR, addr,
72 &recv_word);
73 zassert_ok(ret, "SMBUS read word data failed, ret %d", ret);
74
75 zassert_equal(send_word, recv_word, "SMBUS data compare fail");
76 }
77
78 /* Test SMBus Read / Write Byte on special Qemu SMBus peripheral */
79 for (uint16_t addr = 0; addr < QEMU_SMBUS_EEPROM_SIZE; addr++) {
80 /* Randomize buffer */
81 uint8_t send_byte = (uint8_t)addr;
82 uint8_t recv_byte;
83
84 /* Write byte data to EEPROM device */
85 ret = smbus_byte_data_write(dev, QEMU_SMBUS_EEPROM_ADDR, addr,
86 send_byte);
87 zassert_ok(ret, "SMBUS write byte data failed, ret %d", ret);
88
89 /**
90 * Reading is done through executing two consequitive
91 * operations: write, which sets offset, followed by read, which
92 * reads data from given offset
93 */
94
95 ret = smbus_byte_write(dev, QEMU_SMBUS_EEPROM_ADDR, addr);
96 zassert_ok(ret, "SMBUS write byte failed, ret %d", ret);
97
98 ret = smbus_byte_read(dev, QEMU_SMBUS_EEPROM_ADDR, &recv_byte);
99 zassert_ok(ret, "SMBUS read byte failed, ret %d", ret);
100 zassert_equal(send_byte, recv_byte, "SMBUS data compare fail");
101 }
102
103 /**
104 * The Qemu SMBus implementation does not always correctly
105 * emulate SMBus Block protocol, however it is good enough
106 * to test Block Write followed by Block Read
107 */
108
109 /* Test SMBus Block Write / Block Read */
110 for (uint16_t addr = 0; addr < QEMU_SMBUS_EEPROM_SIZE;
111 addr += SMBUS_BLOCK_BYTES_MAX) {
112 uint8_t send_block[SMBUS_BLOCK_BYTES_MAX];
113 uint8_t recv_block[SMBUS_BLOCK_BYTES_MAX];
114 uint8_t count;
115
116 /* Poor man randomize ;) */
117 for (int i = 0; i < sizeof(send_block); i++) {
118 send_block[i] = addr + i;
119 }
120 ret = smbus_block_write(dev, QEMU_SMBUS_EEPROM_ADDR, addr,
121 sizeof(send_block), send_block);
122 zassert_ok(ret, "SMBUS write block failed, ret %d", ret);
123
124 ret = smbus_block_read(dev, QEMU_SMBUS_EEPROM_ADDR, addr,
125 &count, recv_block);
126 zassert_ok(ret, "SMBUS read block failed, ret %d", ret);
127
128 zassert_equal(count, SMBUS_BLOCK_BYTES_MAX,
129 "Read wrong %d of bytes", count);
130
131 zassert_true(!memcmp(send_block, recv_block, count),
132 "Read / Write data differs");
133 }
134 }
135
136 /* Setup is needed for userspace access */
smbus_test_setup(void)137 static void *smbus_test_setup(void)
138 {
139 const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(smbus0));
140
141 zassert_true(device_is_ready(dev), "Device is not ready");
142
143 k_object_access_grant(dev, k_current_get());
144
145 return NULL;
146 }
147
148 ZTEST_SUITE(test_smbus_qemu, NULL, smbus_test_setup, NULL, NULL, NULL);
149