1 /* SPDX-License-Identifier: Apache-2.0 */
2 /*
3  * Copyright © 2023 Calian Ltd.  All rights reserved.
4  *
5  * Driver for the Xilinx AXI IIC Bus Interface.
6  * This is an FPGA logic core as described by Xilinx document PG090.
7  */
8 
9 #include <errno.h>
10 #include <zephyr/drivers/i2c.h>
11 #include <zephyr/sys/util.h>
12 #include <zephyr/logging/log.h>
13 #include <zephyr/irq.h>
14 
15 LOG_MODULE_REGISTER(i2c_xilinx_axi, CONFIG_I2C_LOG_LEVEL);
16 
17 #include "i2c-priv.h"
18 #include "i2c_xilinx_axi.h"
19 
20 struct i2c_xilinx_axi_config {
21 	mem_addr_t base;
22 	void (*irq_config_func)(const struct device *dev);
23 	/* Whether device has working dynamic read (broken prior to core rev. 2.1) */
24 	bool dyn_read_working;
25 };
26 
27 struct i2c_xilinx_axi_data {
28 	struct k_event irq_event;
29 	/* Serializes between ISR and other calls */
30 	struct k_spinlock lock;
31 	/* Provides exclusion against multiple concurrent requests */
32 	struct k_mutex mutex;
33 
34 #if defined(CONFIG_I2C_TARGET)
35 	struct i2c_target_config *target_cfg;
36 	bool target_reading;
37 	bool target_read_aborted;
38 	bool target_writing;
39 #endif
40 };
41 
42 #if defined(CONFIG_I2C_TARGET)
43 
44 #define I2C_XILINX_AXI_TARGET_INTERRUPTS                                                           \
45 	(ISR_ADDR_TARGET | ISR_NOT_ADDR_TARGET | ISR_RX_FIFO_FULL | ISR_TX_FIFO_EMPTY |            \
46 	 ISR_TX_ERR_TARGET_COMP)
47 
i2c_xilinx_axi_target_register(const struct device * dev,struct i2c_target_config * cfg)48 static int i2c_xilinx_axi_target_register(const struct device *dev, struct i2c_target_config *cfg)
49 {
50 	const struct i2c_xilinx_axi_config *config = dev->config;
51 	struct i2c_xilinx_axi_data *data = dev->data;
52 	k_spinlock_key_t key;
53 	uint32_t int_enable;
54 	uint32_t int_status;
55 	int ret;
56 
57 	if (cfg->flags & I2C_TARGET_FLAGS_ADDR_10_BITS) {
58 		/* Optionally supported in core, but not implemented in driver yet */
59 		return -EOPNOTSUPP;
60 	}
61 
62 	k_mutex_lock(&data->mutex, K_FOREVER);
63 	key = k_spin_lock(&data->lock);
64 
65 	if (data->target_cfg) {
66 		ret = -EBUSY;
67 		goto out_unlock;
68 	}
69 
70 	data->target_cfg = cfg;
71 
72 	int_status = sys_read32(config->base + REG_ISR);
73 	if (int_status & I2C_XILINX_AXI_TARGET_INTERRUPTS) {
74 		sys_write32(int_status & I2C_XILINX_AXI_TARGET_INTERRUPTS, config->base + REG_ISR);
75 	}
76 
77 	sys_write32(CR_EN, config->base + REG_CR);
78 	int_enable = sys_read32(config->base + REG_IER);
79 	int_enable |= ISR_ADDR_TARGET;
80 	sys_write32(int_enable, config->base + REG_IER);
81 
82 	sys_write32(cfg->address << 1, config->base + REG_ADR);
83 	sys_write32(0, config->base + REG_RX_FIFO_PIRQ);
84 
85 	ret = 0;
86 
87 out_unlock:
88 	k_spin_unlock(&data->lock, key);
89 	LOG_DBG("Target register ret=%d", ret);
90 	k_mutex_unlock(&data->mutex);
91 	return ret;
92 }
93 
i2c_xilinx_axi_target_unregister(const struct device * dev,struct i2c_target_config * cfg)94 static int i2c_xilinx_axi_target_unregister(const struct device *dev, struct i2c_target_config *cfg)
95 {
96 	const struct i2c_xilinx_axi_config *config = dev->config;
97 	struct i2c_xilinx_axi_data *data = dev->data;
98 	k_spinlock_key_t key;
99 	uint32_t int_enable;
100 	int ret;
101 
102 	k_mutex_lock(&data->mutex, K_FOREVER);
103 	key = k_spin_lock(&data->lock);
104 
105 	if (!data->target_cfg) {
106 		ret = -EINVAL;
107 		goto out_unlock;
108 	}
109 
110 	if (data->target_reading || data->target_writing) {
111 		ret = -EBUSY;
112 		goto out_unlock;
113 	}
114 
115 	data->target_cfg = NULL;
116 	sys_write32(0, config->base + REG_ADR);
117 
118 	sys_write32(CR_EN, config->base + REG_CR);
119 	int_enable = sys_read32(config->base + REG_IER);
120 	int_enable &= ~I2C_XILINX_AXI_TARGET_INTERRUPTS;
121 	sys_write32(int_enable, config->base + REG_IER);
122 
123 	ret = 0;
124 
125 out_unlock:
126 	k_spin_unlock(&data->lock, key);
127 	LOG_DBG("Target unregister ret=%d", ret);
128 	k_mutex_unlock(&data->mutex);
129 	return ret;
130 }
131 
i2c_xilinx_axi_target_isr(const struct i2c_xilinx_axi_config * config,struct i2c_xilinx_axi_data * data,uint32_t int_status,uint32_t * ints_to_clear,uint32_t * int_enable)132 static void i2c_xilinx_axi_target_isr(const struct i2c_xilinx_axi_config *config,
133 				      struct i2c_xilinx_axi_data *data, uint32_t int_status,
134 				      uint32_t *ints_to_clear, uint32_t *int_enable)
135 {
136 	if (int_status & ISR_ADDR_TARGET) {
137 		LOG_DBG("Addressed as target");
138 		*int_enable &= ~ISR_ADDR_TARGET;
139 		*int_enable |= ISR_NOT_ADDR_TARGET;
140 		*ints_to_clear |= ISR_NOT_ADDR_TARGET;
141 
142 		if (sys_read32(config->base + REG_SR) & SR_SRW) {
143 			uint8_t read_byte;
144 
145 			data->target_reading = true;
146 			*ints_to_clear |= ISR_TX_FIFO_EMPTY | ISR_TX_ERR_TARGET_COMP;
147 			*int_enable |= ISR_TX_FIFO_EMPTY | ISR_TX_ERR_TARGET_COMP;
148 			if ((*data->target_cfg->callbacks->read_requested)(data->target_cfg,
149 									   &read_byte)) {
150 				LOG_DBG("target read_requested rejected");
151 				data->target_read_aborted = true;
152 				read_byte = 0xFF;
153 			}
154 			sys_write32(read_byte, config->base + REG_TX_FIFO);
155 		} else {
156 			data->target_writing = true;
157 			*int_enable |= ISR_RX_FIFO_FULL;
158 			if ((*data->target_cfg->callbacks->write_requested)(data->target_cfg)) {
159 				uint32_t cr = sys_read32(config->base + REG_CR);
160 
161 				LOG_DBG("target write_requested rejected");
162 				cr |= CR_TXAK;
163 				sys_write32(cr, config->base + REG_CR);
164 			}
165 		}
166 	} else if (int_status & ISR_NOT_ADDR_TARGET) {
167 		LOG_DBG("Not addressed as target");
168 		(*data->target_cfg->callbacks->stop)(data->target_cfg);
169 		data->target_reading = false;
170 		data->target_read_aborted = false;
171 		data->target_writing = false;
172 
173 		sys_write32(CR_EN, config->base + REG_CR);
174 		*int_enable &= ~I2C_XILINX_AXI_TARGET_INTERRUPTS;
175 		*int_enable |= ISR_ADDR_TARGET;
176 		*ints_to_clear |= ISR_ADDR_TARGET;
177 	} else if (int_status & ISR_RX_FIFO_FULL) {
178 		const uint8_t written_byte =
179 			sys_read32(config->base + REG_RX_FIFO) & RX_FIFO_DATA_MASK;
180 
181 		if ((*data->target_cfg->callbacks->write_received)(data->target_cfg,
182 								   written_byte)) {
183 			uint32_t cr = sys_read32(config->base + REG_CR);
184 
185 			LOG_DBG("target write_received rejected");
186 			cr |= CR_TXAK;
187 			sys_write32(cr, config->base + REG_CR);
188 		}
189 	} else if (int_status & ISR_TX_ERR_TARGET_COMP) {
190 		if (data->target_reading) {
191 			/* Controller has NAKed the last byte read, so no more to send.
192 			 * Ignore TX FIFO empty so we don't write an extra byte.
193 			 */
194 			LOG_DBG("target read completed");
195 			*int_enable &= ~ISR_TX_FIFO_EMPTY;
196 			*ints_to_clear |= ISR_TX_FIFO_EMPTY;
197 		} else {
198 			LOG_WRN("Unexpected TX complete");
199 		}
200 	} else if (int_status & ISR_TX_FIFO_EMPTY) {
201 		if (data->target_reading) {
202 			uint8_t read_byte = 0xFF;
203 
204 			if (!data->target_read_aborted &&
205 			    (*data->target_cfg->callbacks->read_processed)(data->target_cfg,
206 									   &read_byte)) {
207 				LOG_DBG("target read_processed rejected");
208 				data->target_read_aborted = true;
209 			}
210 			sys_write32(read_byte, config->base + REG_TX_FIFO);
211 		} else {
212 			LOG_WRN("Unexpected TX empty");
213 		}
214 	}
215 }
216 #endif
217 
i2c_xilinx_axi_isr(const struct device * dev)218 static void i2c_xilinx_axi_isr(const struct device *dev)
219 {
220 	const struct i2c_xilinx_axi_config *config = dev->config;
221 	struct i2c_xilinx_axi_data *data = dev->data;
222 	const k_spinlock_key_t key = k_spin_lock(&data->lock);
223 	uint32_t int_enable = sys_read32(config->base + REG_IER);
224 	const uint32_t int_status = sys_read32(config->base + REG_ISR) & int_enable;
225 	uint32_t ints_to_clear = int_status;
226 	uint32_t ints_to_mask = int_status;
227 
228 	LOG_DBG("ISR called for 0x%08" PRIxPTR ", status 0x%02x", config->base, int_status);
229 
230 	if (int_status & ISR_ARB_LOST) {
231 		/* Must clear MSMS before clearing interrupt */
232 		uint32_t cr = sys_read32(config->base + REG_CR);
233 
234 		cr &= ~CR_MSMS;
235 		sys_write32(cr, config->base + REG_CR);
236 	}
237 
238 #if defined(CONFIG_I2C_TARGET)
239 	if (data->target_cfg && (int_status & I2C_XILINX_AXI_TARGET_INTERRUPTS)) {
240 		ints_to_mask &= ~(int_status & I2C_XILINX_AXI_TARGET_INTERRUPTS);
241 		i2c_xilinx_axi_target_isr(config, data, int_status, &ints_to_clear, &int_enable);
242 	}
243 #endif
244 
245 	sys_write32(int_enable & ~ints_to_mask, config->base + REG_IER);
246 	/* Be careful, writing 1 to a bit that is not currently set in ISR will SET it! */
247 	sys_write32(ints_to_clear & sys_read32(config->base + REG_ISR), config->base + REG_ISR);
248 
249 	k_spin_unlock(&data->lock, key);
250 	k_event_post(&data->irq_event, int_status);
251 }
252 
i2c_xilinx_axi_reinit(const struct i2c_xilinx_axi_config * config)253 static void i2c_xilinx_axi_reinit(const struct i2c_xilinx_axi_config *config)
254 {
255 	LOG_DBG("Controller reinit");
256 	sys_write32(SOFTR_KEY, config->base + REG_SOFTR);
257 	sys_write32(CR_TX_FIFO_RST, config->base + REG_CR);
258 	sys_write32(CR_EN, config->base + REG_CR);
259 	sys_write32(GIE_ENABLE, config->base + REG_GIE);
260 }
261 
i2c_xilinx_axi_configure(const struct device * dev,uint32_t dev_config)262 static int i2c_xilinx_axi_configure(const struct device *dev, uint32_t dev_config)
263 {
264 	const struct i2c_xilinx_axi_config *config = dev->config;
265 
266 	LOG_INF("Configuring %s at 0x%08" PRIxPTR, dev->name, config->base);
267 	i2c_xilinx_axi_reinit(config);
268 	return 0;
269 }
270 
i2c_xilinx_axi_wait_interrupt(const struct i2c_xilinx_axi_config * config,struct i2c_xilinx_axi_data * data,uint32_t int_mask)271 static uint32_t i2c_xilinx_axi_wait_interrupt(const struct i2c_xilinx_axi_config *config,
272 					      struct i2c_xilinx_axi_data *data, uint32_t int_mask)
273 {
274 	const k_spinlock_key_t key = k_spin_lock(&data->lock);
275 	const uint32_t int_enable = sys_read32(config->base + REG_IER) | int_mask;
276 	uint32_t events;
277 
278 	LOG_DBG("Set IER to 0x%02x", int_enable);
279 	sys_write32(int_enable, config->base + REG_IER);
280 	k_event_clear(&data->irq_event, int_mask);
281 	k_spin_unlock(&data->lock, key);
282 
283 	events = k_event_wait(&data->irq_event, int_mask, false, K_MSEC(100));
284 
285 	LOG_DBG("Got ISR events 0x%02x", events);
286 	if (!events) {
287 		LOG_ERR("Timeout waiting for ISR events 0x%02x, SR 0x%02x, ISR 0x%02x", int_mask,
288 			sys_read32(config->base + REG_SR), sys_read32(config->base + REG_ISR));
289 	}
290 	return events;
291 }
292 
i2c_xilinx_axi_clear_interrupt(const struct i2c_xilinx_axi_config * config,struct i2c_xilinx_axi_data * data,uint32_t int_mask)293 static void i2c_xilinx_axi_clear_interrupt(const struct i2c_xilinx_axi_config *config,
294 					   struct i2c_xilinx_axi_data *data, uint32_t int_mask)
295 {
296 	const k_spinlock_key_t key = k_spin_lock(&data->lock);
297 	const uint32_t int_status = sys_read32(config->base + REG_ISR);
298 
299 	if (int_status & int_mask) {
300 		sys_write32(int_status & int_mask, config->base + REG_ISR);
301 	}
302 	k_spin_unlock(&data->lock, key);
303 }
304 
i2c_xilinx_axi_wait_rx_full(const struct i2c_xilinx_axi_config * config,struct i2c_xilinx_axi_data * data,uint32_t read_bytes)305 static int i2c_xilinx_axi_wait_rx_full(const struct i2c_xilinx_axi_config *config,
306 				       struct i2c_xilinx_axi_data *data, uint32_t read_bytes)
307 {
308 	uint32_t events;
309 
310 	i2c_xilinx_axi_clear_interrupt(config, data, ISR_RX_FIFO_FULL);
311 	if (!(sys_read32(config->base + REG_SR) & SR_RX_FIFO_EMPTY) &&
312 	    (sys_read32(config->base + REG_RX_FIFO_OCY) & RX_FIFO_OCY_MASK) + 1 >= read_bytes) {
313 		LOG_DBG("RX already full on checking, SR 0x%02x RXOCY 0x%02x",
314 			sys_read32(config->base + REG_SR),
315 			sys_read32(config->base + REG_RX_FIFO_OCY));
316 		return 0;
317 	}
318 	events = i2c_xilinx_axi_wait_interrupt(config, data, ISR_RX_FIFO_FULL | ISR_ARB_LOST);
319 	if (!events) {
320 		return -ETIMEDOUT;
321 	}
322 	if (events & ISR_ARB_LOST) {
323 		LOG_ERR("Arbitration lost on RX");
324 		return -ENXIO;
325 	}
326 	return 0;
327 }
328 
i2c_xilinx_axi_read_nondyn(const struct i2c_xilinx_axi_config * config,struct i2c_xilinx_axi_data * data,struct i2c_msg * msg,uint16_t addr)329 static int i2c_xilinx_axi_read_nondyn(const struct i2c_xilinx_axi_config *config,
330 				      struct i2c_xilinx_axi_data *data, struct i2c_msg *msg,
331 				      uint16_t addr)
332 {
333 	uint8_t *read_ptr = msg->buf;
334 	uint32_t bytes_left = msg->len;
335 	uint32_t cr = CR_EN | CR_MSMS;
336 
337 	if (!bytes_left) {
338 		return -EINVAL;
339 	}
340 	if (bytes_left == 1) {
341 		/* Set TXAK bit now, to NAK after the first byte is received */
342 		cr |= CR_TXAK;
343 	}
344 
345 	/**
346 	 * The Xilinx core's RX FIFO full logic seems rather broken in that the interrupt
347 	 * is triggered, and the I2C receive is throttled, only when the FIFO occupancy
348 	 * equals the PIRQ threshold, not when greater or equal. In the non-dynamic mode
349 	 * of operation, we need to stop the read prior to the last bytes being received
350 	 * from the target in order to set the TXAK bit and clear MSMS to terminate the
351 	 * receive properly.
352 	 * However, if we previously allowed multiple bytes into the RX FIFO, this requires
353 	 * reducing the PIRQ threshold to 0 (single byte) during the receive operation. This
354 	 * can cause the receive to unthrottle (since FIFO occupancy now exceeds PIRQ
355 	 * threshold) and depending on timing between the driver code and the core,
356 	 * this can cause the core to try to receive more data into the FIFO than desired
357 	 * and cause various unexpected results.
358 	 *
359 	 * To avoid this, we only receive one byte at a time in the non-dynamic mode.
360 	 * Dynamic mode doesn't have this issue as it provides the RX byte count to the
361 	 * controller specifically and the TXAK and MSMS bits are handled automatically.
362 	 */
363 	sys_write32(0, config->base + REG_RX_FIFO_PIRQ);
364 
365 	if (msg->flags & I2C_MSG_RESTART) {
366 		cr |= CR_RSTA;
367 
368 		sys_write32(cr, config->base + REG_CR);
369 		sys_write32((addr << 1) | I2C_MSG_READ, config->base + REG_TX_FIFO);
370 	} else {
371 		sys_write32((addr << 1) | I2C_MSG_READ, config->base + REG_TX_FIFO);
372 		sys_write32(cr, config->base + REG_CR);
373 	}
374 
375 	while (bytes_left) {
376 		int ret = i2c_xilinx_axi_wait_rx_full(config, data, 1);
377 
378 		if (ret) {
379 			return ret;
380 		}
381 
382 		if (bytes_left == 2) {
383 			/* Set TXAK so the last byte is NAKed */
384 			cr |= CR_TXAK;
385 		} else if (bytes_left == 1 && (msg->flags & I2C_MSG_STOP)) {
386 			/* Before reading the last byte, clear MSMS to issue a stop if required */
387 			cr &= ~CR_MSMS;
388 		}
389 		cr &= ~CR_RSTA;
390 		sys_write32(cr, config->base + REG_CR);
391 
392 		*read_ptr++ = sys_read32(config->base + REG_RX_FIFO) & RX_FIFO_DATA_MASK;
393 		bytes_left--;
394 	}
395 	return 0;
396 }
397 
i2c_xilinx_axi_read_dyn(const struct i2c_xilinx_axi_config * config,struct i2c_xilinx_axi_data * data,struct i2c_msg * msg,uint16_t addr)398 static int i2c_xilinx_axi_read_dyn(const struct i2c_xilinx_axi_config *config,
399 				   struct i2c_xilinx_axi_data *data, struct i2c_msg *msg,
400 				   uint16_t addr)
401 {
402 	uint8_t *read_ptr = msg->buf;
403 	uint32_t bytes_left = msg->len;
404 	uint32_t bytes_to_read = bytes_left;
405 	uint32_t cr = CR_EN;
406 	uint32_t len_word = bytes_left;
407 
408 	if (!bytes_left || bytes_left > MAX_DYNAMIC_READ_LEN) {
409 		return -EINVAL;
410 	}
411 	if (msg->flags & I2C_MSG_RESTART) {
412 		cr |= CR_MSMS | CR_RSTA;
413 	}
414 	sys_write32(cr, config->base + REG_CR);
415 
416 	if (bytes_to_read > FIFO_SIZE) {
417 		bytes_to_read = FIFO_SIZE;
418 	}
419 	sys_write32(bytes_to_read - 1, config->base + REG_RX_FIFO_PIRQ);
420 	sys_write32((addr << 1) | I2C_MSG_READ | TX_FIFO_START, config->base + REG_TX_FIFO);
421 
422 	if (msg->flags & I2C_MSG_STOP) {
423 		len_word |= TX_FIFO_STOP;
424 	}
425 	sys_write32(len_word, config->base + REG_TX_FIFO);
426 
427 	while (bytes_left) {
428 		int ret;
429 
430 		bytes_to_read = bytes_left;
431 		if (bytes_to_read > FIFO_SIZE) {
432 			bytes_to_read = FIFO_SIZE;
433 		}
434 
435 		sys_write32(bytes_to_read - 1, config->base + REG_RX_FIFO_PIRQ);
436 		ret = i2c_xilinx_axi_wait_rx_full(config, data, bytes_to_read);
437 		if (ret) {
438 			return ret;
439 		}
440 
441 		while (bytes_to_read) {
442 			*read_ptr++ = sys_read32(config->base + REG_RX_FIFO) & RX_FIFO_DATA_MASK;
443 			bytes_to_read--;
444 			bytes_left--;
445 		}
446 	}
447 	return 0;
448 }
449 
i2c_xilinx_axi_wait_tx_done(const struct i2c_xilinx_axi_config * config,struct i2c_xilinx_axi_data * data)450 static int i2c_xilinx_axi_wait_tx_done(const struct i2c_xilinx_axi_config *config,
451 				       struct i2c_xilinx_axi_data *data)
452 {
453 	const uint32_t finish_bits = ISR_BUS_NOT_BUSY | ISR_TX_FIFO_EMPTY;
454 
455 	uint32_t events = i2c_xilinx_axi_wait_interrupt(
456 		config, data, finish_bits | ISR_TX_ERR_TARGET_COMP | ISR_ARB_LOST);
457 	if (!(events & finish_bits) || (events & ~finish_bits)) {
458 		if (!events) {
459 			return -ETIMEDOUT;
460 		}
461 		if (events & ISR_ARB_LOST) {
462 			LOG_ERR("Arbitration lost on TX");
463 			return -EAGAIN;
464 		}
465 		LOG_ERR("TX received NAK");
466 		return -ENXIO;
467 	}
468 	return 0;
469 }
470 
i2c_xilinx_axi_wait_not_busy(const struct i2c_xilinx_axi_config * config,struct i2c_xilinx_axi_data * data)471 static int i2c_xilinx_axi_wait_not_busy(const struct i2c_xilinx_axi_config *config,
472 					struct i2c_xilinx_axi_data *data)
473 {
474 	if (sys_read32(config->base + REG_SR) & SR_BB) {
475 		uint32_t events = i2c_xilinx_axi_wait_interrupt(config, data, ISR_BUS_NOT_BUSY);
476 
477 		if (events != ISR_BUS_NOT_BUSY) {
478 			LOG_ERR("Bus stuck busy");
479 			i2c_xilinx_axi_reinit(config);
480 			return -EBUSY;
481 		}
482 	}
483 	return 0;
484 }
485 
i2c_xilinx_axi_write(const struct i2c_xilinx_axi_config * config,struct i2c_xilinx_axi_data * data,const struct i2c_msg * msg,uint16_t addr)486 static int i2c_xilinx_axi_write(const struct i2c_xilinx_axi_config *config,
487 				struct i2c_xilinx_axi_data *data, const struct i2c_msg *msg,
488 				uint16_t addr)
489 {
490 	const uint8_t *write_ptr = msg->buf;
491 	uint32_t bytes_left = msg->len;
492 	uint32_t cr = CR_EN | CR_TX;
493 	uint32_t fifo_space = FIFO_SIZE - 1; /* account for address being written */
494 
495 	if (msg->flags & I2C_MSG_RESTART) {
496 		cr |= CR_MSMS | CR_RSTA;
497 	}
498 
499 	i2c_xilinx_axi_clear_interrupt(config, data, ISR_TX_ERR_TARGET_COMP | ISR_ARB_LOST);
500 
501 	sys_write32(cr, config->base + REG_CR);
502 	sys_write32((addr << 1) | TX_FIFO_START, config->base + REG_TX_FIFO);
503 
504 	/* TX FIFO empty detection is somewhat fragile because the status register
505 	 * TX_FIFO_EMPTY bit can be set prior to the transaction actually being
506 	 * complete, so we have to rely on the TX empty interrupt.
507 	 * However, delays in writing data to the TX FIFO could cause it
508 	 * to run empty in the middle of the process, causing us to get a spurious
509 	 * completion detection from the interrupt. Therefore we disable interrupts
510 	 * while the TX FIFO is being filled up to try to avoid this.
511 	 */
512 
513 	while (bytes_left) {
514 		uint32_t bytes_to_send = bytes_left;
515 		const k_spinlock_key_t key = k_spin_lock(&data->lock);
516 		int ret;
517 
518 		if (bytes_to_send > fifo_space) {
519 			bytes_to_send = fifo_space;
520 		}
521 		while (bytes_to_send) {
522 			uint32_t write_word = *write_ptr++;
523 
524 			if (bytes_left == 1 && (msg->flags & I2C_MSG_STOP)) {
525 				write_word |= TX_FIFO_STOP;
526 			}
527 			sys_write32(write_word, config->base + REG_TX_FIFO);
528 			bytes_to_send--;
529 			bytes_left--;
530 		}
531 		i2c_xilinx_axi_clear_interrupt(config, data, ISR_TX_FIFO_EMPTY | ISR_BUS_NOT_BUSY);
532 		k_spin_unlock(&data->lock, key);
533 
534 		ret = i2c_xilinx_axi_wait_tx_done(config, data);
535 		if (ret) {
536 			return ret;
537 		}
538 		fifo_space = FIFO_SIZE;
539 	}
540 	return 0;
541 }
542 
i2c_xilinx_axi_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)543 static int i2c_xilinx_axi_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs,
544 				   uint16_t addr)
545 {
546 	const struct i2c_xilinx_axi_config *config = dev->config;
547 	struct i2c_xilinx_axi_data *data = dev->data;
548 	int ret;
549 
550 	k_mutex_lock(&data->mutex, K_FOREVER);
551 
552 	/**
553 	 * Reinitializing before each transfer shouldn't technically be needed, but
554 	 * seems to improve general reliability. The Linux driver also does this.
555 	 */
556 	i2c_xilinx_axi_reinit(config);
557 
558 	ret = i2c_xilinx_axi_wait_not_busy(config, data);
559 	if (ret) {
560 		goto out_unlock;
561 	}
562 
563 	if (!num_msgs) {
564 		goto out_unlock;
565 	}
566 
567 	do {
568 		if (msgs->flags & I2C_MSG_ADDR_10_BITS) {
569 			/* Optionally supported in core, but not implemented in driver yet */
570 			ret = -EOPNOTSUPP;
571 			goto out_unlock;
572 		}
573 		if (msgs->flags & I2C_MSG_READ) {
574 			if (config->dyn_read_working && msgs->len <= MAX_DYNAMIC_READ_LEN) {
575 				ret = i2c_xilinx_axi_read_dyn(config, data, msgs, addr);
576 			} else {
577 				ret = i2c_xilinx_axi_read_nondyn(config, data, msgs, addr);
578 			}
579 		} else {
580 			ret = i2c_xilinx_axi_write(config, data, msgs, addr);
581 		}
582 		if (!ret && (msgs->flags & I2C_MSG_STOP)) {
583 			ret = i2c_xilinx_axi_wait_not_busy(config, data);
584 		}
585 		if (ret) {
586 			goto out_unlock;
587 		}
588 		msgs++;
589 		num_msgs--;
590 	} while (num_msgs);
591 
592 out_unlock:
593 	k_mutex_unlock(&data->mutex);
594 	return ret;
595 }
596 
i2c_xilinx_axi_init(const struct device * dev)597 static int i2c_xilinx_axi_init(const struct device *dev)
598 {
599 	const struct i2c_xilinx_axi_config *config = dev->config;
600 	struct i2c_xilinx_axi_data *data = dev->data;
601 	int error;
602 
603 	k_event_init(&data->irq_event);
604 	k_mutex_init(&data->mutex);
605 
606 	error = i2c_xilinx_axi_configure(dev, I2C_MODE_CONTROLLER);
607 	if (error) {
608 		return error;
609 	}
610 
611 	config->irq_config_func(dev);
612 
613 	LOG_INF("initialized");
614 	return 0;
615 }
616 
617 static const struct i2c_driver_api i2c_xilinx_axi_driver_api = {
618 	.configure = i2c_xilinx_axi_configure,
619 	.transfer = i2c_xilinx_axi_transfer,
620 #if defined(CONFIG_I2C_TARGET)
621 	.target_register = i2c_xilinx_axi_target_register,
622 	.target_unregister = i2c_xilinx_axi_target_unregister,
623 #endif
624 };
625 
626 #define I2C_XILINX_AXI_INIT(n, compat)                                                             \
627 	static void i2c_xilinx_axi_config_func_##compat##_##n(const struct device *dev);           \
628                                                                                                    \
629 	static const struct i2c_xilinx_axi_config i2c_xilinx_axi_config_##compat##_##n = {         \
630 		.base = DT_INST_REG_ADDR(n),                                                       \
631 		.irq_config_func = i2c_xilinx_axi_config_func_##compat##_##n,                      \
632 		.dyn_read_working = DT_NODE_HAS_COMPAT(DT_DRV_INST(n), xlnx_xps_iic_2_1)};         \
633                                                                                                    \
634 	static struct i2c_xilinx_axi_data i2c_xilinx_axi_data_##compat##_##n;                      \
635                                                                                                    \
636 	I2C_DEVICE_DT_INST_DEFINE(n, i2c_xilinx_axi_init, NULL,                                    \
637 				  &i2c_xilinx_axi_data_##compat##_##n,                             \
638 				  &i2c_xilinx_axi_config_##compat##_##n, POST_KERNEL,              \
639 				  CONFIG_I2C_INIT_PRIORITY, &i2c_xilinx_axi_driver_api);           \
640                                                                                                    \
641 	static void i2c_xilinx_axi_config_func_##compat##_##n(const struct device *dev)            \
642 	{                                                                                          \
643 		ARG_UNUSED(dev);                                                                   \
644                                                                                                    \
645 		IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), i2c_xilinx_axi_isr,         \
646 			    DEVICE_DT_INST_GET(n), 0);                                             \
647                                                                                                    \
648 		irq_enable(DT_INST_IRQN(n));                                                       \
649 	}
650 
651 #define DT_DRV_COMPAT xlnx_xps_iic_2_1
652 DT_INST_FOREACH_STATUS_OKAY_VARGS(I2C_XILINX_AXI_INIT, DT_DRV_COMPAT)
653 #undef DT_DRV_COMPAT
654 #define DT_DRV_COMPAT xlnx_xps_iic_2_00_a
655 DT_INST_FOREACH_STATUS_OKAY_VARGS(I2C_XILINX_AXI_INIT, DT_DRV_COMPAT)
656