File indexing completed on 2025-05-11 08:24:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <stdarg.h>
0016
0017 #include <rtems.h>
0018 #include <rtems/bspIo.h>
0019 #include <rtems/irq-extension.h>
0020 #include <rtems/score/assert.h>
0021
0022 #include <dev/i2c/i2c.h>
0023 #include <dev/i2c/xilinx-axi-i2c.h>
0024
0025
0026
0027
0028 #define REG_GIE 0x01c
0029 #define REG_ISR 0x020
0030 #define REG_IER 0x028
0031 #define REG_SOFTR 0x040
0032 #define REG_CR 0x100
0033 #define REG_SR 0x104
0034 #define REG_TX_FIFO 0x108
0035 #define REG_RX_FIFO 0x10c
0036 #define REG_ADR 0x110
0037 #define REG_TX_FIFO_OCY 0x114
0038 #define REG_RX_FIFO_OCY 0x118
0039 #define REG_TEN_ADR 0x11c
0040 #define REG_RX_FIFO_PIRQ 0x120
0041 #define REG_GPO 0x124
0042 #define REG_TSUSTA 0x128
0043 #define REG_TSUSTO 0x12c
0044 #define REG_THDSTA 0x130
0045 #define REG_TSUDAT 0x134
0046 #define REG_TBUF 0x138
0047 #define REG_THIGH 0x13c
0048 #define REG_TLOW 0x140
0049 #define REG_THDDAT 0x144
0050
0051
0052
0053
0054 #define INT_ARB_LOST (1 << 0)
0055 #define INT_TX_ERROR (1 << 1)
0056 #define INT_TX_FIFO_EMPTY (1 << 2)
0057 #define INT_RX_FIFO_FULL (1 << 3)
0058 #define INT_BUS_NOT_BUSY (1 << 4)
0059 #define INT_ADDRESSED_AS_SLAVE (1 << 5)
0060 #define INT_NOT_ADDRESSED_AS_SLAVE (1 << 6)
0061 #define INT_TX_FIFO_HALF_FULL (1 << 7)
0062 #define INT_ALL (0xff)
0063
0064
0065
0066
0067 #define CR_EN (1 << 0)
0068 #define CR_TX_FIFO_RESET (1 << 1)
0069 #define CR_MSMS (1 << 2)
0070 #define CR_TX (1 << 3)
0071 #define CR_TXAK (1 << 4)
0072 #define CR_RSTA (1 << 5)
0073 #define CR_GC_EN (1 << 6)
0074
0075
0076
0077
0078 #define SR_ABGC (1 << 0)
0079 #define SR_AAS (1 << 1)
0080 #define SR_BB (1 << 2)
0081 #define SR_SRW (1 << 3)
0082 #define SR_TX_FIFO_FULL (1 << 4)
0083 #define SR_RX_FIFO_FULL (1 << 5)
0084 #define SR_RX_FIFO_EMPTY (1 << 6)
0085 #define SR_TX_FIFO_EMPTY (1 << 7)
0086
0087
0088
0089
0090 #define TX_FIFO_SIZE 16
0091 #define TX_FIFO_HALF_SIZE (TX_FIFO_SIZE / 2)
0092 #define RX_FIFO_SIZE 16
0093
0094
0095
0096
0097 #define ADDR_TEN (1 << 31)
0098 #define ADDR_GPO (1 << 30)
0099
0100 typedef struct {
0101 i2c_bus base;
0102 uintptr_t regs;
0103 i2c_msg* msgs;
0104 uint32_t msgs_remaining;
0105 i2c_msg* current_msg;
0106 uint32_t current_msg_todo;
0107 uint8_t* current_msg_byte;
0108 uint32_t current_todo;
0109 uint32_t irqstatus;
0110 bool read;
0111 uint32_t addr;
0112 rtems_id task_id;
0113 bool gpo_address;
0114 xilinx_aix_i2c_timing timing;
0115 rtems_vector_number irq;
0116 } xilinx_axi_i2c_bus;
0117
0118 xilinx_axi_i2c_bus* axi_i2c_bus;
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 typedef enum
0137 {
0138 AXI_I2C_NOP,
0139 AXI_I2C_BEGIN,
0140 AXI_I2C_END,
0141 AXI_I2C_TRANSFER,
0142 AXI_I2C_ADDRESS,
0143 AXI_I2C_START_TRANSFER,
0144 AXI_I2C_WRITE,
0145 AXI_I2C_READ,
0146 AXI_I2C_TX_FIFO,
0147 AXI_I2C_RX_FIFO,
0148 AXI_I2C_RX_FIFO_LEVEL,
0149 AXI_I2C_INT,
0150 AXI_I2C_INT_DONE,
0151 AXI_I2C_INT_ERROR,
0152 AXI_I2C_BUS_NOT_BUSY,
0153 AXI_I2C_REG_WRITE,
0154 AXI_I2C_REG_READ,
0155 AXI_I2C_TIMEOUT,
0156 AXI_I2C_WAKE
0157 } axi_i2c_state;
0158
0159 #define RTEMS_AXI_I2C_TRACE 0
0160 #if RTEMS_AXI_I2C_TRACE
0161
0162 #define DRIVER_REG_TRACE 1
0163
0164 typedef struct
0165 {
0166 axi_i2c_state state;
0167 uint32_t vars[3];
0168 } axi_i2c_trace;
0169
0170 #define AXI_I2C_TRACE 5000
0171 axi_i2c_trace axi_trace[AXI_I2C_TRACE];
0172 int axi_trace_in;
0173
0174 static inline void axi_trace_reset(void)
0175 {
0176 axi_trace_in = 0;
0177 }
0178
0179 static inline void axi_trace_append(axi_i2c_state state,
0180 uint32_t v1,
0181 uint32_t v2,
0182 uint32_t v3)
0183 {
0184 if (axi_trace_in < AXI_I2C_TRACE) {
0185 axi_i2c_trace rec = { state, { v1, v2, v3 } };
0186 axi_trace[axi_trace_in++] = rec;
0187 }
0188 }
0189 #else
0190 #define axi_trace_reset()
0191 #define axi_trace_append(s, v1, v2, v3)
0192 #endif
0193
0194 #define DRIVER_DEBUG 0
0195 #define DRIVER_DEBUG_DEFAULT true
0196 #if DRIVER_DEBUG
0197 #ifndef RTEMS_PRINTFLIKE
0198 #define RTEMS_PRINTFLIKE( _format_pos, _ap_pos ) \
0199 __attribute__((__format__(__printf__, _format_pos, _ap_pos)))
0200 #endif
0201 static bool drv_printk_enable = DRIVER_DEBUG_DEFAULT;
0202 static void drv_printk(const char* format, ...) RTEMS_PRINTFLIKE(1, 2);
0203 static void
0204 drv_printk(const char* format, ...)
0205 {
0206 va_list ap;
0207 va_start(ap, format);
0208 if (drv_printk_enable)
0209 vprintk(format, ap);
0210 va_end(ap);
0211 }
0212 #else
0213 #define drv_printk(_fmt, ...)
0214 #endif
0215
0216 static inline void
0217 xilinx_axi_i2c_reg_write(const xilinx_axi_i2c_bus* bus, uint32_t reg, uint32_t value)
0218 {
0219 #if DRIVER_REG_TRACE
0220 axi_trace_append(AXI_I2C_REG_WRITE, reg, value, 0);
0221 #endif
0222 *((volatile uint32_t*) (bus->regs + reg))= value;
0223 }
0224
0225 static inline uint32_t
0226 xilinx_axi_i2c_reg_read(const xilinx_axi_i2c_bus* bus, uint32_t reg)
0227 {
0228 uint32_t value = *((volatile uint32_t*) (bus->regs + reg));
0229 #if DRIVER_REG_TRACE
0230 axi_trace_append(AXI_I2C_REG_READ, reg, value, 0);
0231 #endif
0232 return value;
0233 }
0234
0235 static uint32_t
0236 xilinx_axi_i2c_read_irq_status(const xilinx_axi_i2c_bus* bus)
0237 {
0238 return xilinx_axi_i2c_reg_read(bus, REG_ISR);
0239 }
0240
0241 static uint32_t
0242 xilinx_axi_i2c_read_irq_enabled(const xilinx_axi_i2c_bus* bus)
0243 {
0244 return xilinx_axi_i2c_reg_read(bus, REG_IER);
0245 }
0246
0247 static void
0248 xilinx_axi_i2c_clear_irq(const xilinx_axi_i2c_bus* bus, uint32_t mask)
0249 {
0250
0251
0252
0253 xilinx_axi_i2c_reg_write(bus, REG_ISR,
0254 xilinx_axi_i2c_reg_read(bus, REG_ISR) & mask);
0255 }
0256
0257 static inline void
0258 xilinx_axi_i2c_enable_irq(const xilinx_axi_i2c_bus* bus, uint32_t mask)
0259 {
0260 xilinx_axi_i2c_reg_write(bus, REG_IER,
0261 xilinx_axi_i2c_reg_read(bus, REG_IER) | mask);
0262 }
0263
0264 static inline void
0265 xilinx_axi_i2c_disable_irq(const xilinx_axi_i2c_bus* bus, uint32_t mask)
0266 {
0267 xilinx_axi_i2c_reg_write(bus, REG_IER,
0268 xilinx_axi_i2c_reg_read(bus, REG_IER) & ~mask);
0269 }
0270
0271 static void
0272 xilinx_axi_i2c_clear_enable_irq(const xilinx_axi_i2c_bus* bus, uint32_t mask)
0273 {
0274 xilinx_axi_i2c_clear_irq(bus, mask);
0275 xilinx_axi_i2c_enable_irq(bus, mask);
0276 }
0277
0278 static void
0279 xilinx_axi_i2c_disable_clear_irq(const xilinx_axi_i2c_bus* bus, uint32_t mask)
0280 {
0281 xilinx_axi_i2c_disable_irq(bus, mask);
0282 xilinx_axi_i2c_clear_irq(bus, mask);
0283 }
0284
0285 static inline void
0286 xilinx_axi_i2c_disable_all_irq(const xilinx_axi_i2c_bus* bus)
0287 {
0288 xilinx_axi_i2c_reg_write(bus, REG_GIE, 0);
0289 }
0290
0291 static void
0292 xilinx_axi_i2c_enable_interrupts(const xilinx_axi_i2c_bus* bus)
0293 {
0294 xilinx_axi_i2c_reg_write(bus, REG_GIE, 1 << 31);
0295 }
0296
0297 static void
0298 xilinx_axi_i2c_disable_interrupts(const xilinx_axi_i2c_bus* bus)
0299 {
0300 xilinx_axi_i2c_reg_write(bus, REG_GIE, 0);
0301 xilinx_axi_i2c_reg_write(bus, REG_IER, 0);
0302 }
0303
0304 static inline void
0305 xilinx_axi_i2c_write_cr(const xilinx_axi_i2c_bus* bus, uint32_t value)
0306 {
0307 xilinx_axi_i2c_reg_write(bus, REG_CR, value);
0308 }
0309
0310 static inline uint32_t
0311 xilinx_axi_i2c_read_cr(const xilinx_axi_i2c_bus* bus)
0312 {
0313 return xilinx_axi_i2c_reg_read(bus, REG_CR);
0314 }
0315
0316 static inline void
0317 xilinx_axi_i2c_set_cr(const xilinx_axi_i2c_bus* bus, uint32_t mask)
0318 {
0319 xilinx_axi_i2c_reg_write(bus, REG_CR,
0320 xilinx_axi_i2c_reg_read(bus, REG_CR) | mask);
0321 }
0322
0323 static inline void
0324 xilinx_axi_i2c_clear_cr(const xilinx_axi_i2c_bus* bus, uint32_t mask)
0325 {
0326 xilinx_axi_i2c_write_cr(bus, xilinx_axi_i2c_read_cr(bus) & ~mask);
0327 }
0328
0329 static inline uint32_t
0330 xilinx_axi_i2c_read_sr(const xilinx_axi_i2c_bus* bus)
0331 {
0332 return xilinx_axi_i2c_reg_read(bus, REG_SR);
0333 }
0334
0335 static inline uint32_t
0336 xilinx_axi_i2c_read_rx_level(const xilinx_axi_i2c_bus* bus)
0337 {
0338 if ((xilinx_axi_i2c_read_sr(bus) & SR_RX_FIFO_EMPTY) != 0)
0339 return 0;
0340 return xilinx_axi_i2c_reg_read(bus, REG_RX_FIFO_OCY) + 1;
0341 }
0342
0343 static inline void
0344 xilinx_axi_i2c_write_rx_pirq(const xilinx_axi_i2c_bus* bus, uint32_t level)
0345 {
0346 if (level != 0)
0347 xilinx_axi_i2c_reg_write(bus, REG_RX_FIFO_PIRQ, level - 1);
0348 else
0349 xilinx_axi_i2c_reg_write(bus, REG_RX_FIFO_PIRQ, level);
0350 }
0351
0352 static inline uint32_t
0353 xilinx_axi_i2c_read_tx_space(const xilinx_axi_i2c_bus* bus)
0354 {
0355 if ((xilinx_axi_i2c_read_sr(bus) & SR_TX_FIFO_EMPTY) != 0)
0356 return TX_FIFO_SIZE;
0357 return TX_FIFO_SIZE - xilinx_axi_i2c_reg_read(bus, REG_TX_FIFO_OCY) - 1;
0358 }
0359
0360 static void
0361 xilinx_axi_i2c_write_tx_fifo_data(xilinx_axi_i2c_bus* bus, uint32_t data)
0362 {
0363 axi_trace_append(AXI_I2C_TX_FIFO, data, 0, 0);
0364 xilinx_axi_i2c_reg_write(bus, REG_TX_FIFO, data);
0365 }
0366
0367 static inline uint32_t
0368 xilinx_axi_i2c_read_rx_fifo_data(xilinx_axi_i2c_bus* bus)
0369 {
0370 uint32_t data = xilinx_axi_i2c_reg_read(bus, REG_RX_FIFO);
0371 axi_trace_append(AXI_I2C_RX_FIFO, data, 0, 0);
0372 return data;
0373 }
0374
0375 static void
0376 xilinx_axi_i2c_reset(xilinx_axi_i2c_bus* bus)
0377 {
0378 xilinx_axi_i2c_reg_write(bus, REG_SOFTR, 0x0a);
0379 if ((bus->timing.valid_mask & XILINX_AIX_I2C_ALL_REGS) != 0)
0380 {
0381 static const uint32_t r[8] = {
0382 REG_TSUSTA,
0383 REG_TSUSTO,
0384 REG_THDSTA,
0385 REG_TSUDAT,
0386 REG_TBUF,
0387 REG_THIGH,
0388 REG_TLOW,
0389 REG_THDDAT
0390 };
0391 static const uint32_t m[8] = {
0392 XILINX_AIX_I2C_TSUSTA,
0393 XILINX_AIX_I2C_TSUSTO,
0394 XILINX_AIX_I2C_THDSTA,
0395 XILINX_AIX_I2C_TSUDAT,
0396 XILINX_AIX_I2C_TBUF,
0397 XILINX_AIX_I2C_THIGH,
0398 XILINX_AIX_I2C_TLOW,
0399 XILINX_AIX_I2C_THDDAT
0400 };
0401 uint32_t vm = bus->timing.valid_mask;
0402 const uint32_t* u = &bus->timing.TSUSTA;
0403 size_t i;
0404 for (i = 0; i < (sizeof(r) / sizeof(r[0])); ++i, ++u) {
0405 if ((vm & m[i]) != 0) {
0406 xilinx_axi_i2c_reg_write(bus, r[i], *u);
0407 }
0408 }
0409 }
0410 }
0411
0412
0413 static void
0414 xilinx_axi_i2c_reinit(xilinx_axi_i2c_bus* bus)
0415 {
0416 drv_printk("axi-i2c: reinit\n");
0417 xilinx_axi_i2c_reset(bus);
0418 xilinx_axi_i2c_write_rx_pirq(bus, RX_FIFO_SIZE);
0419 xilinx_axi_i2c_write_cr(bus, CR_TX_FIFO_RESET);
0420 xilinx_axi_i2c_write_cr(bus, CR_EN);
0421 xilinx_axi_i2c_clear_enable_irq(bus, INT_ARB_LOST);
0422 }
0423
0424 static void
0425 xilinx_axi_i2c_wakeup(xilinx_axi_i2c_bus* bus)
0426 {
0427 axi_trace_append(AXI_I2C_WAKE, bus->task_id, bus->irqstatus, 0);
0428 drv_printk("axi-i2c: wakeup: irqstatus: %08lx\n", bus->irqstatus);
0429 rtems_status_code sc = rtems_event_transient_send(bus->task_id);
0430 _Assert(sc == RTEMS_SUCCESSFUL);
0431 (void) sc;
0432 }
0433
0434 static void
0435 xilinx_axi_i2c_next_byte(xilinx_axi_i2c_bus* bus)
0436 {
0437 --bus->current_todo;
0438 --bus->current_msg_todo;
0439 ++bus->current_msg_byte;
0440 if (bus->current_msg_todo == 0) {
0441 if (bus->msgs_remaining != 0 &&
0442 (bus->msgs[0].flags & I2C_M_NOSTART) != 0) {
0443 bus->current_msg_todo = bus->msgs[0].len;
0444 bus->current_msg_byte = bus->msgs[0].buf;
0445 ++bus->msgs;
0446 --bus->msgs_remaining;
0447 }
0448 }
0449 }
0450
0451 static void
0452 xilinx_axi_i2c_read_rx_byte(xilinx_axi_i2c_bus* bus)
0453 {
0454 *bus->current_msg_byte = (uint8_t) xilinx_axi_i2c_read_rx_fifo_data(bus);
0455 xilinx_axi_i2c_next_byte(bus);
0456 }
0457
0458 static void
0459 xilinx_axi_i2c_read_rx_bytes(xilinx_axi_i2c_bus* bus, uint32_t count)
0460 {
0461 while (count-- > 0)
0462 xilinx_axi_i2c_read_rx_byte(bus);
0463 }
0464
0465 static void
0466 xilinx_axi_i2c_set_rx_fifo_level(xilinx_axi_i2c_bus* bus)
0467 {
0468 uint32_t size;
0469 if (bus->current_todo > RX_FIFO_SIZE) {
0470 size = RX_FIFO_SIZE;
0471 } else {
0472 size = bus->current_todo - 1;
0473 }
0474 axi_trace_append(AXI_I2C_RX_FIFO_LEVEL, size, 0, 0);
0475 xilinx_axi_i2c_write_rx_pirq(bus, size);
0476 }
0477
0478 static bool xilinx_axi_i2c_start_transfer(xilinx_axi_i2c_bus* bus);
0479
0480 static bool
0481 xilinx_axi_i2c_read_rx_fifo(xilinx_axi_i2c_bus* bus)
0482 {
0483 drv_printk("axi-i2c: read rx fifo: length:%lu\n", bus->current_todo);
0484
0485 if (bus->current_todo == 0) {
0486 return false;
0487 }
0488
0489 if ((xilinx_axi_i2c_read_sr(bus) & SR_RX_FIFO_EMPTY) == 0) {
0490 uint32_t level = xilinx_axi_i2c_read_rx_level(bus);
0491 bool active;
0492
0493 drv_printk("axi-i2c: read rx fifo: level:%lu\n", level);
0494
0495 if (level > bus->current_todo)
0496 level = bus->current_todo;
0497
0498 switch (bus->current_todo - level) {
0499 case 1:
0500 drv_printk("axi-i2c: read rx fifo: one more\n");
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513 xilinx_axi_i2c_disable_clear_irq(bus, INT_TX_ERROR);
0514 xilinx_axi_i2c_set_cr(bus, CR_TXAK);
0515 xilinx_axi_i2c_read_rx_bytes(bus, level);
0516
0517
0518
0519
0520 xilinx_axi_i2c_write_rx_pirq(bus, 0);
0521 break;
0522
0523 case 0:
0524 drv_printk("axi-i2c: read rx fifo: no more\n");
0525
0526
0527
0528
0529
0530
0531 xilinx_axi_i2c_disable_clear_irq(bus,
0532 INT_RX_FIFO_FULL | INT_TX_ERROR);
0533 if (bus->msgs_remaining == 0) {
0534 xilinx_axi_i2c_clear_cr(bus, CR_MSMS);
0535 xilinx_axi_i2c_clear_enable_irq(bus, INT_BUS_NOT_BUSY);
0536 active = true;
0537 }
0538 xilinx_axi_i2c_read_rx_byte(bus);
0539 if (bus->msgs_remaining != 0)
0540 active = xilinx_axi_i2c_start_transfer(bus);
0541 return active;
0542
0543 default:
0544 drv_printk("axi-i2c: read rx fifo: more:%lu\n", bus->current_todo - level);
0545
0546
0547
0548
0549 xilinx_axi_i2c_read_rx_bytes(bus, level);
0550 if (bus->current_todo > RX_FIFO_SIZE) {
0551 xilinx_axi_i2c_write_rx_pirq(bus, RX_FIFO_SIZE);
0552 } else {
0553 xilinx_axi_i2c_write_rx_pirq(bus, bus->current_todo - 1);
0554 }
0555 break;
0556 }
0557 }
0558
0559 return true;
0560 }
0561
0562 static void
0563 xilinx_axi_i2c_write_tx_byte(xilinx_axi_i2c_bus* bus)
0564 {
0565 xilinx_axi_i2c_write_tx_fifo_data(bus, *bus->current_msg_byte);
0566 xilinx_axi_i2c_next_byte(bus);
0567 }
0568
0569 static void
0570 xilinx_axi_i2c_write_tx_bytes(xilinx_axi_i2c_bus* bus)
0571 {
0572 uint32_t space = xilinx_axi_i2c_read_tx_space(bus);
0573 uint32_t level = bus->current_todo - 1;
0574 uint32_t i;
0575 drv_printk("axi-i2c: tx fifo load: space:%lu level:%lu\n", space, level);
0576 if (level < space)
0577 space = level;
0578 for (i = 0; i < space; ++i)
0579 xilinx_axi_i2c_write_tx_byte(bus);
0580 }
0581
0582 static bool
0583 xilinx_axi_i2c_write_tx_fifo(xilinx_axi_i2c_bus* bus)
0584 {
0585 bool more = true;
0586 drv_printk("axi-i2c: write tx fifo: current_todo: %lu\n", bus->current_todo);
0587 switch (bus->current_todo) {
0588 case 0:
0589 xilinx_axi_i2c_disable_clear_irq(bus,
0590 INT_TX_FIFO_EMPTY |
0591 INT_TX_FIFO_HALF_FULL |
0592 INT_TX_ERROR |
0593 INT_BUS_NOT_BUSY);
0594 more = xilinx_axi_i2c_start_transfer(bus);
0595 break;
0596 case 1:
0597
0598
0599
0600
0601 if (!bus->read && bus->msgs_remaining == 0) {
0602 xilinx_axi_i2c_clear_cr(bus, CR_MSMS);
0603 xilinx_axi_i2c_clear_enable_irq(bus, INT_BUS_NOT_BUSY);
0604 }
0605 xilinx_axi_i2c_write_tx_byte(bus);
0606 break;
0607 default:
0608 xilinx_axi_i2c_write_tx_bytes(bus);
0609 break;
0610 }
0611 return more;
0612 }
0613
0614 static void
0615 xilinx_axi_i2c_write_address(xilinx_axi_i2c_bus* bus)
0616 {
0617 if ((bus->addr & ADDR_GPO) != 0)
0618 xilinx_axi_i2c_reg_write(bus, REG_GPO, (bus->addr >> 12) & 0xf);
0619 if ((bus->addr & ADDR_TEN) != 0)
0620 xilinx_axi_i2c_write_tx_fifo_data(bus, (bus->addr >> 8) & 0xff);
0621 xilinx_axi_i2c_write_tx_fifo_data(bus, bus->addr & 0xff);
0622 }
0623
0624 static void
0625 xilinx_axi_i2c_start_read(xilinx_axi_i2c_bus* bus)
0626 {
0627 uint32_t cr;
0628 uint32_t set = INT_RX_FIFO_FULL;
0629 axi_trace_append(AXI_I2C_READ, bus->current_todo, 0, 0);
0630 drv_printk("axi-i2c: start read: size: %lu\n", bus->current_todo);
0631
0632
0633
0634 cr = xilinx_axi_i2c_read_cr(bus);
0635 if ((cr & CR_MSMS) != 0) {
0636 cr |= CR_RSTA;
0637 xilinx_axi_i2c_write_cr(bus, cr);
0638 }
0639 xilinx_axi_i2c_write_address(bus);
0640 xilinx_axi_i2c_set_rx_fifo_level(bus);
0641
0642
0643
0644
0645 cr &= ~(CR_TX | CR_TXAK);
0646 if (bus->current_todo == 1) {
0647 cr |= CR_TXAK;
0648 } else {
0649 set |= INT_TX_ERROR;
0650 }
0651
0652
0653
0654 cr |= CR_MSMS;
0655 xilinx_axi_i2c_clear_enable_irq(bus, set);
0656 xilinx_axi_i2c_write_cr(bus, cr);
0657 }
0658
0659 static void
0660 xilinx_axi_i2c_start_write(xilinx_axi_i2c_bus* bus)
0661 {
0662 uint32_t space;
0663 uint32_t enable;
0664 uint32_t cr;
0665 axi_trace_append(AXI_I2C_WRITE, bus->current_todo, 0, 0);
0666 cr = xilinx_axi_i2c_read_cr(bus);
0667
0668
0669
0670 if ((cr & CR_MSMS) != 0) {
0671 cr |= CR_RSTA;
0672 xilinx_axi_i2c_write_cr(bus, cr);
0673 }
0674 xilinx_axi_i2c_write_address(bus);
0675 if (bus->current_todo > 1)
0676 xilinx_axi_i2c_write_tx_bytes(bus);
0677 space = xilinx_axi_i2c_read_tx_space(bus);
0678 enable = INT_TX_FIFO_EMPTY | INT_TX_ERROR;
0679 if (space > TX_FIFO_HALF_SIZE && bus->current_todo > 1) {
0680 enable |= INT_TX_FIFO_HALF_FULL;
0681 }
0682 xilinx_axi_i2c_clear_enable_irq(bus, enable);
0683 cr &= ~CR_TXAK;
0684 cr |= CR_MSMS | CR_TX;
0685 xilinx_axi_i2c_write_cr(bus, cr);
0686 }
0687
0688 static bool
0689 xilinx_axi_i2c_start_transfer(xilinx_axi_i2c_bus* bus)
0690 {
0691 const i2c_msg* msgs = bus->msgs;
0692 uint32_t msg_todo = bus->msgs_remaining;
0693 uint32_t i;
0694
0695 axi_trace_append(AXI_I2C_START_TRANSFER, msg_todo, 0, 0);
0696 drv_printk("axi-i2c: start transfer: messages: %lu\n", msg_todo);
0697
0698 if (msg_todo == 0) {
0699 xilinx_axi_i2c_clear_cr(bus, CR_MSMS);
0700 return false;
0701 }
0702
0703
0704
0705
0706
0707 bus->current_todo = msgs[0].len;
0708 for (i = 1; i < msg_todo && (msgs[i].flags & I2C_M_NOSTART) != 0; ++i) {
0709 bus->current_todo += msgs[i].len;
0710 }
0711
0712 bus->read = (msgs->flags & I2C_M_RD) != 0;
0713
0714 if ((msgs->flags & I2C_M_TEN) != 0) {
0715 bus->addr = (ADDR_TEN |
0716 ((msgs->addr & (3 << 8)) << 1) |
0717 ((bus->read ? 1 : 0) << 8) |
0718 (msgs->addr & 0xff));
0719 }
0720 else {
0721 bus->addr = (msgs->addr & 0x7f) << 1 | (bus->read ? 1 : 0);
0722 }
0723
0724 if (bus->gpo_address)
0725 bus->addr |= ADDR_GPO | (msgs->addr & 0xf000);
0726
0727 axi_trace_append(AXI_I2C_TRANSFER,
0728 bus->msgs_remaining,
0729 bus->current_todo, bus->addr);
0730
0731
0732
0733
0734
0735 bus->current_msg_todo = msgs[0].len;
0736 bus->current_msg_byte = msgs[0].buf;
0737 ++bus->msgs;
0738 --bus->msgs_remaining;
0739
0740 if (bus->read) {
0741 xilinx_axi_i2c_start_read(bus);
0742 } else {
0743 xilinx_axi_i2c_start_write(bus);
0744 }
0745
0746 return true;
0747 }
0748
0749 static void
0750 xilinx_axi_i2c_interrupt(void* arg)
0751 {
0752 xilinx_axi_i2c_bus* bus = arg;
0753 uint32_t status = xilinx_axi_i2c_read_irq_status(bus);
0754 uint32_t enabled = xilinx_axi_i2c_read_irq_enabled(bus);
0755 uint32_t active = status & enabled;
0756 uint32_t clear = 0;
0757 int done = 0;
0758
0759 axi_trace_append(AXI_I2C_INT, active, status, enabled);
0760
0761 drv_printk("axi-i2c: interrupt: active:%02lx isr:%02lx ier:%02lx\n",
0762 active, status, enabled);
0763
0764
0765
0766
0767
0768
0769
0770
0771 if (((active & INT_ARB_LOST) != 0) ||
0772 (!bus->read && (active & INT_TX_ERROR) != 0)) {
0773 bus->irqstatus = active & (INT_ARB_LOST | INT_TX_ERROR);
0774 axi_trace_append(AXI_I2C_INT_ERROR, bus->irqstatus, 0, 0);
0775 xilinx_axi_i2c_reinit(bus);
0776 xilinx_axi_i2c_clear_cr(bus, CR_EN);
0777 xilinx_axi_i2c_wakeup(bus);
0778 return;
0779 }
0780
0781
0782
0783
0784 if ((active & INT_RX_FIFO_FULL) != 0) {
0785 clear |= INT_RX_FIFO_FULL;
0786
0787 if (bus->read && !xilinx_axi_i2c_read_rx_fifo(bus)) {
0788 ++done;
0789 axi_trace_append(AXI_I2C_INT_DONE, done, clear, 0);
0790 }
0791
0792 if (bus->current_todo == 0) {
0793 clear |= status & INT_TX_ERROR;
0794 }
0795 }
0796
0797
0798
0799
0800 if ((active & (INT_TX_FIFO_EMPTY | INT_TX_FIFO_HALF_FULL)) != 0) {
0801 clear |= active & (INT_TX_FIFO_EMPTY | INT_TX_FIFO_HALF_FULL);
0802
0803 if (!bus->read && !xilinx_axi_i2c_write_tx_fifo(bus)) {
0804 ++done;
0805 axi_trace_append(AXI_I2C_INT_DONE, done, clear, 1);
0806 }
0807 }
0808
0809
0810
0811
0812
0813
0814 if ((active & INT_BUS_NOT_BUSY) != 0) {
0815 if ((xilinx_axi_i2c_read_sr(bus) & SR_BB) == 0) {
0816 xilinx_axi_i2c_disable_clear_irq(bus, INT_BUS_NOT_BUSY);
0817 if (bus->read && !xilinx_axi_i2c_read_rx_fifo(bus)) {
0818 ++done;
0819 axi_trace_append(AXI_I2C_BUS_NOT_BUSY, done, clear, 0);
0820 }
0821 else if (!bus->read && !xilinx_axi_i2c_write_tx_fifo(bus)) {
0822 ++done;
0823 axi_trace_append(AXI_I2C_BUS_NOT_BUSY, done, clear, 1);
0824 }
0825 }
0826 else {
0827 clear |= INT_BUS_NOT_BUSY;
0828 }
0829 }
0830
0831 if (clear != 0)
0832 xilinx_axi_i2c_clear_irq(bus, clear);
0833
0834 if (done != 0) {
0835 xilinx_axi_i2c_disable_interrupts(bus);
0836 xilinx_axi_i2c_clear_cr(bus, CR_EN);
0837 xilinx_axi_i2c_wakeup(bus);
0838 }
0839 }
0840
0841 static int xilinx_axi_i2c_transfer(i2c_bus* base,
0842 i2c_msg* msgs,
0843 uint32_t msg_count)
0844 {
0845 xilinx_axi_i2c_bus* bus = (xilinx_axi_i2c_bus *) base;
0846 rtems_status_code sc;
0847 int r = 0;
0848
0849 axi_trace_reset();
0850 axi_trace_append(AXI_I2C_BEGIN, msg_count, 0, 0);
0851
0852 drv_printk("axi-i2c: i2c transfer\n");
0853
0854 _Assert(msg_count > 0);
0855
0856 bus->msgs = &msgs[0];
0857 bus->msgs_remaining = msg_count;
0858 bus->irqstatus = 0;
0859 bus->task_id = rtems_task_self();
0860
0861 xilinx_axi_i2c_reinit(bus);
0862 xilinx_axi_i2c_start_transfer(bus);
0863 xilinx_axi_i2c_enable_interrupts(bus);
0864
0865 sc = rtems_event_transient_receive(RTEMS_WAIT, bus->base.timeout);
0866 if (sc != RTEMS_SUCCESSFUL) {
0867 axi_trace_append(AXI_I2C_TIMEOUT, 0, 0, 0);
0868 xilinx_axi_i2c_reinit(bus);
0869 rtems_event_transient_clear();
0870 r = -ETIMEDOUT;
0871 }
0872
0873 if (r == 0 && bus->irqstatus != 0)
0874 r = -EIO;
0875
0876 axi_trace_append(AXI_I2C_END, bus->irqstatus, r, 0);
0877
0878 return r;
0879 }
0880
0881 static int xilinx_axi_i2c_set_clock(i2c_bus *base, unsigned long clock)
0882 {
0883 xilinx_axi_i2c_bus* bus = (xilinx_axi_i2c_bus*) base;
0884
0885 if ((bus->timing.valid_mask & XILINX_AIX_I2C_AXI_CLOCK) == 0)
0886 return -EIO;
0887
0888 bus->timing.THIGH =
0889 (bus->timing.AXI_CLOCK / (2 * clock)) - 7 - bus->timing.SCL_INERTIAL_DELAY;
0890 bus->timing.TLOW = bus->timing.THIGH;
0891
0892 bus->timing.valid_mask |= XILINX_AIX_I2C_THIGH | XILINX_AIX_I2C_TLOW;
0893
0894 return 0;
0895 }
0896
0897 static void xilinx_axi_i2c_destroy(i2c_bus* base)
0898 {
0899 xilinx_axi_i2c_bus* bus = (xilinx_axi_i2c_bus*) base;
0900 rtems_status_code sc;
0901
0902 sc = rtems_interrupt_handler_remove(bus->irq, xilinx_axi_i2c_interrupt, bus);
0903 _Assert(sc == RTEMS_SUCCESSFUL);
0904 (void) sc;
0905
0906 i2c_bus_destroy_and_free(&bus->base);
0907 }
0908
0909 int
0910 i2c_bus_register_xilinx_aix_i2c(const char* bus_path,
0911 uintptr_t register_base,
0912 rtems_vector_number irq,
0913 bool gpo_address,
0914 const xilinx_aix_i2c_timing* timing)
0915 {
0916 xilinx_axi_i2c_bus* bus;
0917 rtems_status_code sc;
0918
0919 bus = (xilinx_axi_i2c_bus*) i2c_bus_alloc_and_init(sizeof(*bus));
0920 if (bus == NULL) {
0921 return -1;
0922 }
0923
0924 bus->regs = register_base;
0925 bus->irq = irq;
0926 bus->gpo_address = gpo_address;
0927 bus->timing = *timing;
0928
0929 sc = rtems_interrupt_handler_install(irq,
0930 "Xilinx AXI I2C",
0931 RTEMS_INTERRUPT_UNIQUE,
0932 xilinx_axi_i2c_interrupt,
0933 bus);
0934 if (sc != RTEMS_SUCCESSFUL) {
0935 drv_printk("axi-i2c: interrupt attach failed\n");
0936 (*bus->base.destroy)(&bus->base);
0937 rtems_set_errno_and_return_minus_one(EIO);
0938 }
0939
0940 bus->base.transfer = xilinx_axi_i2c_transfer;
0941 bus->base.set_clock = xilinx_axi_i2c_set_clock;
0942 bus->base.destroy = xilinx_axi_i2c_destroy;
0943
0944 axi_i2c_bus = bus;
0945
0946 return i2c_bus_register(&bus->base, bus_path);
0947 }