Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:11

0001 /*
0002  * Copyright (c) 2016-2017 Chris Johns <chrisj@rtems.org>  All rights reserved.
0003  *
0004  * The license and distribution terms for this file may be
0005  * found in the file LICENSE in this distribution or at
0006  * http://www.rtems.org/license/LICENSE.
0007  */
0008 
0009 /*
0010  * Xilinx AXI IIC Interface v2.0. See PG090.pdf.
0011  *
0012  * Note, only master support is provided and no dynamic mode by design.
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  * Register map.
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  * Interrupts.
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  * Command register.
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  * Status register.
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  * FIFO Sizes.
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  * Address flags.
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  * Real-time trace buffering with a small overhead. The data can be dumped from
0122  * gdb with:
0123  *
0124  * define axi-i2c
0125  *  set $i = 0
0126  *  while $i < axi_trace_in
0127  *    printf "%4d %08x %08x %08x : ", \
0128  *     $i, axi_trace[$i].vars[0], axi_trace[$i].vars[1], axi_trace[$i].vars[2]
0129  *    output axi_trace[$i].state
0130  *    printf "\n"
0131  *    set $i = $i + 1
0132  *  end
0133  * end
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    * The ISR bits can be toggled so only write a 1 if set.
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          * One more byte to be received. This is set up by programming the RX
0503          * FIFO programmable depth interrupt register with a value that is 2
0504          * less than the number we need (the register is minus 1). When we have
0505          * one byte left, disable the TX error interrupt because setting the NO
0506          * ACK bit in the command register causes a TX error interrupt. Set the
0507          * TXAK bit in the CR to not-acknowledge the next byte received telling
0508          * the slave sender the master accepts no more data, then read the
0509          * FIFO. If the FIFO is ready before the TXAK bit is set the slave will
0510          * see a request for more data. We will come back to the next case
0511          * statement for the last byte once it has been received.
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          * Set the RX PIRQ to 0 after the RX data has been read. There is an
0518          * observed timing issue and glitch if written before.
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          * We should have 1 byte in the FIFO which is the last byte received
0527          * with a NACK. If there are no more message we need to send a STOP by
0528          * clearing he MSMS bit in the CR and then waiting for the bus to not
0529          * be busy.
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          * All the requested data is in the FIFO so read it and update the PIRQ
0547          * level. The PIRQ size is always one less than the maximum size.
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        * If transmitting and the last byte issue a stop and wait for the bus to
0599        * not be busy.
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    * Is this a restart? If there is no active STOP it is a restart.
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    * We must NACK the last byte so if we are receiving a single byte issue a
0643    * NACK.
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    * Issue a start.
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    * If a master issue a restart if there is no active STOP on the bus.
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    * Get the amount of data to transfer. It can span message buffers if the
0705    * I2C_M_NOSTART flag is set.
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    * The bus->msgs is left pointing to the next message because we may need to
0733    * start a new message while completing the current message.
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    * An error or we lost arbitration. If transmitting and there is more data to
0766    * send a INT_TX_ERROR means the slave issue a NOT ACK because there was not
0767    * slave at the address or the addressed slave will not accept any more data.
0768    *
0769    * Clean up and wake the user.
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    * RX FIFO full?
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    * TX FIFO empty or half empty?
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    * Gate the bus not busy interrupt with the bus busy status to know the bus
0811    * is really not busy. It could be an interrupt left over from starting the
0812    * transmission.
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 }