1 /*
2  * Copyright (c) 2018, Nordic Semiconductor ASA
3  * Copyright (c) 2024, Croxel Inc
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/drivers/i2c.h>
9 #include <zephyr/drivers/i2c/rtio.h>
10 #include <zephyr/dt-bindings/i2c/i2c.h>
11 #include <zephyr/pm/device.h>
12 #include <zephyr/drivers/pinctrl.h>
13 #include <soc.h>
14 #include <nrfx_twi.h>
15 #include "i2c_nrfx_twi_common.h"
16 
17 #include <zephyr/logging/log.h>
18 #include <zephyr/irq.h>
19 LOG_MODULE_REGISTER(i2c_nrfx_twi, CONFIG_I2C_LOG_LEVEL);
20 
21 struct i2c_nrfx_twi_rtio_data {
22 	uint32_t dev_config;
23 	bool twi_enabled;
24 	struct i2c_rtio *ctx;
25 };
26 
27 /* Enforce dev_config matches the same offset as the common structure,
28  * otherwise common API won't be compatible with i2c_nrfx_twi_rtio.
29  */
30 BUILD_ASSERT(
31 	offsetof(struct i2c_nrfx_twi_rtio_data, dev_config) ==
32 	offsetof(struct i2c_nrfx_twi_common_data, dev_config)
33 );
34 
35 static void i2c_nrfx_twi_rtio_complete(const struct device *dev, int status);
36 
i2c_nrfx_twi_rtio_msg_start(const struct device * dev,uint8_t flags,uint8_t * buf,size_t buf_len,uint16_t i2c_addr)37 static bool i2c_nrfx_twi_rtio_msg_start(const struct device *dev, uint8_t flags,
38 					uint8_t *buf, size_t buf_len, uint16_t i2c_addr)
39 {
40 	const struct i2c_nrfx_twi_config *config = dev->config;
41 	struct i2c_nrfx_twi_rtio_data *const dev_data = dev->data;
42 	struct i2c_rtio *ctx = dev_data->ctx;
43 	int ret = 0;
44 
45 	/** Enabling while already enabled ends up in a failed assertion: skip it. */
46 	if (!dev_data->twi_enabled) {
47 		nrfx_twi_enable(&config->twi);
48 		dev_data->twi_enabled = true;
49 	}
50 
51 	ret = i2c_nrfx_twi_msg_transfer(dev, flags, buf, buf_len, i2c_addr, false);
52 	if (ret != 0) {
53 		nrfx_twi_disable(&config->twi);
54 		dev_data->twi_enabled = false;
55 
56 		return i2c_rtio_complete(ctx, ret);
57 	}
58 
59 	return false;
60 }
61 
i2c_nrfx_twi_rtio_start(const struct device * dev)62 static bool i2c_nrfx_twi_rtio_start(const struct device *dev)
63 {
64 	struct i2c_nrfx_twi_rtio_data *const dev_data = dev->data;
65 	struct i2c_rtio *ctx = dev_data->ctx;
66 	struct rtio_sqe *sqe = &ctx->txn_curr->sqe;
67 	struct i2c_dt_spec *dt_spec = sqe->iodev->data;
68 
69 	switch (sqe->op) {
70 	case RTIO_OP_RX:
71 		return i2c_nrfx_twi_rtio_msg_start(dev, I2C_MSG_READ | sqe->iodev_flags,
72 						   sqe->rx.buf, sqe->rx.buf_len, dt_spec->addr);
73 	case RTIO_OP_TINY_TX:
74 		return i2c_nrfx_twi_rtio_msg_start(dev, I2C_MSG_WRITE | sqe->iodev_flags,
75 						   (uint8_t *)sqe->tiny_tx.buf,
76 						   sqe->tiny_tx.buf_len, dt_spec->addr);
77 	case RTIO_OP_TX:
78 		return i2c_nrfx_twi_rtio_msg_start(dev, I2C_MSG_WRITE | sqe->iodev_flags,
79 						   (uint8_t *)sqe->tx.buf,
80 						   sqe->tx.buf_len, dt_spec->addr);
81 	case RTIO_OP_I2C_CONFIGURE:
82 		(void)i2c_nrfx_twi_configure(dev, sqe->i2c_config);
83 		return false;
84 	case RTIO_OP_I2C_RECOVER:
85 		(void)i2c_nrfx_twi_recover_bus(dev);
86 		return false;
87 	default:
88 		LOG_ERR("Invalid op code %d for submission %p\n", sqe->op, (void *)sqe);
89 		return i2c_rtio_complete(ctx, -EINVAL);
90 	}
91 }
92 
i2c_nrfx_twi_rtio_complete(const struct device * dev,int status)93 static void i2c_nrfx_twi_rtio_complete(const struct device *dev, int status)
94 {
95 	/** Finalize if there are no more pending xfers */
96 	const struct i2c_nrfx_twi_config *config = dev->config;
97 	struct i2c_nrfx_twi_rtio_data *data = dev->data;
98 	struct i2c_rtio *const ctx = data->ctx;
99 
100 	if (i2c_rtio_complete(ctx, status)) {
101 		(void)i2c_nrfx_twi_rtio_start(dev);
102 	} else {
103 		nrfx_twi_disable(&config->twi);
104 		data->twi_enabled = false;
105 	}
106 }
107 
i2c_nrfx_twi_rtio_configure(const struct device * dev,uint32_t i2c_config)108 static int i2c_nrfx_twi_rtio_configure(const struct device *dev, uint32_t i2c_config)
109 {
110 	struct i2c_rtio *const ctx = ((struct i2c_nrfx_twi_rtio_data *)
111 		dev->data)->ctx;
112 
113 	return i2c_rtio_configure(ctx, i2c_config);
114 }
115 
i2c_nrfx_twi_rtio_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)116 static int i2c_nrfx_twi_rtio_transfer(const struct device *dev, struct i2c_msg *msgs,
117 				      uint8_t num_msgs, uint16_t addr)
118 {
119 	struct i2c_rtio *const ctx = ((struct i2c_nrfx_twi_rtio_data *)
120 		dev->data)->ctx;
121 
122 	return i2c_rtio_transfer(ctx, msgs, num_msgs, addr);
123 }
124 
i2c_nrfx_twi_rtio_recover_bus(const struct device * dev)125 static int i2c_nrfx_twi_rtio_recover_bus(const struct device *dev)
126 {
127 	struct i2c_rtio *const ctx = ((struct i2c_nrfx_twi_rtio_data *)
128 		dev->data)->ctx;
129 
130 	return i2c_rtio_recover(ctx);
131 }
132 
event_handler(nrfx_twi_evt_t const * p_event,void * p_context)133 static void event_handler(nrfx_twi_evt_t const *p_event, void *p_context)
134 {
135 	const struct device *dev = p_context;
136 	int status = 0;
137 
138 	if (i2c_nrfx_twi_get_evt_result(p_event) != NRFX_SUCCESS) {
139 		status = -EIO;
140 	}
141 
142 	i2c_nrfx_twi_rtio_complete(dev, status);
143 }
144 
i2c_nrfx_twi_rtio_submit(const struct device * dev,struct rtio_iodev_sqe * iodev_seq)145 static void i2c_nrfx_twi_rtio_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_seq)
146 {
147 	struct i2c_nrfx_twi_rtio_data *data = dev->data;
148 	struct i2c_rtio *const ctx = data->ctx;
149 
150 	if (i2c_rtio_submit(ctx, iodev_seq)) {
151 		(void)i2c_nrfx_twi_rtio_start(dev);
152 	}
153 }
154 
155 static DEVICE_API(i2c, i2c_nrfx_twi_rtio_driver_api) = {
156 	.configure   = i2c_nrfx_twi_rtio_configure,
157 	.transfer    = i2c_nrfx_twi_rtio_transfer,
158 	.recover_bus = i2c_nrfx_twi_rtio_recover_bus,
159 	.iodev_submit = i2c_nrfx_twi_rtio_submit,
160 };
161 
162 #define I2C_NRFX_TWI_RTIO_DEVICE(idx)					       \
163 	NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(I2C(idx));			       \
164 	BUILD_ASSERT(I2C_FREQUENCY(idx)	!=				       \
165 		     I2C_NRFX_TWI_INVALID_FREQUENCY,			       \
166 		     "Wrong I2C " #idx " frequency setting in dts");	       \
167 	static int twi_##idx##_init(const struct device *dev)		       \
168 	{								       \
169 		IRQ_CONNECT(DT_IRQN(I2C(idx)), DT_IRQ(I2C(idx), priority),     \
170 			    nrfx_isr, nrfx_twi_##idx##_irq_handler, 0);	       \
171 		const struct i2c_nrfx_twi_config *config = dev->config;	       \
172 		const struct i2c_nrfx_twi_rtio_data *dev_data = dev->data;     \
173 		int err = pinctrl_apply_state(config->pcfg,		       \
174 					      PINCTRL_STATE_DEFAULT);	       \
175 		if (err < 0) {						       \
176 			return err;					       \
177 		}							       \
178 		i2c_rtio_init(dev_data->ctx, dev);			       \
179 		return i2c_nrfx_twi_init(dev);				       \
180 	}								       \
181 	I2C_RTIO_DEFINE(_i2c##idx##_twi_rtio,				       \
182 			DT_INST_PROP_OR(n, sq_size, CONFIG_I2C_RTIO_SQ_SIZE),  \
183 			DT_INST_PROP_OR(n, cq_size, CONFIG_I2C_RTIO_CQ_SIZE)); \
184 	static struct i2c_nrfx_twi_rtio_data twi_##idx##_data = {	       \
185 		.ctx = &_i2c##idx##_twi_rtio,				       \
186 	};								       \
187 	PINCTRL_DT_DEFINE(I2C(idx));					       \
188 	static const struct i2c_nrfx_twi_config twi_##idx##z_config = {	       \
189 		.twi = NRFX_TWI_INSTANCE(idx),				       \
190 		.config = {						       \
191 			.skip_gpio_cfg = true,				       \
192 			.skip_psel_cfg = true,				       \
193 			.frequency = I2C_FREQUENCY(idx),		       \
194 		},							       \
195 		.event_handler = event_handler,				       \
196 		.pcfg = PINCTRL_DT_DEV_CONFIG_GET(I2C(idx)),		       \
197 	};								       \
198 	PM_DEVICE_DT_DEFINE(I2C(idx), twi_nrfx_pm_action);		       \
199 	I2C_DEVICE_DT_DEFINE(I2C(idx),					       \
200 		      twi_##idx##_init,					       \
201 		      PM_DEVICE_DT_GET(I2C(idx)),			       \
202 		      &twi_##idx##_data,				       \
203 		      &twi_##idx##z_config,				       \
204 		      POST_KERNEL,					       \
205 		      CONFIG_I2C_INIT_PRIORITY,				       \
206 		      &i2c_nrfx_twi_rtio_driver_api)
207 
208 #ifdef CONFIG_HAS_HW_NRF_TWI0
209 I2C_NRFX_TWI_RTIO_DEVICE(0);
210 #endif
211 
212 #ifdef CONFIG_HAS_HW_NRF_TWI1
213 I2C_NRFX_TWI_RTIO_DEVICE(1);
214 #endif
215