1 /*******************************************************************************
2  * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * PolarFire SoC Microprocessor Subsystem(MSS) I2C bare metal software driver
7  * implementation.
8  *
9  */
10 
11 #include "mpfs_hal/mss_hal.h"
12 #include "mss_i2c_regs.h"
13 #include "mss_i2c.h"
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /*------------------------------------------------------------------------------
20  * I2C transaction direction.
21  */
22 #define WRITE_DIR    0u
23 #define READ_DIR     1u
24 
25 /* -- Transactions types -- */
26 #define NO_TRANSACTION                      0u
27 #define MASTER_WRITE_TRANSACTION            1u
28 #define MASTER_READ_TRANSACTION             2u
29 #define MASTER_RANDOM_READ_TRANSACTION      3u
30 #define WRITE_SLAVE_TRANSACTION             4u
31 #define READ_SLAVE_TRANSACTION              5u
32 
33 /* -- SMBUS h/w states -- */
34 /* -- Master states -- */
35 #define ST_BUS_ERROR        0x00u   /* Bus error during MST or selected slave
36                                      * modes
37                                      */
38 #define ST_I2C_IDLE         0xF8u   /* No activity and no interrupt either.*/
39 #define ST_START            0x08u   /* start condition sent */
40 #define ST_RESTART          0x10u   /* repeated start */
41 #define ST_SLAW_ACK         0x18u   /* SLA+W sent, ack received */
42 #define ST_SLAW_NACK        0x20u   /* SLA+W sent, nack received */
43 #define ST_TX_DATA_ACK      0x28u   /* Data sent, ACK'ed */
44 #define ST_TX_DATA_NACK     0x30u   /* Data sent, NACK'ed */
45 #define ST_LOST_ARB         0x38u   /* Master lost arbitration */
46 #define ST_SLAR_ACK         0x40u   /* SLA+R sent, ACK'ed */
47 #define ST_SLAR_NACK        0x48u   /* SLA+R sent, NACK'ed */
48 #define ST_RX_DATA_ACK      0x50u   /* Data received, ACK sent */
49 #define ST_RX_DATA_NACK     0x58u   /* Data received, NACK sent */
50 #define ST_RESET_ACTIVATED  0xD0u   /* Master reset is activated */
51 
52 /* -- Slave states -- */
53 #define ST_SLAVE_SLAW       0x60u   /* SLA+W received */
54 #define ST_SLAVE_SLAR_ACK   0xA8u   /* SLA+R received, ACK returned */
55 #define ST_SLV_LA           0x68u   /* Slave lost arbitration */
56 #define ST_GCA              0x70u   /* GCA received */
57 #define ST_GCA_LA           0x78u   /* GCA lost arbitration */
58 #define ST_RDATA            0x80u   /* Data received */
59 #define ST_SLA_NACK         0x88u   /* Slave addressed, NACK returned */
60 #define ST_GCA_ACK          0x90u   /* Previously addresses with GCA, data
61                                      * ACKed
62                                      */
63 #define ST_GCA_NACK         0x98u   /* GCA addressed, NACK returned */
64 #define ST_RSTOP            0xA0u   /* Stop received */
65 #define ST_SLARW_LA         0xB0u   /* Arbitration lost */
66 #define ST_RACK             0xB8u   /* Byte sent, ACK received */
67 #define ST_SLAVE_RNACK      0xC0u   /* Byte sent, NACK received */
68 #define ST_FINAL            0xC8u   /* Final byte sent, ACK received */
69 #define ST_SLV_RST          0xD8u   /* Slave reset state */
70 
71 /*
72  * Maximum address offset length in slave write-read transactions.
73  * A maximum of two bytes will be interpreted as address offset within the slave
74  * tx buffer.
75  */
76 #define MAX_OFFSET_LENGTH    2u
77 
78 uint8_t g_i2c_axi_pos = 0x0u;
79 
80 /*------------------------------------------------------------------------------
81  * Local Function
82  */
83 static void mss_i2c_isr( mss_i2c_instance_t * this_i2c );
84 static void enable_slave_if_required( mss_i2c_instance_t * this_i2c );
85 static void global_init( mss_i2c_instance_t * this_i2c );
86 
87 /*------------------------------------------------------------------------------
88  * I2C instances
89  *------------------------------------------------------------------------------
90  */
91 #define MSS_I2C0_LO_BASE           (I2C_TypeDef*)0x2010A000u
92 #define MSS_I2C1_LO_BASE           (I2C_TypeDef*)0x2010B000u
93 #define MSS_I2C0_HI_BASE           (I2C_TypeDef*)0x2810A000u
94 #define MSS_I2C1_HI_BASE           (I2C_TypeDef*)0x2810B000u
95 
96 mss_i2c_instance_t g_mss_i2c0_lo;
97 mss_i2c_instance_t g_mss_i2c1_lo;
98 mss_i2c_instance_t g_mss_i2c0_hi;
99 mss_i2c_instance_t g_mss_i2c1_hi;
100 
101 /*------------------------------------------------------------------------------
102  * MSS_I2C_init()
103  * See "mss_i2c.h" for details of how to use this function.
104  */
MSS_I2C_init(mss_i2c_instance_t * this_i2c,uint8_t ser_address,mss_i2c_clock_divider_t ser_clock_speed)105 void MSS_I2C_init
106 (
107     mss_i2c_instance_t * this_i2c,
108     uint8_t ser_address,
109     mss_i2c_clock_divider_t ser_clock_speed
110 )
111 {
112     uint32_t primask;
113     uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
114 
115     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
116            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
117 
118     /*
119      * Initialize all items of the this_i2c data structure to zero. This
120      * initializes all state variables to their init value. It relies on
121      * the fact that NO_TRANSACTION, I2C_SUCCESS and I2C_RELEASE_BUS all
122      * have an actual value of zero.
123      */
124     primask = disable_interrupts();
125 
126     global_init(this_i2c);
127 
128     /* Update serial address of the device */
129     this_i2c->ser_address = (uint_fast8_t)ser_address << 1u;
130 
131     this_i2c->hw_reg->CTRL |= (uint8_t)((((clock_speed >> 2u) & 0x01u) << CR2)
132                               & CR2_MASK);
133 
134     this_i2c->hw_reg->CTRL |= (uint8_t)((((clock_speed >> 1u) & 0x01u) << CR1)
135                               & CR1_MASK);
136 
137     this_i2c->hw_reg->CTRL |= (uint8_t)(((clock_speed &  (uint8_t)0x01u) << CR0)
138                               & CR0_MASK);
139 
140     this_i2c->hw_reg->ADDR = (uint8_t)this_i2c->ser_address;
141 
142     this_i2c->hw_reg->CTRL |= ENS1_MASK; /* Set enable bit */
143 
144     this_i2c->transfer_completion_handler = NULL;
145 
146     restore_interrupts(primask);
147 }
148 
149 /*------------------------------------------------------------------------------
150  * MSS_I2C_write()
151  * See "mss_i2c.h" for details of how to use this function.
152  */
MSS_I2C_write(mss_i2c_instance_t * this_i2c,uint8_t serial_addr,const uint8_t * write_buffer,uint16_t write_size,uint8_t options)153 void MSS_I2C_write
154 (
155     mss_i2c_instance_t * this_i2c,
156     uint8_t serial_addr,
157     const uint8_t * write_buffer,
158     uint16_t write_size,
159     uint8_t options
160 )
161 {
162     uint32_t primask;
163     volatile uint8_t stat_ctrl;
164     mss_i2c_status_t stat_slave = this_i2c->slave_status;
165 
166     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
167            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
168 
169     primask = disable_interrupts();
170 
171     /* Update the transaction only when there is no transaction going on I2C */
172     if (this_i2c->transaction == NO_TRANSACTION)
173     {
174         this_i2c->transaction = MASTER_WRITE_TRANSACTION;
175     }
176 
177     /* Update the Pending transaction information so that transaction can
178      * restarted
179      */
180     this_i2c->pending_transaction = MASTER_WRITE_TRANSACTION ;
181 
182     /* Update target address */
183     this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
184 
185     this_i2c->dir = WRITE_DIR;
186 
187     this_i2c->master_tx_buffer = write_buffer;
188     this_i2c->master_tx_size = write_size;
189     this_i2c->master_tx_idx = 0u;
190 
191     /* Set I2C status in progress */
192     this_i2c->master_status = MSS_I2C_IN_PROGRESS;
193     this_i2c->options = options;
194 
195     if (MSS_I2C_IN_PROGRESS == stat_slave)
196     {
197         this_i2c->is_transaction_pending = 1u;
198     }
199     else
200     {
201         this_i2c->hw_reg->CTRL |= STA_MASK;
202     }
203 
204     /*
205      * Clear interrupts if required (depends on repeated starts).
206      * Since the Bus is on hold, only then prior status needs to
207      * be cleared.
208      */
209     if (MSS_I2C_HOLD_BUS == this_i2c->bus_status)
210     {
211         this_i2c->hw_reg->CTRL &= ~SI_MASK;
212 
213         stat_ctrl = this_i2c->hw_reg->STATUS;
214     }
215 
216     /* Enable the interrupt. (Re-enable) */
217     PLIC_EnableIRQ(this_i2c->irqn);
218 
219     restore_interrupts(primask);
220 }
221 
222 /*------------------------------------------------------------------------------
223  * MSS_I2C_read()
224  * See "mss_i2c.h" for details of how to use this function.
225  */
MSS_I2C_read(mss_i2c_instance_t * this_i2c,uint8_t serial_addr,uint8_t * read_buffer,uint16_t read_size,uint8_t options)226 void MSS_I2C_read
227 (
228     mss_i2c_instance_t * this_i2c,
229     uint8_t serial_addr,
230     uint8_t * read_buffer,
231     uint16_t read_size,
232     uint8_t options
233 )
234 {
235     uint32_t primask;
236     volatile uint8_t stat_ctrl;
237     mss_i2c_status_t stat_slave = this_i2c->slave_status;
238 
239     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
240            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
241 
242     primask = disable_interrupts();
243 
244     /* Update the transaction only when there is no transaction going on I2C */
245     if (this_i2c->transaction == NO_TRANSACTION)
246     {
247         this_i2c->transaction = MASTER_READ_TRANSACTION;
248     }
249 
250     /* Update the Pending transaction information so that transaction can
251      * restarted
252      */
253     this_i2c->pending_transaction = MASTER_READ_TRANSACTION ;
254 
255     /* Update target address */
256     this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
257 
258     this_i2c->dir = READ_DIR;
259 
260     this_i2c->master_rx_buffer = read_buffer;
261     this_i2c->master_rx_size = read_size;
262     this_i2c->master_rx_idx = 0u;
263 
264     /* Set I2C status in progress */
265     this_i2c->master_status = MSS_I2C_IN_PROGRESS;
266     this_i2c->options = options;
267 
268     if (MSS_I2C_IN_PROGRESS == stat_slave)
269     {
270         this_i2c->is_transaction_pending = 1u;
271     }
272     else
273     {
274         this_i2c->hw_reg->CTRL |= STA_MASK;
275     }
276 
277     /*
278      * Clear interrupts if required (depends on repeated starts).
279      * Since the Bus is on hold, only then prior status needs to
280      * be cleared.
281      */
282     if (MSS_I2C_HOLD_BUS == this_i2c->bus_status)
283     {
284         this_i2c->hw_reg->CTRL &= ~SI_MASK;
285         stat_ctrl = this_i2c->hw_reg->STATUS;
286     }
287 
288     /* Enable the interrupt. ( Re-enable) */
289     PLIC_EnableIRQ(this_i2c->irqn);
290 
291     restore_interrupts(primask);
292 }
293 
294 /*------------------------------------------------------------------------------
295  * MSS_I2C_write_read()
296  * See "mss_i2c.h" for details of how to use this function.
297  */
MSS_I2C_write_read(mss_i2c_instance_t * this_i2c,uint8_t serial_addr,const uint8_t * addr_offset,uint16_t offset_size,uint8_t * read_buffer,uint16_t read_size,uint8_t options)298 void MSS_I2C_write_read
299 (
300     mss_i2c_instance_t * this_i2c,
301     uint8_t serial_addr,
302     const uint8_t * addr_offset,
303     uint16_t offset_size,
304     uint8_t * read_buffer,
305     uint16_t read_size,
306     uint8_t options
307 )
308 {
309     mss_i2c_status_t stat_slave = this_i2c->slave_status;
310 
311     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
312            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
313     ASSERT(offset_size > 0u);
314     ASSERT(addr_offset != (const uint8_t *)0);
315     ASSERT(read_size > 0u);
316     ASSERT(read_buffer != (uint8_t *)0);
317 
318     if ((read_size > 0u) && (offset_size > 0u))
319     {
320         uint32_t primask;
321         volatile uint8_t stat_ctrl;
322 
323         primask = disable_interrupts();
324 
325         /* Update the transaction only when there is no transaction going on
326          * I2C.
327          */
328         if (this_i2c->transaction == NO_TRANSACTION)
329         {
330             this_i2c->transaction = MASTER_RANDOM_READ_TRANSACTION;
331         }
332 
333         /* Update the Pending transaction information so that transaction can
334          * restarted.
335          */
336         this_i2c->pending_transaction = MASTER_RANDOM_READ_TRANSACTION ;
337 
338         /* Update target address */
339         this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
340 
341         this_i2c->dir = WRITE_DIR;
342         this_i2c->master_tx_buffer = addr_offset;
343         this_i2c->master_tx_size = offset_size;
344         this_i2c->master_tx_idx = 0u;
345 
346         this_i2c->master_rx_buffer = read_buffer;
347         this_i2c->master_rx_size = read_size;
348         this_i2c->master_rx_idx = 0u;
349 
350         /* Set I2C status in progress */
351         this_i2c->master_status = MSS_I2C_IN_PROGRESS;
352         this_i2c->options = options;
353 
354         if (MSS_I2C_IN_PROGRESS == stat_slave)
355         {
356             this_i2c->is_transaction_pending = 1u;
357         }
358         else
359         {
360             this_i2c->hw_reg->CTRL |= STA_MASK;
361         }
362 
363         /*
364          * Clear interrupts if required (depends on repeated starts).
365          * Since the Bus is on hold, only then prior status needs to
366          * be cleared.
367          */
368         if (MSS_I2C_HOLD_BUS == this_i2c->bus_status)
369         {
370             this_i2c->hw_reg->CTRL &= ~SI_MASK;
371 
372             stat_ctrl = this_i2c->hw_reg->STATUS;
373         }
374 
375         /* Enable the interrupt. ( Re-enable) */
376         PLIC_EnableIRQ(this_i2c->irqn);
377 
378         restore_interrupts(primask);
379     }
380 }
381 
382 /*------------------------------------------------------------------------------
383  * MSS_I2C_get_status()
384  * See "mss_i2c.h" for details of how to use this function.
385  */
MSS_I2C_get_status(mss_i2c_instance_t * this_i2c)386 mss_i2c_status_t MSS_I2C_get_status
387 (
388     mss_i2c_instance_t * this_i2c
389 )
390 {
391     mss_i2c_status_t i2c_status;
392 
393     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
394            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
395 
396     i2c_status = this_i2c->master_status;
397 
398     return i2c_status;
399 }
400 
401 /*------------------------------------------------------------------------------
402  * MSS_I2C_wait_complete()
403  * See "mss_i2c.h" for details of how to use this function.
404  */
MSS_I2C_wait_complete(mss_i2c_instance_t * this_i2c,uint32_t timeout_ms)405 mss_i2c_status_t MSS_I2C_wait_complete
406 (
407     mss_i2c_instance_t * this_i2c,
408     uint32_t timeout_ms
409 )
410 {
411     mss_i2c_status_t i2c_status;
412 
413     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
414                (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
415 
416     this_i2c->master_timeout_ms = timeout_ms;
417 
418     /* Run the loop until state returns I2C_FAILED  or I2C_SUCESS */
419     do {
420         i2c_status = this_i2c->master_status;
421     } while(MSS_I2C_IN_PROGRESS == i2c_status);
422 
423     return i2c_status;
424 }
425 
426 /*------------------------------------------------------------------------------
427  * MSS_I2C_system_tick()
428  * See "mss_i2c.h" for details of how to use this function.
429  */
MSS_I2C_system_tick(mss_i2c_instance_t * this_i2c,uint32_t ms_since_last_tick)430 void MSS_I2C_system_tick
431 (
432     mss_i2c_instance_t * this_i2c,
433     uint32_t ms_since_last_tick
434 )
435 {
436     if (this_i2c->master_timeout_ms != MSS_I2C_NO_TIMEOUT)
437     {
438         if (this_i2c->master_timeout_ms > ms_since_last_tick)
439         {
440             this_i2c->master_timeout_ms -= ms_since_last_tick;
441         }
442         else
443         {
444             /*
445              * Mark current transaction as having timed out.
446              */
447             this_i2c->master_status = MSS_I2C_TIMED_OUT;
448             this_i2c->transaction = NO_TRANSACTION;
449             this_i2c->is_transaction_pending = (uint8_t)0;
450 
451             /*
452              * Make sure we do not incorrectly signal a timeout for subsequent
453              * transactions.
454              */
455             this_i2c->master_timeout_ms = MSS_I2C_NO_TIMEOUT;
456         }
457     }
458 }
459 
460 /*------------------------------------------------------------------------------
461  * MSS_I2C_set_slave_tx_buffer()
462  * See "mss_i2c.h" for details of how to use this function.
463  */
MSS_I2C_set_slave_tx_buffer(mss_i2c_instance_t * this_i2c,const uint8_t * tx_buffer,uint16_t tx_size)464 void MSS_I2C_set_slave_tx_buffer
465 (
466     mss_i2c_instance_t * this_i2c,
467     const uint8_t * tx_buffer,
468     uint16_t tx_size
469 )
470 {
471     uint32_t primask;
472 
473     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
474            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
475 
476     primask = disable_interrupts();
477 
478     this_i2c->slave_tx_buffer = tx_buffer;
479     this_i2c->slave_tx_size = tx_size;
480     this_i2c->slave_tx_idx = 0u;
481 
482     restore_interrupts(primask);
483 }
484 
485 /*------------------------------------------------------------------------------
486  * MSS_I2C_set_slave_rx_buffer()
487  * See "mss_i2c.h" for details of how to use this function.
488  */
MSS_I2C_set_slave_rx_buffer(mss_i2c_instance_t * this_i2c,uint8_t * rx_buffer,uint16_t rx_size)489 void MSS_I2C_set_slave_rx_buffer
490 (
491     mss_i2c_instance_t * this_i2c,
492     uint8_t * rx_buffer,
493     uint16_t rx_size
494 )
495 {
496     uint32_t primask;
497 
498     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
499            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
500 
501     primask = disable_interrupts();
502 
503     this_i2c->slave_rx_buffer = rx_buffer;
504     this_i2c->slave_rx_size = rx_size;
505     this_i2c->slave_rx_idx = 0u;
506 
507     restore_interrupts(primask);
508 }
509 
510 /*------------------------------------------------------------------------------
511  * MSS_I2C_set_slave_mem_offset_length()
512  * See "mss_i2c.h" for details of how to use this function.
513  */
MSS_I2C_set_slave_mem_offset_length(mss_i2c_instance_t * this_i2c,uint8_t offset_length)514 void MSS_I2C_set_slave_mem_offset_length
515 (
516     mss_i2c_instance_t * this_i2c,
517     uint8_t offset_length
518 )
519 {
520     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
521            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
522     ASSERT(offset_length <= MAX_OFFSET_LENGTH);
523 
524     if (offset_length > MAX_OFFSET_LENGTH)
525     {
526         this_i2c->slave_mem_offset_length = MAX_OFFSET_LENGTH;
527     }
528     else
529     {
530         this_i2c->slave_mem_offset_length = offset_length;
531     }
532 }
533 
534 /*------------------------------------------------------------------------------
535  * MSS_I2C_register_transfer_completion_handler()
536  * See "mss_i2c.h" for details of how to use this function.
537  */
MSS_I2C_register_transfer_completion_handler(mss_i2c_instance_t * this_i2c,mss_i2c_transfer_completion_t completion_handler)538 void MSS_I2C_register_transfer_completion_handler
539 (
540     mss_i2c_instance_t * this_i2c,
541     mss_i2c_transfer_completion_t completion_handler
542 )
543 {
544     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
545            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
546 
547     if (completion_handler == NULL)
548     {
549         this_i2c->transfer_completion_handler = 0u;
550     }
551     else
552     {
553         this_i2c->transfer_completion_handler = completion_handler;
554     }
555 }
556 
557 /*------------------------------------------------------------------------------
558  * MSS_I2C_register_write_handler()
559  * See "mss_i2c.h" for details of how to use this function.
560  */
MSS_I2C_register_write_handler(mss_i2c_instance_t * this_i2c,mss_i2c_slave_wr_handler_t handler)561 void MSS_I2C_register_write_handler
562 (
563     mss_i2c_instance_t * this_i2c,
564     mss_i2c_slave_wr_handler_t handler
565 )
566 {
567     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
568            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
569 
570     this_i2c->slave_write_handler = handler;
571 }
572 
573 /*------------------------------------------------------------------------------
574  * MSS_I2C_enable_slave()
575  * See "mss_i2c.h" for details of how to use this function.
576  */
MSS_I2C_enable_slave(mss_i2c_instance_t * this_i2c)577 void MSS_I2C_enable_slave
578 (
579     mss_i2c_instance_t * this_i2c
580 )
581 {
582     uint32_t primask;
583 
584     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
585            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
586 
587     primask = disable_interrupts();
588 
589     /* Set the assert acknowledge bit. */
590     this_i2c->hw_reg->CTRL |= AA_MASK;
591 
592     /* Enable slave */
593     this_i2c->is_slave_enabled = 1u;
594 
595     restore_interrupts(primask);
596 
597     /* Enable Interrupt */
598     PLIC_EnableIRQ(this_i2c->irqn);
599 }
600 
601 /*------------------------------------------------------------------------------
602  * MSS_I2C_disable_slave()
603  * See "mss_i2c.h" for details of how to use this function.
604  */
MSS_I2C_disable_slave(mss_i2c_instance_t * this_i2c)605 void MSS_I2C_disable_slave
606 (
607     mss_i2c_instance_t * this_i2c
608 )
609 {
610     uint32_t primask;
611 
612     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
613            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
614 
615     primask = disable_interrupts();
616 
617     /* Reset the assert acknowledge bit. */
618     this_i2c->hw_reg->CTRL &= ~AA_MASK;
619 
620     /* Disable slave */
621     this_i2c->is_slave_enabled = 0u;
622 
623     restore_interrupts(primask);
624 }
625 
626 /*------------------------------------------------------------------------------
627  *  MSS Slave enable function
628  */
enable_slave_if_required(mss_i2c_instance_t * this_i2c)629 static void enable_slave_if_required
630 (
631     mss_i2c_instance_t * this_i2c
632 )
633 {
634     if(this_i2c->is_slave_enabled)
635     {
636         this_i2c->hw_reg->CTRL |= AA_MASK;
637     }
638 }
639 
640 /*------------------------------------------------------------------------------
641  * MSS I2C interrupt service routine.
642  *------------------------------------------------------------------------------
643  * Parameters:
644  *
645  * mss_i2c_instance_t * this_i2c:
646  * Pointer to the mss_i2c_instance_t data structure holding all data related to
647  * the MSS I2C instance that generated the interrupt.
648  */
649 
mss_i2c_isr(mss_i2c_instance_t * this_i2c)650 static void mss_i2c_isr
651 (
652     mss_i2c_instance_t * this_i2c
653 )
654 {
655     volatile uint8_t status;
656     uint8_t data;
657     uint8_t hold_bus;
658     uint8_t clear_irq = 1u;
659 
660     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
661            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
662 
663     status = this_i2c->hw_reg->STATUS;
664     switch( status )
665     {
666         /*----------------------------------------------------------------------
667          *  Master transmitter / Receiver
668          */
669         case ST_START: /* Start has been xmt'd */
670         case ST_RESTART: /* Repeated start has been xmt'd */
671             this_i2c->hw_reg->CTRL &= ~STA_MASK;
672 
673             this_i2c->hw_reg->DATA = (uint8_t)(this_i2c->target_addr  |
674                                      (this_i2c->dir & DATA_DIR_MASK));
675 
676             if (this_i2c->dir == WRITE_DIR)
677             {
678                 this_i2c->master_tx_idx = 0u;
679             }
680             else if (this_i2c->dir == READ_DIR)
681             {
682                 this_i2c->master_rx_idx = 0u;
683             }
684             else
685             {
686                 ; /* To avoid LDRA warning. */
687             }
688 
689             /*
690              * Clear the pending transaction. This condition will be true if the
691              * slave has acquired the bus to carry out pending master
692              * transaction which it had received during its slave transmission
693              * or reception mode.
694              */
695             if (this_i2c->is_transaction_pending)
696             {
697                 this_i2c->is_transaction_pending = 0u;
698             }
699 
700             /*
701              * Make sure to update proper transaction after master START
702              * or RESTART
703              */
704             if (this_i2c->transaction != this_i2c->pending_transaction)
705             {
706                 this_i2c->transaction = this_i2c->pending_transaction;
707             }
708             break;
709 
710         case ST_LOST_ARB:
711             /* Set start bit.  Let's keep trying!  Don't give up! */
712             this_i2c->hw_reg->CTRL |= STA_MASK;
713             break;
714 
715         /*----------------------------------------------------------------------
716          *  Master transmitter
717          */
718         case ST_SLAW_NACK:
719             /* SLA+W has been transmitted; not ACK has been received - let's stop. */
720             this_i2c->hw_reg->CTRL |= STO_MASK;
721 
722             this_i2c->master_status = MSS_I2C_FAILED;
723             this_i2c->transaction = NO_TRANSACTION;
724             enable_slave_if_required(this_i2c);
725             break;
726 
727         case ST_SLAW_ACK:
728         case ST_TX_DATA_ACK:
729             /* Data byte has been xmt'd with ACK, time to send stop bit or
730              * repeated start.
731              */
732             if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
733             {
734                 this_i2c->hw_reg->DATA = this_i2c->master_tx_buffer[this_i2c->master_tx_idx];
735                 this_i2c->master_tx_idx++;
736             }
737             else if (this_i2c->transaction == MASTER_RANDOM_READ_TRANSACTION)
738             {
739                 /* We are finished sending the address offset part of a random
740                  * read transaction.
741                  * It is is time to send a restart in order to change direction.
742                  */
743                  this_i2c->dir = READ_DIR;
744                  this_i2c->hw_reg->CTRL |= STA_MASK;
745             }
746             else /* Done sending. let's stop */
747             {
748                 /*
749                  * Set the transaction back to NO_TRANSACTION to allow user to
750                  * do further transaction
751                  */
752                 this_i2c->transaction = NO_TRANSACTION;
753                 hold_bus = this_i2c->options & MSS_I2C_HOLD_BUS;
754 
755                 /* Store the information of current I2C bus status in the
756                  * bus_status.
757                  */
758                 this_i2c->bus_status  = hold_bus;
759                 if (hold_bus == 0u)
760                 {
761                     /* Transmit stop condition. */
762                     this_i2c->hw_reg->CTRL |= STO_MASK;
763                     enable_slave_if_required(this_i2c);
764                 }
765                 else
766                 {
767                     PLIC_DisableIRQ(this_i2c->irqn);
768                     clear_irq = 0u;
769                 }
770                 this_i2c->master_status = MSS_I2C_SUCCESS;
771             }
772             break;
773 
774         case ST_TX_DATA_NACK:
775             /* data byte SENT, ACK to be received
776              * In fact, this means we've received a NACK (This may not be
777              * obvious, but if we've rec'd an ACK then we would be in state
778              * 0x28!) hence, let's send a stop bit
779              */
780             this_i2c->hw_reg->CTRL |= STO_MASK;
781             this_i2c->master_status = MSS_I2C_FAILED;
782 
783             /*
784              * Set the transaction back to NO_TRANSACTION to allow user to do
785              * further transaction.
786              */
787             this_i2c->transaction = NO_TRANSACTION;
788             enable_slave_if_required(this_i2c);
789 
790             break;
791 
792         /*----------------------------------------------------------------------
793          *  Master (or slave?) receiver
794          */
795         /* STATUS codes 08H, 10H, 38H are all covered in MTX mode */
796         case ST_SLAR_ACK: /* SLA+R tx'ed. */
797             /* Let's make sure we ACK the first data byte received (set AA bit
798              * in CTRL) unless the next byte is the last byte of the read
799              transaction.
800              */
801             if (this_i2c->master_rx_size > 1u)
802             {
803                 this_i2c->hw_reg->CTRL |= AA_MASK;
804             }
805             else if (1u == this_i2c->master_rx_size)
806             {
807                 this_i2c->hw_reg->CTRL &= ~AA_MASK;
808             }
809             else /* this_i2c->master_rx_size == 0u */
810             {
811                 this_i2c->hw_reg->CTRL |= AA_MASK;
812                 this_i2c->hw_reg->CTRL |= STO_MASK;
813                 this_i2c->master_status = MSS_I2C_SUCCESS;
814                 this_i2c->transaction = NO_TRANSACTION;
815             }
816             break;
817 
818         case ST_SLAR_NACK:
819             /* SLA+R tx'ed; let's release the bus (send a stop condition) */
820             this_i2c->hw_reg->CTRL |= STO_MASK;
821             this_i2c->master_status = MSS_I2C_FAILED;
822 
823             /*
824              * Set the transaction back to NO_TRANSACTION to allow user to do
825              * further transaction.
826              */
827             this_i2c->transaction = NO_TRANSACTION;
828             enable_slave_if_required(this_i2c);
829             break;
830 
831         case ST_RX_DATA_ACK: /* Data byte received, ACK returned */
832             /* First, get the data */
833             this_i2c->master_rx_buffer[this_i2c->master_rx_idx] = this_i2c->hw_reg->DATA;
834             this_i2c->master_rx_idx++;
835 
836             if (this_i2c->master_rx_idx >= (this_i2c->master_rx_size - 1u))
837             {
838                 /* If we're at the second last byte, let's set AA to 0 so
839                  * we return a NACK at the last byte. */
840                 this_i2c->hw_reg->CTRL &= ~AA_MASK;
841             }
842             break;
843 
844         case ST_RX_DATA_NACK: /* Data byte received, NACK returned */
845             /* Get the data, then send a stop condition */
846             this_i2c->master_rx_buffer[this_i2c->master_rx_idx] = this_i2c->hw_reg->DATA;
847 
848             hold_bus = this_i2c->options &  MSS_I2C_HOLD_BUS;
849 
850             /* Store the information of current I2C bus status in the bus_status*/
851             this_i2c->bus_status  = hold_bus;
852             if (hold_bus == 0u)
853             {
854                 this_i2c->hw_reg->CTRL |= STO_MASK;  /*xmt stop condition */
855 
856                 /* Bus is released, now we can start listening to bus, if it is slave */
857                 enable_slave_if_required(this_i2c);
858             }
859             else
860             {
861                 PLIC_DisableIRQ(this_i2c->irqn);
862                 clear_irq = 0u;
863             }
864 
865             /*
866              * Set the transaction back to NO_TRANSACTION to allow user to do
867              * further transaction.
868              */
869             this_i2c->transaction = NO_TRANSACTION;
870             this_i2c->master_status = MSS_I2C_SUCCESS;
871             break;
872 
873         /*----------------------------------------------------------------------
874          *  Slave receiver
875          */
876         case ST_GCA_NACK: /* NACK after, GCA addressing */
877         case ST_SLA_NACK: /* Re-enable AA (assert ack) bit for
878                            * future transmissions
879                            */
880             this_i2c->hw_reg->CTRL |= AA_MASK;
881 
882             this_i2c->transaction = NO_TRANSACTION;
883             this_i2c->slave_status = MSS_I2C_SUCCESS;
884 
885             /* Check if transaction was pending. If yes, set the START bit */
886             if (this_i2c->is_transaction_pending)
887             {
888                 this_i2c->hw_reg->CTRL |= STA_MASK ;
889             }
890             break;
891 
892         case ST_GCA_LA: /* Arbitr. lost (GCA rec'd) */
893         case ST_SLV_LA: /* Arbitr. lost (SLA rec'd) */
894             /*
895              *  We lost arbitration and either the GCE or our address was the
896              *  one received so pend the master operation we were starting.
897              */
898             this_i2c->is_transaction_pending = 1u;
899             /* Fall through to normal ST processing as we are now in slave
900              * mode
901              */
902         case ST_GCA: /* General call address received, ACK returned */
903         case ST_SLAVE_SLAW: /* SLA+W received, ACK returned */
904 
905             this_i2c->transaction = WRITE_SLAVE_TRANSACTION;
906             this_i2c->slave_rx_idx = 0u;
907             this_i2c->random_read_addr = 0u;
908 
909              /* If Start Bit is set, clear it, but store that information since
910               * it is because of pending transaction
911               */
912             if (this_i2c->hw_reg->CTRL & STA_MASK)
913             {
914                 this_i2c->hw_reg->CTRL &= ~STA_MASK ;
915                 this_i2c->is_transaction_pending = 1u;
916             }
917             this_i2c->slave_status = MSS_I2C_IN_PROGRESS;
918 
919 #ifdef MSS_I2C_INCLUDE_SLA_IN_RX_PAYLOAD
920             /* Fall through to put address as first byte in payload buffer */
921 #else
922             /* Only break from this case if the slave address must NOT be
923              * included at the beginning of the received write data.
924              */
925             break;
926 #endif
927         case ST_GCA_ACK: /* DATA received; ACK sent after GCA */
928         case ST_RDATA: /* DATA received; must clear DATA register */
929             if ((this_i2c->slave_rx_buffer != (uint8_t *)0)
930                && (this_i2c->slave_rx_idx < this_i2c->slave_rx_size))
931             {
932                 data = this_i2c->hw_reg->DATA;
933                 this_i2c->slave_rx_buffer[this_i2c->slave_rx_idx] = data;
934                 this_i2c->slave_rx_idx++;
935 
936 #ifdef MSS_I2C_INCLUDE_SLA_IN_RX_PAYLOAD
937                 if ((ST_RDATA == status) || (ST_GCA_ACK == status))
938                 {
939                     /* Ignore the slave address byte in the random read address
940                      * computation in the case where INCLUDE_SLA_IN_RX_PAYLOAD
941                      * is defined.
942                      */
943 #endif
944                     this_i2c->random_read_addr = (this_i2c->random_read_addr << 8) + data;
945 #ifdef MSS_I2C_INCLUDE_SLA_IN_RX_PAYLOAD
946                 }
947 #endif
948             }
949 
950             if (this_i2c->slave_rx_idx >= this_i2c->slave_rx_size)
951             {
952                 /* Send a NACK when done (next reception) */
953                 this_i2c->hw_reg->CTRL &= ~AA_MASK;
954             }
955             break;
956 
957         case ST_RSTOP:
958             /* STOP or repeated START occurred. */
959             /* We cannot be sure if the transaction has actually completed as
960              * this hardware state reports that either a STOP or repeated START
961              * condition has occurred. We assume that this is a repeated START
962              * if the transaction was a write from the master to this point.*/
963             if (this_i2c->transaction == WRITE_SLAVE_TRANSACTION)
964             {
965                 if (this_i2c->slave_rx_idx == this_i2c->slave_mem_offset_length)
966                 {
967                     this_i2c->slave_tx_idx = this_i2c->random_read_addr;
968                 }
969                 {
970                     /* Call the slave's write transaction handler if it exists.
971                      */
972                     if (this_i2c->slave_write_handler != (mss_i2c_slave_wr_handler_t)0u)
973                     {
974                         mss_i2c_slave_handler_ret_t h_ret;
975                         h_ret = this_i2c->slave_write_handler( this_i2c, this_i2c->slave_rx_buffer, (uint16_t)this_i2c->slave_rx_idx );
976                         if (MSS_I2C_REENABLE_SLAVE_RX == h_ret)
977                         {
978                             /* There is a small risk that the write handler
979                              * could call MSS_I2C_disable_slave() but return
980                              * MSS_I2C_REENABLE_SLAVE_RX in error so we only
981                              * enable ACKs if still in slave mode. */
982                              enable_slave_if_required(this_i2c);
983                              this_i2c->hw_reg->CTRL |= AA_MASK;
984                         }
985                         else
986                         {
987                             this_i2c->hw_reg->CTRL &= ~AA_MASK;
988                             /* Clear slave mode flag as well otherwise in mixed
989                              * master/slave applications, the AA bit will get
990                              * set by subsequent master operations. */
991                             this_i2c->is_slave_enabled = 0u;
992                         }
993                     }
994                     else
995                     {
996                         /* Re-enable address acknowledge in case we were ready
997                          * to nack the next received byte.
998                          */
999                         this_i2c->hw_reg->CTRL |= AA_MASK;
1000                     }
1001                 }
1002             }
1003             else /* A stop or repeated start outside a write/read operation */
1004             {
1005                 /*
1006                  * Reset slave_tx_idx so that a subsequent read will result in
1007                  * the slave's transmit buffer being sent from the first byte.
1008                  */
1009                 this_i2c->slave_tx_idx = 0u;
1010                 /*
1011                  * See if we need to re-enable acknowledgment as some error
1012                  * conditions, such as a master prematurely ending a transfer,
1013                  * can see us get here with AA set to 0 which will disable
1014                  * slave operation if we are not careful.
1015                  */
1016                 enable_slave_if_required(this_i2c);
1017             }
1018 
1019             /* Mark any previous master write transaction as complete. */
1020             this_i2c->slave_status = MSS_I2C_SUCCESS;
1021 
1022             /* Check if transaction was pending. If yes, set the START bit */
1023             if (this_i2c->is_transaction_pending)
1024             {
1025                 this_i2c->hw_reg->CTRL |= STA_MASK ;
1026             }
1027 
1028             /*
1029              * Set the transaction back to NO_TRANSACTION to allow user to do
1030              * further transaction.
1031              */
1032             this_i2c->transaction = NO_TRANSACTION;
1033             break;
1034 
1035         case ST_SLV_RST: /* SMBUS ONLY: timeout state. must clear interrupt */
1036             /*
1037              * Set the transaction back to NO_TRANSACTION to allow user to do
1038              * further transaction.
1039              */
1040             this_i2c->transaction = NO_TRANSACTION;
1041             /*
1042              * Reset slave_tx_idx so that a subsequent read will result in the
1043              * slave's transmit buffer being sent from the first byte.
1044              */
1045             this_i2c->slave_tx_idx = 0u;
1046             /*
1047              * Clear status to I2C_FAILED only if there was an operation in
1048              * progress.
1049              */
1050             if (MSS_I2C_IN_PROGRESS == this_i2c->slave_status)
1051             {
1052                 this_i2c->slave_status = MSS_I2C_FAILED;
1053             }
1054 
1055             /* Make sure AA is set correctly. */
1056             enable_slave_if_required(this_i2c);
1057 
1058             break;
1059 
1060         /*----------------------------------------------------------------------
1061          *  Slave transmitter
1062          */
1063         case ST_SLAVE_SLAR_ACK: /* SLA+R received, ACK returned */
1064         case ST_SLARW_LA:   /* Arbitration lost, SLA+R received, ACK returned */
1065         case ST_RACK: /* Data tx'ed, ACK received */
1066             if (status == ST_SLAVE_SLAR_ACK)
1067             {
1068                 this_i2c->transaction = READ_SLAVE_TRANSACTION;
1069                 this_i2c->random_read_addr = 0u;
1070 
1071                 this_i2c->slave_status = MSS_I2C_IN_PROGRESS;
1072 
1073                 /* If Start Bit is set, clear it, but store that information
1074                  * since it is because of pending transaction.
1075                  */
1076                 if ((this_i2c->hw_reg->CTRL & STA_MASK))
1077                 {
1078                     this_i2c->hw_reg->CTRL &= ~STA_MASK ;
1079                     this_i2c->is_transaction_pending = 1u;
1080                 }
1081             }
1082             if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size)
1083             {
1084                 /* Ensure 0xFF is returned to the master when the slave s
1085                  * pecifies an empty transmit buffer.
1086                  */
1087                 this_i2c->hw_reg->DATA = 0xFFu;
1088             }
1089             else
1090             {
1091                 /* Load the data the data byte to be sent to the master. */
1092                 this_i2c->hw_reg->DATA = this_i2c->slave_tx_buffer[this_i2c->slave_tx_idx];
1093                 this_i2c->slave_tx_idx++;
1094             }
1095             /* Determine if this is the last data byte to send to the master. */
1096             if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size) /* last byte? */
1097             {
1098                 this_i2c->hw_reg->CTRL &= ~AA_MASK;
1099                 /* Next read transaction will result in slave's transmit buffer
1100                  * being sent from the first byte. */
1101                 this_i2c->slave_tx_idx = 0u;
1102             }
1103             break;
1104 
1105         case ST_SLAVE_RNACK:    /* Data byte has been transmitted; not-ACK has
1106                                  * been received.
1107                                  */
1108         case ST_FINAL: /* Last Data byte tx'ed, ACK received */
1109             /* We assume that the transaction will be stopped by the master.
1110              * Reset slave_tx_idx so that a subsequent read will result in the slave's
1111              * transmit buffer being sent from the first byte.
1112              */
1113             this_i2c->slave_tx_idx = 0u;
1114             this_i2c->hw_reg->CTRL |= AA_MASK;
1115 
1116             /*  Mark previous state as complete */
1117             this_i2c->slave_status = MSS_I2C_SUCCESS;
1118 
1119             /* Check if transaction was pending. If yes, set the START bit */
1120             if (this_i2c->is_transaction_pending)
1121             {
1122                 this_i2c->hw_reg->CTRL |= STA_MASK ;
1123             }
1124 
1125             /*
1126              * Set the transaction back to NO_TRANSACTION to allow user to do further
1127              * transaction
1128              */
1129             this_i2c->transaction = NO_TRANSACTION;
1130             break;
1131 
1132         /* Master Reset has been activated Wait 35 ms for interrupt to be set,
1133          * clear interrupt and proceed to 0xF8 state. */
1134         case ST_RESET_ACTIVATED:
1135         case ST_BUS_ERROR: /* Bus error during MST or selected slave modes */
1136         default:
1137             /* Some undefined state has encountered. Clear Start bit to make
1138              * sure, next good transaction happen */
1139             this_i2c->hw_reg->CTRL &= ~STA_MASK;
1140             /*
1141              * Set the transaction back to NO_TRANSACTION to allow user to do further
1142              * transaction
1143              */
1144             this_i2c->transaction = NO_TRANSACTION;
1145             /*
1146              * Reset slave_tx_idx so that a subsequent read will result in the slave's
1147              * transmit buffer being sent from the first byte.
1148              */
1149             this_i2c->slave_tx_idx = 0u;
1150             /*
1151              * Clear statuses to I2C_FAILED only if there was an operation in progress.
1152              */
1153             if (MSS_I2C_IN_PROGRESS == this_i2c->master_status)
1154             {
1155                 this_i2c->master_status = MSS_I2C_FAILED;
1156             }
1157 
1158             if (MSS_I2C_IN_PROGRESS == this_i2c->slave_status)
1159             {
1160                 this_i2c->slave_status = MSS_I2C_FAILED;
1161             }
1162 
1163             break;
1164     }
1165 
1166     if ((this_i2c->master_status != MSS_I2C_IN_PROGRESS) &&
1167        (this_i2c->slave_status != MSS_I2C_IN_PROGRESS) &&
1168        (this_i2c->transfer_completion_handler) &&
1169        (this_i2c->is_slave_enabled == 0))
1170     {
1171         if ((this_i2c->master_status != MSS_I2C_IN_PROGRESS))
1172         {
1173             this_i2c->transfer_completion_handler(this_i2c, this_i2c->master_status);
1174         }
1175         else if ((this_i2c->slave_status != MSS_I2C_IN_PROGRESS))
1176         {
1177             this_i2c->transfer_completion_handler(this_i2c, this_i2c->slave_status);
1178         }
1179         else
1180         {
1181             ; /* To remove LDRA warning. */
1182         }
1183     }
1184 
1185     /* ST_BUS_ERROR */
1186     if (clear_irq)
1187     {
1188         /* Clear interrupt. */
1189         this_i2c->hw_reg->CTRL &= ~SI_MASK;
1190     }
1191 
1192     /* Read the status register to ensure the last I2C registers write took place
1193      * in a system built around a bus making use of posted writes. */
1194     status = this_i2c->hw_reg->STATUS;
1195 }
1196 
1197 /*------------------------------------------------------------------------------
1198  * MSS_I2C_smbus_init()
1199  * See "mss_i2c.h" for details of how to use this function.
1200  */
1201 
1202  /*
1203  * SMBSUS_NO    = 1
1204  * SMBALERT_NO  = 1
1205  * SMBus enable = 1
1206  */
1207 #define MSS_INIT_AND_ENABLE_SMBUS   0x54u
1208 
MSS_I2C_smbus_init(mss_i2c_instance_t * this_i2c,uint8_t frequency)1209 void MSS_I2C_smbus_init
1210 (
1211     mss_i2c_instance_t * this_i2c,
1212     uint8_t frequency
1213 )
1214 {
1215     /* Set the frequency before enabling time out logic. */
1216     this_i2c->hw_reg->FREQ = frequency;
1217 
1218     /* Enable SMBUS. */
1219     this_i2c->hw_reg->SMBUS = MSS_INIT_AND_ENABLE_SMBUS;
1220 }
1221 
1222 /*------------------------------------------------------------------------------
1223  * MSS_I2C_enable_smbus_irq()
1224  * See "mss_i2c.h" for details of how to use this function.
1225  */
MSS_I2C_enable_smbus_irq(mss_i2c_instance_t * this_i2c,uint8_t irq_type)1226 void MSS_I2C_enable_smbus_irq
1227 (
1228     mss_i2c_instance_t * this_i2c,
1229     uint8_t  irq_type
1230 )
1231 {
1232     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
1233            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
1234 
1235     /* Enable any interrupts selected by the user. */
1236     if ((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi))
1237     {
1238         if (irq_type & MSS_I2C_SMBALERT_IRQ)
1239         {
1240             this_i2c->hw_reg->SMBUS |= SMBALERT_IE_MASK;
1241             /* Enable the interrupt at the PLIC. */
1242             PLIC_EnableIRQ(I2C0_ALERT_PLIC);
1243 
1244         }
1245         if (irq_type & MSS_I2C_SMBSUS_IRQ)
1246         {
1247             this_i2c->hw_reg->SMBUS |= SMBSUS_IE_MASK;
1248             /* Enable the interrupt at the PLIC. */
1249             PLIC_EnableIRQ(I2C0_SUS_PLIC);
1250         }
1251     }
1252     else
1253     {
1254         if (irq_type & MSS_I2C_SMBALERT_IRQ)
1255         {
1256             this_i2c->hw_reg->SMBUS |= SMBALERT_IE_MASK;
1257             /* Enable the interrupt at the PLIC. */
1258             PLIC_EnableIRQ(I2C1_ALERT_PLIC);
1259         }
1260         if (irq_type & MSS_I2C_SMBSUS_IRQ)
1261         {
1262             this_i2c->hw_reg->SMBUS |= SMBSUS_IE_MASK;
1263             /* Enable the interrupt at the PLIC. */
1264             PLIC_EnableIRQ(I2C1_SUS_PLIC);
1265         }
1266     }
1267 }
1268 
1269 /*------------------------------------------------------------------------------
1270  * MSS_I2C_disable_smbus_irq()
1271  * See "mss_i2c.h" for details of how to use this function.
1272  */
MSS_I2C_disable_smbus_irq(mss_i2c_instance_t * this_i2c,uint8_t irq_type)1273 void MSS_I2C_disable_smbus_irq
1274 (
1275     mss_i2c_instance_t * this_i2c,
1276     uint8_t  irq_type
1277 )
1278 {
1279     ASSERT((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi) ||
1280            (this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi));
1281 
1282     /* Disable any interrupts selected by the user. */
1283     if ((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi))
1284     {
1285         if (irq_type & MSS_I2C_SMBALERT_IRQ)
1286         {
1287             /* Disable interrupt at the PLIC and the MSS I2C. */
1288             this_i2c->hw_reg->SMBUS &= ~SMBALERT_IE_MASK;
1289             PLIC_DisableIRQ(I2C0_ALERT_PLIC);
1290         }
1291         if (irq_type & MSS_I2C_SMBSUS_IRQ)
1292         {
1293             /* Disable interrupt at the PLIC and the MSS I2C. */
1294             this_i2c->hw_reg->SMBUS &= ~SMBSUS_IE_MASK;
1295             PLIC_DisableIRQ(I2C0_SUS_PLIC);
1296         }
1297     }
1298     else
1299     {
1300         if (irq_type & MSS_I2C_SMBALERT_IRQ)
1301         {
1302             /* Disable interrupt at the PLIC and the MSS I2C. */
1303             this_i2c->hw_reg->SMBUS &= ~SMBALERT_IE_MASK;
1304             PLIC_DisableIRQ(I2C1_ALERT_PLIC);
1305         }
1306         if (irq_type & MSS_I2C_SMBSUS_IRQ)
1307         {
1308             /* Disable interrupt at the PLIC and the MSS I2C. */
1309             this_i2c->hw_reg->SMBUS &= ~SMBSUS_IE_MASK;
1310             PLIC_DisableIRQ(I2C1_SUS_PLIC);
1311         }
1312     }
1313 }
1314 
1315 /*------------------------------------------------------------------------------
1316  * MSS_I2C_suspend_smbus_slave()
1317  * See "mss_i2c.h" for details of how to use this function.
1318  */
MSS_I2C_suspend_smbus_slave(mss_i2c_instance_t * this_i2c)1319 void MSS_I2C_suspend_smbus_slave
1320 (
1321     mss_i2c_instance_t * this_i2c
1322 )
1323 {
1324     /* Active low output so 0 asserts condition. */
1325     this_i2c->hw_reg->SMBUS &= ~SMBSUS_NO_MASK;
1326 }
1327 
1328 /*------------------------------------------------------------------------------
1329  * MSS_I2C_resume_smbus_slave()
1330  * See "mss_i2c.h" for details of how to use this function.
1331  */
MSS_I2C_resume_smbus_slave(mss_i2c_instance_t * this_i2c)1332 void MSS_I2C_resume_smbus_slave
1333 (
1334     mss_i2c_instance_t * this_i2c
1335 )
1336 {
1337     /* Active low output so 1 clears condition. */
1338     this_i2c->hw_reg->SMBUS |= SMBSUS_NO_MASK;
1339 }
1340 
1341 /*------------------------------------------------------------------------------
1342  * MSS_I2C_reset_smbus()
1343  * See "mss_i2c.h" for details of how to use this function.
1344  */
MSS_I2C_reset_smbus(mss_i2c_instance_t * this_i2c)1345 void MSS_I2C_reset_smbus
1346 (
1347     mss_i2c_instance_t * this_i2c
1348 )
1349 {
1350     this_i2c->hw_reg->SMBUS |= SMBUS_RESET_MASK;
1351 }
1352 
1353 /*------------------------------------------------------------------------------
1354  * MSS_I2C_set_smbus_alert()
1355  * See "mss_i2c.h" for details of how to use this function.
1356  */
MSS_I2C_set_smbus_alert(mss_i2c_instance_t * this_i2c)1357 void MSS_I2C_set_smbus_alert
1358 (
1359     mss_i2c_instance_t * this_i2c
1360 )
1361 {
1362     /* Active low output so 0 asserts condition. */
1363     this_i2c->hw_reg->SMBUS &= ~SMBALERT_NO_MASK;
1364 }
1365 
1366 /*------------------------------------------------------------------------------
1367  * MSS_I2C_clear_smbus_alert()
1368  * See "mss_i2c.h" for details of how to use this function.
1369  */
MSS_I2C_clear_smbus_alert(mss_i2c_instance_t * this_i2c)1370 void MSS_I2C_clear_smbus_alert
1371 (
1372     mss_i2c_instance_t * this_i2c
1373 )
1374 {
1375     /* Active low output so 1 clears condition. */
1376     this_i2c->hw_reg->SMBUS |= SMBALERT_NO_MASK;
1377 }
1378 
1379 /*------------------------------------------------------------------------------
1380  * MSS_i2C_set_gca()
1381  * See "mss_i2c.h" for details of how to use this function.
1382  */
MSS_I2C_set_gca(mss_i2c_instance_t * this_i2c)1383 void MSS_I2C_set_gca
1384 (
1385     mss_i2c_instance_t * this_i2c
1386 )
1387 {
1388     /* Accept GC addressing. */
1389     this_i2c->hw_reg->ADDR |= ADDR_GC_MASK;
1390 }
1391 
1392 /*------------------------------------------------------------------------------
1393  * MSS_I2C_clear_gca()
1394  * See "mss_i2c.h" for details of how to use this function.
1395  */
MSS_I2C_clear_gca(mss_i2c_instance_t * this_i2c)1396 void MSS_I2C_clear_gca
1397 (
1398     mss_i2c_instance_t * this_i2c
1399 )
1400 {
1401     /* Disable GC addressing. */
1402     this_i2c->hw_reg->ADDR &= ~ADDR_GC_MASK;
1403 }
1404 
1405 /*------------------------------------------------------------------------------
1406  * MSS_I2C_set_user_data()
1407  * See "mss_i2c.h" for details of how to use this function.
1408  */
MSS_I2C_set_user_data(mss_i2c_instance_t * this_i2c,void * p_user_data)1409 void MSS_I2C_set_user_data
1410 (
1411     mss_i2c_instance_t * this_i2c,
1412     void * p_user_data
1413 )
1414 {
1415     this_i2c->p_user_data = p_user_data ;
1416 }
1417 
1418 /*------------------------------------------------------------------------------
1419  * MSS_I2C_get_user_data()
1420  * See "mss_i2c.h" for details of how to use this function.
1421  */
MSS_I2C_get_user_data(mss_i2c_instance_t * this_i2c)1422 void * MSS_I2C_get_user_data
1423 (
1424     mss_i2c_instance_t * this_i2c
1425 )
1426 {
1427     return (this_i2c->p_user_data);
1428 }
1429 
1430 /*******************************************************************************
1431  * Global initialization based on instance
1432  */
global_init(mss_i2c_instance_t * this_i2c)1433 static void global_init
1434 (
1435     mss_i2c_instance_t * this_i2c
1436 )
1437 {
1438     if (&g_mss_i2c0_lo == this_i2c)
1439     {
1440         this_i2c->hw_reg = MSS_I2C0_LO_BASE;
1441         g_i2c_axi_pos |= 0x01;
1442     }
1443     else if (&g_mss_i2c1_lo == this_i2c)
1444     {
1445         this_i2c->hw_reg = MSS_I2C1_LO_BASE;
1446         g_i2c_axi_pos |= 0x02;
1447     }
1448     else if (&g_mss_i2c0_hi == this_i2c)
1449     {
1450         this_i2c->hw_reg = MSS_I2C0_HI_BASE;
1451         g_i2c_axi_pos |= 0x04;
1452     }
1453     else if (&g_mss_i2c1_hi == this_i2c)
1454     {
1455         this_i2c->hw_reg = MSS_I2C1_HI_BASE;
1456         g_i2c_axi_pos |= 0x08;
1457     }
1458     else
1459     {
1460         ;
1461     }
1462 
1463     if ((this_i2c == &g_mss_i2c0_lo) || (this_i2c == &g_mss_i2c0_hi))
1464     {
1465         this_i2c->irqn = I2C0_MAIN_PLIC;
1466     }
1467     else if ((this_i2c == &g_mss_i2c1_lo) || (this_i2c == &g_mss_i2c1_hi))
1468     {
1469         this_i2c->irqn = I2C1_MAIN_PLIC;
1470     }
1471     else
1472     {
1473         ;
1474     }
1475 
1476 }
1477 
1478 /*------------------------------------------------------------------------------
1479  * External_i2c0_main_plic_IRQHandler interrupt handler
1480  */
External_i2c0_main_plic_IRQHandler(void)1481 uint8_t  External_i2c0_main_plic_IRQHandler(void)
1482 {
1483     if (g_i2c_axi_pos & 0x01)
1484     {
1485         mss_i2c_isr(&g_mss_i2c0_lo);
1486     }
1487     else
1488     {
1489         mss_i2c_isr(&g_mss_i2c0_hi);
1490     }
1491 
1492     return (uint8_t)EXT_IRQ_KEEP_ENABLED;
1493 }
1494 
1495 /*------------------------------------------------------------------------------
1496  * i2c1_main_plic_IRQHandler interrupt handler
1497  */
i2c1_main_plic_IRQHandler(void)1498 uint8_t i2c1_main_plic_IRQHandler(void)
1499 {
1500     if (g_i2c_axi_pos & 0x02)
1501     {
1502         mss_i2c_isr(&g_mss_i2c1_lo);
1503     }
1504     else
1505     {
1506         mss_i2c_isr(&g_mss_i2c1_hi);
1507     }
1508     return (uint8_t)EXT_IRQ_KEEP_ENABLED;
1509 }
1510 
1511 #ifdef __cplusplus
1512 }
1513 #endif
1514