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