1 /*
2 * Copyright (c) 2022 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/i2c.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/ztest.h>
10
11 #define FXOS8700_I2C_ADDR 0x1d
12
13 /* Reduced regmap for FXOS8700 */
14 #define FXOS8700_REG_STATUS 0x00
15 #define FXOS8700_REG_F_SETUP 0x09
16 #define FXOS8700_REG_WHOAMI 0x0d
17 #define FXOS8700_REG_CTRLREG1 0x2a
18 #define FXOS8700_REG_CTRLREG2 0x2b
19 #define FXOS8700_REG_CTRLREG3 0x2c
20 #define FXOS8700_REG_CTRLREG4 0x2d
21 #define FXOS8700_REG_CTRLREG5 0x2e
22
23 #define WHOAMI_ID_FXOS8700 0xC7
24
25 #define FXOS8700_CTRLREG2_RST_MASK 0x40
26
27
28 static const struct device *const i2c_bus = DEVICE_DT_GET(DT_NODELABEL(i2c0));
29
30 /**
31 * Setup and enable the fxos8700 with its max sample rate and
32 * FIFO.
33 */
fxos8700_fifo_cfg(void)34 static int fxos8700_fifo_cfg(void)
35 {
36 int res;
37 uint8_t data;
38
39 TC_PRINT("Configuring FXOS8700\n");
40
41 /* Signal a reset */
42 i2c_reg_write_byte(i2c_bus, FXOS8700_I2C_ADDR,
43 FXOS8700_REG_CTRLREG2, FXOS8700_CTRLREG2_RST_MASK);
44
45 k_busy_wait(USEC_PER_MSEC);
46
47 TC_PRINT("Getting whoami\n");
48 res = i2c_reg_read_byte(i2c_bus, FXOS8700_I2C_ADDR,
49 FXOS8700_REG_WHOAMI, &data);
50 if (res != 0) {
51 TC_PRINT("Could not get WHOAMI value after reset\n");
52 return TC_FAIL;
53 }
54
55 if (data != WHOAMI_ID_FXOS8700) {
56 TC_PRINT("Not an FXOS8700 sensor\n");
57 return TC_FAIL;
58 }
59
60 /* Enable FIFO mode with a watermark of 16 */
61 res = i2c_reg_write_byte(i2c_bus,
62 FXOS8700_I2C_ADDR,
63 FXOS8700_REG_F_SETUP,
64 0x50);
65
66 if (res != 0) {
67 TC_PRINT("Failed to setup FIFO\n");
68 return TC_FAIL;
69 }
70
71 /* Activate the sensor */
72 res = i2c_reg_write_byte(i2c_bus,
73 FXOS8700_I2C_ADDR,
74 FXOS8700_REG_CTRLREG1,
75 0x01);
76
77 if (res != 0) {
78 TC_PRINT("Failed to activate the sensor\n");
79 return TC_FAIL;
80 }
81
82 TC_PRINT("Configured FXOS8700\n");
83
84 return TC_PASS;
85 }
86
87 #define FXOS8700_XFERS 10
88
89 static uint8_t sample_buf[64];
90 static uint8_t reg = 0x01;
91 static struct i2c_msg msgs[2] = { { .buf = ®, .len = 1, .flags = I2C_MSG_WRITE },
92 { .buf = sample_buf,
93 .len = sizeof(sample_buf),
94 .flags = I2C_MSG_READ | I2C_MSG_RESTART | I2C_MSG_STOP } };
95
96 /* Read 3 axis 14 bit (2 byte) data */
97
test_i2c_fxos8700_sync(void)98 static int test_i2c_fxos8700_sync(void)
99 {
100 int res;
101
102 TC_PRINT("fxos8700 sync test ...\n");
103 fxos8700_fifo_cfg();
104
105 for (int i = 0; i < FXOS8700_XFERS; i++) {
106 res = i2c_transfer(i2c_bus,
107 msgs,
108 2,
109 FXOS8700_I2C_ADDR);
110
111 zassert_ok(res, "expected xfer success");
112 }
113
114 TC_PRINT("fxos8700 async test pass\n");
115 return TC_PASS;
116 }
117
ZTEST(frdm_k64f_i2c,test_i2c_sync)118 ZTEST(frdm_k64f_i2c, test_i2c_sync)
119 {
120 zassert_equal(test_i2c_fxos8700_sync(), TC_PASS, "i2c sync test");
121 }
122
123 static uint32_t xfer_count;
124 static int xfer_res;
125 static struct k_sem xfer_sem;
126
test_i2c_fxos8700_async_cb(const struct device * dev,int result,void * userdata)127 static void test_i2c_fxos8700_async_cb(const struct device *dev, int result, void *userdata)
128 {
129 int res;
130
131 if (result != 0) {
132 xfer_res = result;
133 k_sem_give(&xfer_sem);
134 return;
135 }
136
137 if (xfer_count >= FXOS8700_XFERS) {
138 xfer_res = 0;
139 k_sem_give(&xfer_sem);
140 return;
141 }
142
143 xfer_count++;
144 res = i2c_transfer_cb(dev, msgs, 2, FXOS8700_I2C_ADDR,
145 test_i2c_fxos8700_async_cb, NULL);
146 zassert_ok(res, "expected ok for async transfer start");
147 }
148
149
test_i2c_fxos8700_transfer_cb(void)150 static int test_i2c_fxos8700_transfer_cb(void)
151 {
152 int res;
153
154 TC_PRINT("fxos8700 async test ...\n");
155
156 fxos8700_fifo_cfg();
157
158 xfer_count = 0;
159 k_sem_init(&xfer_sem, 0, 1);
160
161 res = i2c_transfer_cb(i2c_bus, msgs, 2, FXOS8700_I2C_ADDR,
162 test_i2c_fxos8700_async_cb, NULL);
163 zassert_ok(res, "expected ok for async transfer start");
164
165 k_sem_take(&xfer_sem, K_FOREVER);
166
167 zassert_ok(xfer_res, "expected success of xfer");
168
169 TC_PRINT("fxos8700 async test pass\n");
170 return TC_PASS;
171 }
172
ZTEST(frdm_k64f_i2c,test_i2c_transfer_cb)173 ZTEST(frdm_k64f_i2c, test_i2c_transfer_cb)
174 {
175 zassert_equal(test_i2c_fxos8700_transfer_cb(), TC_PASS, "i2c_transfer_cb");
176 }
177
178
179
180 static struct k_poll_signal xfer_signal;
181
182 /* Mimic synchronous call with async_sem data and callback */
test_i2c_fxos8700_transfer_signal(void)183 static int test_i2c_fxos8700_transfer_signal(void)
184 {
185 int res;
186
187 TC_PRINT("fxos8700 i2c_transfer_signal test ...\n");
188
189 uint8_t usample_buf[64];
190 uint8_t ureg = 0x01;
191 struct i2c_msg umsgs[2] = { { .buf = &ureg, .len = 1, .flags = I2C_MSG_WRITE },
192 { .buf = usample_buf,
193 .len = sizeof(usample_buf),
194 .flags = I2C_MSG_READ | I2C_MSG_RESTART | I2C_MSG_STOP } };
195
196 for (int i = 0; i < 2; i++) {
197 TC_PRINT("umsgs[%d].flags %x\n", i, umsgs[i].flags);
198 }
199
200 k_poll_signal_init(&xfer_signal);
201
202 struct k_poll_event events[1] = {
203 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &xfer_signal),
204 };
205
206 fxos8700_fifo_cfg();
207
208 for (int i = 0; i < FXOS8700_XFERS; i++) {
209 res = i2c_transfer_signal(i2c_bus, umsgs, 2, FXOS8700_I2C_ADDR,
210 &xfer_signal);
211 TC_PRINT("result of transfer_signal, %d\n", res);
212
213 zassert_ok(res, "expected ok for async transfer start");
214
215 TC_PRINT("polling for completion\n");
216
217 /* Poll signal */
218 k_poll(events, 1, K_FOREVER);
219
220 unsigned int signaled;
221 int signal_result;
222
223 k_poll_signal_check(&xfer_signal, &signaled, &signal_result);
224
225 TC_PRINT("signaled %d, signal result %d\n", signaled, signal_result);
226
227 zassert_true(signaled > 0, "expected signaled to be non-zero");
228 zassert_ok(signal_result, "expected result to be ok\n");
229
230 TC_PRINT("resetting signal\n");
231 k_poll_signal_reset(&xfer_signal);
232 }
233
234 TC_PRINT("fxos8700 i2c_transfer_signal test pass\n");
235 return TC_PASS;
236 }
237
ZTEST(frdm_k64f_i2c,test_i2c_transfer_signal)238 ZTEST(frdm_k64f_i2c, test_i2c_transfer_signal)
239 {
240 zassert_equal(test_i2c_fxos8700_transfer_signal(), TC_PASS,
241 "i2c_transfer_signal supervisor mode");
242 }
243
244 ZTEST_SUITE(frdm_k64f_i2c, NULL, NULL, NULL, NULL, NULL);
245