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