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