1 /*
2 * Copyright (c) 2015-2020, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <stdint.h>
34 #include <stdbool.h>
35 #include <stdlib.h>
36
37 /*
38 * By default disable asserts for this module.
39 * This must be done before DebugP.h is included.
40 */
41 #ifndef DebugP_ASSERT_ENABLED
42 #define DebugP_ASSERT_ENABLED 0
43 #endif
44
45 #include <ti/drivers/dpl/DebugP.h>
46 #include <ti/drivers/dpl/ClockP.h>
47 #include <ti/drivers/dpl/HwiP.h>
48 #include <ti/drivers/dpl/SemaphoreP.h>
49
50 #include <ti/drivers/Power.h>
51 #include <ti/drivers/power/PowerCC32XX.h>
52
53 #include <ti/drivers/i2c/I2CCC32XX.h>
54
55 #include <ti/devices/cc32xx/inc/hw_types.h>
56 #include <ti/devices/cc32xx/inc/hw_memmap.h>
57 #include <ti/devices/cc32xx/inc/hw_common_reg.h>
58 #include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
59 #include <ti/devices/cc32xx/driverlib/rom.h>
60 #include <ti/devices/cc32xx/driverlib/rom_map.h>
61 #include <ti/devices/cc32xx/driverlib/i2c.h>
62 #include <ti/devices/cc32xx/driverlib/prcm.h>
63 #include <ti/devices/cc32xx/inc/hw_i2c.h>
64 #include <ti/devices/cc32xx/driverlib/pin.h>
65
66 /* Pad configuration defines */
67 #define PAD_CONFIG_BASE (OCP_SHARED_BASE + OCP_SHARED_O_GPIO_PAD_CONFIG_0)
68 #define PAD_DEFAULT_STATE 0xC60 /* pad reset, plus set GPIO mode to free I2C */
69
70 #define I2CCC32XX_ERROR_INTS (I2C_MASTER_INT_NACK | \
71 I2C_MASTER_INT_ARB_LOST | I2C_MASTER_INT_TIMEOUT)
72
73 #define I2CCC32XX_TRANSFER_INTS (I2C_MASTER_INT_STOP | \
74 I2CCC32XX_ERROR_INTS)
75
76 #define I2CCC32XX_FIFO_SIZE 8
77 #define I2CCC32XX_MAX_BURST 255
78
79 /* Map MCS read bits to write bits */
80 #define I2C_MCS_START (I2C_MCS_ERROR)
81 #define I2C_MCS_STOP (I2C_MCS_ADRACK)
82 #define I2C_MCS_BURST (I2C_MCS_BUSBSY)
83 #define I2C_MCS_DATACK (I2C_MCS_ACK)
84
85 /* Prototypes */
86 void I2CCC32XX_cancel(I2C_Handle handle);
87 void I2CCC32XX_close(I2C_Handle handle);
88 int_fast16_t I2CCC32XX_control(I2C_Handle handle, uint_fast16_t cmd, void *arg);
89 void I2CCC32XX_init(I2C_Handle handle);
90 I2C_Handle I2CCC32XX_open(I2C_Handle handle, I2C_Params *params);
91 void I2CCC32XX_reset();
92 int_fast16_t I2CCC32XX_transfer(I2C_Handle handle,
93 I2C_Transaction *transaction, uint32_t timeout);
94
95 static void I2CCC32XX_blockingCallback(I2C_Handle handle, I2C_Transaction *msg,
96 bool transferStatus);
97 static void I2CCC32XX_completeTransfer(I2C_Handle handle);
98 static void I2CCC32XX_initHw(I2C_Handle handle);
99 static int I2CCC32XX_postNotify(unsigned int eventType, uintptr_t eventArg,
100 uintptr_t clientArg);
101 static void I2CCC32XX_primeReadBurst(I2CCC32XX_Object *object,
102 I2CCC32XX_HWAttrsV1 const *hwAttrs);
103 static void I2CCC32XX_primeWriteBurst(I2CCC32XX_Object *object,
104 I2CCC32XX_HWAttrsV1 const *hwAttrs);
105 static int_fast16_t I2CCC32XX_primeTransfer(I2CCC32XX_Object *object,
106 I2CCC32XX_HWAttrsV1 const *hwAttrs, I2C_Transaction *transaction);
107 static void I2CCC32XX_readRecieveFifo(I2CCC32XX_Object *object,
108 I2CCC32XX_HWAttrsV1 const *hwAttrs);
109 static void I2CCC32XX_updateReg(uint32_t reg, uint32_t mask, uint32_t val);
110
111 /* I2C function table for I2CCC32XX implementation */
112 const I2C_FxnTable I2CCC32XX_fxnTable = {
113 I2CCC32XX_cancel,
114 I2CCC32XX_close,
115 I2CCC32XX_control,
116 I2CCC32XX_init,
117 I2CCC32XX_open,
118 I2CCC32XX_transfer
119 };
120
121 /*
122 * ======== I2CCC32XX_blockingCallback ========
123 */
I2CCC32XX_blockingCallback(I2C_Handle handle,I2C_Transaction * msg,bool transferStatus)124 static void I2CCC32XX_blockingCallback(I2C_Handle handle,
125 I2C_Transaction *msg, bool transferStatus)
126 {
127 I2CCC32XX_Object *object = handle->object;
128
129 /* Indicate transfer complete */
130 SemaphoreP_post(object->transferComplete);
131 }
132
133 /*
134 * ======== I2CCC32XX_fillTransmitFifo ========
135 */
I2CCC32XX_fillTransmitFifo(I2CCC32XX_Object * object,I2CCC32XX_HWAttrsV1 const * hwAttrs)136 static inline void I2CCC32XX_fillTransmitFifo(I2CCC32XX_Object *object,
137 I2CCC32XX_HWAttrsV1 const *hwAttrs)
138 {
139 while(object->writeCount && object->burstCount &&
140 I2CFIFODataPutNonBlocking(hwAttrs->baseAddr, *(object->writeBuf))) {
141
142 object->writeBuf++;
143 object->writeCount--;
144 object->burstCount--;
145 }
146
147 I2CMasterIntClearEx(hwAttrs->baseAddr, I2C_MASTER_INT_TX_FIFO_EMPTY);
148 }
149
150 /*
151 * ======== I2CCC32XX_initHw ========
152 */
I2CCC32XX_initHw(I2C_Handle handle)153 static void I2CCC32XX_initHw(I2C_Handle handle)
154 {
155 ClockP_FreqHz freq;
156 I2CCC32XX_Object *object = handle->object;
157 I2CCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
158 uint32_t ulRegVal;
159
160 /*
161 * Take I2C hardware semaphore to prevent NWP from accessing I2C.
162 *
163 * This is done in initHw() instead of postNotify(), so the
164 * hardware sempahore is also taken during open().
165 */
166 ulRegVal = HWREG(COMMON_REG_BASE + COMMON_REG_O_I2C_Properties_Register);
167 ulRegVal = (ulRegVal & ~0x3) | 0x1;
168 HWREG(0x400F7000) = ulRegVal;
169
170 /* Disable all interrupts */
171 MAP_I2CMasterIntDisableEx(hwAttrs->baseAddr, 0xFFFFFFFF);
172
173 /* Get CPU Frequency */
174 ClockP_getCpuFreq(&freq);
175
176 /* I2CMasterEnable() invoked in this call */
177 MAP_I2CMasterInitExpClk(hwAttrs->baseAddr, freq.lo,
178 object->bitRate > I2C_100kHz);
179
180 /* Flush the FIFOs. They must be empty before re-assignment */
181 MAP_I2CTxFIFOFlush(hwAttrs->baseAddr);
182 MAP_I2CRxFIFOFlush(hwAttrs->baseAddr);
183
184 /* Set TX and RX FIFOs to master mode */
185 MAP_I2CTxFIFOConfigSet(hwAttrs->baseAddr, I2C_FIFO_CFG_TX_MASTER);
186 MAP_I2CRxFIFOConfigSet(hwAttrs->baseAddr, I2C_FIFO_CFG_RX_MASTER);
187
188 /* Clear any pending interrupts */
189 MAP_I2CMasterIntClearEx(hwAttrs->baseAddr, 0xFFFFFFFF);
190 }
191
192 /*
193 * ======== I2CCC32XX_postNotify ========
194 * This functions is called to notify the I2C driver of an ongoing transition
195 * out of LPDS mode.
196 * clientArg should be pointing to a hardware module which has already
197 * been opened.
198 */
I2CCC32XX_postNotify(unsigned int eventType,uintptr_t eventArg,uintptr_t clientArg)199 static int I2CCC32XX_postNotify(unsigned int eventType,
200 uintptr_t eventArg, uintptr_t clientArg)
201 {
202 /* Reconfigure the hardware when returning from LPDS */
203 I2CCC32XX_initHw((I2C_Handle) clientArg);
204
205 return (Power_NOTIFYDONE);
206 }
207
208
209 /*
210 * ======== I2CCC32XX_completeTransfer ========
211 */
I2CCC32XX_completeTransfer(I2C_Handle handle)212 static void I2CCC32XX_completeTransfer(I2C_Handle handle)
213 {
214 I2CCC32XX_Object *object = handle->object;
215 I2CCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
216
217 /* Disable and clear all interrupts */
218 I2CMasterIntDisableEx(hwAttrs->baseAddr, 0xFFFFFFFF);
219 I2CMasterIntClearEx(hwAttrs->baseAddr, 0xFFFFFFFF);
220
221 /*
222 * If this current transaction was canceled, we need to cancel
223 * any queued transactions
224 */
225 if (object->currentTransaction->status == I2C_STATUS_CANCEL) {
226
227 /*
228 * Allow callback to run. If in CALLBACK mode, the application
229 * may initiate a transfer in the callback which will call
230 * primeTransfer().
231 */
232 object->transferCallbackFxn(handle, object->currentTransaction, false);
233 object->currentTransaction->status = I2C_STATUS_CANCEL;
234
235 /* also dequeue and call the transfer callbacks for any queued transfers */
236 while (object->headPtr != object->tailPtr) {
237 object->headPtr = object->headPtr->nextPtr;
238 object->headPtr->status = I2C_STATUS_CANCEL;
239 object->transferCallbackFxn(handle, object->headPtr, false);
240 object->headPtr->status = I2C_STATUS_CANCEL;
241 }
242
243 /* clean up object */
244 object->currentTransaction = NULL;
245 object->headPtr = NULL;
246 object->tailPtr = NULL;
247 }
248 /* See if we need to process any other transactions */
249 else if (object->headPtr == object->tailPtr) {
250
251 /* No other transactions need to occur */
252 object->headPtr = NULL;
253 object->tailPtr = NULL;
254
255 /*
256 * Allow callback to run. If in CALLBACK mode, the application
257 * may initiate a transfer in the callback which will call
258 * primeTransfer().
259 */
260 object->transferCallbackFxn(handle, object->currentTransaction,
261 (object->currentTransaction->status == I2C_STATUS_SUCCESS));
262
263 /* Release constraint since transaction is done */
264 Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
265 }
266 else {
267 /* Another transfer needs to take place */
268 object->headPtr = object->headPtr->nextPtr;
269
270 /*
271 * Allow application callback to run. The application may
272 * initiate a transfer in the callback which will add an
273 * additional transfer to the queue.
274 */
275 object->transferCallbackFxn(handle, object->currentTransaction,
276 (object->currentTransaction->status == I2C_STATUS_SUCCESS));
277
278 I2CCC32XX_primeTransfer(object,
279 (I2CCC32XX_HWAttrsV1 const *)handle->hwAttrs, object->headPtr);
280 }
281 }
282
283 /*
284 * ======== I2CCC32XX_control ========
285 * @pre Function assumes that the handle is not NULL
286 */
I2CCC32XX_control(I2C_Handle handle,uint_fast16_t cmd,void * arg)287 int_fast16_t I2CCC32XX_control(I2C_Handle handle, uint_fast16_t cmd, void *arg)
288 {
289 /* No implementation yet */
290 return (I2C_STATUS_UNDEFINEDCMD);
291 }
292
293 /*
294 * ======== I2CCC32XX_hwiFxn ========
295 * Hwi interrupt handler to service the I2C peripheral
296 *
297 * The handler is a generic handler for a I2C object.
298 */
I2CCC32XX_hwiFxn(uintptr_t arg)299 static void I2CCC32XX_hwiFxn(uintptr_t arg)
300 {
301 /* Get the pointer to the object and hwAttrs */
302 I2CCC32XX_Object *object = ((I2C_Handle)arg)->object;
303 I2CCC32XX_HWAttrsV1 const *hwAttrs = ((I2C_Handle)arg)->hwAttrs;
304 uint32_t intStatus;
305
306 /* Read and clear masked interrupts */
307 intStatus = I2CMasterIntStatusEx(hwAttrs->baseAddr, true);
308 I2CMasterIntClearEx(hwAttrs->baseAddr, intStatus);
309
310 if (intStatus & I2CCC32XX_ERROR_INTS) {
311
312 /* The MSR contains all error bits */
313 uint32_t status = HWREG(hwAttrs->baseAddr + I2C_O_MCS);
314
315 /* Decode interrupt status */
316 if (status & I2C_MCS_ARBLST) {
317 object->currentTransaction->status = I2C_STATUS_ARB_LOST;
318 }
319 else if (status & I2C_MCS_DATACK) {
320 object->currentTransaction->status = I2C_STATUS_DATA_NACK;
321 }
322 else if (status & I2C_MCS_ADRACK) {
323 object->currentTransaction->status = I2C_STATUS_ADDR_NACK;
324 }
325 else if (status & I2C_MCS_CLKTO) {
326 object->currentTransaction->status = I2C_STATUS_CLOCK_TIMEOUT;
327 }
328 else {
329 object->currentTransaction->status = I2C_STATUS_ERROR;
330 }
331
332 /* If arbitration is lost, another I2C master owns the bus */
333 if (status & I2C_MCS_ARBLST) {
334 I2CCC32XX_completeTransfer((I2C_Handle) arg);
335 return;
336 }
337
338 /* If the stop interrupt has not occurred, force a STOP condition */
339 if (!(intStatus & I2C_MASTER_INT_STOP)) {
340
341 HWREG(hwAttrs->baseAddr + I2C_O_MCS) = I2C_MCS_STOP;
342 return;
343 }
344 }
345 else if (intStatus & I2C_MASTER_INT_TX_FIFO_EMPTY) {
346
347 /* If there is more data to transmit */
348 if (object->writeCount) {
349
350 /* If we need to configure a new burst */
351 if (0 == object->burstCount) {
352 I2CCC32XX_primeWriteBurst(object, hwAttrs);
353 }
354 else {
355 I2CCC32XX_fillTransmitFifo(object, hwAttrs);
356 }
357 }
358 /* Finished writing, is there data to receive? */
359 else if (object->readCount) {
360
361 /* Disable TX interrupt */
362 I2CMasterIntDisableEx(hwAttrs->baseAddr,
363 I2C_MASTER_INT_TX_FIFO_EMPTY);
364
365 object->burstStarted = false;
366 I2CCC32XX_primeReadBurst(object, hwAttrs);
367 }
368 }
369 else if (intStatus & I2C_MASTER_INT_RX_FIFO_REQ ||
370 !(HWREG(hwAttrs->baseAddr + I2C_O_FIFOSTATUS) & I2C_FIFOSTATUS_RXFE)) {
371
372 I2CCC32XX_readRecieveFifo(object, hwAttrs);
373
374 /* If we need to configure a new burst */
375 if (object->readCount && (0 == object->burstCount)) {
376 I2CCC32XX_primeReadBurst(object, hwAttrs);
377 }
378 }
379
380 /* If the STOP condition was set, complete the transfer */
381 if (intStatus & I2C_MASTER_INT_STOP) {
382
383 /* If the transaction completed, update the transaction status */
384 if (object->currentTransaction->status == I2C_STATUS_INCOMPLETE &&
385 (!(object->readCount || object->writeCount))) {
386
387 uint32_t fifoStatus = I2CFIFOStatus(hwAttrs->baseAddr) &
388 (I2C_FIFO_TX_EMPTY | I2C_FIFO_RX_EMPTY);
389
390 /* If both FIFOs are empty */
391 if (fifoStatus == (I2C_FIFO_RX_EMPTY | I2C_FIFO_TX_EMPTY)) {
392 object->currentTransaction->status = I2C_STATUS_SUCCESS;
393 }
394 }
395
396 I2CCC32XX_completeTransfer((I2C_Handle) arg);
397 }
398 }
399
400
401 /*
402 * ======== I2CCC32XX_primeReadBurst =======
403 */
I2CCC32XX_primeReadBurst(I2CCC32XX_Object * object,I2CCC32XX_HWAttrsV1 const * hwAttrs)404 static void I2CCC32XX_primeReadBurst(I2CCC32XX_Object *object,
405 I2CCC32XX_HWAttrsV1 const *hwAttrs)
406 {
407 uint32_t command;
408
409 /* Specify the I2C slave address in receive mode */
410 I2CMasterSlaveAddrSet(hwAttrs->baseAddr,
411 object->currentTransaction->slaveAddress, true);
412
413 /* Determine the size of this burst */
414 if(object->readCount > I2CCC32XX_MAX_BURST) {
415 object->burstCount = I2CCC32XX_MAX_BURST;
416 }
417 else {
418 object->burstCount = object->readCount;
419 }
420
421 /*
422 * If we are reading less than FIFO_SIZE bytes, set the RX FIFO
423 * REQ interrupt to trigger when we finish burstCount bytes.
424 * Else we are reading more than 8 bytes. set the RX FIFO REQ
425 * interrupt to trigger when full. If we are reading less than RXTRIG
426 * bytes during the final byte reads, the RXDONE interrupt will allow
427 * us to complete the read transaction.
428 */
429 if(object->burstCount < I2CCC32XX_FIFO_SIZE) {
430 I2CCC32XX_updateReg(hwAttrs->baseAddr + I2C_O_FIFOCTL,
431 I2C_FIFOCTL_RXTRIG_M, object->burstCount << I2C_FIFOCTL_RXTRIG_S);
432 }
433 else {
434 I2CCC32XX_updateReg(hwAttrs->baseAddr + I2C_O_FIFOCTL,
435 I2C_FIFOCTL_RXTRIG_M, I2C_FIFOCTL_RXTRIG_M);
436 }
437
438 I2CMasterBurstLengthSet(hwAttrs->baseAddr, object->burstCount);
439
440 /* If we will be sending multiple bursts */
441 if(object->readCount > I2CCC32XX_MAX_BURST) {
442 /* Setting the ACK enable ensures we ACK the last byte of a burst */
443 command = (I2C_MCS_BURST | I2C_MCS_ACK);
444 }
445 else {
446 command = (I2C_MCS_BURST | I2C_MCS_STOP);
447 }
448
449 /* Only generate a start condition if the burst hasn't started */
450 if (!object->burstStarted) {
451 command |= I2C_MCS_START;
452 object->burstStarted = true;
453 }
454
455 I2CMasterIntEnableEx(hwAttrs->baseAddr, I2C_MASTER_INT_RX_FIFO_REQ |
456 I2CCC32XX_TRANSFER_INTS);
457
458 HWREG(hwAttrs->baseAddr + I2C_O_MCS) = command;
459 }
460
461 /*
462 * ======== I2CCC32XX_primeWriteBurst =======
463 */
I2CCC32XX_primeWriteBurst(I2CCC32XX_Object * object,I2CCC32XX_HWAttrsV1 const * hwAttrs)464 static void I2CCC32XX_primeWriteBurst(I2CCC32XX_Object *object,
465 I2CCC32XX_HWAttrsV1 const *hwAttrs)
466 {
467 uint32_t command;
468
469 /* Write I2C Slave Address and transmit direction */
470 I2CMasterSlaveAddrSet(hwAttrs->baseAddr,
471 object->currentTransaction->slaveAddress, false);
472
473 /* Determine the size of this burst */
474 if(object->writeCount > I2CCC32XX_MAX_BURST) {
475 object->burstCount = I2CCC32XX_MAX_BURST;
476 }
477 else {
478 object->burstCount = object->writeCount;
479 }
480
481 /* Write burst length */
482 I2CMasterBurstLengthSet(hwAttrs->baseAddr,
483 object->burstCount);
484
485 /* If we will be sending multiple bursts */
486 if (object->readCount || object->writeCount > I2CCC32XX_MAX_BURST) {
487 command = I2C_MCS_BURST;
488 }
489 else {
490 command = I2C_MCS_BURST | I2C_MCS_STOP;
491 }
492
493 /* Only generate a start condition if the burst hasn't started */
494 if (!object->burstStarted) {
495 command |= I2C_MCS_START;
496 object->burstStarted = true;
497 }
498
499 /* Fill transmit FIFO. This will modify the object counts */
500 I2CCC32XX_fillTransmitFifo(object, hwAttrs);
501
502 /* Enable TXFIFOEMPTY interrupt and other standard transfer interrupts */
503 I2CMasterIntEnableEx(hwAttrs->baseAddr, I2C_MASTER_INT_TX_FIFO_EMPTY
504 | I2CCC32XX_TRANSFER_INTS);
505
506 /* Write the Master Control & Status register */
507 HWREG(hwAttrs->baseAddr + I2C_O_MCS) = command;
508 }
509
510 /*
511 * ======== I2CCC32XX_primeTransfer =======
512 */
I2CCC32XX_primeTransfer(I2CCC32XX_Object * object,I2CCC32XX_HWAttrsV1 const * hwAttrs,I2C_Transaction * transaction)513 static int_fast16_t I2CCC32XX_primeTransfer(I2CCC32XX_Object *object,
514 I2CCC32XX_HWAttrsV1 const *hwAttrs, I2C_Transaction *transaction)
515 {
516 int_fast16_t status = I2C_STATUS_SUCCESS;
517
518 /* Store the new internal counters and pointers */
519 object->currentTransaction = transaction;
520
521 object->writeBuf = transaction->writeBuf;
522 object->writeCount = transaction->writeCount;
523
524 object->readBuf = transaction->readBuf;
525 object->readCount = transaction->readCount;
526
527 object->burstCount = 0;
528 object->burstStarted = false;
529
530 /*
531 * Transaction is incomplete unless the stop condition occurs AND
532 * all bytes have been sent and received. This condition is checked
533 * in the hardware interrupt when the STOP condition occurs.
534 */
535 transaction->status = I2C_STATUS_INCOMPLETE;
536
537 /* Flush the FIFOs */
538 I2CTxFIFOFlush(hwAttrs->baseAddr);
539 I2CRxFIFOFlush(hwAttrs->baseAddr);
540
541 /* Determine if the bus is in use by another I2C Master */
542 if (I2CMasterBusBusy(hwAttrs->baseAddr))
543 {
544 transaction->status = I2C_STATUS_BUS_BUSY;
545 status = I2C_STATUS_BUS_BUSY;
546 }
547 /* Start transfer in Transmit mode */
548 else if (object->writeCount) {
549 I2CCC32XX_primeWriteBurst(object, hwAttrs);
550 }
551 /* Start transfer in Receive mode */
552 else {
553 I2CCC32XX_primeReadBurst(object, hwAttrs);
554 }
555
556 return (status);
557 }
558
559 /*
560 * ======== I2CCC32XX_readRecieveFifo ========
561 */
I2CCC32XX_readRecieveFifo(I2CCC32XX_Object * object,I2CCC32XX_HWAttrsV1 const * hwAttrs)562 static void I2CCC32XX_readRecieveFifo(I2CCC32XX_Object *object,
563 I2CCC32XX_HWAttrsV1 const *hwAttrs)
564 {
565
566 while(object->readCount && object->burstCount &&
567 I2CFIFODataGetNonBlocking(hwAttrs->baseAddr, object->readBuf)) {
568 object->readBuf++;
569 object->readCount--;
570 object->burstCount--;
571 }
572
573 I2CMasterIntClearEx(hwAttrs->baseAddr, I2C_MASTER_INT_RX_FIFO_REQ);
574 }
575
576 /*
577 * ======== I2CCC32XX_updateReg ========
578 */
I2CCC32XX_updateReg(uint32_t reg,uint32_t mask,uint32_t val)579 static void I2CCC32XX_updateReg(uint32_t reg, uint32_t mask, uint32_t val)
580 {
581 uint32_t regL = HWREG(reg) & ~mask;
582 HWREG(reg) = (regL | (val & mask));
583 }
584
585 /*
586 * ======== I2CC32XX_cancel ========
587 */
I2CCC32XX_cancel(I2C_Handle handle)588 void I2CCC32XX_cancel(I2C_Handle handle)
589 {
590 I2CCC32XX_Object *object = handle->object;
591 I2CCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
592 uintptr_t key;
593
594 key = HwiP_disable();
595
596 /* Return if no transfer in progress */
597 if (!object->headPtr) {
598 HwiP_restore(key);
599 return;
600 }
601
602 /*
603 * Writing the STOP command may put the I2C peripheral's FSM in a
604 * bad state, so we write RUN | STOP such that the current burst
605 * is transferred or received.
606 */
607 MAP_I2CMasterControl(hwAttrs->baseAddr, I2C_MASTER_CMD_BURST_SEND_FINISH);
608
609 /* Set current transaction as canceled */
610 object->currentTransaction->status = I2C_STATUS_CANCEL;
611
612 HwiP_restore(key);
613 }
614
615 /*
616 * ======== I2CCC32XX_close ========
617 */
I2CCC32XX_close(I2C_Handle handle)618 void I2CCC32XX_close(I2C_Handle handle)
619 {
620 I2CCC32XX_Object *object = handle->object;
621 I2CCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
622 uint32_t padRegister;
623
624 /* Check to see if a I2C transaction is in progress */
625 DebugP_assert(object->headPtr == NULL);
626
627 /* Mask I2C interrupts */
628 MAP_I2CMasterIntDisableEx(hwAttrs->baseAddr, I2CCC32XX_TRANSFER_INTS);
629
630 /* Disable the I2C Master */
631 MAP_I2CMasterDisable(hwAttrs->baseAddr);
632
633 /* Disable I2C module clocks */
634 Power_releaseDependency(PowerCC32XX_PERIPH_I2CA0);
635
636 Power_unregisterNotify(&(object->notifyObj));
637
638 /* Restore pin pads to their reset states */
639 padRegister = (PinToPadGet((hwAttrs->clkPin) & 0xff)<<2) + PAD_CONFIG_BASE;
640 HWREG(padRegister) = PAD_DEFAULT_STATE;
641 padRegister = (PinToPadGet((hwAttrs->dataPin) & 0xff)<<2) + PAD_CONFIG_BASE;
642 HWREG(padRegister) = PAD_DEFAULT_STATE;
643
644 if (object->hwiHandle) {
645 HwiP_delete(object->hwiHandle);
646 object->hwiHandle = NULL;
647 }
648 if (object->mutex) {
649 SemaphoreP_delete(object->mutex);
650 object->mutex = NULL;
651 }
652 /* Destruct the Semaphore */
653 if (object->transferComplete) {
654 SemaphoreP_delete(object->transferComplete);
655 object->transferComplete = NULL;
656 }
657
658 object->isOpen = false;
659
660 return;
661 }
662
663 /*
664 * ======== I2CCC32XX_init ========
665 */
I2CCC32XX_init(I2C_Handle handle)666 void I2CCC32XX_init(I2C_Handle handle)
667 {
668 }
669
670 /*
671 * ======== I2CCC32XX_open ========
672 */
I2CCC32XX_open(I2C_Handle handle,I2C_Params * params)673 I2C_Handle I2CCC32XX_open(I2C_Handle handle, I2C_Params *params)
674 {
675 uintptr_t key;
676 I2CCC32XX_Object *object = handle->object;
677 I2CCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
678 SemaphoreP_Params semParams;
679 HwiP_Params hwiParams;
680 uint16_t pin;
681 uint16_t mode;
682
683 /* Check for valid bit rate */
684 if (params->bitRate > I2C_400kHz) {
685 return (NULL);
686 }
687
688 /* Determine if the device index was already opened */
689 key = HwiP_disable();
690 if(object->isOpen == true){
691 HwiP_restore(key);
692 return (NULL);
693 }
694
695 /* Mark the handle as being used */
696 object->isOpen = true;
697 HwiP_restore(key);
698
699 /* Save parameters */
700 object->transferMode = params->transferMode;
701 object->transferCallbackFxn = params->transferCallbackFxn;
702 object->bitRate = params->bitRate;
703
704 /* Enable the I2C module clocks */
705 Power_setDependency(PowerCC32XX_PERIPH_I2CA0);
706
707 /* In case of app restart: disable I2C module, clear interrupt at NVIC */
708 MAP_I2CMasterDisable(hwAttrs->baseAddr);
709 HwiP_clearInterrupt(hwAttrs->intNum);
710
711 pin = hwAttrs->clkPin & 0xff;
712 mode = (hwAttrs->clkPin >> 8) & 0xff;
713 MAP_PinTypeI2C((unsigned long)pin, (unsigned long)mode);
714
715 pin = hwAttrs->dataPin & 0xff;
716 mode = (hwAttrs->dataPin >> 8) & 0xff;
717 MAP_PinTypeI2C((unsigned long)pin, (unsigned long)mode);
718
719 Power_registerNotify(&(object->notifyObj), PowerCC32XX_AWAKE_LPDS,
720 I2CCC32XX_postNotify, (uint32_t)handle);
721
722 HwiP_Params_init(&hwiParams);
723 hwiParams.arg = (uintptr_t)handle;
724 hwiParams.priority = hwAttrs->intPriority;
725 object->hwiHandle = HwiP_create(hwAttrs->intNum, I2CCC32XX_hwiFxn,
726 &hwiParams);
727 if (object->hwiHandle == NULL) {
728 I2CCC32XX_close(handle);
729 return (NULL);
730 }
731
732 /*
733 * Create threadsafe handles for this I2C peripheral
734 * Semaphore to provide exclusive access to the I2C peripheral
735 */
736 SemaphoreP_Params_init(&semParams);
737 semParams.mode = SemaphoreP_Mode_BINARY;
738 object->mutex = SemaphoreP_create(1, &semParams);
739 if (object->mutex == NULL) {
740 I2CCC32XX_close(handle);
741 return (NULL);
742 }
743
744 /*
745 * Store a callback function that posts the transfer complete
746 * semaphore for synchronous mode
747 */
748 if (object->transferMode == I2C_MODE_BLOCKING) {
749 /*
750 * Semaphore to cause the waiting task to block for the I2C
751 * to finish
752 */
753 object->transferComplete = SemaphoreP_create(0, &semParams);
754 if (object->transferComplete == NULL) {
755 I2CCC32XX_close(handle);
756 return (NULL);
757 }
758
759 /* Store internal callback function */
760 object->transferCallbackFxn = I2CCC32XX_blockingCallback;
761 }
762 else {
763 /* Check to see if a callback function was defined for async mode */
764 DebugP_assert(object->transferCallbackFxn != NULL);
765 }
766
767 /* Clear the head pointer */
768 object->headPtr = NULL;
769 object->tailPtr = NULL;
770 object->currentTransaction = NULL;
771
772 /* Set the I2C configuration */
773 I2CCC32XX_initHw(handle);
774
775 /* Return the address of the handle */
776 return (handle);
777 }
778
779
780
781
782 /*
783 * ======== I2CC32XX_reset ========
784 */
I2CCC32XX_reset()785 void I2CCC32XX_reset()
786 {
787 PRCMPeripheralReset(PRCM_I2CA0);
788 while(!PRCMPeripheralStatusGet(PRCM_I2CA0)) {}
789 }
790
791 /*
792 * ======== I2CCC32XX_transfer ========
793 */
I2CCC32XX_transfer(I2C_Handle handle,I2C_Transaction * transaction,uint32_t timeout)794 int_fast16_t I2CCC32XX_transfer(I2C_Handle handle, I2C_Transaction *transaction,
795 uint32_t timeout)
796 {
797 uintptr_t key;
798 int_fast16_t ret;
799 I2CCC32XX_Object *object = handle->object;
800 I2CCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
801
802 /* Check if anything needs to be written or read */
803 if ((!transaction->writeCount) && (!transaction->readCount)) {
804 transaction->status = I2C_STATUS_INVALID_TRANS;
805 /* Nothing to write or read */
806 return (transaction->status);
807 }
808
809 key = HwiP_disable();
810
811 if (object->transferMode == I2C_MODE_CALLBACK) {
812 /* Check if a transfer is in progress */
813 if (object->headPtr) {
814
815 /*
816 * Queued transactions are being canceled. Can't allow additional
817 * transactions to be queued.
818 */
819 if (object->headPtr->status == I2C_STATUS_CANCEL) {
820 transaction->status = I2C_STATUS_INVALID_TRANS;
821 ret = transaction->status;
822 }
823 /* Transfer in progress */
824 else {
825
826 /*
827 * Update the message pointed by the tailPtr to point to the next
828 * message in the queue
829 */
830 object->tailPtr->nextPtr = transaction;
831
832 /* Update the tailPtr to point to the last message */
833 object->tailPtr = transaction;
834
835 /* Set queued status */
836 transaction->status = I2C_STATUS_QUEUED;
837
838 ret = I2C_STATUS_SUCCESS;
839 }
840
841 HwiP_restore(key);
842 return (ret);
843 }
844 }
845
846 /* Store the headPtr indicating I2C is in use */
847 object->headPtr = transaction;
848 object->tailPtr = transaction;
849
850 /* In blocking mode, transactions can queue on the I2C mutex */
851 transaction->status = I2C_STATUS_QUEUED;
852
853 HwiP_restore(key);
854
855 /* Get the lock for this I2C handle */
856 if (SemaphoreP_pend(object->mutex, SemaphoreP_NO_WAIT)
857 == SemaphoreP_TIMEOUT) {
858
859 /* We were unable to get the mutex in CALLBACK mode */
860 if (object->transferMode == I2C_MODE_CALLBACK) {
861 /*
862 * Recursively call transfer() and attempt to place transaction
863 * on the queue. This may only occur if a thread is preempted
864 * after restoring interrupts and attempting to grab this mutex.
865 */
866 return (I2CCC32XX_transfer(handle, transaction, timeout));
867 }
868
869 /* Wait for the I2C lock. If it times-out before we retrieve it, then
870 * return I2C_STATUS_TIMEOUT to cancel the transaction. */
871 if(SemaphoreP_pend(object->mutex, timeout) == SemaphoreP_TIMEOUT) {
872 transaction->status = I2C_STATUS_TIMEOUT;
873 return (I2C_STATUS_TIMEOUT);
874 }
875 }
876
877 if (object->transferMode == I2C_MODE_BLOCKING) {
878 /*
879 * In the case of a timeout, It is possible for the timed-out transaction
880 * to call the hwi function and post the object->transferComplete Semaphore
881 * To clear this, we simply do a NO_WAIT pend on (binary)
882 * object->transferComplete, so that it resets the Semaphore count.
883 */
884 SemaphoreP_pend(object->transferComplete, SemaphoreP_NO_WAIT);
885 }
886
887 Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
888
889 /*
890 * I2CCC32XX_primeTransfer is a longer process and
891 * protection is needed from the I2C interrupt
892 */
893 HwiP_disableInterrupt(hwAttrs->intNum);
894 ret = I2CCC32XX_primeTransfer(object, hwAttrs, transaction);
895 HwiP_enableInterrupt(hwAttrs->intNum);
896
897 if (ret != I2C_STATUS_SUCCESS) {
898 /* Error occured, fall through */
899 }
900 else if (object->transferMode == I2C_MODE_BLOCKING) {
901 /* Wait for the primed transfer to complete */
902 if (SemaphoreP_pend(object->transferComplete, timeout)
903 == SemaphoreP_TIMEOUT) {
904
905 key = HwiP_disable();
906
907 /*
908 * Protect against a race condition in which the transfer may
909 * finish immediately after the timeout. If this occurs, we
910 * will preemptively consume the semaphore on the next initiated
911 * transfer.
912 */
913 if (object->headPtr) {
914
915 /*
916 * It's okay to call cancel here since this is blocking mode.
917 * Cancel will generate a STOP condition and immediately
918 * return.
919 */
920 I2CCC32XX_cancel(handle);
921
922 HwiP_restore(key);
923
924 /*
925 * We must wait until the STOP interrupt occurs. When this
926 * occurs, the semaphore will be posted. Since the STOP
927 * condition will finish the current burst, we can't
928 * unblock the object->mutex until this occurs.
929 *
930 * This may block forever if the slave holds the clock line--
931 * rendering the I2C bus un-usable.
932 */
933 SemaphoreP_pend(object->transferComplete,
934 SemaphoreP_WAIT_FOREVER);
935
936 transaction->status = I2C_STATUS_TIMEOUT;
937 }
938 else {
939 HwiP_restore(key);
940 }
941 }
942
943 ret = transaction->status;
944 }
945
946 /* Release the lock for this particular I2C handle */
947 SemaphoreP_post(object->mutex);
948
949 return (ret);
950 }
951