1 /*
2  * Copyright (c) 2024 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*
8  * @addtogroup t_i2c_basic
9  * @{
10  * @defgroup t_i2c_read_write test_i2c_read_write
11  * @brief TestPurpose: verify I2C master can read and write
12  * @}
13  */
14 
15 #include <zephyr/drivers/i2c.h>
16 #include <zephyr/pm/device_runtime.h>
17 #include <zephyr/kernel.h>
18 #include <zephyr/ztest.h>
19 #include <zephyr/tc_util.h>
20 
21 #define RAM_ADDR (0b10100010 >> 1)
22 
23 #if DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(i2c_ram))
24 #define I2C_DEV_NODE	DT_ALIAS(i2c_ram)
25 #define TX_DATA_OFFSET 2
26 static uint8_t tx_data[9] = {0x00, 0x00, 'Z', 'e', 'p', 'h', 'y', 'r', '\n'};
27 static uint8_t rx_cmd[2] = {0x00, 0x00};
28 #else
29 #error "Please set the correct I2C device and alias for i2c_ram to be status okay"
30 #endif
31 
32 uint32_t i2c_cfg = I2C_SPEED_SET(I2C_SPEED_STANDARD) | I2C_MODE_CONTROLLER;
33 struct i2c_msg msgs[2];
34 uint8_t rx_data[7];
35 
36 const struct device *i2c_dev = DEVICE_DT_GET(I2C_DEV_NODE);
37 
38 /* Address from datasheet is 0b1010xxxr where x bits are additional
39  * memory address bits and r is the r/w i2c bit.
40  *
41  * However... the address needs to be shifted into the lower 7 bits as
42  * Zephyr expects a 7bit device address and shifts this left to set the
43  * i2c r/w bit.
44  */
45 
i2c_ram_setup(void)46 static void *i2c_ram_setup(void)
47 {
48 	int ret;
49 	uint32_t i2c_cfg_tmp;
50 
51 	zassert_true(device_is_ready(i2c_dev), "I2C device is not read");
52 
53 	/* 1. Verify i2c_configure() */
54 	zassert_ok(i2c_configure(i2c_dev, i2c_cfg), "I2C config failed");
55 
56 	/* 2. Verify i2c_get_config(), optional API */
57 	ret = i2c_get_config(i2c_dev, &i2c_cfg_tmp);
58 	if (ret != -ENOSYS) {
59 		zassert_equal(i2c_cfg, i2c_cfg_tmp,
60 			      "I2C get_config returned invalid config");
61 	}
62 
63 	return NULL;
64 }
65 
66 
67 static uint16_t addr;
68 
i2c_ram_before(void * f)69 static void i2c_ram_before(void *f)
70 {
71 	tx_data[0] = (addr >> 8) & 0xFF;
72 	tx_data[1] = (addr) & 0xFF;
73 	rx_cmd[0] = (addr >> 8) & 0xFF;
74 	rx_cmd[1] = (addr) & 0xFF;
75 	addr += ARRAY_SIZE(tx_data) - TX_DATA_OFFSET;
76 	memset(rx_data, 0, ARRAY_SIZE(rx_data));
77 
78 #ifdef CONFIG_PM_DEVICE_RUNTIME
79 	pm_device_runtime_get(i2c_dev);
80 #endif
81 }
82 
i2c_ram_after(void * f)83 static void i2c_ram_after(void *f)
84 {
85 #ifdef CONFIG_PM_DEVICE_RUNTIME
86 	pm_device_runtime_put(i2c_dev);
87 #endif
88 }
89 
ZTEST(i2c_ram,test_ram_transfer)90 ZTEST(i2c_ram, test_ram_transfer)
91 {
92 	TC_PRINT("ram using i2c_transfer from thread %p addr %x\n", k_current_get(), addr);
93 
94 	msgs[0].buf = tx_data;
95 	msgs[0].len = ARRAY_SIZE(tx_data);
96 	msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;
97 
98 	zassert_ok(i2c_transfer(i2c_dev, msgs, 1, RAM_ADDR),
99 		   "I2C write to fram failed");
100 
101 	/* Write the address and read the data back */
102 	msgs[0].buf = rx_cmd;
103 	msgs[0].len = ARRAY_SIZE(rx_cmd);
104 	msgs[0].flags = I2C_MSG_WRITE;
105 	msgs[1].buf = rx_data;
106 	msgs[1].len = 7;
107 	msgs[1].flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP;
108 
109 	zassert_ok(i2c_transfer(i2c_dev, msgs, 2, RAM_ADDR),
110 		   "I2C read from fram failed");
111 
112 	zassert_equal(memcmp(&tx_data[TX_DATA_OFFSET], &rx_data[0], ARRAY_SIZE(rx_data)), 0,
113 		      "Written and Read data should match");
114 }
115 
ZTEST(i2c_ram,test_ram_write_read)116 ZTEST(i2c_ram, test_ram_write_read)
117 {
118 	TC_PRINT("ram using i2c_write and i2c_write_read from thread %p addr %x\n",
119 		 k_current_get(), addr);
120 
121 	zassert_ok(i2c_write(i2c_dev, tx_data, ARRAY_SIZE(tx_data), RAM_ADDR),
122 		   "I2C write to fram failed");
123 
124 	zassert_ok(i2c_write_read(i2c_dev, RAM_ADDR, rx_cmd, ARRAY_SIZE(rx_cmd),
125 				  rx_data, ARRAY_SIZE(rx_data)),
126 		   "I2C read from fram failed");
127 
128 	zassert_equal(memcmp(&tx_data[TX_DATA_OFFSET], &rx_data[0], ARRAY_SIZE(rx_data)), 0,
129 		      "Written and Read data should match");
130 }
131 
132 
133 #ifdef CONFIG_I2C_CALLBACK
134 K_SEM_DEFINE(transfer_sem, 0, 1);
135 
i2c_ram_transfer_cb(const struct device * dev,int result,void * data)136 static void i2c_ram_transfer_cb(const struct device *dev, int result, void *data)
137 {
138 	struct k_sem *s = data;
139 
140 	k_sem_give(s);
141 }
142 
ZTEST(i2c_ram,test_ram_transfer_cb)143 ZTEST(i2c_ram, test_ram_transfer_cb)
144 {
145 	msgs[0].buf = tx_data;
146 	msgs[0].len = ARRAY_SIZE(tx_data);
147 	msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;
148 
149 	zassert_ok(i2c_transfer_cb(i2c_dev, msgs, 1, RAM_ADDR,
150 				   i2c_ram_transfer_cb,
151 				   &transfer_sem), "I2C write to fram failed");
152 
153 	k_sem_take(&transfer_sem, K_FOREVER);
154 
155 	/* Write the address and read the data back */
156 	msgs[0].buf = rx_cmd;
157 	msgs[0].len = ARRAY_SIZE(rx_cmd);
158 	msgs[0].flags = I2C_MSG_WRITE;
159 	msgs[1].buf = rx_data;
160 	msgs[1].len = ARRAY_SIZE(rx_data);
161 	msgs[1].flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP;
162 
163 	zassert_ok(i2c_transfer_cb(i2c_dev, msgs, 2, RAM_ADDR,
164 			   i2c_ram_transfer_cb, &transfer_sem),
165 		   "I2C read from fram failed");
166 
167 	k_sem_take(&transfer_sem, K_FOREVER);
168 
169 	zassert_equal(memcmp(&tx_data[TX_DATA_OFFSET], &rx_data[0], ARRAY_SIZE(rx_data)), 0,
170 		      "Written and Read data should match");
171 
172 }
173 #endif /* CONFIG_I2C_CALLBACK */
174 
175 #ifdef CONFIG_I2C_RTIO
176 #include <zephyr/rtio/rtio.h>
177 
178 I2C_IODEV_DEFINE(i2c_iodev, I2C_DEV_NODE, RAM_ADDR);
179 RTIO_DEFINE(i2c_rtio, 2, 2);
180 
ZTEST(i2c_ram,test_ram_rtio)181 ZTEST(i2c_ram, test_ram_rtio)
182 {
183 	struct rtio_sqe *wr_sqe, *rd_sqe;
184 	struct rtio_cqe *wr_cqe, *rd_cqe;
185 
186 	TC_PRINT("submitting write from thread %p addr %x\n", k_current_get(), addr);
187 	wr_sqe = rtio_sqe_acquire(&i2c_rtio);
188 	rtio_sqe_prep_write(wr_sqe, &i2c_iodev, 0, tx_data, ARRAY_SIZE(tx_data), tx_data);
189 	wr_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP;
190 	zassert_ok(rtio_submit(&i2c_rtio, 1), "submit should succeed");
191 
192 	wr_cqe = rtio_cqe_consume(&i2c_rtio);
193 	zassert_ok(wr_cqe->result, "i2c write should succeed");
194 	rtio_cqe_release(&i2c_rtio, wr_cqe);
195 
196 	/* Write the address and read the data back */
197 	msgs[0].len = ARRAY_SIZE(rx_cmd);
198 	msgs[0].flags = I2C_MSG_WRITE;
199 	msgs[1].buf = rx_data;
200 	msgs[1].len = ARRAY_SIZE(rx_data);
201 	msgs[1].flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP;
202 
203 	wr_sqe = rtio_sqe_acquire(&i2c_rtio);
204 	rd_sqe = rtio_sqe_acquire(&i2c_rtio);
205 	rtio_sqe_prep_write(wr_sqe, &i2c_iodev, 0, rx_cmd, ARRAY_SIZE(rx_cmd), rx_cmd);
206 	rtio_sqe_prep_read(rd_sqe, &i2c_iodev, 0, rx_data, ARRAY_SIZE(rx_data), rx_data);
207 	wr_sqe->flags |= RTIO_SQE_TRANSACTION;
208 	rd_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
209 	zassert_ok(rtio_submit(&i2c_rtio, 2), "submit should succeed");
210 
211 	wr_cqe = rtio_cqe_consume(&i2c_rtio);
212 	rd_cqe = rtio_cqe_consume(&i2c_rtio);
213 	zassert_ok(wr_cqe->result, "i2c write should succeed");
214 	zassert_ok(rd_cqe->result, "i2c read should succeed");
215 	rtio_cqe_release(&i2c_rtio, wr_cqe);
216 	rtio_cqe_release(&i2c_rtio, rd_cqe);
217 
218 	zassert_equal(memcmp(&tx_data[TX_DATA_OFFSET], &rx_data[0], ARRAY_SIZE(rx_data)), 0,
219 		      "Written and Read data should match");
220 }
221 
222 static enum isr_rtio_state {
223 	INIT,
224 	WRITE_WAIT,
225 	READ_CMD_WAIT,
226 	READ_DATA_WAIT,
227 	DONE
228 } isr_state = INIT;
229 
230 K_SEM_DEFINE(ram_rtio_isr_sem, 0, 1);
231 
ram_rtio_isr(struct k_timer * tid)232 void ram_rtio_isr(struct k_timer *tid)
233 {
234 	struct rtio_sqe *wr_sqe, *rd_sqe;
235 	struct rtio_cqe *wr_cqe, *rd_cqe;
236 
237 	switch (isr_state) {
238 	case INIT:
239 		TC_PRINT("timer submitting write, addr %x\n", addr);
240 		wr_sqe = rtio_sqe_acquire(&i2c_rtio);
241 		rtio_sqe_prep_write(wr_sqe, &i2c_iodev, 0, tx_data, ARRAY_SIZE(tx_data), tx_data);
242 		wr_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP;
243 		zassert_ok(rtio_submit(&i2c_rtio, 0), "submit should succeed");
244 		isr_state += 1;
245 		break;
246 	case WRITE_WAIT:
247 		wr_cqe = rtio_cqe_consume(&i2c_rtio);
248 		if (wr_cqe) {
249 			TC_PRINT("timer checking write result, submitting read\n");
250 			zassert_ok(wr_cqe->result, "i2c write should succeed");
251 			rtio_cqe_release(&i2c_rtio, wr_cqe);
252 
253 			/* Write the address and read the data back */
254 			msgs[0].len = ARRAY_SIZE(rx_cmd);
255 			msgs[0].flags = I2C_MSG_WRITE;
256 			msgs[1].buf = rx_data;
257 			msgs[1].len = ARRAY_SIZE(rx_data);
258 			msgs[1].flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP;
259 
260 			wr_sqe = rtio_sqe_acquire(&i2c_rtio);
261 			rd_sqe = rtio_sqe_acquire(&i2c_rtio);
262 			rtio_sqe_prep_write(wr_sqe, &i2c_iodev, 0, rx_cmd,
263 					    ARRAY_SIZE(rx_cmd), rx_cmd);
264 			rtio_sqe_prep_read(rd_sqe, &i2c_iodev, 0, rx_data,
265 					   ARRAY_SIZE(rx_data), rx_data);
266 			wr_sqe->flags |= RTIO_SQE_TRANSACTION;
267 			rd_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
268 			zassert_ok(rtio_submit(&i2c_rtio, 0), "submit should succeed");
269 			isr_state += 1;
270 		}
271 		break;
272 	case READ_CMD_WAIT:
273 		wr_cqe = rtio_cqe_consume(&i2c_rtio);
274 		if (wr_cqe) {
275 			TC_PRINT("read command complete\n");
276 			zassert_ok(wr_cqe->result, "i2c read command should succeed");
277 			rtio_cqe_release(&i2c_rtio, wr_cqe);
278 			isr_state += 1;
279 		}
280 		break;
281 	case READ_DATA_WAIT:
282 		rd_cqe = rtio_cqe_consume(&i2c_rtio);
283 		if (rd_cqe) {
284 			TC_PRINT("read data complete\n");
285 			zassert_ok(rd_cqe->result, "i2c read data should succeed");
286 			rtio_cqe_release(&i2c_rtio, rd_cqe);
287 			isr_state += 1;
288 			k_sem_give(&ram_rtio_isr_sem);
289 			k_timer_stop(tid);
290 		}
291 		break;
292 	default:
293 
294 		zassert_ok(-1, "Should not get here");
295 	}
296 }
297 
298 K_TIMER_DEFINE(ram_rtio_isr_timer, ram_rtio_isr, NULL);
299 
300 
ZTEST(i2c_ram,test_ram_rtio_isr)301 ZTEST(i2c_ram, test_ram_rtio_isr)
302 {
303 	k_timer_start(&ram_rtio_isr_timer, K_MSEC(1), K_MSEC(1));
304 	k_sem_take(&ram_rtio_isr_sem, K_FOREVER);
305 }
306 
307 #endif /* CONFIG_I2C_RTIO */
308 
309 ZTEST_SUITE(i2c_ram, NULL, i2c_ram_setup, i2c_ram_before, i2c_ram_after, NULL);
310