1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <errno.h>
8 #include <string.h>
9 
10 #include <zephyr/kernel.h>
11 #include <zephyr/linker/devicetree_regions.h>
12 #include <zephyr/device.h>
13 #include <zephyr/drivers/pinctrl.h>
14 
15 #include <zephyr/drivers/i2c.h>
16 #include <nrfx_twis.h>
17 
18 #include <zephyr/ztest.h>
19 
20 #if CONFIG_NRFX_TWIS1
21 #define I2C_S_INSTANCE 1
22 #elif CONFIG_NRFX_TWIS2
23 #define I2C_S_INSTANCE 2
24 #elif CONFIG_NRFX_TWIS22
25 #define I2C_S_INSTANCE 22
26 #elif CONFIG_NRFX_TWIS131
27 #define I2C_S_INSTANCE 131
28 #else
29 #error "TWIS instance not enabled or not supported"
30 #endif
31 
32 #define NODE_SENSOR DT_NODELABEL(sensor)
33 #define NODE_TWIS   DT_ALIAS(i2c_slave)
34 
35 #define TWIS_MEMORY_SECTION                                                                        \
36 	COND_CODE_1(DT_NODE_HAS_PROP(NODE_TWIS, memory_regions),                                   \
37 		    (__attribute__((__section__(                                                   \
38 			    LINKER_DT_NODE_REGION_NAME(DT_PHANDLE(NODE_TWIS, memory_regions)))))), \
39 		    ())
40 
41 #define TEST_DATA_SIZE 6
42 static const uint8_t msg[TEST_DATA_SIZE] = "Nordic";
43 static const nrfx_twis_t twis = NRFX_TWIS_INSTANCE(I2C_S_INSTANCE);
44 
45 static uint8_t i2c_slave_buffer[TEST_DATA_SIZE] TWIS_MEMORY_SECTION;
46 static uint8_t i2c_master_buffer[TEST_DATA_SIZE];
47 struct i2c_api_twis_fixture {
48 	const struct device *dev;
49 	uint8_t addr;
50 	uint8_t *const master_buffer;
51 	uint8_t *const slave_buffer;
52 };
53 
i2s_slave_handler(nrfx_twis_evt_t const * p_event)54 void i2s_slave_handler(nrfx_twis_evt_t const *p_event)
55 {
56 	switch (p_event->type) {
57 	case NRFX_TWIS_EVT_READ_REQ:
58 		nrfx_twis_tx_prepare(&twis, i2c_slave_buffer, TEST_DATA_SIZE);
59 		TC_PRINT("TWIS event: read request\n");
60 		break;
61 	case NRFX_TWIS_EVT_READ_DONE:
62 		TC_PRINT("TWIS event: read done\n");
63 		break;
64 	case NRFX_TWIS_EVT_WRITE_REQ:
65 		nrfx_twis_rx_prepare(&twis, i2c_slave_buffer, TEST_DATA_SIZE);
66 		TC_PRINT("TWIS event: write request\n");
67 		break;
68 	case NRFX_TWIS_EVT_WRITE_DONE:
69 		zassert_mem_equal(i2c_slave_buffer, msg, TEST_DATA_SIZE);
70 		TC_PRINT("TWIS event: write done\n");
71 		break;
72 	default:
73 		TC_PRINT("TWIS event: %d\n", p_event->type);
74 		break;
75 	}
76 }
77 
test_setup(void)78 static void *test_setup(void)
79 {
80 	static struct i2c_api_twis_fixture fixture = {
81 		.dev = DEVICE_DT_GET(DT_BUS(NODE_SENSOR)),
82 		.addr = DT_REG_ADDR(NODE_SENSOR),
83 		.master_buffer = i2c_master_buffer,
84 		.slave_buffer = i2c_slave_buffer,
85 	};
86 	const nrfx_twis_config_t config = {
87 		.addr = {fixture.addr, 0},
88 		.skip_gpio_cfg = true,
89 		.skip_psel_cfg = true,
90 	};
91 	int ret;
92 
93 	zassert_equal(NRFX_SUCCESS, nrfx_twis_init(&twis, &config, i2s_slave_handler),
94 		      "TWIS initialization failed");
95 
96 	PINCTRL_DT_DEFINE(NODE_TWIS);
97 	ret = pinctrl_apply_state(PINCTRL_DT_DEV_CONFIG_GET(NODE_TWIS), PINCTRL_STATE_DEFAULT);
98 	zassert_ok(ret);
99 
100 	IRQ_CONNECT(DT_IRQN(NODE_TWIS), DT_IRQ(NODE_TWIS, priority),
101 		    NRFX_TWIS_INST_HANDLER_GET(I2C_S_INSTANCE), NULL, 0);
102 
103 	nrfx_twis_enable(&twis);
104 
105 	return &fixture;
106 }
107 
cleanup_buffers(void * argc)108 static void cleanup_buffers(void *argc)
109 {
110 	struct i2c_api_twis_fixture *fixture = (struct i2c_api_twis_fixture *)argc;
111 
112 	memset(fixture->slave_buffer, 0, TEST_DATA_SIZE);
113 	memset(fixture->master_buffer, 0, TEST_DATA_SIZE);
114 }
115 
ZTEST_USER_F(i2c_api_twis,test_i2c_read_write)116 ZTEST_USER_F(i2c_api_twis, test_i2c_read_write)
117 {
118 	int ret = i2c_write_read(fixture->dev, fixture->addr, msg, TEST_DATA_SIZE,
119 				 fixture->master_buffer, TEST_DATA_SIZE);
120 
121 	zassert_ok(ret);
122 	zassert_mem_equal(fixture->master_buffer, msg, TEST_DATA_SIZE);
123 }
124 
ZTEST_USER_F(i2c_api_twis,test_i2c_read)125 ZTEST_USER_F(i2c_api_twis, test_i2c_read)
126 {
127 	/* Prepare slave data */
128 	strncpy(fixture->slave_buffer, msg, TEST_DATA_SIZE);
129 	zassert_mem_equal(fixture->slave_buffer, msg, TEST_DATA_SIZE);
130 
131 	int ret = i2c_read(fixture->dev, fixture->master_buffer, TEST_DATA_SIZE, fixture->addr);
132 
133 	zassert_ok(ret);
134 	zassert_mem_equal(fixture->master_buffer, msg, TEST_DATA_SIZE);
135 }
136 
ZTEST_USER_F(i2c_api_twis,test_i2c_write)137 ZTEST_USER_F(i2c_api_twis, test_i2c_write)
138 {
139 	int ret = i2c_write(fixture->dev, msg, TEST_DATA_SIZE, fixture->addr);
140 
141 	zassert_ok(ret);
142 	zassert_mem_equal(fixture->slave_buffer, msg, TEST_DATA_SIZE);
143 }
144 
145 ZTEST_SUITE(i2c_api_twis, NULL, test_setup, NULL, cleanup_buffers, NULL);
146