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